1 /* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17 #include "dnsmasq.h"
18
19 static int add_resource_record(HEADER* header, char* limit, int* truncp, unsigned int nameoffset,
20 unsigned char** pp, unsigned long ttl, unsigned int* offset,
21 unsigned short type, unsigned short class, char* format, ...);
22
23 #define CHECK_LEN(header, pp, plen, len) \
24 ((size_t)((pp) - (unsigned char*) (header) + (len)) <= (plen))
25
26 #define ADD_RDLEN(header, pp, plen, len) \
27 (!CHECK_LEN(header, pp, plen, len) ? 0 : (long) ((pp) += (len)), 1)
28
extract_name(HEADER * header,size_t plen,unsigned char ** pp,char * name,int isExtract,int extrabytes)29 static int extract_name(HEADER* header, size_t plen, unsigned char** pp, char* name, int isExtract,
30 int extrabytes) {
31 unsigned char *cp = (unsigned char*) name, *p = *pp, *p1 = NULL;
32 unsigned int j, l, hops = 0;
33 int retvalue = 1;
34
35 if (isExtract) *cp = 0;
36
37 while (1) {
38 unsigned int label_type;
39
40 if (!CHECK_LEN(header, p, plen, 1)) return 0;
41
42 if ((l = *p++) == 0)
43 /* end marker */
44 {
45 /* check that there are the correct no of bytes after the name */
46 if (!CHECK_LEN(header, p1 ? p1 : p, plen, extrabytes)) return 0;
47
48 if (isExtract) {
49 if (cp != (unsigned char*) name) cp--;
50 *cp = 0; /* terminate: lose final period */
51 } else if (*cp != 0)
52 retvalue = 2;
53
54 if (p1) /* we jumped via compression */
55 *pp = p1;
56 else
57 *pp = p;
58
59 return retvalue;
60 }
61
62 label_type = l & 0xc0;
63
64 if (label_type == 0xc0) /* pointer */
65 {
66 if (!CHECK_LEN(header, p, plen, 1)) return 0;
67
68 /* get offset */
69 l = (l & 0x3f) << 8;
70 l |= *p++;
71
72 if (!p1) /* first jump, save location to go back to */
73 p1 = p;
74
75 hops++; /* break malicious infinite loops */
76 if (hops > 255) return 0;
77
78 p = l + (unsigned char*) header;
79 } else if (label_type == 0x80)
80 return 0; /* reserved */
81 else if (label_type == 0x40) { /* ELT */
82 unsigned int count, digs;
83
84 if ((l & 0x3f) != 1) return 0; /* we only understand bitstrings */
85
86 if (!isExtract) return 0; /* Cannot compare bitsrings */
87
88 count = *p++;
89 if (count == 0) count = 256;
90 digs = ((count - 1) >> 2) + 1;
91
92 /* output is \[x<hex>/siz]. which is digs+9 chars */
93 if (cp - (unsigned char*) name + digs + 9 >= MAXDNAME) return 0;
94 if (!CHECK_LEN(header, p, plen, (count - 1) >> 3)) return 0;
95
96 *cp++ = '\\';
97 *cp++ = '[';
98 *cp++ = 'x';
99 for (j = 0; j < digs; j++) {
100 unsigned int dig;
101 if (j % 2 == 0)
102 dig = *p >> 4;
103 else
104 dig = *p++ & 0x0f;
105
106 *cp++ = dig < 10 ? dig + '0' : dig + 'A' - 10;
107 }
108 cp += sprintf((char*) cp, "/%d]", count);
109 /* do this here to overwrite the zero char from sprintf */
110 *cp++ = '.';
111 } else { /* label_type = 0 -> label. */
112 if (cp - (unsigned char*) name + l + 1 >= MAXDNAME) return 0;
113 if (!CHECK_LEN(header, p, plen, l)) return 0;
114
115 for (j = 0; j < l; j++, p++)
116 if (isExtract) {
117 unsigned char c = *p;
118 if (isascii(c) && !iscntrl(c) && c != '.')
119 *cp++ = *p;
120 else
121 return 0;
122 } else {
123 unsigned char c1 = *cp, c2 = *p;
124
125 if (c1 == 0)
126 retvalue = 2;
127 else {
128 cp++;
129 if (c1 >= 'A' && c1 <= 'Z') c1 += 'a' - 'A';
130 if (c2 >= 'A' && c2 <= 'Z') c2 += 'a' - 'A';
131
132 if (c1 != c2) retvalue = 2;
133 }
134 }
135
136 if (isExtract)
137 *cp++ = '.';
138 else if (*cp != 0 && *cp++ != '.')
139 retvalue = 2;
140 }
141 }
142 }
143
144 /* Max size of input string (for IPv6) is 75 chars.) */
145 #define MAXARPANAME 75
in_arpa_name_2_addr(char * namein,struct all_addr * addrp)146 static int in_arpa_name_2_addr(char* namein, struct all_addr* addrp) {
147 int j;
148 char name[MAXARPANAME + 1], *cp1;
149 unsigned char* addr = (unsigned char*) addrp;
150 char *lastchunk = NULL, *penchunk = NULL;
151
152 if (strlen(namein) > MAXARPANAME) return 0;
153
154 memset(addrp, 0, sizeof(struct all_addr));
155
156 /* turn name into a series of asciiz strings */
157 /* j counts no of labels */
158 for (j = 1, cp1 = name; *namein; cp1++, namein++)
159 if (*namein == '.') {
160 penchunk = lastchunk;
161 lastchunk = cp1 + 1;
162 *cp1 = 0;
163 j++;
164 } else
165 *cp1 = *namein;
166
167 *cp1 = 0;
168
169 if (j < 3) return 0;
170
171 if (hostname_isequal(lastchunk, "arpa") && hostname_isequal(penchunk, "in-addr")) {
172 /* IP v4 */
173 /* address arives as a name of the form
174 www.xxx.yyy.zzz.in-addr.arpa
175 some of the low order address octets might be missing
176 and should be set to zero. */
177 for (cp1 = name; cp1 != penchunk; cp1 += strlen(cp1) + 1) {
178 /* check for digits only (weeds out things like
179 50.0/24.67.28.64.in-addr.arpa which are used
180 as CNAME targets according to RFC 2317 */
181 char* cp;
182 for (cp = cp1; *cp; cp++)
183 if (!isdigit((int) *cp)) return 0;
184
185 addr[3] = addr[2];
186 addr[2] = addr[1];
187 addr[1] = addr[0];
188 addr[0] = atoi(cp1);
189 }
190
191 return F_IPV4;
192 }
193 #ifdef HAVE_IPV6
194 else if (hostname_isequal(penchunk, "ip6") &&
195 (hostname_isequal(lastchunk, "int") || hostname_isequal(lastchunk, "arpa"))) {
196 /* IP v6:
197 Address arrives as 0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.ip6.[int|arpa]
198 or \[xfedcba9876543210fedcba9876543210/128].ip6.[int|arpa]
199
200 Note that most of these the various reprentations are obsolete and
201 left-over from the many DNS-for-IPv6 wars. We support all the formats
202 that we can since there is no reason not to.
203 */
204
205 /* TODO: does this make sense? */
206
207 if (*name == '\\' && *(name + 1) == '[' && (*(name + 2) == 'x' || *(name + 2) == 'X')) {
208 for (j = 0, cp1 = name + 3; *cp1 && isxdigit((int) *cp1) && j < 32; cp1++, j++) {
209 char xdig[2];
210 xdig[0] = *cp1;
211 xdig[1] = 0;
212 if (j % 2)
213 addr[j / 2] |= strtol(xdig, NULL, 16);
214 else
215 addr[j / 2] = strtol(xdig, NULL, 16) << 4;
216 }
217
218 if (*cp1 == '/' && j == 32) return F_IPV6;
219 } else {
220 for (cp1 = name; cp1 != penchunk; cp1 += strlen(cp1) + 1) {
221 if (*(cp1 + 1) || !isxdigit((int) *cp1)) return 0;
222
223 for (j = sizeof(struct all_addr) - 1; j > 0; j--)
224 addr[j] = (addr[j] >> 4) | (addr[j - 1] << 4);
225 addr[0] = (addr[0] >> 4) | (strtol(cp1, NULL, 16) << 4);
226 }
227
228 return F_IPV6;
229 }
230 }
231 #endif
232
233 return 0;
234 }
235
skip_name(unsigned char * ansp,HEADER * header,size_t plen,int extrabytes)236 static unsigned char* skip_name(unsigned char* ansp, HEADER* header, size_t plen, int extrabytes) {
237 while (1) {
238 unsigned int label_type;
239
240 if (!CHECK_LEN(header, ansp, plen, 1)) return NULL;
241
242 label_type = (*ansp) & 0xc0;
243
244 if (label_type == 0xc0) {
245 /* pointer for compression. */
246 ansp += 2;
247 break;
248 } else if (label_type == 0x80)
249 return NULL; /* reserved */
250 else if (label_type == 0x40) {
251 /* Extended label type */
252 unsigned int count;
253
254 if (!CHECK_LEN(header, ansp, plen, 2)) return NULL;
255
256 if (((*ansp++) & 0x3f) != 1) return NULL; /* we only understand bitstrings */
257
258 count = *(ansp++); /* Bits in bitstring */
259
260 if (count == 0) /* count == 0 means 256 bits */
261 ansp += 32;
262 else
263 ansp += ((count - 1) >> 3) + 1;
264 } else { /* label type == 0 Bottom six bits is length */
265 unsigned int len = (*ansp++) & 0x3f;
266
267 if (!ADD_RDLEN(header, ansp, plen, len)) return NULL;
268
269 if (len == 0) break; /* zero length label marks the end. */
270 }
271 }
272
273 if (!CHECK_LEN(header, ansp, plen, extrabytes)) return NULL;
274
275 return ansp;
276 }
277
skip_questions(HEADER * header,size_t plen)278 static unsigned char* skip_questions(HEADER* header, size_t plen) {
279 int q;
280 unsigned char* ansp = (unsigned char*) (header + 1);
281
282 for (q = ntohs(header->qdcount); q != 0; q--) {
283 if (!(ansp = skip_name(ansp, header, plen, 4))) return NULL;
284 ansp += 4; /* class and type */
285 }
286
287 return ansp;
288 }
289
skip_section(unsigned char * ansp,int count,HEADER * header,size_t plen)290 static unsigned char* skip_section(unsigned char* ansp, int count, HEADER* header, size_t plen) {
291 int i, rdlen;
292
293 for (i = 0; i < count; i++) {
294 if (!(ansp = skip_name(ansp, header, plen, 10))) return NULL;
295 ansp += 8; /* type, class, TTL */
296 GETSHORT(rdlen, ansp);
297 if (!ADD_RDLEN(header, ansp, plen, rdlen)) return NULL;
298 }
299
300 return ansp;
301 }
302
303 /* CRC the question section. This is used to safely detect query
304 retransmision and to detect answers to questions we didn't ask, which
305 might be poisoning attacks. Note that we decode the name rather
306 than CRC the raw bytes, since replies might be compressed differently.
307 We ignore case in the names for the same reason. Return all-ones
308 if there is not question section. */
questions_crc(HEADER * header,size_t plen,char * name)309 unsigned int questions_crc(HEADER* header, size_t plen, char* name) {
310 int q;
311 unsigned int crc = 0xffffffff;
312 unsigned char *p1, *p = (unsigned char*) (header + 1);
313
314 for (q = ntohs(header->qdcount); q != 0; q--) {
315 if (!extract_name(header, plen, &p, name, 1, 4)) return crc; /* bad packet */
316
317 for (p1 = (unsigned char*) name; *p1; p1++) {
318 int i = 8;
319 char c = *p1;
320
321 if (c >= 'A' && c <= 'Z') c += 'a' - 'A';
322
323 crc ^= c << 24;
324 while (i--) crc = crc & 0x80000000 ? (crc << 1) ^ 0x04c11db7 : crc << 1;
325 }
326
327 /* CRC the class and type as well */
328 for (p1 = p; p1 < p + 4; p1++) {
329 int i = 8;
330 crc ^= *p1 << 24;
331 while (i--) crc = crc & 0x80000000 ? (crc << 1) ^ 0x04c11db7 : crc << 1;
332 }
333
334 p += 4;
335 if (!CHECK_LEN(header, p, plen, 0)) return crc; /* bad packet */
336 }
337
338 return crc;
339 }
340
resize_packet(HEADER * header,size_t plen,unsigned char * pheader,size_t hlen)341 size_t resize_packet(HEADER* header, size_t plen, unsigned char* pheader, size_t hlen) {
342 unsigned char* ansp = skip_questions(header, plen);
343
344 /* if packet is malformed, just return as-is. */
345 if (!ansp) return plen;
346
347 if (!(ansp = skip_section(
348 ansp, ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount),
349 header, plen)))
350 return plen;
351
352 /* restore pseudoheader */
353 if (pheader && ntohs(header->arcount) == 0) {
354 /* must use memmove, may overlap */
355 memmove(ansp, pheader, hlen);
356 header->arcount = htons(1);
357 ansp += hlen;
358 }
359
360 return ansp - (unsigned char*) header;
361 }
362
find_pseudoheader(HEADER * header,size_t plen,size_t * len,unsigned char ** p,int * is_sign)363 unsigned char* find_pseudoheader(HEADER* header, size_t plen, size_t* len, unsigned char** p,
364 int* is_sign) {
365 /* See if packet has an RFC2671 pseudoheader, and if so return a pointer to it.
366 also return length of pseudoheader in *len and pointer to the UDP size in *p
367 Finally, check to see if a packet is signed. If it is we cannot change a single bit before
368 forwarding. We look for SIG and TSIG in the addition section, and TKEY queries (for GSS-TSIG) */
369
370 int i, arcount = ntohs(header->arcount);
371 unsigned char* ansp = (unsigned char*) (header + 1);
372 unsigned short rdlen, type, class;
373 unsigned char* ret = NULL;
374
375 if (is_sign) {
376 *is_sign = 0;
377
378 if (header->opcode == QUERY) {
379 for (i = ntohs(header->qdcount); i != 0; i--) {
380 if (!(ansp = skip_name(ansp, header, plen, 4))) return NULL;
381
382 GETSHORT(type, ansp);
383 GETSHORT(class, ansp);
384
385 if (class == C_IN && type == T_TKEY) *is_sign = 1;
386 }
387 }
388 } else {
389 if (!(ansp = skip_questions(header, plen))) return NULL;
390 }
391
392 if (arcount == 0) return NULL;
393
394 if (!(ansp = skip_section(ansp, ntohs(header->ancount) + ntohs(header->nscount), header, plen)))
395 return NULL;
396
397 for (i = 0; i < arcount; i++) {
398 unsigned char *save, *start = ansp;
399 if (!(ansp = skip_name(ansp, header, plen, 10))) return NULL;
400
401 GETSHORT(type, ansp);
402 save = ansp;
403 GETSHORT(class, ansp);
404 ansp += 4; /* TTL */
405 GETSHORT(rdlen, ansp);
406 if (!ADD_RDLEN(header, ansp, plen, rdlen)) return NULL;
407 if (type == T_OPT) {
408 if (len) *len = ansp - start;
409 if (p) *p = save;
410 ret = start;
411 } else if (is_sign && i == arcount - 1 && class == C_ANY &&
412 (type == T_SIG || type == T_TSIG))
413 *is_sign = 1;
414 }
415
416 return ret;
417 }
418
419 /* is addr in the non-globally-routed IP space? */
private_net(struct in_addr addr)420 static int private_net(struct in_addr addr) {
421 in_addr_t ip_addr = ntohl(addr.s_addr);
422
423 return ((ip_addr & 0xFF000000) == 0x7F000000) /* 127.0.0.0/8 (loopback) */ ||
424 ((ip_addr & 0xFFFF0000) == 0xC0A80000) /* 192.168.0.0/16 (private) */ ||
425 ((ip_addr & 0xFF000000) == 0x0A000000) /* 10.0.0.0/8 (private) */ ||
426 ((ip_addr & 0xFFF00000) == 0xAC100000) /* 172.16.0.0/12 (private) */ ||
427 ((ip_addr & 0xFFFF0000) == 0xA9FE0000) /* 169.254.0.0/16 (zeroconf) */;
428 }
429
do_doctor(unsigned char * p,int count,HEADER * header,size_t qlen)430 static unsigned char* do_doctor(unsigned char* p, int count, HEADER* header, size_t qlen) {
431 int i, qtype, qclass, rdlen;
432 unsigned long ttl;
433
434 for (i = count; i != 0; i--) {
435 if (!(p = skip_name(p, header, qlen, 10))) return 0; /* bad packet */
436
437 GETSHORT(qtype, p);
438 GETSHORT(qclass, p);
439 GETLONG(ttl, p);
440 GETSHORT(rdlen, p);
441
442 if ((qclass == C_IN) && (qtype == T_A)) {
443 struct doctor* doctor;
444 struct in_addr addr;
445
446 if (!CHECK_LEN(header, p, qlen, INADDRSZ)) return 0;
447
448 /* alignment */
449 memcpy(&addr, p, INADDRSZ);
450
451 for (doctor = daemon->doctors; doctor; doctor = doctor->next) {
452 if (doctor->end.s_addr == 0) {
453 if (!is_same_net(doctor->in, addr, doctor->mask)) continue;
454 } else if (ntohl(doctor->in.s_addr) > ntohl(addr.s_addr) ||
455 ntohl(doctor->end.s_addr) < ntohl(addr.s_addr))
456 continue;
457
458 addr.s_addr &= ~doctor->mask.s_addr;
459 addr.s_addr |= (doctor->out.s_addr & doctor->mask.s_addr);
460 /* Since we munged the data, the server it came from is no longer authoritative */
461 header->aa = 0;
462 memcpy(p, &addr, INADDRSZ);
463 break;
464 }
465 }
466
467 if (!ADD_RDLEN(header, p, qlen, rdlen)) return 0; /* bad packet */
468 }
469
470 return p;
471 }
472
find_soa(HEADER * header,size_t qlen)473 static int find_soa(HEADER* header, size_t qlen) {
474 unsigned char* p;
475 int qtype, qclass, rdlen;
476 unsigned long ttl, minttl = ULONG_MAX;
477 int i, found_soa = 0;
478
479 /* first move to NS section and find TTL from any SOA section */
480 if (!(p = skip_questions(header, qlen)) ||
481 !(p = do_doctor(p, ntohs(header->ancount), header, qlen)))
482 return 0; /* bad packet */
483
484 for (i = ntohs(header->nscount); i != 0; i--) {
485 if (!(p = skip_name(p, header, qlen, 10))) return 0; /* bad packet */
486
487 GETSHORT(qtype, p);
488 GETSHORT(qclass, p);
489 GETLONG(ttl, p);
490 GETSHORT(rdlen, p);
491
492 if ((qclass == C_IN) && (qtype == T_SOA)) {
493 found_soa = 1;
494 if (ttl < minttl) minttl = ttl;
495
496 /* MNAME */
497 if (!(p = skip_name(p, header, qlen, 0))) return 0;
498 /* RNAME */
499 if (!(p = skip_name(p, header, qlen, 20))) return 0;
500 p += 16; /* SERIAL REFRESH RETRY EXPIRE */
501
502 GETLONG(ttl, p); /* minTTL */
503 if (ttl < minttl) minttl = ttl;
504 } else if (!ADD_RDLEN(header, p, qlen, rdlen))
505 return 0; /* bad packet */
506 }
507
508 /* rewrite addresses in additioal section too */
509 if (!do_doctor(p, ntohs(header->arcount), header, qlen)) return 0;
510
511 if (!found_soa) minttl = daemon->neg_ttl;
512
513 return minttl;
514 }
515
516 /* Note that the following code can create CNAME chains that don't point to a real record,
517 either because of lack of memory, or lack of SOA records. These are treated by the cache code as
518 expired and cleaned out that way.
519 Return 1 if we reject an address because it look like parct of dns-rebinding attack. */
extract_addresses(HEADER * header,size_t qlen,char * name,time_t now)520 int extract_addresses(HEADER* header, size_t qlen, char* name, time_t now) {
521 unsigned char *p, *p1, *endrr, *namep;
522 int i, j, qtype, qclass, aqtype, aqclass, ardlen, res, searched_soa = 0;
523 unsigned long ttl = 0;
524 struct all_addr addr;
525
526 cache_start_insert();
527
528 /* find_soa is needed for dns_doctor side-effects, so don't call it lazily if there are any. */
529 if (daemon->doctors) {
530 searched_soa = 1;
531 ttl = find_soa(header, qlen);
532 }
533
534 /* go through the questions. */
535 p = (unsigned char*) (header + 1);
536
537 for (i = ntohs(header->qdcount); i != 0; i--) {
538 int found = 0, cname_count = 5;
539 struct crec* cpp = NULL;
540 int flags = header->rcode == NXDOMAIN ? F_NXDOMAIN : 0;
541 unsigned long cttl = ULONG_MAX, attl;
542
543 namep = p;
544 if (!extract_name(header, qlen, &p, name, 1, 4)) return 0; /* bad packet */
545
546 GETSHORT(qtype, p);
547 GETSHORT(qclass, p);
548
549 if (qclass != C_IN) continue;
550
551 /* PTRs: we chase CNAMEs here, since we have no way to
552 represent them in the cache. */
553 if (qtype == T_PTR) {
554 int name_encoding = in_arpa_name_2_addr(name, &addr);
555
556 if (!name_encoding) continue;
557
558 if (!(flags & F_NXDOMAIN)) {
559 cname_loop:
560 if (!(p1 = skip_questions(header, qlen))) return 0;
561
562 for (j = ntohs(header->ancount); j != 0; j--) {
563 unsigned char* tmp = namep;
564 /* the loop body overwrites the original name, so get it back here. */
565 if (!extract_name(header, qlen, &tmp, name, 1, 0) ||
566 !(res = extract_name(header, qlen, &p1, name, 0, 10)))
567 return 0; /* bad packet */
568
569 GETSHORT(aqtype, p1);
570 GETSHORT(aqclass, p1);
571 GETLONG(attl, p1);
572 GETSHORT(ardlen, p1);
573 endrr = p1 + ardlen;
574
575 /* TTL of record is minimum of CNAMES and PTR */
576 if (attl < cttl) cttl = attl;
577
578 if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == T_PTR)) {
579 if (!extract_name(header, qlen, &p1, name, 1, 0)) return 0;
580
581 if (aqtype == T_CNAME) {
582 if (!cname_count--) return 0; /* looped CNAMES */
583 goto cname_loop;
584 }
585
586 cache_insert(name, &addr, now, cttl, name_encoding | F_REVERSE);
587 found = 1;
588 }
589
590 p1 = endrr;
591 if (!CHECK_LEN(header, p1, qlen, 0)) return 0; /* bad packet */
592 }
593 }
594
595 if (!found && !(daemon->options & OPT_NO_NEG)) {
596 if (!searched_soa) {
597 searched_soa = 1;
598 ttl = find_soa(header, qlen);
599 }
600 if (ttl)
601 cache_insert(NULL, &addr, now, ttl, name_encoding | F_REVERSE | F_NEG | flags);
602 }
603 } else {
604 /* everything other than PTR */
605 struct crec* newc;
606 int addrlen;
607
608 if (qtype == T_A) {
609 addrlen = INADDRSZ;
610 flags |= F_IPV4;
611 }
612 #ifdef HAVE_IPV6
613 else if (qtype == T_AAAA) {
614 addrlen = IN6ADDRSZ;
615 flags |= F_IPV6;
616 }
617 #endif
618 else
619 continue;
620
621 if (!(flags & F_NXDOMAIN)) {
622 cname_loop1:
623 if (!(p1 = skip_questions(header, qlen))) return 0;
624
625 for (j = ntohs(header->ancount); j != 0; j--) {
626 if (!(res = extract_name(header, qlen, &p1, name, 0, 10)))
627 return 0; /* bad packet */
628
629 GETSHORT(aqtype, p1);
630 GETSHORT(aqclass, p1);
631 GETLONG(attl, p1);
632 GETSHORT(ardlen, p1);
633 endrr = p1 + ardlen;
634
635 if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == qtype)) {
636 if (aqtype == T_CNAME) {
637 if (!cname_count--) return 0; /* looped CNAMES */
638 newc = cache_insert(name, NULL, now, attl, F_CNAME | F_FORWARD);
639 if (newc && cpp) {
640 cpp->addr.cname.cache = newc;
641 cpp->addr.cname.uid = newc->uid;
642 }
643
644 cpp = newc;
645 if (attl < cttl) cttl = attl;
646
647 if (!extract_name(header, qlen, &p1, name, 1, 0)) return 0;
648 goto cname_loop1;
649 } else {
650 found = 1;
651
652 /* copy address into aligned storage */
653 if (!CHECK_LEN(header, p1, qlen, addrlen)) return 0; /* bad packet */
654 memcpy(&addr, p1, addrlen);
655
656 /* check for returned address in private space */
657 if ((daemon->options & OPT_NO_REBIND) && (flags & F_IPV4) &&
658 private_net(addr.addr.addr4))
659 return 1;
660
661 newc = cache_insert(name, &addr, now, attl, flags | F_FORWARD);
662 if (newc && cpp) {
663 cpp->addr.cname.cache = newc;
664 cpp->addr.cname.uid = newc->uid;
665 }
666 cpp = NULL;
667 }
668 }
669
670 p1 = endrr;
671 if (!CHECK_LEN(header, p1, qlen, 0)) return 0; /* bad packet */
672 }
673 }
674
675 if (!found && !(daemon->options & OPT_NO_NEG)) {
676 if (!searched_soa) {
677 searched_soa = 1;
678 ttl = find_soa(header, qlen);
679 }
680 /* If there's no SOA to get the TTL from, but there is a CNAME
681 pointing at this, inherit its TTL */
682 if (ttl || cpp) {
683 newc =
684 cache_insert(name, NULL, now, ttl ? ttl : cttl, F_FORWARD | F_NEG | flags);
685 if (newc && cpp) {
686 cpp->addr.cname.cache = newc;
687 cpp->addr.cname.uid = newc->uid;
688 }
689 }
690 }
691 }
692 }
693
694 /* Don't put stuff from a truncated packet into the cache, but do everything else */
695 if (!header->tc) cache_end_insert();
696
697 return 0;
698 }
699
700 /* If the packet holds exactly one query
701 return F_IPV4 or F_IPV6 and leave the name from the query in name.
702 Abuse F_BIGNAME to indicate an NS query - yuck. */
703
extract_request(HEADER * header,size_t qlen,char * name,unsigned short * typep)704 unsigned short extract_request(HEADER* header, size_t qlen, char* name, unsigned short* typep) {
705 unsigned char* p = (unsigned char*) (header + 1);
706 int qtype, qclass;
707
708 if (typep) *typep = 0;
709
710 if (ntohs(header->qdcount) != 1 || header->opcode != QUERY)
711 return 0; /* must be exactly one query. */
712
713 if (!extract_name(header, qlen, &p, name, 1, 4)) return 0; /* bad packet */
714
715 GETSHORT(qtype, p);
716 GETSHORT(qclass, p);
717
718 if (typep) *typep = qtype;
719
720 if (qclass == C_IN) {
721 if (qtype == T_A) return F_IPV4;
722 if (qtype == T_AAAA) return F_IPV6;
723 if (qtype == T_ANY) return F_IPV4 | F_IPV6;
724 if (qtype == T_NS || qtype == T_SOA) return F_QUERY | F_BIGNAME;
725 }
726
727 return F_QUERY;
728 }
729
setup_reply(HEADER * header,size_t qlen,struct all_addr * addrp,unsigned short flags,unsigned long ttl)730 size_t setup_reply(HEADER* header, size_t qlen, struct all_addr* addrp, unsigned short flags,
731 unsigned long ttl) {
732 unsigned char* p;
733
734 if (!(p = skip_questions(header, qlen))) return 0;
735
736 header->qr = 1; /* response */
737 header->aa = 0; /* authoritive */
738 header->ra = 1; /* recursion if available */
739 header->tc = 0; /* not truncated */
740 header->nscount = htons(0);
741 header->arcount = htons(0);
742 header->ancount = htons(0); /* no answers unless changed below */
743 if (flags == F_NEG)
744 header->rcode = SERVFAIL; /* couldn't get memory */
745 else if (flags == F_NOERR)
746 header->rcode = NOERROR; /* empty domain */
747 else if (flags == F_NXDOMAIN)
748 header->rcode = NXDOMAIN;
749 else if (flags == F_IPV4) { /* we know the address */
750 header->rcode = NOERROR;
751 header->ancount = htons(1);
752 header->aa = 1;
753 add_resource_record(header, NULL, NULL, sizeof(HEADER), &p, ttl, NULL, T_A, C_IN, "4",
754 addrp);
755 }
756 #ifdef HAVE_IPV6
757 else if (flags == F_IPV6) {
758 header->rcode = NOERROR;
759 header->ancount = htons(1);
760 header->aa = 1;
761 add_resource_record(header, NULL, NULL, sizeof(HEADER), &p, ttl, NULL, T_AAAA, C_IN, "6",
762 addrp);
763 }
764 #endif
765 else /* nowhere to forward to */
766 header->rcode = REFUSED;
767
768 return p - (unsigned char*) header;
769 }
770
771 /* check if name matches local names ie from /etc/hosts or DHCP or local mx names. */
check_for_local_domain(char * name,time_t now)772 int check_for_local_domain(char* name, time_t now) {
773 struct crec* crecp;
774 struct mx_srv_record* mx;
775 struct txt_record* txt;
776 struct interface_name* intr;
777 struct ptr_record* ptr;
778
779 if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6)) &&
780 (crecp->flags & (F_HOSTS | F_DHCP)))
781 return 1;
782
783 for (mx = daemon->mxnames; mx; mx = mx->next)
784 if (hostname_isequal(name, mx->name)) return 1;
785
786 for (txt = daemon->txt; txt; txt = txt->next)
787 if (hostname_isequal(name, txt->name)) return 1;
788
789 for (intr = daemon->int_names; intr; intr = intr->next)
790 if (hostname_isequal(name, intr->name)) return 1;
791
792 for (ptr = daemon->ptr; ptr; ptr = ptr->next)
793 if (hostname_isequal(name, ptr->name)) return 1;
794
795 return 0;
796 }
797
798 /* Is the packet a reply with the answer address equal to addr?
799 If so mung is into an NXDOMAIN reply and also put that information
800 in the cache. */
check_for_bogus_wildcard(HEADER * header,size_t qlen,char * name,struct bogus_addr * baddr,time_t now)801 int check_for_bogus_wildcard(HEADER* header, size_t qlen, char* name, struct bogus_addr* baddr,
802 time_t now) {
803 unsigned char* p;
804 int i, qtype, qclass, rdlen;
805 unsigned long ttl;
806 struct bogus_addr* baddrp;
807
808 /* skip over questions */
809 if (!(p = skip_questions(header, qlen))) return 0; /* bad packet */
810
811 for (i = ntohs(header->ancount); i != 0; i--) {
812 if (!extract_name(header, qlen, &p, name, 1, 10)) return 0; /* bad packet */
813
814 GETSHORT(qtype, p);
815 GETSHORT(qclass, p);
816 GETLONG(ttl, p);
817 GETSHORT(rdlen, p);
818
819 if (qclass == C_IN && qtype == T_A) {
820 if (!CHECK_LEN(header, p, qlen, INADDRSZ)) return 0;
821
822 for (baddrp = baddr; baddrp; baddrp = baddrp->next)
823 if (memcmp(&baddrp->addr, p, INADDRSZ) == 0) {
824 /* Found a bogus address. Insert that info here, since there no SOA record
825 to get the ttl from in the normal processing */
826 cache_start_insert();
827 cache_insert(name, NULL, now, ttl,
828 F_IPV4 | F_FORWARD | F_NEG | F_NXDOMAIN | F_CONFIG);
829 cache_end_insert();
830
831 return 1;
832 }
833 }
834
835 if (!ADD_RDLEN(header, p, qlen, rdlen)) return 0;
836 }
837
838 return 0;
839 }
840
add_resource_record(HEADER * header,char * limit,int * truncp,unsigned int nameoffset,unsigned char ** pp,unsigned long ttl,unsigned int * offset,unsigned short type,unsigned short class,char * format,...)841 static int add_resource_record(HEADER* header, char* limit, int* truncp, unsigned int nameoffset,
842 unsigned char** pp, unsigned long ttl, unsigned int* offset,
843 unsigned short type, unsigned short class, char* format, ...) {
844 va_list ap;
845 unsigned char *sav, *p = *pp;
846 int j;
847 unsigned short usval;
848 long lval;
849 char* sval;
850
851 if (truncp && *truncp) return 0;
852
853 PUTSHORT(nameoffset | 0xc000, p);
854 PUTSHORT(type, p);
855 PUTSHORT(class, p);
856 PUTLONG(ttl, p); /* TTL */
857
858 sav = p; /* Save pointer to RDLength field */
859 PUTSHORT(0, p); /* Placeholder RDLength */
860
861 va_start(ap, format); /* make ap point to 1st unamed argument */
862
863 for (; *format; format++) switch (*format) {
864 #ifdef HAVE_IPV6
865 case '6':
866 sval = va_arg(ap, char*);
867 memcpy(p, sval, IN6ADDRSZ);
868 p += IN6ADDRSZ;
869 break;
870 #endif
871
872 case '4':
873 sval = va_arg(ap, char*);
874 memcpy(p, sval, INADDRSZ);
875 p += INADDRSZ;
876 break;
877
878 case 's':
879 usval = va_arg(ap, int);
880 PUTSHORT(usval, p);
881 break;
882
883 case 'l':
884 lval = va_arg(ap, long);
885 PUTLONG(lval, p);
886 break;
887
888 case 'd':
889 /* get domain-name answer arg and store it in RDATA field */
890 if (offset) *offset = p - (unsigned char*) header;
891 p = do_rfc1035_name(p, va_arg(ap, char*));
892 *p++ = 0;
893 break;
894
895 case 't':
896 usval = va_arg(ap, int);
897 sval = va_arg(ap, char*);
898 memcpy(p, sval, usval);
899 p += usval;
900 break;
901
902 case 'z':
903 sval = va_arg(ap, char*);
904 usval = sval ? strlen(sval) : 0;
905 if (usval > 255) usval = 255;
906 *p++ = (unsigned char) usval;
907 memcpy(p, sval, usval);
908 p += usval;
909 break;
910 }
911
912 va_end(ap); /* clean up variable argument pointer */
913
914 j = p - sav - 2;
915 PUTSHORT(j, sav); /* Now, store real RDLength */
916
917 /* check for overflow of buffer */
918 if (limit && ((unsigned char*) limit - p) < 0) {
919 if (truncp) *truncp = 1;
920 return 0;
921 }
922
923 *pp = p;
924 return 1;
925 }
926
crec_ttl(struct crec * crecp,time_t now)927 static unsigned long crec_ttl(struct crec* crecp, time_t now) {
928 /* Return 0 ttl for DHCP entries, which might change
929 before the lease expires. */
930
931 if (crecp->flags & (F_IMMORTAL | F_DHCP)) return daemon->local_ttl;
932
933 return crecp->ttd - now;
934 }
935
936 /* return zero if we can't answer from cache, or packet size if we can */
answer_request(HEADER * header,char * limit,size_t qlen,struct in_addr local_addr,struct in_addr local_netmask,time_t now)937 size_t answer_request(HEADER* header, char* limit, size_t qlen, struct in_addr local_addr,
938 struct in_addr local_netmask, time_t now) {
939 char* name = daemon->namebuff;
940 unsigned char *p, *ansp, *pheader;
941 int qtype, qclass;
942 struct all_addr addr;
943 unsigned int nameoffset;
944 unsigned short flag;
945 int q, ans, anscount = 0, addncount = 0;
946 int dryrun = 0, sec_reqd = 0;
947 int is_sign;
948 struct crec* crecp;
949 int nxdomain = 0, auth = 1, trunc = 0;
950 struct mx_srv_record* rec;
951
952 // Make sure we do not underflow here too.
953 if (qlen > (size_t)(limit - ((char*) header))) return 0;
954
955 /* If there is an RFC2671 pseudoheader then it will be overwritten by
956 partial replies, so we have to do a dry run to see if we can answer
957 the query. We check to see if the do bit is set, if so we always
958 forward rather than answering from the cache, which doesn't include
959 security information. */
960
961 if (find_pseudoheader(header, qlen, NULL, &pheader, &is_sign)) {
962 unsigned short udpsz, ext_rcode, flags;
963 unsigned char* psave = pheader;
964
965 GETSHORT(udpsz, pheader);
966 GETSHORT(ext_rcode, pheader);
967 GETSHORT(flags, pheader);
968
969 sec_reqd = flags & 0x8000; /* do bit */
970
971 /* If our client is advertising a larger UDP packet size
972 than we allow, trim it so that we don't get an overlarge
973 response from upstream */
974
975 if (!is_sign && (udpsz > daemon->edns_pktsz)) PUTSHORT(daemon->edns_pktsz, psave);
976
977 dryrun = 1;
978 }
979
980 if (ntohs(header->qdcount) == 0 || header->opcode != QUERY) return 0;
981
982 for (rec = daemon->mxnames; rec; rec = rec->next) rec->offset = 0;
983
984 rerun:
985 /* determine end of question section (we put answers there) */
986 if (!(ansp = skip_questions(header, qlen))) return 0; /* bad packet */
987
988 /* now process each question, answers go in RRs after the question */
989 p = (unsigned char*) (header + 1);
990
991 for (q = ntohs(header->qdcount); q != 0; q--) {
992 /* save pointer to name for copying into answers */
993 nameoffset = p - (unsigned char*) header;
994
995 /* now extract name as .-concatenated string into name */
996 if (!extract_name(header, qlen, &p, name, 1, 4)) return 0; /* bad packet */
997
998 GETSHORT(qtype, p);
999 GETSHORT(qclass, p);
1000
1001 ans = 0; /* have we answered this question */
1002
1003 if (qtype == T_TXT || qtype == T_ANY) {
1004 struct txt_record* t;
1005 for (t = daemon->txt; t; t = t->next) {
1006 if (t->class == qclass && hostname_isequal(name, t->name)) {
1007 ans = 1;
1008 if (!dryrun) {
1009 log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL, "<TXT>");
1010 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1011 daemon->local_ttl, NULL, T_TXT, t->class, "t",
1012 t->len, t->txt))
1013 anscount++;
1014 }
1015 }
1016 }
1017 }
1018
1019 if (qclass == C_IN) {
1020 if (qtype == T_PTR || qtype == T_ANY) {
1021 /* see if it's w.z.y.z.in-addr.arpa format */
1022 int is_arpa = in_arpa_name_2_addr(name, &addr);
1023 struct ptr_record* ptr;
1024 struct interface_name* intr = NULL;
1025
1026 for (ptr = daemon->ptr; ptr; ptr = ptr->next)
1027 if (hostname_isequal(name, ptr->name)) break;
1028
1029 if (is_arpa == F_IPV4)
1030 for (intr = daemon->int_names; intr; intr = intr->next) {
1031 if (addr.addr.addr4.s_addr == get_ifaddr(intr->intr).s_addr)
1032 break;
1033 else
1034 while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
1035 intr = intr->next;
1036 }
1037
1038 if (intr) {
1039 ans = 1;
1040 if (!dryrun) {
1041 log_query(F_IPV4 | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
1042 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1043 daemon->local_ttl, NULL, T_PTR, C_IN, "d",
1044 intr->name))
1045 anscount++;
1046 }
1047 } else if (ptr) {
1048 ans = 1;
1049 if (!dryrun) {
1050 log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL, "<PTR>");
1051 for (ptr = daemon->ptr; ptr; ptr = ptr->next)
1052 if (hostname_isequal(name, ptr->name) &&
1053 add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1054 daemon->local_ttl, NULL, T_PTR, C_IN, "d",
1055 ptr->ptr))
1056 anscount++;
1057 }
1058 } else if ((crecp = cache_find_by_addr(NULL, &addr, now, is_arpa)))
1059 do {
1060 /* don't answer wildcard queries with data not from /etc/hosts or dhcp leases */
1061 if (qtype == T_ANY && !(crecp->flags & (F_HOSTS | F_DHCP))) continue;
1062
1063 if (crecp->flags & F_NEG) {
1064 ans = 1;
1065 auth = 0;
1066 if (crecp->flags & F_NXDOMAIN) nxdomain = 1;
1067 if (!dryrun) log_query(crecp->flags & ~F_FORWARD, name, &addr, NULL);
1068 } else if ((crecp->flags & (F_HOSTS | F_DHCP)) || !sec_reqd) {
1069 ans = 1;
1070 if (!(crecp->flags & (F_HOSTS | F_DHCP))) auth = 0;
1071 if (!dryrun) {
1072 log_query(crecp->flags & ~F_FORWARD, cache_get_name(crecp), &addr,
1073 record_source(crecp->uid));
1074
1075 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1076 crec_ttl(crecp, now), NULL, T_PTR, C_IN,
1077 "d", cache_get_name(crecp)))
1078 anscount++;
1079 }
1080 }
1081 } while ((crecp = cache_find_by_addr(crecp, &addr, now, is_arpa)));
1082 else if (is_arpa == F_IPV4 && (daemon->options & OPT_BOGUSPRIV) &&
1083 private_net(addr.addr.addr4)) {
1084 /* if not in cache, enabled and private IPV4 address, return NXDOMAIN */
1085 ans = 1;
1086 nxdomain = 1;
1087 if (!dryrun)
1088 log_query(F_CONFIG | F_REVERSE | F_IPV4 | F_NEG | F_NXDOMAIN, name, &addr,
1089 NULL);
1090 }
1091 }
1092
1093 for (flag = F_IPV4; flag; flag = (flag == F_IPV4) ? F_IPV6 : 0) {
1094 unsigned short type = T_A;
1095
1096 if (flag == F_IPV6)
1097 #ifdef HAVE_IPV6
1098 type = T_AAAA;
1099 #else
1100 break;
1101 #endif
1102
1103 if (qtype != type && qtype != T_ANY) continue;
1104
1105 /* Check for "A for A" queries */
1106 if (qtype == T_A && (addr.addr.addr4.s_addr = inet_addr(name)) != (in_addr_t) -1) {
1107 ans = 1;
1108 if (!dryrun) {
1109 log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL);
1110 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1111 daemon->local_ttl, NULL, type, C_IN, "4", &addr))
1112 anscount++;
1113 }
1114 continue;
1115 }
1116
1117 /* interface name stuff */
1118 if (qtype == T_A) {
1119 struct interface_name* intr;
1120
1121 for (intr = daemon->int_names; intr; intr = intr->next)
1122 if (hostname_isequal(name, intr->name)) break;
1123
1124 if (intr) {
1125 ans = 1;
1126 if (!dryrun) {
1127 if ((addr.addr.addr4 = get_ifaddr(intr->intr)).s_addr == (in_addr_t) -1)
1128 log_query(F_FORWARD | F_CONFIG | F_IPV4 | F_NEG, name, NULL, NULL);
1129 else {
1130 log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL);
1131 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1132 daemon->local_ttl, NULL, type, C_IN, "4",
1133 &addr))
1134 anscount++;
1135 }
1136 }
1137 continue;
1138 }
1139 }
1140
1141 cname_restart:
1142 if ((crecp = cache_find_by_name(NULL, name, now, flag | F_CNAME))) {
1143 int localise = 0;
1144
1145 /* See if a putative address is on the network from which we recieved
1146 the query, is so we'll filter other answers. */
1147 if (local_addr.s_addr != 0 && (daemon->options & OPT_LOCALISE) &&
1148 flag == F_IPV4) {
1149 struct crec* save = crecp;
1150 do {
1151 if ((crecp->flags & F_HOSTS) &&
1152 is_same_net(*((struct in_addr*) &crecp->addr), local_addr,
1153 local_netmask)) {
1154 localise = 1;
1155 break;
1156 }
1157 } while ((crecp = cache_find_by_name(crecp, name, now, flag | F_CNAME)));
1158 crecp = save;
1159 }
1160
1161 do {
1162 /* don't answer wildcard queries with data not from /etc/hosts
1163 or DHCP leases */
1164 if (qtype == T_ANY && !(crecp->flags & (F_HOSTS | F_DHCP))) break;
1165
1166 if (crecp->flags & F_CNAME) {
1167 if (!dryrun) {
1168 log_query(crecp->flags, name, NULL, record_source(crecp->uid));
1169 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1170 crec_ttl(crecp, now), &nameoffset, T_CNAME,
1171 C_IN, "d",
1172 cache_get_name(crecp->addr.cname.cache)))
1173 anscount++;
1174 }
1175
1176 strcpy(name, cache_get_name(crecp->addr.cname.cache));
1177 goto cname_restart;
1178 }
1179
1180 if (crecp->flags & F_NEG) {
1181 ans = 1;
1182 auth = 0;
1183 if (crecp->flags & F_NXDOMAIN) nxdomain = 1;
1184 if (!dryrun) log_query(crecp->flags, name, NULL, NULL);
1185 } else if ((crecp->flags & (F_HOSTS | F_DHCP)) || !sec_reqd) {
1186 /* If we are returning local answers depending on network,
1187 filter here. */
1188 if (localise && (crecp->flags & F_HOSTS) &&
1189 !is_same_net(*((struct in_addr*) &crecp->addr), local_addr,
1190 local_netmask))
1191 continue;
1192
1193 if (!(crecp->flags & (F_HOSTS | F_DHCP))) auth = 0;
1194
1195 ans = 1;
1196 if (!dryrun) {
1197 log_query(crecp->flags & ~F_REVERSE, name, &crecp->addr.addr,
1198 record_source(crecp->uid));
1199
1200 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1201 crec_ttl(crecp, now), NULL, type, C_IN,
1202 type == T_A ? "4" : "6", &crecp->addr))
1203 anscount++;
1204 }
1205 }
1206 } while ((crecp = cache_find_by_name(crecp, name, now, flag | F_CNAME)));
1207 }
1208 }
1209
1210 if (qtype == T_MX || qtype == T_ANY) {
1211 int found = 0;
1212 for (rec = daemon->mxnames; rec; rec = rec->next)
1213 if (!rec->issrv && hostname_isequal(name, rec->name)) {
1214 ans = found = 1;
1215 if (!dryrun) {
1216 unsigned int offset;
1217 log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL,
1218 "<MX>");
1219 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1220 daemon->local_ttl, &offset, T_MX, C_IN, "sd",
1221 rec->weight, rec->target)) {
1222 anscount++;
1223 if (rec->target) rec->offset = offset;
1224 }
1225 }
1226 }
1227
1228 if (!found && (daemon->options & (OPT_SELFMX | OPT_LOCALMX)) &&
1229 cache_find_by_name(NULL, name, now, F_HOSTS | F_DHCP)) {
1230 ans = 1;
1231 if (!dryrun) {
1232 log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL, "<MX>");
1233 if (add_resource_record(
1234 header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, NULL,
1235 T_MX, C_IN, "sd", 1,
1236 (daemon->options & OPT_SELFMX) ? name : daemon->mxtarget))
1237 anscount++;
1238 }
1239 }
1240 }
1241
1242 if (qtype == T_SRV || qtype == T_ANY) {
1243 int found = 0;
1244
1245 for (rec = daemon->mxnames; rec; rec = rec->next)
1246 if (rec->issrv && hostname_isequal(name, rec->name)) {
1247 found = ans = 1;
1248 if (!dryrun) {
1249 unsigned int offset;
1250 log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL,
1251 "<SRV>");
1252 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1253 daemon->local_ttl, &offset, T_SRV, C_IN, "sssd",
1254 rec->priority, rec->weight, rec->srvport,
1255 rec->target)) {
1256 anscount++;
1257 if (rec->target) rec->offset = offset;
1258 }
1259 }
1260 }
1261
1262 if (!found && (daemon->options & OPT_FILTER) &&
1263 (qtype == T_SRV || (qtype == T_ANY && strchr(name, '_')))) {
1264 ans = 1;
1265 if (!dryrun) log_query(F_CONFIG | F_NEG, name, NULL, NULL);
1266 }
1267 }
1268
1269 if (qtype == T_NAPTR || qtype == T_ANY) {
1270 struct naptr* na;
1271 for (na = daemon->naptr; na; na = na->next)
1272 if (hostname_isequal(name, na->name)) {
1273 ans = 1;
1274 if (!dryrun) {
1275 log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL,
1276 "<NAPTR>");
1277 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1278 daemon->local_ttl, NULL, T_NAPTR, C_IN,
1279 "sszzzd", na->order, na->pref, na->flags,
1280 na->services, na->regexp, na->replace))
1281 anscount++;
1282 }
1283 }
1284 }
1285
1286 if (qtype == T_MAILB) ans = 1, nxdomain = 1;
1287
1288 if (qtype == T_SOA && (daemon->options & OPT_FILTER)) {
1289 ans = 1;
1290 if (!dryrun) log_query(F_CONFIG | F_NEG, name, &addr, NULL);
1291 }
1292 }
1293
1294 if (!ans) return 0; /* failed to answer a question */
1295 }
1296
1297 if (dryrun) {
1298 dryrun = 0;
1299 goto rerun;
1300 }
1301
1302 /* create an additional data section, for stuff in SRV and MX record replies. */
1303 for (rec = daemon->mxnames; rec; rec = rec->next)
1304 if (rec->offset != 0) {
1305 /* squash dupes */
1306 struct mx_srv_record* tmp;
1307 for (tmp = rec->next; tmp; tmp = tmp->next)
1308 if (tmp->offset != 0 && hostname_isequal(rec->target, tmp->target)) tmp->offset = 0;
1309
1310 crecp = NULL;
1311 while ((crecp = cache_find_by_name(crecp, rec->target, now, F_IPV4 | F_IPV6))) {
1312 #ifdef HAVE_IPV6
1313 int type = crecp->flags & F_IPV4 ? T_A : T_AAAA;
1314 #else
1315 int type = T_A;
1316 #endif
1317 if (crecp->flags & F_NEG) continue;
1318
1319 if (add_resource_record(header, limit, NULL, rec->offset, &ansp,
1320 crec_ttl(crecp, now), NULL, type, C_IN,
1321 crecp->flags & F_IPV4 ? "4" : "6", &crecp->addr))
1322 addncount++;
1323 }
1324 }
1325
1326 /* done all questions, set up header and return length of result */
1327 header->qr = 1; /* response */
1328 header->aa = auth; /* authoritive - only hosts and DHCP derived names. */
1329 header->ra = 1; /* recursion if available */
1330 header->tc = trunc; /* truncation */
1331 if (anscount == 0 && nxdomain)
1332 header->rcode = NXDOMAIN;
1333 else
1334 header->rcode = NOERROR; /* no error */
1335 header->ancount = htons(anscount);
1336 header->nscount = htons(0);
1337 header->arcount = htons(addncount);
1338 return ansp - (unsigned char*) header;
1339 }
1340