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