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