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