diff options
Diffstat (limited to 'main.c')
-rw-r--r-- | main.c | 190 |
1 files changed, 190 insertions, 0 deletions
@@ -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) { + +} |