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