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