djbdnscurve6 53
djbdnscurve6
Loading...
Searching...
No Matches
tdlookup.c
Go to the documentation of this file.
1
2#include <unistd.h>
3#include "uint_t.h"
4#include "open.h"
5#include "tai.h"
6#include "cdbread.h"
7#include "byte.h"
8#include "case.h"
9#include "dns.h"
10#include "seek.h"
11#include "response.h"
12#include "ip.h"
13#include "clientloc.h"
14
15static int want(const char *owner,const char type[2])
16{
17 unsigned int pos;
18 static char *d;
19 char x[10];
20 uint16 datalen;
21
22 pos = dns_packet_skipname(response,response_len,12); if (!pos) return 0;
23 pos += 4;
24
25 while (pos < response_len) {
26 pos = dns_packet_getname(response,response_len,pos,&d); if (!pos) return 0;
27 pos = dns_packet_copy(response,response_len,pos,x,10); if (!pos) return 0;
29 if (byte_equal(type,2,x)) return 0;
30 uint16_unpack_big(x + 8,&datalen);
31 pos += datalen;
32 }
33 return 1;
34}
35
36static char *d1;
37
38static char clientloc[2];
39static struct tai now;
40static struct cdb c;
41
42static char data[32767];
43static uint32 dlen;
44static unsigned int dpos;
45static char type[2];
46static uint32 ttl;
47
48static int find(char *d,int flagwild)
49{
50 int r;
51 char ch;
52 struct tai cutoff;
53 char ttd[8];
54 char ttlstr[4];
55 char recordloc[2];
56 double newttl;
57
58 for (;;) {
59 r = cdb_findnext(&c,d,dns_domain_length(d));
60 if (r <= 0) return r;
61 dlen = cdb_datalen(&c);
62 if (dlen > sizeof(data)) return DNS_ERR;
63 if (cdb_read(&c,data,dlen,cdb_datapos(&c)) == -1) return DNS_INT;
64 dpos = dns_packet_copy(data,dlen,0,type,2); if (!dpos) return DNS_ERR;
65 dpos = dns_packet_copy(data,dlen,dpos,&ch,1); if (!dpos) return DNS_ERR;
66 if ((ch == '=' + 1) || (ch == '*' + 1)) { // XXX: locator '='/'>' (in/out); wildcard '+'
67 --ch;
68 dpos = dns_packet_copy(data,dlen,dpos,recordloc,2); if (!dpos) return DNS_ERR;
69 if (byte_diff(recordloc,2,clientloc)) continue;
70 }
71 if (flagwild != (ch == '*')) continue;
72 dpos = dns_packet_copy(data,dlen,dpos,ttlstr,4); if (!dpos) return DNS_ERR;
73 uint32_unpack_big(ttlstr,&ttl);
74 dpos = dns_packet_copy(data,dlen,dpos,ttd,8); if (!dpos) return DNS_ERR;
75 if (byte_diff(ttd,8,"\0\0\0\0\0\0\0\0")) {
76 tai_unpack(ttd,&cutoff);
77 if (ttl == 0) {
78 if (tai_less(&cutoff,&now)) continue;
79 tai_sub(&cutoff,&cutoff,&now);
80 newttl = tai_approx(&cutoff);
81 if (newttl <= 2.0) newttl = 2.0;
82 if (newttl >= 3600.0) newttl = 3600.0;
83 ttl = newttl;
84 }
85 else
86 if (!tai_less(&cutoff,&now)) continue;
87 }
88 return 1;
89 }
90}
91
92static int dobytes(unsigned int len)
93{
94 char buf[20];
95 if (len > 20) return 0;
97 if (!dpos) return 0;
99}
100
101static int doname(void)
102{
104 if (!dpos) return 0;
105 return response_addname(d1);
106}
107
108static int doit(char *q,char qtype[2])
109{
110 unsigned int bpos;
111 unsigned int anpos;
112 unsigned int aupos;
113 unsigned int arpos;
114 char *control;
115 char *wild;
116 int flaggavesoa;
117 int flagfound;
118 int r;
119 int flagns;
120 int flagauthoritative;
121 char x[20];
122 char dn[FQDN_LEN + 1];
123 uint16 u16;
124 char addr4[MAX_ANSWERS][4];
125 char addr6[MAX_ANSWERS][16];
126 int addr4num, addr6num;
127 uint32 addr4ttl;
128 uint32 addr6ttl;
129 int i;
130
131 anpos = response_len;
132
133 control = q;
134 for (;;) {
135 flagns = 0;
136 flagauthoritative = 0;
137 cdb_findstart(&c);
138 while ((r = find(control,0))) {
139 if (r == -1) return 0;
140 if (byte_equal(type,2,DNS_T_SOA)) flagauthoritative = 1;
141 if (byte_equal(type,2,DNS_T_NS)) flagns = 1;
142 }
143 if (flagns) break;
144 if (!*control) return 0; /* q is not within our bailiwick */
145 control += *control;
146 control += 1;
147 }
148
149 if (!flagauthoritative) {
150 response[2] &= ~4;
151 goto AUTHORITY; /* q is in a child zone */
152 }
153
154
155 flaggavesoa = 0;
156 flagfound = 0;
157 wild = q;
158
159 for (;;) {
160 addr4num = addr6num = 0;
161 addr4ttl = addr6ttl = 0;
162 cdb_findstart(&c);
163 while ((r = find(wild,wild != q))) {
164 if (r == -1) return 0;
165 flagfound = 1;
166 if (flaggavesoa && byte_equal(type,2,DNS_T_SOA)) continue;
167 if (byte_diff(type,2,qtype) && byte_diff(qtype,2,DNS_T_ANY) &&
168 byte_diff(type,2,DNS_T_CNAME)) continue;
169
170 if (byte_equal(type,2,DNS_T_A) && (dlen - dpos == 4)) {
171 addr4ttl = ttl;
172 i = dns_random(addr4num + 1);
173 if (i < MAX_ANSWERS) {
174 if ((i < addr4num) && (addr4num < MAX_ANSWERS))
175 byte_copy(addr4[addr4num],4,addr4[i]);
176 byte_copy(addr4[i],4,data + dpos);
177 }
178 if (addr4num < 1000000) ++addr4num;
179 continue;
180 }
181 if (byte_equal(type,2,DNS_T_AAAA) && (dlen - dpos == 16)) {
182 addr6ttl = ttl;
183 i = dns_random(addr6num + 1);
184 if (i < MAX_ANSWERS) {
185 if ((i < addr6num) && (addr6num < MAX_ANSWERS))
186 byte_copy(addr6[addr6num],16,addr6[i]);
187 byte_copy(addr6[i],16,data + dpos);
188 }
189 if (addr6num < 1000000) ++addr6num;
190 continue;
191 }
192 if (!response_rstart(q,type,ttl)) return 0;
193 if (byte_equal(type,2,DNS_T_NS) ||
194 byte_equal(type,2,DNS_T_CNAME) ||
195 byte_equal(type,2,DNS_T_PTR)) {
196 if (!doname()) return 0;
197 }
198 else if (byte_equal(type,2,DNS_T_MX)) {
199 if (!dobytes(2)) return 0;
200 if (!doname()) return 0;
201 }
202 else if (byte_equal(type,2,DNS_T_SOA)) {
203 if (!doname()) return 0;
204 if (!doname()) return 0;
205 if (!dobytes(20)) return 0;
206 flaggavesoa = 1;
207 }
208 else
209 if (!response_addbytes(data + dpos,dlen - dpos)) return 0;
211 }
212 for (i = 0; i < addr4num; ++i)
213 if (i < MAX_ANSWERS) {
214 if (!response_rstart(q,DNS_T_A,addr4ttl)) return 0;
215 if (!response_addbytes(addr4[i],4)) return 0;
217 }
218 for (i = 0; i < addr6num; ++i)
219 if (i < MAX_ANSWERS) {
220 if (!response_rstart(q,DNS_T_AAAA,addr6ttl)) return 0;
221 if (!response_addbytes(addr6[i],16)) return 0;
223 }
224
225 if (flagfound) break;
226 if (wild == control) break;
227 if (!*wild) break; /* impossible */
228 wild += *wild;
229 wild += 1;
230 }
231
232 if (!flagfound) response_nxdomain();
233
234
235 AUTHORITY:
236 aupos = response_len;
237
238 if (flagauthoritative && (aupos == anpos)) {
239 cdb_findstart(&c);
240 while ((r = find(control,0))) {
241 if (r == -1) return 0;
242 if (byte_equal(type,2,DNS_T_SOA)) {
243 if (!response_rstart(control,DNS_T_SOA,ttl)) return 0;
244 if (!doname()) return 0;
245 if (!doname()) return 0;
246 if (!dobytes(20)) return 0;
248 break;
249 }
250 }
251 } else if (want(control,DNS_T_NS)) {
252 cdb_findstart(&c);
253 while ((r = find(control,0))) {
254 if (r == -1) return 0;
255 if (byte_equal(type,2,DNS_T_NS)) {
256 if (!response_rstart(control,DNS_T_NS,ttl)) return 0;
257 if (!doname()) return 0;
259 }
260 }
261 }
262
263 arpos = response_len;
264
265 // Fill Additional Section
266
267 bpos = anpos;
268 while (bpos < arpos) {
269 bpos = dns_packet_skipname(response,arpos,bpos); if (!bpos) return 0;
270 bpos = dns_packet_copy(response,arpos,bpos,x,10); if (!bpos) return 0;
271
272 if (byte_equal(x,2,DNS_T_NS) || byte_equal(x,2,DNS_T_MX)) {
273 if (byte_equal(x,2,DNS_T_NS)) {
274 if (!dns_packet_getname(response,arpos,bpos,&d1)) return 0;
275 }
276 else if (!dns_packet_getname(response,arpos,bpos + 2,&d1)) return 0;
277
278 int dl = dns_domain_length(d1); // core a DJB bug
279 case_lowerb(d1,dl);
280
281 case_lowerb(d1,dns_domain_length(d1));
282
283 byte_zero(dn,FQDN_LEN);
284 if (want(d1,DNS_T_A) || want(d1,DNS_T_AAAA)) {
285 cdb_findstart(&c);
286 while ((r = find(d1,0))) {
287 if (r == -1) return 0;
288 if (byte_equal(type,2,DNS_T_A)) {
289 if (byte_equal(d1,dl,dn)) continue;
290 if (!response_rstart(d1,DNS_T_A,ttl)) return 0;
291 byte_copy(dn,dl,d1);
292 if (!dobytes(4)) return 0;
294 }
295 else if (byte_equal(type,2,DNS_T_AAAA)) {
296 if (byte_equal(d1,dl,dn)) continue;
297 if (!response_rstart(d1,DNS_T_AAAA,ttl)) return 0;
298 byte_copy(dn,dl,d1);
299 if (!dobytes(16)) return 0;
301 }
302 }
303 }
304 }
305 uint16_unpack_big(x + 8,&u16);
306 bpos += u16;
307 }
308
309 if (flagauthoritative && (response_len > max_response_len)) {
310 byte_zero(response + RESPONSE_ADDITIONAL,2);
311 response_len = arpos;
312 if (response_len > MSGSIZE) { // from macro, not udp_msgsize()
313 byte_zero(response + RESPONSE_AUTHORITY,2);
314 response_len = aupos;
315 }
316 }
317
318 return 1;
319}
320
321int respond(char *q,char qtype[2],char ip[16])
322{
323 int fd;
324 int r;
325
327
328 tai_now(&now);
329 fd = open_read("data.cdb");
330 if (fd == -1) return 0;
331 cdb_init(&c,fd);
332
333 r = doit(q,qtype);
334
335 cdb_free(&c);
336 close(fd);
337 return r;
338}
int fd
Definition: axfr-get.c:103
unsigned int doit(char *buf, unsigned int len, unsigned int pos)
Definition: axfr-get.c:131
char data[32767]
Definition: axfrdns.c:133
struct tai now
Definition: axfrdns.c:132
char clientloc[2]
Definition: axfrdns.c:130
char ip[16]
Definition: axfrdns.c:128
uint16 len
Definition: axfrdns.c:322
char buf[MSGSIZE]
Definition: axfrdns.c:321
uint32 dpos
Definition: axfrdns.c:135
void doname(stralloc *sa)
Definition: axfrdns.c:143
uint32 dlen
Definition: axfrdns.c:134
int find_clientloc(char clientloc[2], const char ip[16])
Definition: clientloc.c:8
#define DNS_ERR
Definition: dns.h:41
#define DNS_T_A
Definition: dns.h:65
#define MAX_ANSWERS
Definition: dns.h:58
#define DNS_T_ANY
Definition: dns.h:96
#define MSGSIZE
Definition: dns.h:47
#define DNS_INT
Definition: dns.h:43
#define DNS_T_PTR
Definition: dns.h:69
#define DNS_T_SOA
Definition: dns.h:68
#define DNS_T_NS
Definition: dns.h:66
#define DNS_T_CNAME
Definition: dns.h:67
#define DNS_T_AAAA
Definition: dns.h:76
#define DNS_T_MX
Definition: dns.h:71
#define FQDN_LEN
Definition: dns.h:57
int dns_domain_equal(const char *dn1, const char *dn2)
Definition: dns_domain.c:39
unsigned int dns_domain_length(const char *dn)
Definition: dns_domain.c:6
unsigned int dns_packet_getname(const char *buf, unsigned int len, unsigned int pos, char **d)
Definition: dns_packet.c:35
unsigned int dns_packet_copy(const char *buf, unsigned int len, unsigned int pos, char *out, unsigned int outlen)
Definition: dns_packet.c:8
unsigned int dns_packet_skipname(const char *buf, unsigned int len, unsigned int pos)
Definition: dns_packet.c:18
unsigned int dns_random(unsigned int n)
Definition: dns_random.c:55
struct line * x
char type[2]
Definition: dnsq.c:60
void owner(int uid, int gid)
Definition: generic-conf.c:76
void d(const char *home, const char *subdir, int uid, int gid, int mode)
struct cdb_make cdb
Definition: rbldns-data.c:36
int response_rstart(const char *, const char[2], uint32)
Definition: response.c:75
int response_addname(const char *)
Definition: response.c:25
void response_rfinish(int)
Definition: response.c:89
int response_addbytes(const char *, unsigned int)
Definition: response.c:17
char response[]
Definition: response.c:6
unsigned int max_response_len
Definition: response.c:8
unsigned int response_len
Definition: response.c:7
#define RESPONSE_AUTHORITY
Definition: response.h:24
#define RESPONSE_ANSWER
Definition: response.h:23
void response_nxdomain(void)
Definition: response.c:103
#define RESPONSE_ADDITIONAL
Definition: response.h:25
int respond(char *q, char qtype[2], char ip[16])
Definition: tdlookup.c:321