summaryrefslogtreecommitdiffstats
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c190
1 files changed, 190 insertions, 0 deletions
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..ec94e3f
--- /dev/null
+++ b/main.c
@@ -0,0 +1,190 @@
+#include <sys/socket.h> /* udp(7) */ /* TODO: random XID */
+#include <netinet/in.h>
+#include <netinet/udp.h>
+#include <poll.h> /* poll(2) */
+#include <sys/types.h> /* socket(2) */
+#include <sys/socket.h>
+#include <unistd.h> /* close(2) */
+#include <stdio.h> /* perror(3) */
+#include <sys/stat.h> /* open(2) */
+#include <fcntl.h>
+#include <errno.h> /* errno(3) */
+#include <arpa/inet.h> /* byteorder(3) */
+#include <string.h> /* strlen(3) */
+#include "domain2name.c"
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define MAXDOMAIN 255
+#define QUERYDOMAIN "http://sijanec.eu/link?r=.sijanec.eu."
+#define EXPECTEDA 93.103.235.126
+#define HELP "find recursive DNS resolvers on IPv4 networks\n" \
+ "%s [-h] [-d domain] [-a ipv4] network1 [network2 [network3 ...]]\n" \
+ " -a Specify the IPv4 of the -d domain to be used instead of getaddrinfo(3).\n" \
+ " -d Specify the domain name to be used in queries that has a single A record.\n" \
+ " -h Show this help and exit.\n" \
+ "Networks are specified as domain names or IPv4 addresses followed by a forward slash\n" \
+ "and the netmask in decimal (0-32) or dot notation. For example: example.com/32. \n" \
+ "When scanning the Internet please make sure that you specify your own domain instead\n" \
+ "of the default one (f@sijanec.eu-http://sijanec.eu/link?r=.sijanec.eu). Make sure it\n" \
+ "somehow contains your contact information so the network/server administrator when\n" \
+ "looking at the logs will be able to contact you.\n"
+/* DNS PACKET: HEADER (12 bytes) QUESTION ANSWER AUTHORITY ADDITIONAL
+
+DEFINITIONS: (those appear somewhere in the packet, packet does not start with definitions!)
+ LABLEN 8 bits: first two bits zero, then 6 bits length of label
+ POINTER 8 bits: first two bits one, then 6 bits as offset from first byte of packet
+ STRING a single byte for defining length (0-256 - all eight bits) and then string of chars
+ DOMAIN i.) one or more LABLEN followed by ASCII label (no dots) end with either LABLEN 0
+ or a POINTER that points to some LABLEN somewhere else in the packet -OR-:
+ ii.) a POINTER that points to some LABLEN somewhere else in the packet
+
+HEADER:
+ XID 16 bits: random string to be matched in response to prevent cache poisoning
+ / QR 1 bit : what type is this packet? 0 query 1 response
+ | OPCODE 4 bits: type of query 0 std 1 invrs 2 srvst 3-15 reserved
+1 byte AA 1 bit : is response authoritative? 0 no 1 yes
+ | TC 1 bit : was response truncated? 0 no 1 yes
+ \ RD 1 bit : does query desire recursion? 0 no 1 yes
+ / RA 1 bit : does response server recurse? 0 no 1 yes
+1 byte Z 3 bits: reserved for future 0 only option
+ \ RCODE 4 bits: error condition 0 ok 1 fmter 2 srvfa 3 nxdom 4 N/I 5 forbidden
+ QDCOUNT 16 bits: number of questions
+ ANCOUNT 16 bits: number of answers
+ NSCOUNT 16 bits: authority section (where to ask for actual response - NS RECORDS)
+ ARCOUNT 16 bits: additional section (glue records)
+QUESTION:
+ QNAME DOMAIN
+ QTYPE 16 bits: 1 A 2 NS 5 CNAME 6 SOA 10 NULL 12 PTR 13 HINFO 15 MX 16 TXT ...
+ QCLASS 16 bits: 1 INTERNET 2 CSNET (obsolete) 3 CHAOS 4 HESIOD 255 ANY ...
+ANSWER:
+ NAME DOMAIN
+ TYPE same as QTYPE
+ CLASS same description as QCLASS, except class 255 ANY is not allowed here
+ RDLEN 16 bits: length of RDATA field - this is a number 0-65536, no two zero bits
+ RDATA A: 4 bytes IP address NS: DOMAIN CNAME: DOMAIN
+ SOA: NAME-ns1 NAME-email 32b-serial 32b-refresh 32b-retry 32b-expire 32b-nxdomainttl
+ NULL: any data up to RDLEN PTR: DOMAIN HINFO: STRING-CPU, STRING-OS
+ MX: 16 bit preference, NAME-like domain TXT: one or more STRING
+
+
+*/
+enum qr {
+ Query,
+ Response
+};
+enum opcode {
+ Query,
+ Iquery,
+ Stauts
+};
+enum rcode {
+ Success,
+ Format_error,
+ Servfail,
+ Nxdomain,
+ Ni,
+ Forbidden
+};
+enum type {
+ A = 1,
+ Ns,
+ Md,
+ Mf,
+ Cname,
+ Soa,
+ Mb,
+ Mg,
+ Mr,
+ Null,
+ Wks,
+ Ptr,
+ Hinfo,
+ Minfo,
+ Mx,
+ Txt
+}
+enum class {
+ In = 1,
+ Cs,
+ Ch,
+ He,
+ Any = 255
+}
+struct header {
+ uint16_t xid;
+ enum qr qr : 1;
+ enum opcode opcode : 4;
+ unsigned int aa : 1;
+ unsigned int tc : 1;
+ unsigned int rd : 1;
+ unsigned int ra : 1;
+ unsigned int z : 3;
+ enum rcode rcode : 4;
+ uint16_t qdcount;
+ uint16_t ancount;
+ uint16_t nscount;
+ uint16_t arcount;
+};
+struct question {
+ char * qname;
+ enum qtype qtype : 16;
+ enum qclass qclass : 16;
+};
+struct answer {
+ char * name;
+ enum class class : 16;
+ uint16_t rdlen;
+ char * rdata;
+}
+int main (int argc, char ** argv) {
+ int r = 0;
+ while (t) {
+ switch (getopt(argc, argv, ":a:d:h")) {
+ /* TODO */
+ case 'h':
+ printf(HELP, argv[0]);
+ r = 0;
+ goto r;
+ case -1:
+ d = optarg;
+ if (!d || !*d) {
+ fprintf(stderr, "specify the domain :: " HELP, argv[0]);
+ r = 4;
+ goto r;
+ }
+ if (strlen(d) > MAXDOMAIN) {
+ fprintf(stderr, "domain is too long - max "#MAXDOMAIN".\n");
+ r = 5;
+ goto r;
+ }
+ t = 0;
+ break;
+ case '?':
+ fprintf(stderr, "unknown option :: " HELP, argv[0]);
+ if (db != -1)
+ close(db);
+ r = 6;
+ goto r;
+ case ':':
+ fprintf(stderr, "missing option argument :: " HELP, argv[0]);
+ r = 7;
+ goto r;
+ }
+ }
+r:
+ if (s != -1)
+ if (close(s))
+ perror("close(s)");
+ }
+ return r;
+}
+int handle () {
+ char buf[512]; /* we don't support EDNS0 here, so max DNS packet is 512 bytes */
+ recvfrom();
+}
+int query () {
+ sendto();
+}
+int erase (char * dbfn, int dbfd, char * db) {
+
+}