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