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