Annotation of embedaddon/dnsmasq/src/rfc1035.c, revision 1.1.1.2
1.1.1.2 ! misho 1: /* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
1.1 misho 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: int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
20: char *name, int isExtract, int extrabytes)
21: {
22: unsigned char *cp = (unsigned char *)name, *p = *pp, *p1 = NULL;
23: unsigned int j, l, hops = 0;
24: int retvalue = 1;
25:
26: if (isExtract)
27: *cp = 0;
28:
29: while (1)
30: {
31: unsigned int label_type;
32:
33: if (!CHECK_LEN(header, p, plen, 1))
34: return 0;
35:
36: if ((l = *p++) == 0)
37: /* end marker */
38: {
39: /* check that there are the correct no of bytes after the name */
40: if (!CHECK_LEN(header, p, plen, extrabytes))
41: return 0;
42:
43: if (isExtract)
44: {
45: if (cp != (unsigned char *)name)
46: cp--;
47: *cp = 0; /* terminate: lose final period */
48: }
49: else if (*cp != 0)
50: retvalue = 2;
51:
52: if (p1) /* we jumped via compression */
53: *pp = p1;
54: else
55: *pp = p;
56:
57: return retvalue;
58: }
59:
60: label_type = l & 0xc0;
61:
62: if (label_type == 0xc0) /* pointer */
63: {
64: if (!CHECK_LEN(header, p, plen, 1))
65: return 0;
66:
67: /* get offset */
68: l = (l&0x3f) << 8;
69: l |= *p++;
70:
71: if (!p1) /* first jump, save location to go back to */
72: p1 = p;
73:
74: hops++; /* break malicious infinite loops */
75: if (hops > 255)
76: return 0;
77:
78: p = l + (unsigned char *)header;
79: }
80: else if (label_type == 0x80)
81: return 0; /* reserved */
82: else if (label_type == 0x40)
83: { /* ELT */
84: unsigned int count, digs;
85:
86: if ((l & 0x3f) != 1)
87: return 0; /* we only understand bitstrings */
88:
89: if (!isExtract)
90: return 0; /* Cannot compare bitsrings */
91:
92: count = *p++;
93: if (count == 0)
94: count = 256;
95: digs = ((count-1)>>2)+1;
96:
97: /* output is \[x<hex>/siz]. which is digs+9 chars */
98: if (cp - (unsigned char *)name + digs + 9 >= MAXDNAME)
99: return 0;
100: if (!CHECK_LEN(header, p, plen, (count-1)>>3))
101: return 0;
102:
103: *cp++ = '\\';
104: *cp++ = '[';
105: *cp++ = 'x';
106: for (j=0; j<digs; j++)
107: {
108: unsigned int dig;
109: if (j%2 == 0)
110: dig = *p >> 4;
111: else
112: dig = *p++ & 0x0f;
113:
114: *cp++ = dig < 10 ? dig + '0' : dig + 'A' - 10;
115: }
116: cp += sprintf((char *)cp, "/%d]", count);
117: /* do this here to overwrite the zero char from sprintf */
118: *cp++ = '.';
119: }
120: else
121: { /* label_type = 0 -> label. */
122: if (cp - (unsigned char *)name + l + 1 >= MAXDNAME)
123: return 0;
124: if (!CHECK_LEN(header, p, plen, l))
125: return 0;
126:
127: for(j=0; j<l; j++, p++)
128: if (isExtract)
129: {
130: unsigned char c = *p;
131: if (isascii(c) && !iscntrl(c) && c != '.')
132: *cp++ = *p;
133: else
134: return 0;
135: }
136: else
137: {
138: unsigned char c1 = *cp, c2 = *p;
139:
140: if (c1 == 0)
141: retvalue = 2;
142: else
143: {
144: cp++;
145: if (c1 >= 'A' && c1 <= 'Z')
146: c1 += 'a' - 'A';
147: if (c2 >= 'A' && c2 <= 'Z')
148: c2 += 'a' - 'A';
149:
150: if (c1 != c2)
151: retvalue = 2;
152: }
153: }
154:
155: if (isExtract)
156: *cp++ = '.';
157: else if (*cp != 0 && *cp++ != '.')
158: retvalue = 2;
159: }
160: }
161: }
162:
163: /* Max size of input string (for IPv6) is 75 chars.) */
164: #define MAXARPANAME 75
165: int in_arpa_name_2_addr(char *namein, struct all_addr *addrp)
166: {
167: int j;
168: char name[MAXARPANAME+1], *cp1;
169: unsigned char *addr = (unsigned char *)addrp;
170: char *lastchunk = NULL, *penchunk = NULL;
171:
172: if (strlen(namein) > MAXARPANAME)
173: return 0;
174:
175: memset(addrp, 0, sizeof(struct all_addr));
176:
177: /* turn name into a series of asciiz strings */
178: /* j counts no of labels */
179: for(j = 1,cp1 = name; *namein; cp1++, namein++)
180: if (*namein == '.')
181: {
182: penchunk = lastchunk;
183: lastchunk = cp1 + 1;
184: *cp1 = 0;
185: j++;
186: }
187: else
188: *cp1 = *namein;
189:
190: *cp1 = 0;
191:
192: if (j<3)
193: return 0;
194:
195: if (hostname_isequal(lastchunk, "arpa") && hostname_isequal(penchunk, "in-addr"))
196: {
197: /* IP v4 */
198: /* address arives as a name of the form
199: www.xxx.yyy.zzz.in-addr.arpa
200: some of the low order address octets might be missing
201: and should be set to zero. */
202: for (cp1 = name; cp1 != penchunk; cp1 += strlen(cp1)+1)
203: {
204: /* check for digits only (weeds out things like
205: 50.0/24.67.28.64.in-addr.arpa which are used
206: as CNAME targets according to RFC 2317 */
207: char *cp;
208: for (cp = cp1; *cp; cp++)
209: if (!isdigit((unsigned char)*cp))
210: return 0;
211:
212: addr[3] = addr[2];
213: addr[2] = addr[1];
214: addr[1] = addr[0];
215: addr[0] = atoi(cp1);
216: }
217:
218: return F_IPV4;
219: }
220: #ifdef HAVE_IPV6
221: else if (hostname_isequal(penchunk, "ip6") &&
222: (hostname_isequal(lastchunk, "int") || hostname_isequal(lastchunk, "arpa")))
223: {
224: /* IP v6:
225: Address arrives as 0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.ip6.[int|arpa]
226: or \[xfedcba9876543210fedcba9876543210/128].ip6.[int|arpa]
227:
228: Note that most of these the various reprentations are obsolete and
229: left-over from the many DNS-for-IPv6 wars. We support all the formats
230: that we can since there is no reason not to.
231: */
232:
233: if (*name == '\\' && *(name+1) == '[' &&
234: (*(name+2) == 'x' || *(name+2) == 'X'))
235: {
236: for (j = 0, cp1 = name+3; *cp1 && isxdigit((unsigned char) *cp1) && j < 32; cp1++, j++)
237: {
238: char xdig[2];
239: xdig[0] = *cp1;
240: xdig[1] = 0;
241: if (j%2)
242: addr[j/2] |= strtol(xdig, NULL, 16);
243: else
244: addr[j/2] = strtol(xdig, NULL, 16) << 4;
245: }
246:
247: if (*cp1 == '/' && j == 32)
248: return F_IPV6;
249: }
250: else
251: {
252: for (cp1 = name; cp1 != penchunk; cp1 += strlen(cp1)+1)
253: {
254: if (*(cp1+1) || !isxdigit((unsigned char)*cp1))
255: return 0;
256:
257: for (j = sizeof(struct all_addr)-1; j>0; j--)
258: addr[j] = (addr[j] >> 4) | (addr[j-1] << 4);
259: addr[0] = (addr[0] >> 4) | (strtol(cp1, NULL, 16) << 4);
260: }
261:
262: return F_IPV6;
263: }
264: }
265: #endif
266:
267: return 0;
268: }
269:
1.1.1.2 ! misho 270: unsigned char *skip_name(unsigned char *ansp, struct dns_header *header, size_t plen, int extrabytes)
1.1 misho 271: {
272: while(1)
273: {
274: unsigned int label_type;
275:
276: if (!CHECK_LEN(header, ansp, plen, 1))
277: return NULL;
278:
279: label_type = (*ansp) & 0xc0;
280:
281: if (label_type == 0xc0)
282: {
283: /* pointer for compression. */
284: ansp += 2;
285: break;
286: }
287: else if (label_type == 0x80)
288: return NULL; /* reserved */
289: else if (label_type == 0x40)
290: {
291: /* Extended label type */
292: unsigned int count;
293:
294: if (!CHECK_LEN(header, ansp, plen, 2))
295: return NULL;
296:
297: if (((*ansp++) & 0x3f) != 1)
298: return NULL; /* we only understand bitstrings */
299:
300: count = *(ansp++); /* Bits in bitstring */
301:
302: if (count == 0) /* count == 0 means 256 bits */
303: ansp += 32;
304: else
305: ansp += ((count-1)>>3)+1;
306: }
307: else
308: { /* label type == 0 Bottom six bits is length */
309: unsigned int len = (*ansp++) & 0x3f;
310:
311: if (!ADD_RDLEN(header, ansp, plen, len))
312: return NULL;
313:
314: if (len == 0)
315: break; /* zero length label marks the end. */
316: }
317: }
318:
319: if (!CHECK_LEN(header, ansp, plen, extrabytes))
320: return NULL;
321:
322: return ansp;
323: }
324:
325: unsigned char *skip_questions(struct dns_header *header, size_t plen)
326: {
327: int q;
328: unsigned char *ansp = (unsigned char *)(header+1);
329:
330: for (q = ntohs(header->qdcount); q != 0; q--)
331: {
332: if (!(ansp = skip_name(ansp, header, plen, 4)))
333: return NULL;
334: ansp += 4; /* class and type */
335: }
336:
337: return ansp;
338: }
339:
1.1.1.2 ! misho 340: unsigned char *skip_section(unsigned char *ansp, int count, struct dns_header *header, size_t plen)
1.1 misho 341: {
342: int i, rdlen;
343:
344: for (i = 0; i < count; i++)
345: {
346: if (!(ansp = skip_name(ansp, header, plen, 10)))
347: return NULL;
348: ansp += 8; /* type, class, TTL */
349: GETSHORT(rdlen, ansp);
350: if (!ADD_RDLEN(header, ansp, plen, rdlen))
351: return NULL;
352: }
353:
354: return ansp;
355: }
356:
357: /* CRC the question section. This is used to safely detect query
358: retransmision and to detect answers to questions we didn't ask, which
359: might be poisoning attacks. Note that we decode the name rather
360: than CRC the raw bytes, since replies might be compressed differently.
361: We ignore case in the names for the same reason. Return all-ones
362: if there is not question section. */
1.1.1.2 ! misho 363: #ifndef HAVE_DNSSEC
1.1 misho 364: unsigned int questions_crc(struct dns_header *header, size_t plen, char *name)
365: {
366: int q;
367: unsigned int crc = 0xffffffff;
368: unsigned char *p1, *p = (unsigned char *)(header+1);
369:
370: for (q = ntohs(header->qdcount); q != 0; q--)
371: {
372: if (!extract_name(header, plen, &p, name, 1, 4))
373: return crc; /* bad packet */
374:
375: for (p1 = (unsigned char *)name; *p1; p1++)
376: {
377: int i = 8;
378: char c = *p1;
379:
380: if (c >= 'A' && c <= 'Z')
381: c += 'a' - 'A';
382:
383: crc ^= c << 24;
384: while (i--)
385: crc = crc & 0x80000000 ? (crc << 1) ^ 0x04c11db7 : crc << 1;
386: }
387:
388: /* CRC the class and type as well */
389: for (p1 = p; p1 < p+4; p1++)
390: {
391: int i = 8;
392: crc ^= *p1 << 24;
393: while (i--)
394: crc = crc & 0x80000000 ? (crc << 1) ^ 0x04c11db7 : crc << 1;
395: }
396:
397: p += 4;
398: if (!CHECK_LEN(header, p, plen, 0))
399: return crc; /* bad packet */
400: }
401:
402: return crc;
403: }
1.1.1.2 ! misho 404: #endif
1.1 misho 405:
406: size_t resize_packet(struct dns_header *header, size_t plen, unsigned char *pheader, size_t hlen)
407: {
408: unsigned char *ansp = skip_questions(header, plen);
409:
410: /* if packet is malformed, just return as-is. */
411: if (!ansp)
412: return plen;
413:
414: if (!(ansp = skip_section(ansp, ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount),
415: header, plen)))
416: return plen;
417:
418: /* restore pseudoheader */
419: if (pheader && ntohs(header->arcount) == 0)
420: {
421: /* must use memmove, may overlap */
422: memmove(ansp, pheader, hlen);
423: header->arcount = htons(1);
424: ansp += hlen;
425: }
426:
427: return ansp - (unsigned char *)header;
428: }
429:
430: unsigned char *find_pseudoheader(struct dns_header *header, size_t plen, size_t *len, unsigned char **p, int *is_sign)
431: {
432: /* See if packet has an RFC2671 pseudoheader, and if so return a pointer to it.
433: also return length of pseudoheader in *len and pointer to the UDP size in *p
434: Finally, check to see if a packet is signed. If it is we cannot change a single bit before
435: forwarding. We look for SIG and TSIG in the addition section, and TKEY queries (for GSS-TSIG) */
436:
437: int i, arcount = ntohs(header->arcount);
438: unsigned char *ansp = (unsigned char *)(header+1);
439: unsigned short rdlen, type, class;
440: unsigned char *ret = NULL;
441:
442: if (is_sign)
443: {
444: *is_sign = 0;
445:
446: if (OPCODE(header) == QUERY)
447: {
448: for (i = ntohs(header->qdcount); i != 0; i--)
449: {
450: if (!(ansp = skip_name(ansp, header, plen, 4)))
451: return NULL;
452:
453: GETSHORT(type, ansp);
454: GETSHORT(class, ansp);
455:
456: if (class == C_IN && type == T_TKEY)
457: *is_sign = 1;
458: }
459: }
460: }
461: else
462: {
463: if (!(ansp = skip_questions(header, plen)))
464: return NULL;
465: }
466:
467: if (arcount == 0)
468: return NULL;
469:
470: if (!(ansp = skip_section(ansp, ntohs(header->ancount) + ntohs(header->nscount), header, plen)))
471: return NULL;
472:
473: for (i = 0; i < arcount; i++)
474: {
475: unsigned char *save, *start = ansp;
476: if (!(ansp = skip_name(ansp, header, plen, 10)))
477: return NULL;
478:
479: GETSHORT(type, ansp);
480: save = ansp;
481: GETSHORT(class, ansp);
482: ansp += 4; /* TTL */
483: GETSHORT(rdlen, ansp);
484: if (!ADD_RDLEN(header, ansp, plen, rdlen))
485: return NULL;
486: if (type == T_OPT)
487: {
488: if (len)
489: *len = ansp - start;
490: if (p)
491: *p = save;
492: ret = start;
493: }
494: else if (is_sign &&
495: i == arcount - 1 &&
496: class == C_ANY &&
1.1.1.2 ! misho 497: type == T_TSIG)
1.1 misho 498: *is_sign = 1;
499: }
500:
501: return ret;
502: }
503:
504: struct macparm {
505: unsigned char *limit;
506: struct dns_header *header;
507: size_t plen;
508: union mysockaddr *l3;
509: };
510:
1.1.1.2 ! misho 511: static size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *limit,
! 512: int optno, unsigned char *opt, size_t optlen, int set_do)
! 513: {
! 514: unsigned char *lenp, *datap, *p;
! 515: int rdlen, is_sign;
1.1 misho 516:
1.1.1.2 ! misho 517: if (!(p = find_pseudoheader(header, plen, NULL, NULL, &is_sign)))
1.1 misho 518: {
1.1.1.2 ! misho 519: if (is_sign)
! 520: return plen;
! 521:
1.1 misho 522: /* We are adding the pseudoheader */
1.1.1.2 ! misho 523: if (!(p = skip_questions(header, plen)) ||
1.1 misho 524: !(p = skip_section(p,
1.1.1.2 ! misho 525: ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount),
! 526: header, plen)))
! 527: return plen;
1.1 misho 528: *p++ = 0; /* empty name */
529: PUTSHORT(T_OPT, p);
1.1.1.2 ! misho 530: PUTSHORT(daemon->edns_pktsz, p); /* max packet length */
! 531: PUTSHORT(0, p); /* extended RCODE and version */
! 532: PUTSHORT(set_do ? 0x8000 : 0, p); /* DO flag */
1.1 misho 533: lenp = p;
534: PUTSHORT(0, p); /* RDLEN */
535: rdlen = 0;
1.1.1.2 ! misho 536: if (((ssize_t)optlen) > (limit - (p + 4)))
! 537: return plen; /* Too big */
! 538: header->arcount = htons(ntohs(header->arcount) + 1);
1.1 misho 539: datap = p;
540: }
541: else
542: {
1.1.1.2 ! misho 543: int i;
! 544: unsigned short code, len, flags;
1.1 misho 545:
1.1.1.2 ! misho 546: /* Must be at the end, if exists */
1.1 misho 547: if (ntohs(header->arcount) != 1 ||
548: is_sign ||
1.1.1.2 ! misho 549: (!(p = skip_name(p, header, plen, 10))))
! 550: return plen;
1.1 misho 551:
1.1.1.2 ! misho 552: p += 6; /* skip UDP length and RCODE */
! 553: GETSHORT(flags, p);
! 554: if (set_do)
! 555: {
! 556: p -=2;
! 557: PUTSHORT(flags | 0x8000, p);
! 558: }
! 559:
1.1 misho 560: lenp = p;
561: GETSHORT(rdlen, p);
1.1.1.2 ! misho 562: if (!CHECK_LEN(header, p, plen, rdlen))
! 563: return plen; /* bad packet */
1.1 misho 564: datap = p;
565:
1.1.1.2 ! misho 566: /* no option to add */
! 567: if (optno == 0)
! 568: return plen;
! 569:
1.1 misho 570: /* check if option already there */
571: for (i = 0; i + 4 < rdlen; i += len + 4)
572: {
573: GETSHORT(code, p);
574: GETSHORT(len, p);
1.1.1.2 ! misho 575: if (code == optno)
! 576: return plen;
1.1 misho 577: p += len;
578: }
579:
1.1.1.2 ! misho 580: if (((ssize_t)optlen) > (limit - (p + 4)))
! 581: return plen; /* Too big */
1.1 misho 582: }
583:
1.1.1.2 ! misho 584: if (optno != 0)
! 585: {
! 586: PUTSHORT(optno, p);
! 587: PUTSHORT(optlen, p);
! 588: memcpy(p, opt, optlen);
! 589: p += optlen;
! 590: }
1.1 misho 591:
592: PUTSHORT(p - datap, lenp);
1.1.1.2 ! misho 593: return p - (unsigned char *)header;
! 594:
! 595: }
! 596:
! 597: static int filter_mac(int family, char *addrp, char *mac, size_t maclen, void *parmv)
! 598: {
! 599: struct macparm *parm = parmv;
! 600: int match = 0;
! 601:
! 602: if (family == parm->l3->sa.sa_family)
! 603: {
! 604: if (family == AF_INET && memcmp(&parm->l3->in.sin_addr, addrp, INADDRSZ) == 0)
! 605: match = 1;
! 606: #ifdef HAVE_IPV6
! 607: else
! 608: if (family == AF_INET6 && memcmp(&parm->l3->in6.sin6_addr, addrp, IN6ADDRSZ) == 0)
! 609: match = 1;
! 610: #endif
! 611: }
! 612:
! 613: if (!match)
! 614: return 1; /* continue */
! 615:
! 616: parm->plen = add_pseudoheader(parm->header, parm->plen, parm->limit, EDNS0_OPTION_MAC, (unsigned char *)mac, maclen, 0);
1.1 misho 617:
618: return 0; /* done */
619: }
620:
621: size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysockaddr *l3)
622: {
623: struct macparm parm;
624:
625: /* Must have an existing pseudoheader as the only ar-record,
626: or have no ar-records. Must also not be signed */
627:
628: if (ntohs(header->arcount) > 1)
629: return plen;
630:
631: parm.header = header;
632: parm.limit = (unsigned char *)limit;
633: parm.plen = plen;
634: parm.l3 = l3;
635:
636: iface_enumerate(AF_UNSPEC, &parm, filter_mac);
637:
638: return parm.plen;
639: }
640:
1.1.1.2 ! misho 641: struct subnet_opt {
! 642: u16 family;
! 643: u8 source_netmask, scope_netmask;
! 644: #ifdef HAVE_IPV6
! 645: u8 addr[IN6ADDRSZ];
! 646: #else
! 647: u8 addr[INADDRSZ];
! 648: #endif
! 649: };
! 650:
! 651: static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source)
! 652: {
! 653: /* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
! 654:
! 655: int len;
! 656: void *addrp;
! 657:
! 658: #ifdef HAVE_IPV6
! 659: if (source->sa.sa_family == AF_INET6)
! 660: {
! 661: opt->family = htons(2);
! 662: opt->source_netmask = daemon->addr6_netmask;
! 663: addrp = &source->in6.sin6_addr;
! 664: }
! 665: else
! 666: #endif
! 667: {
! 668: opt->family = htons(1);
! 669: opt->source_netmask = daemon->addr4_netmask;
! 670: addrp = &source->in.sin_addr;
! 671: }
! 672:
! 673: opt->scope_netmask = 0;
! 674: len = 0;
! 675:
! 676: if (opt->source_netmask != 0)
! 677: {
! 678: len = ((opt->source_netmask - 1) >> 3) + 1;
! 679: memcpy(opt->addr, addrp, len);
! 680: if (opt->source_netmask & 7)
! 681: opt->addr[len-1] &= 0xff << (8 - (opt->source_netmask & 7));
! 682: }
! 683:
! 684: return len + 4;
! 685: }
! 686:
! 687: size_t add_source_addr(struct dns_header *header, size_t plen, char *limit, union mysockaddr *source)
! 688: {
! 689: /* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
! 690:
! 691: int len;
! 692: struct subnet_opt opt;
! 693:
! 694: len = calc_subnet_opt(&opt, source);
! 695: return add_pseudoheader(header, plen, (unsigned char *)limit, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0);
! 696: }
! 697:
! 698: #ifdef HAVE_DNSSEC
! 699: size_t add_do_bit(struct dns_header *header, size_t plen, char *limit)
! 700: {
! 701: return add_pseudoheader(header, plen, (unsigned char *)limit, 0, NULL, 0, 1);
! 702: }
! 703: #endif
! 704:
! 705: int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer)
! 706: {
! 707: /* Section 9.2, Check that subnet option in reply matches. */
! 708:
! 709:
! 710: int len, calc_len;
! 711: struct subnet_opt opt;
! 712: unsigned char *p;
! 713: int code, i, rdlen;
! 714:
! 715: calc_len = calc_subnet_opt(&opt, peer);
! 716:
! 717: if (!(p = skip_name(pseudoheader, header, plen, 10)))
! 718: return 1;
! 719:
! 720: p += 8; /* skip UDP length and RCODE */
! 721:
! 722: GETSHORT(rdlen, p);
! 723: if (!CHECK_LEN(header, p, plen, rdlen))
! 724: return 1; /* bad packet */
! 725:
! 726: /* check if option there */
! 727: for (i = 0; i + 4 < rdlen; i += len + 4)
! 728: {
! 729: GETSHORT(code, p);
! 730: GETSHORT(len, p);
! 731: if (code == EDNS0_OPTION_CLIENT_SUBNET)
! 732: {
! 733: /* make sure this doesn't mismatch. */
! 734: opt.scope_netmask = p[3];
! 735: if (len != calc_len || memcmp(p, &opt, len) != 0)
! 736: return 0;
! 737: }
! 738: p += len;
! 739: }
! 740:
! 741: return 1;
! 742: }
! 743:
1.1 misho 744: /* is addr in the non-globally-routed IP space? */
1.1.1.2 ! misho 745: int private_net(struct in_addr addr, int ban_localhost)
1.1 misho 746: {
747: in_addr_t ip_addr = ntohl(addr.s_addr);
748:
749: return
750: (((ip_addr & 0xFF000000) == 0x7F000000) && ban_localhost) /* 127.0.0.0/8 (loopback) */ ||
751: ((ip_addr & 0xFFFF0000) == 0xC0A80000) /* 192.168.0.0/16 (private) */ ||
752: ((ip_addr & 0xFF000000) == 0x0A000000) /* 10.0.0.0/8 (private) */ ||
753: ((ip_addr & 0xFFF00000) == 0xAC100000) /* 172.16.0.0/12 (private) */ ||
754: ((ip_addr & 0xFFFF0000) == 0xA9FE0000) /* 169.254.0.0/16 (zeroconf) */ ;
755: }
756:
1.1.1.2 ! misho 757: static unsigned char *do_doctor(unsigned char *p, int count, struct dns_header *header, size_t qlen, char *name, int *doctored)
1.1 misho 758: {
759: int i, qtype, qclass, rdlen;
760:
761: for (i = count; i != 0; i--)
762: {
763: if (name && option_bool(OPT_LOG))
764: {
765: if (!extract_name(header, qlen, &p, name, 1, 10))
766: return 0;
767: }
768: else if (!(p = skip_name(p, header, qlen, 10)))
769: return 0; /* bad packet */
770:
771: GETSHORT(qtype, p);
772: GETSHORT(qclass, p);
773: p += 4; /* ttl */
774: GETSHORT(rdlen, p);
775:
776: if (qclass == C_IN && qtype == T_A)
777: {
778: struct doctor *doctor;
779: struct in_addr addr;
780:
781: if (!CHECK_LEN(header, p, qlen, INADDRSZ))
782: return 0;
783:
784: /* alignment */
785: memcpy(&addr, p, INADDRSZ);
786:
787: for (doctor = daemon->doctors; doctor; doctor = doctor->next)
788: {
789: if (doctor->end.s_addr == 0)
790: {
791: if (!is_same_net(doctor->in, addr, doctor->mask))
792: continue;
793: }
794: else if (ntohl(doctor->in.s_addr) > ntohl(addr.s_addr) ||
795: ntohl(doctor->end.s_addr) < ntohl(addr.s_addr))
796: continue;
797:
798: addr.s_addr &= ~doctor->mask.s_addr;
799: addr.s_addr |= (doctor->out.s_addr & doctor->mask.s_addr);
800: /* Since we munged the data, the server it came from is no longer authoritative */
801: header->hb3 &= ~HB3_AA;
1.1.1.2 ! misho 802: *doctored = 1;
1.1 misho 803: memcpy(p, &addr, INADDRSZ);
804: break;
805: }
806: }
807: else if (qtype == T_TXT && name && option_bool(OPT_LOG))
808: {
809: unsigned char *p1 = p;
810: if (!CHECK_LEN(header, p1, qlen, rdlen))
811: return 0;
812: while ((p1 - p) < rdlen)
813: {
814: unsigned int i, len = *p1;
815: unsigned char *p2 = p1;
816: /* make counted string zero-term and sanitise */
817: for (i = 0; i < len; i++)
818: {
819: if (!isprint((int)*(p2+1)))
820: break;
821:
822: *p2 = *(p2+1);
823: p2++;
824: }
825: *p2 = 0;
826: my_syslog(LOG_INFO, "reply %s is %s", name, p1);
827: /* restore */
828: memmove(p1 + 1, p1, i);
829: *p1 = len;
830: p1 += len+1;
831: }
832: }
833:
834: if (!ADD_RDLEN(header, p, qlen, rdlen))
835: return 0; /* bad packet */
836: }
837:
838: return p;
839: }
840:
1.1.1.2 ! misho 841: static int find_soa(struct dns_header *header, size_t qlen, char *name, int *doctored)
1.1 misho 842: {
843: unsigned char *p;
844: int qtype, qclass, rdlen;
845: unsigned long ttl, minttl = ULONG_MAX;
846: int i, found_soa = 0;
847:
848: /* first move to NS section and find TTL from any SOA section */
849: if (!(p = skip_questions(header, qlen)) ||
1.1.1.2 ! misho 850: !(p = do_doctor(p, ntohs(header->ancount), header, qlen, name, doctored)))
1.1 misho 851: return 0; /* bad packet */
852:
853: for (i = ntohs(header->nscount); i != 0; i--)
854: {
855: if (!(p = skip_name(p, header, qlen, 10)))
856: return 0; /* bad packet */
857:
858: GETSHORT(qtype, p);
859: GETSHORT(qclass, p);
860: GETLONG(ttl, p);
861: GETSHORT(rdlen, p);
862:
863: if ((qclass == C_IN) && (qtype == T_SOA))
864: {
865: found_soa = 1;
866: if (ttl < minttl)
867: minttl = ttl;
868:
869: /* MNAME */
870: if (!(p = skip_name(p, header, qlen, 0)))
871: return 0;
872: /* RNAME */
873: if (!(p = skip_name(p, header, qlen, 20)))
874: return 0;
875: p += 16; /* SERIAL REFRESH RETRY EXPIRE */
876:
877: GETLONG(ttl, p); /* minTTL */
878: if (ttl < minttl)
879: minttl = ttl;
880: }
881: else if (!ADD_RDLEN(header, p, qlen, rdlen))
882: return 0; /* bad packet */
883: }
884:
1.1.1.2 ! misho 885: /* rewrite addresses in additional section too */
! 886: if (!do_doctor(p, ntohs(header->arcount), header, qlen, NULL, doctored))
1.1 misho 887: return 0;
888:
889: if (!found_soa)
890: minttl = daemon->neg_ttl;
891:
892: return minttl;
893: }
894:
895: /* Note that the following code can create CNAME chains that don't point to a real record,
896: either because of lack of memory, or lack of SOA records. These are treated by the cache code as
897: expired and cleaned out that way.
898: Return 1 if we reject an address because it look like part of dns-rebinding attack. */
899: int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t now,
1.1.1.2 ! misho 900: char **ipsets, int is_sign, int check_rebind, int no_cache_dnssec, int secure, int *doctored)
1.1 misho 901: {
902: unsigned char *p, *p1, *endrr, *namep;
903: int i, j, qtype, qclass, aqtype, aqclass, ardlen, res, searched_soa = 0;
904: unsigned long ttl = 0;
905: struct all_addr addr;
906: #ifdef HAVE_IPSET
907: char **ipsets_cur;
908: #else
909: (void)ipsets; /* unused */
910: #endif
911:
912: cache_start_insert();
913:
914: /* find_soa is needed for dns_doctor and logging side-effects, so don't call it lazily if there are any. */
1.1.1.2 ! misho 915: if (daemon->doctors || option_bool(OPT_LOG) || option_bool(OPT_DNSSEC_VALID))
1.1 misho 916: {
917: searched_soa = 1;
1.1.1.2 ! misho 918: ttl = find_soa(header, qlen, name, doctored);
! 919: #ifdef HAVE_DNSSEC
! 920: if (*doctored && secure)
! 921: return 0;
! 922: #endif
1.1 misho 923: }
924:
925: /* go through the questions. */
926: p = (unsigned char *)(header+1);
927:
928: for (i = ntohs(header->qdcount); i != 0; i--)
929: {
1.1.1.2 ! misho 930: int found = 0, cname_count = CNAME_CHAIN;
1.1 misho 931: struct crec *cpp = NULL;
932: int flags = RCODE(header) == NXDOMAIN ? F_NXDOMAIN : 0;
1.1.1.2 ! misho 933: int secflag = secure ? F_DNSSECOK : 0;
1.1 misho 934: unsigned long cttl = ULONG_MAX, attl;
1.1.1.2 ! misho 935:
1.1 misho 936: namep = p;
937: if (!extract_name(header, qlen, &p, name, 1, 4))
938: return 0; /* bad packet */
939:
940: GETSHORT(qtype, p);
941: GETSHORT(qclass, p);
942:
943: if (qclass != C_IN)
944: continue;
945:
946: /* PTRs: we chase CNAMEs here, since we have no way to
947: represent them in the cache. */
948: if (qtype == T_PTR)
949: {
950: int name_encoding = in_arpa_name_2_addr(name, &addr);
951:
952: if (!name_encoding)
953: continue;
954:
955: if (!(flags & F_NXDOMAIN))
956: {
957: cname_loop:
958: if (!(p1 = skip_questions(header, qlen)))
959: return 0;
960:
961: for (j = ntohs(header->ancount); j != 0; j--)
962: {
963: unsigned char *tmp = namep;
964: /* the loop body overwrites the original name, so get it back here. */
965: if (!extract_name(header, qlen, &tmp, name, 1, 0) ||
966: !(res = extract_name(header, qlen, &p1, name, 0, 10)))
967: return 0; /* bad packet */
968:
969: GETSHORT(aqtype, p1);
970: GETSHORT(aqclass, p1);
971: GETLONG(attl, p1);
972: if ((daemon->max_ttl != 0) && (attl > daemon->max_ttl) && !is_sign)
973: {
974: (p1) -= 4;
975: PUTLONG(daemon->max_ttl, p1);
976: }
977: GETSHORT(ardlen, p1);
978: endrr = p1+ardlen;
979:
980: /* TTL of record is minimum of CNAMES and PTR */
981: if (attl < cttl)
982: cttl = attl;
983:
984: if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == T_PTR))
985: {
986: if (!extract_name(header, qlen, &p1, name, 1, 0))
987: return 0;
988:
989: if (aqtype == T_CNAME)
990: {
1.1.1.2 ! misho 991: if (!cname_count-- || secure)
! 992: return 0; /* looped CNAMES, or DNSSEC, which we can't cache. */
1.1 misho 993: goto cname_loop;
994: }
995:
1.1.1.2 ! misho 996: cache_insert(name, &addr, now, cttl, name_encoding | secflag | F_REVERSE);
1.1 misho 997: found = 1;
998: }
999:
1000: p1 = endrr;
1001: if (!CHECK_LEN(header, p1, qlen, 0))
1002: return 0; /* bad packet */
1003: }
1004: }
1005:
1006: if (!found && !option_bool(OPT_NO_NEG))
1007: {
1008: if (!searched_soa)
1009: {
1010: searched_soa = 1;
1.1.1.2 ! misho 1011: ttl = find_soa(header, qlen, NULL, doctored);
1.1 misho 1012: }
1013: if (ttl)
1.1.1.2 ! misho 1014: cache_insert(NULL, &addr, now, ttl, name_encoding | F_REVERSE | F_NEG | flags | secflag);
1.1 misho 1015: }
1016: }
1017: else
1018: {
1019: /* everything other than PTR */
1020: struct crec *newc;
1021: int addrlen;
1022:
1023: if (qtype == T_A)
1024: {
1025: addrlen = INADDRSZ;
1026: flags |= F_IPV4;
1027: }
1028: #ifdef HAVE_IPV6
1029: else if (qtype == T_AAAA)
1030: {
1031: addrlen = IN6ADDRSZ;
1032: flags |= F_IPV6;
1033: }
1034: #endif
1035: else
1036: continue;
1037:
1.1.1.2 ! misho 1038: cname_loop1:
! 1039: if (!(p1 = skip_questions(header, qlen)))
! 1040: return 0;
! 1041:
! 1042: for (j = ntohs(header->ancount); j != 0; j--)
1.1 misho 1043: {
1.1.1.2 ! misho 1044: if (!(res = extract_name(header, qlen, &p1, name, 0, 10)))
! 1045: return 0; /* bad packet */
1.1 misho 1046:
1.1.1.2 ! misho 1047: GETSHORT(aqtype, p1);
! 1048: GETSHORT(aqclass, p1);
! 1049: GETLONG(attl, p1);
! 1050: if ((daemon->max_ttl != 0) && (attl > daemon->max_ttl) && !is_sign)
1.1 misho 1051: {
1.1.1.2 ! misho 1052: (p1) -= 4;
! 1053: PUTLONG(daemon->max_ttl, p1);
! 1054: }
! 1055: GETSHORT(ardlen, p1);
! 1056: endrr = p1+ardlen;
! 1057:
! 1058: if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == qtype))
! 1059: {
! 1060: if (aqtype == T_CNAME)
1.1 misho 1061: {
1.1.1.2 ! misho 1062: if (!cname_count--)
! 1063: return 0; /* looped CNAMES */
! 1064: newc = cache_insert(name, NULL, now, attl, F_CNAME | F_FORWARD | secflag);
! 1065: if (newc)
1.1 misho 1066: {
1.1.1.2 ! misho 1067: newc->addr.cname.target.cache = NULL;
! 1068: /* anything other than zero, to avoid being mistaken for CNAME to interface-name */
! 1069: newc->addr.cname.uid = 1;
! 1070: if (cpp)
1.1 misho 1071: {
1.1.1.2 ! misho 1072: cpp->addr.cname.target.cache = newc;
! 1073: cpp->addr.cname.uid = newc->uid;
1.1 misho 1074: }
1075: }
1.1.1.2 ! misho 1076:
! 1077: cpp = newc;
! 1078: if (attl < cttl)
! 1079: cttl = attl;
! 1080:
! 1081: if (!extract_name(header, qlen, &p1, name, 1, 0))
! 1082: return 0;
! 1083: goto cname_loop1;
! 1084: }
! 1085: else if (!(flags & F_NXDOMAIN))
! 1086: {
! 1087: found = 1;
! 1088:
! 1089: /* copy address into aligned storage */
! 1090: if (!CHECK_LEN(header, p1, qlen, addrlen))
! 1091: return 0; /* bad packet */
! 1092: memcpy(&addr, p1, addrlen);
! 1093:
! 1094: /* check for returned address in private space */
! 1095: if (check_rebind &&
! 1096: (flags & F_IPV4) &&
! 1097: private_net(addr.addr.addr4, !option_bool(OPT_LOCAL_REBIND)))
! 1098: return 1;
! 1099:
1.1 misho 1100: #ifdef HAVE_IPSET
1.1.1.2 ! misho 1101: if (ipsets && (flags & (F_IPV4 | F_IPV6)))
! 1102: {
! 1103: ipsets_cur = ipsets;
! 1104: while (*ipsets_cur)
1.1 misho 1105: {
1.1.1.2 ! misho 1106: log_query((flags & (F_IPV4 | F_IPV6)) | F_IPSET, name, &addr, *ipsets_cur);
! 1107: add_to_ipset(*ipsets_cur++, &addr, flags, 0);
1.1 misho 1108: }
1.1.1.2 ! misho 1109: }
1.1 misho 1110: #endif
1.1.1.2 ! misho 1111:
! 1112: newc = cache_insert(name, &addr, now, attl, flags | F_FORWARD | secflag);
! 1113: if (newc && cpp)
! 1114: {
! 1115: cpp->addr.cname.target.cache = newc;
! 1116: cpp->addr.cname.uid = newc->uid;
1.1 misho 1117: }
1.1.1.2 ! misho 1118: cpp = NULL;
1.1 misho 1119: }
1120: }
1.1.1.2 ! misho 1121:
! 1122: p1 = endrr;
! 1123: if (!CHECK_LEN(header, p1, qlen, 0))
! 1124: return 0; /* bad packet */
1.1 misho 1125: }
1126:
1127: if (!found && !option_bool(OPT_NO_NEG))
1128: {
1129: if (!searched_soa)
1130: {
1131: searched_soa = 1;
1.1.1.2 ! misho 1132: ttl = find_soa(header, qlen, NULL, doctored);
1.1 misho 1133: }
1134: /* If there's no SOA to get the TTL from, but there is a CNAME
1135: pointing at this, inherit its TTL */
1136: if (ttl || cpp)
1137: {
1.1.1.2 ! misho 1138: newc = cache_insert(name, NULL, now, ttl ? ttl : cttl, F_FORWARD | F_NEG | flags | secflag);
1.1 misho 1139: if (newc && cpp)
1140: {
1.1.1.2 ! misho 1141: cpp->addr.cname.target.cache = newc;
1.1 misho 1142: cpp->addr.cname.uid = newc->uid;
1143: }
1144: }
1145: }
1146: }
1147: }
1148:
1149: /* Don't put stuff from a truncated packet into the cache.
1150: Don't cache replies from non-recursive nameservers, since we may get a
1151: reply containing a CNAME but not its target, even though the target
1152: does exist. */
1153: if (!(header->hb3 & HB3_TC) &&
1154: !(header->hb4 & HB4_CD) &&
1155: (header->hb4 & HB4_RA) &&
1.1.1.2 ! misho 1156: !no_cache_dnssec)
1.1 misho 1157: cache_end_insert();
1158:
1159: return 0;
1160: }
1161:
1162: /* If the packet holds exactly one query
1163: return F_IPV4 or F_IPV6 and leave the name from the query in name */
1164: unsigned int extract_request(struct dns_header *header, size_t qlen, char *name, unsigned short *typep)
1165: {
1166: unsigned char *p = (unsigned char *)(header+1);
1167: int qtype, qclass;
1168:
1169: if (typep)
1170: *typep = 0;
1171:
1172: if (ntohs(header->qdcount) != 1 || OPCODE(header) != QUERY)
1173: return 0; /* must be exactly one query. */
1174:
1175: if (!extract_name(header, qlen, &p, name, 1, 4))
1176: return 0; /* bad packet */
1177:
1178: GETSHORT(qtype, p);
1179: GETSHORT(qclass, p);
1180:
1181: if (typep)
1182: *typep = qtype;
1183:
1184: if (qclass == C_IN)
1185: {
1186: if (qtype == T_A)
1187: return F_IPV4;
1188: if (qtype == T_AAAA)
1189: return F_IPV6;
1190: if (qtype == T_ANY)
1191: return F_IPV4 | F_IPV6;
1192: }
1193:
1194: return F_QUERY;
1195: }
1196:
1197:
1198: size_t setup_reply(struct dns_header *header, size_t qlen,
1199: struct all_addr *addrp, unsigned int flags, unsigned long ttl)
1200: {
1201: unsigned char *p = skip_questions(header, qlen);
1202:
1203: /* clear authoritative and truncated flags, set QR flag */
1204: header->hb3 = (header->hb3 & ~(HB3_AA | HB3_TC)) | HB3_QR;
1205: /* set RA flag */
1206: header->hb4 |= HB4_RA;
1207:
1208: header->nscount = htons(0);
1209: header->arcount = htons(0);
1210: header->ancount = htons(0); /* no answers unless changed below */
1211: if (flags == F_NEG)
1212: SET_RCODE(header, SERVFAIL); /* couldn't get memory */
1213: else if (flags == F_NOERR)
1214: SET_RCODE(header, NOERROR); /* empty domain */
1215: else if (flags == F_NXDOMAIN)
1216: SET_RCODE(header, NXDOMAIN);
1217: else if (p && flags == F_IPV4)
1218: { /* we know the address */
1219: SET_RCODE(header, NOERROR);
1220: header->ancount = htons(1);
1221: header->hb3 |= HB3_AA;
1222: add_resource_record(header, NULL, NULL, sizeof(struct dns_header), &p, ttl, NULL, T_A, C_IN, "4", addrp);
1223: }
1224: #ifdef HAVE_IPV6
1225: else if (p && flags == F_IPV6)
1226: {
1227: SET_RCODE(header, NOERROR);
1228: header->ancount = htons(1);
1229: header->hb3 |= HB3_AA;
1230: add_resource_record(header, NULL, NULL, sizeof(struct dns_header), &p, ttl, NULL, T_AAAA, C_IN, "6", addrp);
1231: }
1232: #endif
1233: else /* nowhere to forward to */
1234: SET_RCODE(header, REFUSED);
1235:
1236: return p - (unsigned char *)header;
1237: }
1238:
1239: /* check if name matches local names ie from /etc/hosts or DHCP or local mx names. */
1240: int check_for_local_domain(char *name, time_t now)
1241: {
1242: struct crec *crecp;
1243: struct mx_srv_record *mx;
1244: struct txt_record *txt;
1245: struct interface_name *intr;
1246: struct ptr_record *ptr;
1247: struct naptr *naptr;
1248:
1.1.1.2 ! misho 1249: if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6 | F_CNAME | F_DS | F_NO_RR)) &&
! 1250: (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
1.1 misho 1251: return 1;
1252:
1253: for (naptr = daemon->naptr; naptr; naptr = naptr->next)
1254: if (hostname_isequal(name, naptr->name))
1255: return 1;
1256:
1257: for (mx = daemon->mxnames; mx; mx = mx->next)
1258: if (hostname_isequal(name, mx->name))
1259: return 1;
1260:
1261: for (txt = daemon->txt; txt; txt = txt->next)
1262: if (hostname_isequal(name, txt->name))
1263: return 1;
1264:
1265: for (intr = daemon->int_names; intr; intr = intr->next)
1266: if (hostname_isequal(name, intr->name))
1267: return 1;
1268:
1269: for (ptr = daemon->ptr; ptr; ptr = ptr->next)
1270: if (hostname_isequal(name, ptr->name))
1271: return 1;
1272:
1273: return 0;
1274: }
1275:
1276: /* Is the packet a reply with the answer address equal to addr?
1277: If so mung is into an NXDOMAIN reply and also put that information
1278: in the cache. */
1279: int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
1280: struct bogus_addr *baddr, time_t now)
1281: {
1282: unsigned char *p;
1283: int i, qtype, qclass, rdlen;
1284: unsigned long ttl;
1285: struct bogus_addr *baddrp;
1286:
1287: /* skip over questions */
1288: if (!(p = skip_questions(header, qlen)))
1289: return 0; /* bad packet */
1290:
1291: for (i = ntohs(header->ancount); i != 0; i--)
1292: {
1293: if (!extract_name(header, qlen, &p, name, 1, 10))
1294: return 0; /* bad packet */
1295:
1296: GETSHORT(qtype, p);
1297: GETSHORT(qclass, p);
1298: GETLONG(ttl, p);
1299: GETSHORT(rdlen, p);
1300:
1301: if (qclass == C_IN && qtype == T_A)
1302: {
1303: if (!CHECK_LEN(header, p, qlen, INADDRSZ))
1304: return 0;
1305:
1306: for (baddrp = baddr; baddrp; baddrp = baddrp->next)
1307: if (memcmp(&baddrp->addr, p, INADDRSZ) == 0)
1308: {
1309: /* Found a bogus address. Insert that info here, since there no SOA record
1310: to get the ttl from in the normal processing */
1311: cache_start_insert();
1.1.1.2 ! misho 1312: cache_insert(name, NULL, now, ttl, F_IPV4 | F_FORWARD | F_NEG | F_NXDOMAIN);
1.1 misho 1313: cache_end_insert();
1314:
1315: return 1;
1316: }
1317: }
1318:
1319: if (!ADD_RDLEN(header, p, qlen, rdlen))
1320: return 0;
1321: }
1322:
1323: return 0;
1324: }
1325:
1326: int add_resource_record(struct dns_header *header, char *limit, int *truncp, int nameoffset, unsigned char **pp,
1327: unsigned long ttl, int *offset, unsigned short type, unsigned short class, char *format, ...)
1328: {
1329: va_list ap;
1330: unsigned char *sav, *p = *pp;
1331: int j;
1332: unsigned short usval;
1333: long lval;
1334: char *sval;
1335:
1336: if (truncp && *truncp)
1337: return 0;
1338:
1339: va_start(ap, format); /* make ap point to 1st unamed argument */
1340:
1341: if (nameoffset > 0)
1342: {
1343: PUTSHORT(nameoffset | 0xc000, p);
1344: }
1345: else
1346: {
1347: char *name = va_arg(ap, char *);
1348: if (name)
1349: p = do_rfc1035_name(p, name);
1350: if (nameoffset < 0)
1351: {
1352: PUTSHORT(-nameoffset | 0xc000, p);
1353: }
1354: else
1355: *p++ = 0;
1356: }
1357:
1358: PUTSHORT(type, p);
1359: PUTSHORT(class, p);
1360: PUTLONG(ttl, p); /* TTL */
1361:
1362: sav = p; /* Save pointer to RDLength field */
1363: PUTSHORT(0, p); /* Placeholder RDLength */
1364:
1365: for (; *format; format++)
1366: switch (*format)
1367: {
1368: #ifdef HAVE_IPV6
1369: case '6':
1370: sval = va_arg(ap, char *);
1371: memcpy(p, sval, IN6ADDRSZ);
1372: p += IN6ADDRSZ;
1373: break;
1374: #endif
1375:
1376: case '4':
1377: sval = va_arg(ap, char *);
1378: memcpy(p, sval, INADDRSZ);
1379: p += INADDRSZ;
1380: break;
1381:
1.1.1.2 ! misho 1382: case 'b':
! 1383: usval = va_arg(ap, int);
! 1384: *p++ = usval;
! 1385: break;
! 1386:
1.1 misho 1387: case 's':
1388: usval = va_arg(ap, int);
1389: PUTSHORT(usval, p);
1390: break;
1391:
1392: case 'l':
1393: lval = va_arg(ap, long);
1394: PUTLONG(lval, p);
1395: break;
1396:
1397: case 'd':
1398: /* get domain-name answer arg and store it in RDATA field */
1399: if (offset)
1400: *offset = p - (unsigned char *)header;
1401: p = do_rfc1035_name(p, va_arg(ap, char *));
1402: *p++ = 0;
1403: break;
1404:
1405: case 't':
1406: usval = va_arg(ap, int);
1407: sval = va_arg(ap, char *);
1408: if (usval != 0)
1409: memcpy(p, sval, usval);
1410: p += usval;
1411: break;
1412:
1413: case 'z':
1414: sval = va_arg(ap, char *);
1415: usval = sval ? strlen(sval) : 0;
1416: if (usval > 255)
1417: usval = 255;
1418: *p++ = (unsigned char)usval;
1419: memcpy(p, sval, usval);
1420: p += usval;
1421: break;
1422: }
1423:
1424: va_end(ap); /* clean up variable argument pointer */
1425:
1426: j = p - sav - 2;
1427: PUTSHORT(j, sav); /* Now, store real RDLength */
1428:
1429: /* check for overflow of buffer */
1430: if (limit && ((unsigned char *)limit - p) < 0)
1431: {
1432: if (truncp)
1433: *truncp = 1;
1434: return 0;
1435: }
1436:
1437: *pp = p;
1438: return 1;
1439: }
1440:
1441: static unsigned long crec_ttl(struct crec *crecp, time_t now)
1442: {
1443: /* Return 0 ttl for DHCP entries, which might change
1444: before the lease expires. */
1445:
1446: if (crecp->flags & (F_IMMORTAL | F_DHCP))
1447: return daemon->local_ttl;
1448:
1449: /* Return the Max TTL value if it is lower then the actual TTL */
1450: if (daemon->max_ttl == 0 || ((unsigned)(crecp->ttd - now) < daemon->max_ttl))
1451: return crecp->ttd - now;
1452: else
1453: return daemon->max_ttl;
1454: }
1455:
1456:
1457: /* return zero if we can't answer from cache, or packet size if we can */
1458: size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
1.1.1.2 ! misho 1459: struct in_addr local_addr, struct in_addr local_netmask,
! 1460: time_t now, int *ad_reqd, int *do_bit)
1.1 misho 1461: {
1462: char *name = daemon->namebuff;
1463: unsigned char *p, *ansp, *pheader;
1.1.1.2 ! misho 1464: unsigned int qtype, qclass;
1.1 misho 1465: struct all_addr addr;
1466: int nameoffset;
1467: unsigned short flag;
1468: int q, ans, anscount = 0, addncount = 0;
1.1.1.2 ! misho 1469: int dryrun = 0, sec_reqd = 0, have_pseudoheader = 0;
1.1 misho 1470: int is_sign;
1471: struct crec *crecp;
1.1.1.2 ! misho 1472: int nxdomain = 0, auth = 1, trunc = 0, sec_data = 1;
1.1 misho 1473: struct mx_srv_record *rec;
1.1.1.2 ! misho 1474: size_t len;
1.1 misho 1475:
1.1.1.2 ! misho 1476: /* Don't return AD set if checking disabled. */
! 1477: if (header->hb4 & HB4_CD)
! 1478: sec_data = 0;
! 1479:
! 1480: /* RFC 6840 5.7 */
! 1481: *ad_reqd = header->hb4 & HB4_AD;
! 1482: *do_bit = 0;
! 1483:
1.1 misho 1484: /* If there is an RFC2671 pseudoheader then it will be overwritten by
1485: partial replies, so we have to do a dry run to see if we can answer
1486: the query. We check to see if the do bit is set, if so we always
1487: forward rather than answering from the cache, which doesn't include
1.1.1.2 ! misho 1488: security information, unless we're in DNSSEC validation mode. */
1.1 misho 1489:
1490: if (find_pseudoheader(header, qlen, NULL, &pheader, &is_sign))
1491: {
1492: unsigned short udpsz, flags;
1493: unsigned char *psave = pheader;
1494:
1.1.1.2 ! misho 1495: have_pseudoheader = 1;
! 1496:
1.1 misho 1497: GETSHORT(udpsz, pheader);
1498: pheader += 2; /* ext_rcode */
1499: GETSHORT(flags, pheader);
1500:
1.1.1.2 ! misho 1501: if ((sec_reqd = flags & 0x8000))
! 1502: *do_bit = 1;/* do bit */
! 1503: *ad_reqd = 1;
1.1 misho 1504:
1505: /* If our client is advertising a larger UDP packet size
1506: than we allow, trim it so that we don't get an overlarge
1507: response from upstream */
1508:
1509: if (!is_sign && (udpsz > daemon->edns_pktsz))
1510: PUTSHORT(daemon->edns_pktsz, psave);
1511:
1512: dryrun = 1;
1513: }
1514:
1515: if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY )
1516: return 0;
1517:
1518: for (rec = daemon->mxnames; rec; rec = rec->next)
1519: rec->offset = 0;
1520:
1521: rerun:
1522: /* determine end of question section (we put answers there) */
1523: if (!(ansp = skip_questions(header, qlen)))
1524: return 0; /* bad packet */
1525:
1526: /* now process each question, answers go in RRs after the question */
1527: p = (unsigned char *)(header+1);
1528:
1529: for (q = ntohs(header->qdcount); q != 0; q--)
1530: {
1531: /* save pointer to name for copying into answers */
1532: nameoffset = p - (unsigned char *)header;
1533:
1534: /* now extract name as .-concatenated string into name */
1535: if (!extract_name(header, qlen, &p, name, 1, 4))
1536: return 0; /* bad packet */
1537:
1538: GETSHORT(qtype, p);
1539: GETSHORT(qclass, p);
1540:
1541: ans = 0; /* have we answered this question */
1542:
1543: if (qtype == T_TXT || qtype == T_ANY)
1544: {
1545: struct txt_record *t;
1546: for(t = daemon->txt; t ; t = t->next)
1547: {
1548: if (t->class == qclass && hostname_isequal(name, t->name))
1549: {
1550: ans = 1;
1551: if (!dryrun)
1552: {
1.1.1.2 ! misho 1553: unsigned long ttl = daemon->local_ttl;
! 1554: int ok = 1;
1.1 misho 1555: log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
1.1.1.2 ! misho 1556: /* Dynamically generate stat record */
! 1557: if (t->stat != 0)
! 1558: {
! 1559: ttl = 0;
! 1560: if (!cache_make_stat(t))
! 1561: ok = 0;
! 1562: }
! 1563:
! 1564: if (ok && add_resource_record(header, limit, &trunc, nameoffset, &ansp,
! 1565: ttl, NULL,
! 1566: T_TXT, t->class, "t", t->len, t->txt))
1.1 misho 1567: anscount++;
1568:
1569: }
1570: }
1571: }
1572: }
1573:
1.1.1.2 ! misho 1574: #ifdef HAVE_DNSSEC
! 1575: if (option_bool(OPT_DNSSEC_VALID) && (qtype == T_DNSKEY || qtype == T_DS))
! 1576: {
! 1577: int gotone = 0;
! 1578: struct blockdata *keydata;
! 1579:
! 1580: /* Do we have RRSIG? Can't do DS or DNSKEY otherwise. */
! 1581: if (sec_reqd)
! 1582: {
! 1583: crecp = NULL;
! 1584: while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY | F_DS)))
! 1585: if (crecp->uid == qclass && crecp->addr.sig.type_covered == qtype)
! 1586: break;
! 1587: }
! 1588:
! 1589: if (!sec_reqd || crecp)
! 1590: {
! 1591: if (qtype == T_DS)
! 1592: {
! 1593: crecp = NULL;
! 1594: while ((crecp = cache_find_by_name(crecp, name, now, F_DS)))
! 1595: if (crecp->uid == qclass)
! 1596: {
! 1597: gotone = 1;
! 1598: if (!dryrun)
! 1599: {
! 1600: if (crecp->flags & F_NEG)
! 1601: {
! 1602: if (crecp->flags & F_NXDOMAIN)
! 1603: nxdomain = 1;
! 1604: log_query(F_UPSTREAM, name, NULL, "secure no DS");
! 1605: }
! 1606: else if ((keydata = blockdata_retrieve(crecp->addr.ds.keydata, crecp->addr.ds.keylen, NULL)))
! 1607: {
! 1608: struct all_addr a;
! 1609: a.addr.keytag = crecp->addr.ds.keytag;
! 1610: log_query(F_KEYTAG | (crecp->flags & F_CONFIG), name, &a, "DS keytag %u");
! 1611: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
! 1612: crec_ttl(crecp, now), &nameoffset,
! 1613: T_DS, qclass, "sbbt",
! 1614: crecp->addr.ds.keytag, crecp->addr.ds.algo,
! 1615: crecp->addr.ds.digest, crecp->addr.ds.keylen, keydata))
! 1616: anscount++;
! 1617:
! 1618: }
! 1619: }
! 1620: }
! 1621: }
! 1622: else /* DNSKEY */
! 1623: {
! 1624: crecp = NULL;
! 1625: while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY)))
! 1626: if (crecp->uid == qclass)
! 1627: {
! 1628: gotone = 1;
! 1629: if (!dryrun && (keydata = blockdata_retrieve(crecp->addr.key.keydata, crecp->addr.key.keylen, NULL)))
! 1630: {
! 1631: struct all_addr a;
! 1632: a.addr.keytag = crecp->addr.key.keytag;
! 1633: log_query(F_KEYTAG | (crecp->flags & F_CONFIG), name, &a, "DNSKEY keytag %u");
! 1634: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
! 1635: crec_ttl(crecp, now), &nameoffset,
! 1636: T_DNSKEY, qclass, "sbbt",
! 1637: crecp->addr.key.flags, 3, crecp->addr.key.algo, crecp->addr.key.keylen, keydata))
! 1638: anscount++;
! 1639: }
! 1640: }
! 1641: }
! 1642: }
! 1643:
! 1644: /* Now do RRSIGs */
! 1645: if (gotone)
! 1646: {
! 1647: ans = 1;
! 1648: auth = 0;
! 1649: if (!dryrun && sec_reqd)
! 1650: {
! 1651: crecp = NULL;
! 1652: while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY | F_DS)))
! 1653: if (crecp->uid == qclass && crecp->addr.sig.type_covered == qtype &&
! 1654: (keydata = blockdata_retrieve(crecp->addr.sig.keydata, crecp->addr.sig.keylen, NULL)))
! 1655: {
! 1656: add_resource_record(header, limit, &trunc, nameoffset, &ansp,
! 1657: crec_ttl(crecp, now), &nameoffset,
! 1658: T_RRSIG, qclass, "t", crecp->addr.sig.keylen, keydata);
! 1659: anscount++;
! 1660: }
! 1661: }
! 1662: }
! 1663: }
! 1664: #endif
! 1665:
1.1 misho 1666: if (qclass == C_IN)
1667: {
1668: struct txt_record *t;
1669:
1670: for (t = daemon->rr; t; t = t->next)
1671: if ((t->class == qtype || qtype == T_ANY) && hostname_isequal(name, t->name))
1672: {
1673: ans = 1;
1674: if (!dryrun)
1675: {
1676: log_query(F_CONFIG | F_RRNAME, name, NULL, "<RR>");
1677: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1678: daemon->local_ttl, NULL,
1679: t->class, C_IN, "t", t->len, t->txt))
1680: anscount ++;
1681: }
1682: }
1683:
1684: if (qtype == T_PTR || qtype == T_ANY)
1685: {
1686: /* see if it's w.z.y.z.in-addr.arpa format */
1687: int is_arpa = in_arpa_name_2_addr(name, &addr);
1688: struct ptr_record *ptr;
1689: struct interface_name* intr = NULL;
1690:
1691: for (ptr = daemon->ptr; ptr; ptr = ptr->next)
1692: if (hostname_isequal(name, ptr->name))
1693: break;
1694:
1695: if (is_arpa == F_IPV4)
1696: for (intr = daemon->int_names; intr; intr = intr->next)
1697: {
1.1.1.2 ! misho 1698: struct addrlist *addrlist;
! 1699:
! 1700: for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
! 1701: if (!(addrlist->flags & ADDRLIST_IPV6) && addr.addr.addr4.s_addr == addrlist->addr.addr.addr4.s_addr)
! 1702: break;
! 1703:
! 1704: if (addrlist)
1.1 misho 1705: break;
1706: else
1707: while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
1708: intr = intr->next;
1709: }
1.1.1.2 ! misho 1710: #ifdef HAVE_IPV6
! 1711: else if (is_arpa == F_IPV6)
! 1712: for (intr = daemon->int_names; intr; intr = intr->next)
! 1713: {
! 1714: struct addrlist *addrlist;
! 1715:
! 1716: for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
! 1717: if ((addrlist->flags & ADDRLIST_IPV6) && IN6_ARE_ADDR_EQUAL(&addr.addr.addr6, &addrlist->addr.addr.addr6))
! 1718: break;
! 1719:
! 1720: if (addrlist)
! 1721: break;
! 1722: else
! 1723: while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
! 1724: intr = intr->next;
! 1725: }
! 1726: #endif
1.1 misho 1727:
1728: if (intr)
1729: {
1730: ans = 1;
1731: if (!dryrun)
1732: {
1.1.1.2 ! misho 1733: log_query(is_arpa | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
1.1 misho 1734: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1735: daemon->local_ttl, NULL,
1736: T_PTR, C_IN, "d", intr->name))
1737: anscount++;
1738: }
1739: }
1740: else if (ptr)
1741: {
1742: ans = 1;
1743: if (!dryrun)
1744: {
1745: log_query(F_CONFIG | F_RRNAME, name, NULL, "<PTR>");
1746: for (ptr = daemon->ptr; ptr; ptr = ptr->next)
1747: if (hostname_isequal(name, ptr->name) &&
1748: add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1749: daemon->local_ttl, NULL,
1750: T_PTR, C_IN, "d", ptr->ptr))
1751: anscount++;
1752:
1753: }
1754: }
1755: else if ((crecp = cache_find_by_addr(NULL, &addr, now, is_arpa)))
1.1.1.2 ! misho 1756: {
! 1757: if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) && sec_reqd)
! 1758: {
! 1759: if (!option_bool(OPT_DNSSEC_VALID) || ((crecp->flags & F_NEG) && (crecp->flags & F_DNSSECOK)))
! 1760: crecp = NULL;
! 1761: #ifdef HAVE_DNSSEC
! 1762: else if (crecp->flags & F_DNSSECOK)
! 1763: {
! 1764: int gotsig = 0;
! 1765: struct crec *rr_crec = NULL;
! 1766:
! 1767: while ((rr_crec = cache_find_by_name(rr_crec, name, now, F_DS | F_DNSKEY)))
! 1768: {
! 1769: if (rr_crec->addr.sig.type_covered == T_PTR && rr_crec->uid == C_IN)
! 1770: {
! 1771: char *sigdata = blockdata_retrieve(rr_crec->addr.sig.keydata, rr_crec->addr.sig.keylen, NULL);
! 1772: gotsig = 1;
! 1773:
! 1774: if (!dryrun &&
! 1775: add_resource_record(header, limit, &trunc, nameoffset, &ansp,
! 1776: rr_crec->ttd - now, &nameoffset,
! 1777: T_RRSIG, C_IN, "t", crecp->addr.sig.keylen, sigdata))
! 1778: anscount++;
! 1779: }
! 1780: }
! 1781:
! 1782: if (!gotsig)
! 1783: crecp = NULL;
! 1784: }
! 1785: #endif
! 1786: }
! 1787:
! 1788: if (crecp)
! 1789: {
! 1790: do
! 1791: {
! 1792: /* don't answer wildcard queries with data not from /etc/hosts or dhcp leases */
! 1793: if (qtype == T_ANY && !(crecp->flags & (F_HOSTS | F_DHCP)))
! 1794: continue;
! 1795:
! 1796: if (!(crecp->flags & F_DNSSECOK))
! 1797: sec_data = 0;
! 1798:
! 1799: if (crecp->flags & F_NEG)
! 1800: {
! 1801: ans = 1;
! 1802: auth = 0;
! 1803: if (crecp->flags & F_NXDOMAIN)
! 1804: nxdomain = 1;
! 1805: if (!dryrun)
! 1806: log_query(crecp->flags & ~F_FORWARD, name, &addr, NULL);
! 1807: }
! 1808: else if ((crecp->flags & (F_HOSTS | F_DHCP)) || !sec_reqd || option_bool(OPT_DNSSEC_VALID))
! 1809: {
! 1810: ans = 1;
! 1811: if (!(crecp->flags & (F_HOSTS | F_DHCP)))
! 1812: auth = 0;
! 1813: if (!dryrun)
! 1814: {
! 1815: log_query(crecp->flags & ~F_FORWARD, cache_get_name(crecp), &addr,
! 1816: record_source(crecp->uid));
! 1817:
! 1818: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
! 1819: crec_ttl(crecp, now), NULL,
! 1820: T_PTR, C_IN, "d", cache_get_name(crecp)))
! 1821: anscount++;
! 1822: }
! 1823: }
! 1824: } while ((crecp = cache_find_by_addr(crecp, &addr, now, is_arpa)));
! 1825: }
! 1826: }
! 1827: else if (is_rev_synth(is_arpa, &addr, name))
! 1828: {
! 1829: ans = 1;
! 1830: if (!dryrun)
! 1831: {
! 1832: log_query(F_CONFIG | F_REVERSE | is_arpa, name, &addr, NULL);
! 1833:
! 1834: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
! 1835: daemon->local_ttl, NULL,
! 1836: T_PTR, C_IN, "d", name))
1.1 misho 1837: anscount++;
1.1.1.2 ! misho 1838: }
! 1839: }
1.1 misho 1840: else if (is_arpa == F_IPV4 &&
1841: option_bool(OPT_BOGUSPRIV) &&
1842: private_net(addr.addr.addr4, 1))
1843: {
1844: /* if not in cache, enabled and private IPV4 address, return NXDOMAIN */
1845: ans = 1;
1846: nxdomain = 1;
1847: if (!dryrun)
1848: log_query(F_CONFIG | F_REVERSE | F_IPV4 | F_NEG | F_NXDOMAIN,
1849: name, &addr, NULL);
1850: }
1851: }
1852:
1853: for (flag = F_IPV4; flag; flag = (flag == F_IPV4) ? F_IPV6 : 0)
1854: {
1855: unsigned short type = T_A;
1.1.1.2 ! misho 1856: struct interface_name *intr;
! 1857:
1.1 misho 1858: if (flag == F_IPV6)
1859: #ifdef HAVE_IPV6
1860: type = T_AAAA;
1861: #else
1862: break;
1863: #endif
1864:
1865: if (qtype != type && qtype != T_ANY)
1866: continue;
1867:
1868: /* Check for "A for A" queries; be rather conservative
1869: about what looks like dotted-quad. */
1870: if (qtype == T_A)
1871: {
1872: char *cp;
1873: unsigned int i, a;
1874: int x;
1875:
1876: for (cp = name, i = 0, a = 0; *cp; i++)
1877: {
1878: if (!isdigit((unsigned char)*cp) || (x = strtol(cp, &cp, 10)) > 255)
1879: {
1880: i = 5;
1881: break;
1882: }
1883:
1884: a = (a << 8) + x;
1885:
1886: if (*cp == '.')
1887: cp++;
1888: }
1889:
1890: if (i == 4)
1891: {
1892: ans = 1;
1893: if (!dryrun)
1894: {
1895: addr.addr.addr4.s_addr = htonl(a);
1896: log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL);
1897: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1898: daemon->local_ttl, NULL, type, C_IN, "4", &addr))
1899: anscount++;
1900: }
1901: continue;
1902: }
1903: }
1904:
1905: /* interface name stuff */
1.1.1.2 ! misho 1906: intname_restart:
! 1907: for (intr = daemon->int_names; intr; intr = intr->next)
! 1908: if (hostname_isequal(name, intr->name))
! 1909: break;
! 1910:
! 1911: if (intr)
1.1 misho 1912: {
1.1.1.2 ! misho 1913: struct addrlist *addrlist;
! 1914: int gotit = 0;
1.1 misho 1915:
1.1.1.2 ! misho 1916: enumerate_interfaces(0);
! 1917:
1.1 misho 1918: for (intr = daemon->int_names; intr; intr = intr->next)
1919: if (hostname_isequal(name, intr->name))
1.1.1.2 ! misho 1920: {
! 1921: ans = 1;
! 1922: if (!dryrun)
! 1923: {
! 1924:
! 1925: for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
! 1926: #ifdef HAVE_IPV6
! 1927: if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == type)
! 1928: #endif
! 1929: {
! 1930: gotit = 1;
! 1931: log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL);
! 1932: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
! 1933: daemon->local_ttl, NULL, type, C_IN,
! 1934: type == T_A ? "4" : "6", &addrlist->addr))
! 1935: anscount++;
! 1936: }
! 1937: }
! 1938: }
1.1 misho 1939:
1.1.1.2 ! misho 1940: if (!dryrun && !gotit)
! 1941: log_query(F_FORWARD | F_CONFIG | flag | F_NEG, name, NULL, NULL);
! 1942:
! 1943: continue;
1.1 misho 1944: }
1945:
1946: cname_restart:
1.1.1.2 ! misho 1947: if ((crecp = cache_find_by_name(NULL, name, now, flag | F_CNAME | (dryrun ? F_NO_RR : 0))))
1.1 misho 1948: {
1949: int localise = 0;
1950:
1951: /* See if a putative address is on the network from which we recieved
1952: the query, is so we'll filter other answers. */
1953: if (local_addr.s_addr != 0 && option_bool(OPT_LOCALISE) && flag == F_IPV4)
1954: {
1955: struct crec *save = crecp;
1956: do {
1957: if ((crecp->flags & F_HOSTS) &&
1958: is_same_net(*((struct in_addr *)&crecp->addr), local_addr, local_netmask))
1959: {
1960: localise = 1;
1961: break;
1962: }
1963: } while ((crecp = cache_find_by_name(crecp, name, now, flag | F_CNAME)));
1964: crecp = save;
1965: }
1.1.1.2 ! misho 1966:
! 1967: /* If the client asked for DNSSEC and we can't provide RRSIGs, either
! 1968: because we've not doing DNSSEC or the cached answer is signed by negative,
! 1969: don't answer from the cache, forward instead. */
! 1970: if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) && sec_reqd)
! 1971: {
! 1972: if (!option_bool(OPT_DNSSEC_VALID) || ((crecp->flags & F_NEG) && (crecp->flags & F_DNSSECOK)))
! 1973: crecp = NULL;
! 1974: #ifdef HAVE_DNSSEC
! 1975: else if (crecp->flags & F_DNSSECOK)
1.1 misho 1976: {
1.1.1.2 ! misho 1977: /* We're returning validated data, need to return the RRSIG too. */
! 1978: struct crec *rr_crec = NULL;
! 1979: int sigtype = type;
! 1980: /* The signature may have expired even though the data is still in cache,
! 1981: forward instead of answering from cache if so. */
! 1982: int gotsig = 0;
1.1 misho 1983:
1.1.1.2 ! misho 1984: if (crecp->flags & F_CNAME)
! 1985: sigtype = T_CNAME;
1.1 misho 1986:
1.1.1.2 ! misho 1987: while ((rr_crec = cache_find_by_name(rr_crec, name, now, F_DS | F_DNSKEY)))
1.1 misho 1988: {
1.1.1.2 ! misho 1989: if (rr_crec->addr.sig.type_covered == sigtype && rr_crec->uid == C_IN)
! 1990: {
! 1991: char *sigdata = blockdata_retrieve(rr_crec->addr.sig.keydata, rr_crec->addr.sig.keylen, NULL);
! 1992: gotsig = 1;
! 1993:
! 1994: if (!dryrun &&
! 1995: add_resource_record(header, limit, &trunc, nameoffset, &ansp,
! 1996: rr_crec->ttd - now, &nameoffset,
! 1997: T_RRSIG, C_IN, "t", rr_crec->addr.sig.keylen, sigdata))
! 1998: anscount++;
! 1999: }
1.1 misho 2000: }
1.1.1.2 ! misho 2001:
! 2002: if (!gotsig)
! 2003: crecp = NULL;
1.1 misho 2004: }
1.1.1.2 ! misho 2005: #endif
! 2006: }
! 2007:
! 2008: if (crecp)
! 2009: do
! 2010: {
! 2011: /* don't answer wildcard queries with data not from /etc/hosts
! 2012: or DHCP leases */
! 2013: if (qtype == T_ANY && !(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
! 2014: break;
! 2015:
! 2016: if (!(crecp->flags & F_DNSSECOK))
! 2017: sec_data = 0;
! 2018:
! 2019: if (crecp->flags & F_CNAME)
! 2020: {
! 2021: char *cname_target = cache_get_cname_target(crecp);
! 2022:
! 2023: if (!dryrun)
! 2024: {
! 2025: log_query(crecp->flags, name, NULL, record_source(crecp->uid));
! 2026: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
! 2027: crec_ttl(crecp, now), &nameoffset,
! 2028: T_CNAME, C_IN, "d", cname_target))
! 2029: anscount++;
! 2030: }
! 2031:
! 2032: strcpy(name, cname_target);
! 2033: /* check if target interface_name */
! 2034: if (crecp->addr.cname.uid == SRC_INTERFACE)
! 2035: goto intname_restart;
! 2036: else
! 2037: goto cname_restart;
! 2038: }
! 2039:
! 2040: if (crecp->flags & F_NEG)
! 2041: {
! 2042: /* We don't cache NSEC records, so if a DNSSEC-validated negative answer
! 2043: is cached and the client wants DNSSEC, forward rather than answering from the cache */
! 2044: if (!sec_reqd || !(crecp->flags & F_DNSSECOK))
! 2045: {
! 2046: ans = 1;
! 2047: auth = 0;
! 2048: if (crecp->flags & F_NXDOMAIN)
! 2049: nxdomain = 1;
! 2050: if (!dryrun)
! 2051: log_query(crecp->flags, name, NULL, NULL);
! 2052: }
! 2053: }
! 2054: else
! 2055: {
! 2056: /* If we are returning local answers depending on network,
! 2057: filter here. */
! 2058: if (localise &&
! 2059: (crecp->flags & F_HOSTS) &&
! 2060: !is_same_net(*((struct in_addr *)&crecp->addr), local_addr, local_netmask))
! 2061: continue;
! 2062:
! 2063: if (!(crecp->flags & (F_HOSTS | F_DHCP)))
! 2064: auth = 0;
! 2065:
! 2066: ans = 1;
! 2067: if (!dryrun)
! 2068: {
! 2069: log_query(crecp->flags & ~F_REVERSE, name, &crecp->addr.addr,
! 2070: record_source(crecp->uid));
! 2071:
! 2072: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
! 2073: crec_ttl(crecp, now), NULL, type, C_IN,
! 2074: type == T_A ? "4" : "6", &crecp->addr))
! 2075: anscount++;
! 2076: }
! 2077: }
! 2078: } while ((crecp = cache_find_by_name(crecp, name, now, flag | F_CNAME)));
! 2079: }
! 2080: else if (is_name_synthetic(flag, name, &addr))
! 2081: {
! 2082: ans = 1;
! 2083: if (!dryrun)
! 2084: {
! 2085: log_query(F_FORWARD | F_CONFIG | flag, name, &addr, NULL);
! 2086: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
! 2087: daemon->local_ttl, NULL, type, C_IN, type == T_A ? "4" : "6", &addr))
! 2088: anscount++;
! 2089: }
1.1 misho 2090: }
2091: }
2092:
2093: if (qtype == T_CNAME || qtype == T_ANY)
2094: {
2095: if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME)) &&
1.1.1.2 ! misho 2096: (qtype == T_CNAME || (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG | (dryrun ? F_NO_RR : 0)))))
1.1 misho 2097: {
1.1.1.2 ! misho 2098: if (!(crecp->flags & F_DNSSECOK))
! 2099: sec_data = 0;
! 2100:
1.1 misho 2101: ans = 1;
2102: if (!dryrun)
2103: {
2104: log_query(crecp->flags, name, NULL, record_source(crecp->uid));
2105: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
2106: crec_ttl(crecp, now), &nameoffset,
1.1.1.2 ! misho 2107: T_CNAME, C_IN, "d", cache_get_cname_target(crecp)))
1.1 misho 2108: anscount++;
2109: }
2110: }
2111: }
1.1.1.2 ! misho 2112:
1.1 misho 2113: if (qtype == T_MX || qtype == T_ANY)
2114: {
2115: int found = 0;
2116: for (rec = daemon->mxnames; rec; rec = rec->next)
2117: if (!rec->issrv && hostname_isequal(name, rec->name))
2118: {
2119: ans = found = 1;
2120: if (!dryrun)
2121: {
2122: int offset;
2123: log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");
2124: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
2125: &offset, T_MX, C_IN, "sd", rec->weight, rec->target))
2126: {
2127: anscount++;
2128: if (rec->target)
2129: rec->offset = offset;
2130: }
2131: }
2132: }
2133:
2134: if (!found && (option_bool(OPT_SELFMX) || option_bool(OPT_LOCALMX)) &&
1.1.1.2 ! misho 2135: cache_find_by_name(NULL, name, now, F_HOSTS | F_DHCP | F_NO_RR))
1.1 misho 2136: {
2137: ans = 1;
2138: if (!dryrun)
2139: {
2140: log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");
2141: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, NULL,
2142: T_MX, C_IN, "sd", 1,
2143: option_bool(OPT_SELFMX) ? name : daemon->mxtarget))
2144: anscount++;
2145: }
2146: }
2147: }
2148:
2149: if (qtype == T_SRV || qtype == T_ANY)
2150: {
2151: int found = 0;
2152: struct mx_srv_record *move = NULL, **up = &daemon->mxnames;
2153:
2154: for (rec = daemon->mxnames; rec; rec = rec->next)
2155: if (rec->issrv && hostname_isequal(name, rec->name))
2156: {
2157: found = ans = 1;
2158: if (!dryrun)
2159: {
2160: int offset;
2161: log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>");
2162: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
2163: &offset, T_SRV, C_IN, "sssd",
2164: rec->priority, rec->weight, rec->srvport, rec->target))
2165: {
2166: anscount++;
2167: if (rec->target)
2168: rec->offset = offset;
2169: }
2170: }
2171:
2172: /* unlink first SRV record found */
2173: if (!move)
2174: {
2175: move = rec;
2176: *up = rec->next;
2177: }
2178: else
2179: up = &rec->next;
2180: }
2181: else
2182: up = &rec->next;
2183:
2184: /* put first SRV record back at the end. */
2185: if (move)
2186: {
2187: *up = move;
2188: move->next = NULL;
2189: }
2190:
2191: if (!found && option_bool(OPT_FILTER) && (qtype == T_SRV || (qtype == T_ANY && strchr(name, '_'))))
2192: {
2193: ans = 1;
2194: if (!dryrun)
2195: log_query(F_CONFIG | F_NEG, name, NULL, NULL);
2196: }
2197: }
2198:
2199: if (qtype == T_NAPTR || qtype == T_ANY)
2200: {
2201: struct naptr *na;
2202: for (na = daemon->naptr; na; na = na->next)
2203: if (hostname_isequal(name, na->name))
2204: {
2205: ans = 1;
2206: if (!dryrun)
2207: {
2208: log_query(F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>");
2209: if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
2210: NULL, T_NAPTR, C_IN, "sszzzd",
2211: na->order, na->pref, na->flags, na->services, na->regexp, na->replace))
2212: anscount++;
2213: }
2214: }
2215: }
2216:
2217: if (qtype == T_MAILB)
2218: ans = 1, nxdomain = 1;
2219:
2220: if (qtype == T_SOA && option_bool(OPT_FILTER))
2221: {
2222: ans = 1;
2223: if (!dryrun)
2224: log_query(F_CONFIG | F_NEG, name, &addr, NULL);
2225: }
2226: }
2227:
2228: if (!ans)
2229: return 0; /* failed to answer a question */
2230: }
2231:
2232: if (dryrun)
2233: {
2234: dryrun = 0;
2235: goto rerun;
2236: }
2237:
2238: /* create an additional data section, for stuff in SRV and MX record replies. */
2239: for (rec = daemon->mxnames; rec; rec = rec->next)
2240: if (rec->offset != 0)
2241: {
2242: /* squash dupes */
2243: struct mx_srv_record *tmp;
2244: for (tmp = rec->next; tmp; tmp = tmp->next)
2245: if (tmp->offset != 0 && hostname_isequal(rec->target, tmp->target))
2246: tmp->offset = 0;
2247:
2248: crecp = NULL;
2249: while ((crecp = cache_find_by_name(crecp, rec->target, now, F_IPV4 | F_IPV6)))
2250: {
2251: #ifdef HAVE_IPV6
2252: int type = crecp->flags & F_IPV4 ? T_A : T_AAAA;
2253: #else
2254: int type = T_A;
2255: #endif
2256: if (crecp->flags & F_NEG)
2257: continue;
2258:
2259: if (add_resource_record(header, limit, NULL, rec->offset, &ansp,
2260: crec_ttl(crecp, now), NULL, type, C_IN,
2261: crecp->flags & F_IPV4 ? "4" : "6", &crecp->addr))
2262: addncount++;
2263: }
2264: }
2265:
2266: /* done all questions, set up header and return length of result */
2267: /* clear authoritative and truncated flags, set QR flag */
2268: header->hb3 = (header->hb3 & ~(HB3_AA | HB3_TC)) | HB3_QR;
2269: /* set RA flag */
2270: header->hb4 |= HB4_RA;
2271:
2272: /* authoritive - only hosts and DHCP derived names. */
2273: if (auth)
2274: header->hb3 |= HB3_AA;
2275:
2276: /* truncation */
2277: if (trunc)
2278: header->hb3 |= HB3_TC;
1.1.1.2 ! misho 2279:
! 2280: if (nxdomain)
1.1 misho 2281: SET_RCODE(header, NXDOMAIN);
2282: else
2283: SET_RCODE(header, NOERROR); /* no error */
2284: header->ancount = htons(anscount);
2285: header->nscount = htons(0);
2286: header->arcount = htons(addncount);
1.1.1.2 ! misho 2287:
! 2288: len = ansp - (unsigned char *)header;
! 2289:
! 2290: if (have_pseudoheader)
! 2291: len = add_pseudoheader(header, len, (unsigned char *)limit, 0, NULL, 0, sec_reqd);
! 2292:
! 2293: if (*ad_reqd && sec_data)
! 2294: header->hb4 |= HB4_AD;
! 2295: else
! 2296: header->hb4 &= ~HB4_AD;
! 2297:
! 2298: return len;
1.1 misho 2299: }
2300:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>