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