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