1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
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) {
}
|