]> git.ipfire.org Git - people/ms/dnsmasq.git/blame - src/rfc1035.c
zero arcount.
[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
4f7b304f
SK
1188int add_resource_record(struct dns_header *header, char *limit, int *truncp, unsigned int nameoffset, unsigned char **pp,
1189 unsigned long ttl, unsigned 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
1203 if (nameoffset != 0)
1204 {
1205 PUTSHORT(nameoffset | 0xc000, p);
1206 }
1207 else
1208 {
1209 p = do_rfc1035_name(p, va_arg(ap, char *));
1210 *p++ = 0;
1211 }
f6b7dc47 1212
f6b7dc47
SK
1213 PUTSHORT(type, p);
1214 PUTSHORT(class, p);
1215 PUTLONG(ttl, p); /* TTL */
1216
1217 sav = p; /* Save pointer to RDLength field */
1218 PUTSHORT(0, p); /* Placeholder RDLength */
1219
f6b7dc47
SK
1220 for (; *format; format++)
1221 switch (*format)
1222 {
1223#ifdef HAVE_IPV6
1224 case '6':
1225 sval = va_arg(ap, char *);
1226 memcpy(p, sval, IN6ADDRSZ);
1227 p += IN6ADDRSZ;
1228 break;
1229#endif
1230
1231 case '4':
1232 sval = va_arg(ap, char *);
1233 memcpy(p, sval, INADDRSZ);
1234 p += INADDRSZ;
1235 break;
1236
1237 case 's':
1238 usval = va_arg(ap, int);
1239 PUTSHORT(usval, p);
1240 break;
1241
1242 case 'l':
1243 lval = va_arg(ap, long);
1244 PUTLONG(lval, p);
1245 break;
1246
1247 case 'd':
1248 /* get domain-name answer arg and store it in RDATA field */
0a852541
SK
1249 if (offset)
1250 *offset = p - (unsigned char *)header;
3d8df260 1251 p = do_rfc1035_name(p, va_arg(ap, char *));
f6b7dc47
SK
1252 *p++ = 0;
1253 break;
3d8df260 1254
f6b7dc47 1255 case 't':
0a852541 1256 usval = va_arg(ap, int);
f6b7dc47 1257 sval = va_arg(ap, char *);
9f7f3b12
SK
1258 if (usval != 0)
1259 memcpy(p, sval, usval);
0a852541 1260 p += usval;
f6b7dc47 1261 break;
1a6bca81
SK
1262
1263 case 'z':
1264 sval = va_arg(ap, char *);
1265 usval = sval ? strlen(sval) : 0;
1266 if (usval > 255)
1267 usval = 255;
1268 *p++ = (unsigned char)usval;
1269 memcpy(p, sval, usval);
1270 p += usval;
1271 break;
f6b7dc47
SK
1272 }
1273
1274 va_end(ap); /* clean up variable argument pointer */
1275
1276 j = p - sav - 2;
1277 PUTSHORT(j, sav); /* Now, store real RDLength */
1278
f6b7dc47
SK
1279 /* check for overflow of buffer */
1280 if (limit && ((unsigned char *)limit - p) < 0)
1281 {
1282 if (truncp)
1283 *truncp = 1;
1284 return 0;
1285 }
1286
1287 *pp = p;
1288 return 1;
1289}
1290
9009d746
SK
1291static unsigned long crec_ttl(struct crec *crecp, time_t now)
1292{
1293 /* Return 0 ttl for DHCP entries, which might change
1294 before the lease expires. */
1295
1296 if (crecp->flags & (F_IMMORTAL | F_DHCP))
1297 return daemon->local_ttl;
1298
8ef5ada2
SK
1299 /* Return the Max TTL value if it is lower then the actual TTL */
1300 if (daemon->max_ttl == 0 || ((unsigned)(crecp->ttd - now) < daemon->max_ttl))
1301 return crecp->ttd - now;
1302 else
1303 return daemon->max_ttl;
9009d746
SK
1304}
1305
1306
9e4abcb5 1307/* return zero if we can't answer from cache, or packet size if we can */
572b41eb 1308size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
cdeda28f 1309 struct in_addr local_addr, struct in_addr local_netmask, time_t now)
9e4abcb5 1310{
3be34541 1311 char *name = daemon->namebuff;
feba5c1d 1312 unsigned char *p, *ansp, *pheader;
832af0ba 1313 int qtype, qclass;
9e4abcb5
SK
1314 struct all_addr addr;
1315 unsigned int nameoffset;
feba5c1d 1316 unsigned short flag;
0a852541 1317 int q, ans, anscount = 0, addncount = 0;
feba5c1d 1318 int dryrun = 0, sec_reqd = 0;
832af0ba 1319 int is_sign;
9e4abcb5 1320 struct crec *crecp;
f6b7dc47 1321 int nxdomain = 0, auth = 1, trunc = 0;
0a852541
SK
1322 struct mx_srv_record *rec;
1323
feba5c1d
SK
1324 /* If there is an RFC2671 pseudoheader then it will be overwritten by
1325 partial replies, so we have to do a dry run to see if we can answer
1326 the query. We check to see if the do bit is set, if so we always
1327 forward rather than answering from the cache, which doesn't include
1328 security information. */
1329
832af0ba 1330 if (find_pseudoheader(header, qlen, NULL, &pheader, &is_sign))
feba5c1d 1331 {
7de060b0 1332 unsigned short udpsz, flags;
feba5c1d
SK
1333 unsigned char *psave = pheader;
1334
1335 GETSHORT(udpsz, pheader);
7de060b0 1336 pheader += 2; /* ext_rcode */
feba5c1d
SK
1337 GETSHORT(flags, pheader);
1338
1339 sec_reqd = flags & 0x8000; /* do bit */
1340
1341 /* If our client is advertising a larger UDP packet size
1342 than we allow, trim it so that we don't get an overlarge
1343 response from upstream */
1344
832af0ba 1345 if (!is_sign && (udpsz > daemon->edns_pktsz))
3be34541 1346 PUTSHORT(daemon->edns_pktsz, psave);
feba5c1d
SK
1347
1348 dryrun = 1;
1349 }
1350
572b41eb 1351 if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY )
832af0ba
SK
1352 return 0;
1353
0a852541
SK
1354 for (rec = daemon->mxnames; rec; rec = rec->next)
1355 rec->offset = 0;
1356
feba5c1d 1357 rerun:
9e4abcb5
SK
1358 /* determine end of question section (we put answers there) */
1359 if (!(ansp = skip_questions(header, qlen)))
1360 return 0; /* bad packet */
1361
1362 /* now process each question, answers go in RRs after the question */
1363 p = (unsigned char *)(header+1);
feba5c1d 1364
5aabfc78 1365 for (q = ntohs(header->qdcount); q != 0; q--)
9e4abcb5
SK
1366 {
1367 /* save pointer to name for copying into answers */
1368 nameoffset = p - (unsigned char *)header;
1369
1370 /* now extract name as .-concatenated string into name */
9009d746 1371 if (!extract_name(header, qlen, &p, name, 1, 4))
9e4abcb5 1372 return 0; /* bad packet */
832af0ba 1373
9e4abcb5
SK
1374 GETSHORT(qtype, p);
1375 GETSHORT(qclass, p);
1376
1377 ans = 0; /* have we answered this question */
1378
0a852541 1379 if (qtype == T_TXT || qtype == T_ANY)
9e4abcb5 1380 {
0a852541
SK
1381 struct txt_record *t;
1382 for(t = daemon->txt; t ; t = t->next)
9e4abcb5 1383 {
0a852541
SK
1384 if (t->class == qclass && hostname_isequal(name, t->name))
1385 {
1386 ans = 1;
e17fb629
SK
1387 if (!dryrun)
1388 {
28866e95 1389 log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
e17fb629
SK
1390 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1391 daemon->local_ttl, NULL,
1392 T_TXT, t->class, "t", t->len, t->txt))
1393 anscount++;
1394
1395 }
0a852541 1396 }
9e4abcb5 1397 }
0a852541 1398 }
f6b7dc47 1399
0a852541 1400 if (qclass == C_IN)
9e4abcb5 1401 {
9f7f3b12
SK
1402 struct txt_record *t;
1403
1404 for (t = daemon->rr; t; t = t->next)
1405 if ((t->class == qtype || qtype == T_ANY) && hostname_isequal(name, t->name))
1406 {
1407 ans = 1;
1408 if (!dryrun)
1409 {
1410 log_query(F_CONFIG | F_RRNAME, name, NULL, "<RR>");
1411 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1412 daemon->local_ttl, NULL,
1413 t->class, C_IN, "t", t->len, t->txt))
1414 anscount ++;
1415 }
1416 }
1417
f6b7dc47 1418 if (qtype == T_PTR || qtype == T_ANY)
c1bb8504 1419 {
832af0ba
SK
1420 /* see if it's w.z.y.z.in-addr.arpa format */
1421 int is_arpa = in_arpa_name_2_addr(name, &addr);
1422 struct ptr_record *ptr;
f2621c7f 1423 struct interface_name* intr = NULL;
832af0ba
SK
1424
1425 for (ptr = daemon->ptr; ptr; ptr = ptr->next)
1426 if (hostname_isequal(name, ptr->name))
1427 break;
1428
f2621c7f
SK
1429 if (is_arpa == F_IPV4)
1430 for (intr = daemon->int_names; intr; intr = intr->next)
5aabfc78
SK
1431 {
1432 if (addr.addr.addr4.s_addr == get_ifaddr(intr->intr).s_addr)
1433 break;
1434 else
1435 while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
1436 intr = intr->next;
1437 }
f2621c7f
SK
1438
1439 if (intr)
1440 {
1441 ans = 1;
1442 if (!dryrun)
f6b7dc47 1443 {
1a6bca81 1444 log_query(F_IPV4 | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
f2621c7f
SK
1445 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1446 daemon->local_ttl, NULL,
1447 T_PTR, C_IN, "d", intr->name))
1448 anscount++;
9e4abcb5 1449 }
9e4abcb5 1450 }
832af0ba
SK
1451 else if (ptr)
1452 {
1453 ans = 1;
1454 if (!dryrun)
1455 {
28866e95 1456 log_query(F_CONFIG | F_RRNAME, name, NULL, "<PTR>");
832af0ba 1457 for (ptr = daemon->ptr; ptr; ptr = ptr->next)
f2621c7f
SK
1458 if (hostname_isequal(name, ptr->name) &&
1459 add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1460 daemon->local_ttl, NULL,
1461 T_PTR, C_IN, "d", ptr->ptr))
1462 anscount++;
1463
1464 }
1465 }
1466 else if ((crecp = cache_find_by_addr(NULL, &addr, now, is_arpa)))
1467 do
1468 {
1469 /* don't answer wildcard queries with data not from /etc/hosts or dhcp leases */
1470 if (qtype == T_ANY && !(crecp->flags & (F_HOSTS | F_DHCP)))
1471 continue;
1472
1473 if (crecp->flags & F_NEG)
1474 {
1475 ans = 1;
1476 auth = 0;
1477 if (crecp->flags & F_NXDOMAIN)
1478 nxdomain = 1;
1479 if (!dryrun)
1a6bca81 1480 log_query(crecp->flags & ~F_FORWARD, name, &addr, NULL);
f2621c7f
SK
1481 }
1482 else if ((crecp->flags & (F_HOSTS | F_DHCP)) || !sec_reqd)
1483 {
1484 ans = 1;
1485 if (!(crecp->flags & (F_HOSTS | F_DHCP)))
1486 auth = 0;
1487 if (!dryrun)
832af0ba 1488 {
1a6bca81 1489 log_query(crecp->flags & ~F_FORWARD, cache_get_name(crecp), &addr,
7622fc06 1490 record_source(crecp->uid));
f2621c7f 1491
9009d746
SK
1492 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1493 crec_ttl(crecp, now), NULL,
f2621c7f 1494 T_PTR, C_IN, "d", cache_get_name(crecp)))
832af0ba
SK
1495 anscount++;
1496 }
f2621c7f
SK
1497 }
1498 } while ((crecp = cache_find_by_addr(crecp, &addr, now, is_arpa)));
1499 else if (is_arpa == F_IPV4 &&
28866e95 1500 option_bool(OPT_BOGUSPRIV) &&
8ef5ada2 1501 private_net(addr.addr.addr4, 1))
f2621c7f
SK
1502 {
1503 /* if not in cache, enabled and private IPV4 address, return NXDOMAIN */
1504 ans = 1;
1505 nxdomain = 1;
1506 if (!dryrun)
1507 log_query(F_CONFIG | F_REVERSE | F_IPV4 | F_NEG | F_NXDOMAIN,
1a6bca81 1508 name, &addr, NULL);
832af0ba 1509 }
f6b7dc47 1510 }
f2621c7f 1511
f6b7dc47
SK
1512 for (flag = F_IPV4; flag; flag = (flag == F_IPV4) ? F_IPV6 : 0)
1513 {
1514 unsigned short type = T_A;
f2621c7f 1515
f6b7dc47 1516 if (flag == F_IPV6)
feba5c1d 1517#ifdef HAVE_IPV6
3d8df260 1518 type = T_AAAA;
feba5c1d 1519#else
3d8df260 1520 break;
feba5c1d 1521#endif
f6b7dc47
SK
1522
1523 if (qtype != type && qtype != T_ANY)
1524 continue;
1525
316e2730
SK
1526 /* Check for "A for A" queries; be rather conservative
1527 about what looks like dotted-quad. */
1528 if (qtype == T_A)
3d8df260 1529 {
316e2730
SK
1530 char *cp;
1531 unsigned int i, a;
1532 int x;
1533
1534 for (cp = name, i = 0, a = 0; *cp; i++)
3d8df260 1535 {
572b41eb 1536 if (!isdigit((unsigned char)*cp) || (x = strtol(cp, &cp, 10)) > 255)
316e2730
SK
1537 {
1538 i = 5;
1539 break;
1540 }
1541
1542 a = (a << 8) + x;
1543
1544 if (*cp == '.')
1545 cp++;
1546 }
1547
1548 if (i == 4)
1549 {
1550 ans = 1;
1551 if (!dryrun)
1552 {
1553 addr.addr.addr4.s_addr = htonl(a);
1554 log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL);
1555 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1556 daemon->local_ttl, NULL, type, C_IN, "4", &addr))
1557 anscount++;
1558 }
1559 continue;
3d8df260 1560 }
3d8df260
SK
1561 }
1562
f2621c7f
SK
1563 /* interface name stuff */
1564 if (qtype == T_A)
1565 {
1566 struct interface_name *intr;
1567
1568 for (intr = daemon->int_names; intr; intr = intr->next)
1569 if (hostname_isequal(name, intr->name))
1570 break;
1571
1572 if (intr)
1573 {
1574 ans = 1;
1575 if (!dryrun)
1576 {
5aabfc78 1577 if ((addr.addr.addr4 = get_ifaddr(intr->intr)).s_addr == (in_addr_t) -1)
1a6bca81 1578 log_query(F_FORWARD | F_CONFIG | F_IPV4 | F_NEG, name, NULL, NULL);
f2621c7f
SK
1579 else
1580 {
1a6bca81 1581 log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL);
f2621c7f
SK
1582 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1583 daemon->local_ttl, NULL, type, C_IN, "4", &addr))
1584 anscount++;
1585 }
1586 }
1587 continue;
1588 }
1589 }
1590
f6b7dc47
SK
1591 cname_restart:
1592 if ((crecp = cache_find_by_name(NULL, name, now, flag | F_CNAME)))
1593 {
1594 int localise = 0;
feba5c1d 1595
f6b7dc47
SK
1596 /* See if a putative address is on the network from which we recieved
1597 the query, is so we'll filter other answers. */
28866e95 1598 if (local_addr.s_addr != 0 && option_bool(OPT_LOCALISE) && flag == F_IPV4)
f6b7dc47
SK
1599 {
1600 struct crec *save = crecp;
1601 do {
1602 if ((crecp->flags & F_HOSTS) &&
1603 is_same_net(*((struct in_addr *)&crecp->addr), local_addr, local_netmask))
1604 {
1605 localise = 1;
1606 break;
1607 }
1608 } while ((crecp = cache_find_by_name(crecp, name, now, flag | F_CNAME)));
1609 crecp = save;
1610 }
1611
1612 do
9e4abcb5 1613 {
26128d27
SK
1614 /* don't answer wildcard queries with data not from /etc/hosts
1615 or DHCP leases */
1616 if (qtype == T_ANY && !(crecp->flags & (F_HOSTS | F_DHCP)))
1617 break;
1618
fd9fa481
SK
1619 if (crecp->flags & F_CNAME)
1620 {
fd9fa481
SK
1621 if (!dryrun)
1622 {
7622fc06 1623 log_query(crecp->flags, name, NULL, record_source(crecp->uid));
9009d746
SK
1624 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1625 crec_ttl(crecp, now), &nameoffset,
f6b7dc47
SK
1626 T_CNAME, C_IN, "d", cache_get_name(crecp->addr.cname.cache)))
1627 anscount++;
fd9fa481 1628 }
f6b7dc47 1629
fd9fa481
SK
1630 strcpy(name, cache_get_name(crecp->addr.cname.cache));
1631 goto cname_restart;
1632 }
f6b7dc47 1633
9e4abcb5
SK
1634 if (crecp->flags & F_NEG)
1635 {
feba5c1d 1636 ans = 1;
f6b7dc47
SK
1637 auth = 0;
1638 if (crecp->flags & F_NXDOMAIN)
1639 nxdomain = 1;
feba5c1d 1640 if (!dryrun)
1a6bca81 1641 log_query(crecp->flags, name, NULL, NULL);
9e4abcb5 1642 }
feba5c1d 1643 else if ((crecp->flags & (F_HOSTS | F_DHCP)) || !sec_reqd)
9e4abcb5 1644 {
f6b7dc47
SK
1645 /* If we are returning local answers depending on network,
1646 filter here. */
1647 if (localise &&
1648 (crecp->flags & F_HOSTS) &&
1649 !is_same_net(*((struct in_addr *)&crecp->addr), local_addr, local_netmask))
1650 continue;
1651
1652 if (!(crecp->flags & (F_HOSTS | F_DHCP)))
1653 auth = 0;
1654
feba5c1d
SK
1655 ans = 1;
1656 if (!dryrun)
1657 {
fd9fa481 1658 log_query(crecp->flags & ~F_REVERSE, name, &crecp->addr.addr,
7622fc06 1659 record_source(crecp->uid));
feba5c1d 1660
9009d746
SK
1661 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1662 crec_ttl(crecp, now), NULL, type, C_IN,
f6b7dc47
SK
1663 type == T_A ? "4" : "6", &crecp->addr))
1664 anscount++;
feba5c1d 1665 }
9e4abcb5 1666 }
f6b7dc47 1667 } while ((crecp = cache_find_by_name(crecp, name, now, flag | F_CNAME)));
9e4abcb5 1668 }
f6b7dc47 1669 }
d1c759c5
SK
1670
1671 if (qtype == T_CNAME || qtype == T_ANY)
1672 {
1673 if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME)) &&
1674 (qtype == T_CNAME || (crecp->flags & (F_HOSTS | F_DHCP))))
1675 {
1676 ans = 1;
1677 if (!dryrun)
1678 {
1679 log_query(crecp->flags, name, NULL, record_source(crecp->uid));
1680 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1681 crec_ttl(crecp, now), &nameoffset,
1682 T_CNAME, C_IN, "d", cache_get_name(crecp->addr.cname.cache)))
1683 anscount++;
1684 }
1685 }
1686 }
f6b7dc47
SK
1687
1688 if (qtype == T_MX || qtype == T_ANY)
1689 {
1690 int found = 0;
0a852541
SK
1691 for (rec = daemon->mxnames; rec; rec = rec->next)
1692 if (!rec->issrv && hostname_isequal(name, rec->name))
f6b7dc47
SK
1693 {
1694 ans = found = 1;
1695 if (!dryrun)
feba5c1d 1696 {
3d8df260 1697 unsigned int offset;
28866e95 1698 log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");
0a852541
SK
1699 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
1700 &offset, T_MX, C_IN, "sd", rec->weight, rec->target))
1701 {
1702 anscount++;
1703 if (rec->target)
1704 rec->offset = offset;
1705 }
feba5c1d 1706 }
f6b7dc47
SK
1707 }
1708
28866e95 1709 if (!found && (option_bool(OPT_SELFMX) || option_bool(OPT_LOCALMX)) &&
f6b7dc47
SK
1710 cache_find_by_name(NULL, name, now, F_HOSTS | F_DHCP))
1711 {
1712 ans = 1;
1713 if (!dryrun)
1714 {
28866e95 1715 log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");
f6b7dc47
SK
1716 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, NULL,
1717 T_MX, C_IN, "sd", 1,
28866e95 1718 option_bool(OPT_SELFMX) ? name : daemon->mxtarget))
f6b7dc47 1719 anscount++;
9e4abcb5
SK
1720 }
1721 }
f6b7dc47
SK
1722 }
1723
1724 if (qtype == T_SRV || qtype == T_ANY)
1725 {
1726 int found = 0;
28866e95
SK
1727 struct mx_srv_record *move = NULL, **up = &daemon->mxnames;
1728
0a852541
SK
1729 for (rec = daemon->mxnames; rec; rec = rec->next)
1730 if (rec->issrv && hostname_isequal(name, rec->name))
f6b7dc47
SK
1731 {
1732 found = ans = 1;
1733 if (!dryrun)
1734 {
3d8df260 1735 unsigned int offset;
28866e95 1736 log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>");
f6b7dc47 1737 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
0a852541
SK
1738 &offset, T_SRV, C_IN, "sssd",
1739 rec->priority, rec->weight, rec->srvport, rec->target))
1740 {
1741 anscount++;
1742 if (rec->target)
1743 rec->offset = offset;
1744 }
f6b7dc47 1745 }
28866e95
SK
1746
1747 /* unlink first SRV record found */
1748 if (!move)
1749 {
1750 move = rec;
1751 *up = rec->next;
1752 }
1753 else
1754 up = &rec->next;
f6b7dc47 1755 }
28866e95
SK
1756 else
1757 up = &rec->next;
1758
1759 /* put first SRV record back at the end. */
1760 if (move)
1761 {
1762 *up = move;
1763 move->next = NULL;
1764 }
feba5c1d 1765
28866e95 1766 if (!found && option_bool(OPT_FILTER) && (qtype == T_SRV || (qtype == T_ANY && strchr(name, '_'))))
f6b7dc47
SK
1767 {
1768 ans = 1;
1769 if (!dryrun)
1a6bca81 1770 log_query(F_CONFIG | F_NEG, name, NULL, NULL);
f6b7dc47
SK
1771 }
1772 }
1a6bca81
SK
1773
1774 if (qtype == T_NAPTR || qtype == T_ANY)
1775 {
1776 struct naptr *na;
1777 for (na = daemon->naptr; na; na = na->next)
1778 if (hostname_isequal(name, na->name))
1779 {
1780 ans = 1;
1781 if (!dryrun)
1782 {
28866e95 1783 log_query(F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>");
1a6bca81
SK
1784 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
1785 NULL, T_NAPTR, C_IN, "sszzzd",
1786 na->order, na->pref, na->flags, na->services, na->regexp, na->replace))
1787 anscount++;
1788 }
1789 }
1790 }
f6b7dc47
SK
1791
1792 if (qtype == T_MAILB)
1793 ans = 1, nxdomain = 1;
1794
28866e95 1795 if (qtype == T_SOA && option_bool(OPT_FILTER))
f6b7dc47
SK
1796 {
1797 ans = 1;
1798 if (!dryrun)
1a6bca81 1799 log_query(F_CONFIG | F_NEG, name, &addr, NULL);
feba5c1d 1800 }
9e4abcb5 1801 }
f6b7dc47
SK
1802
1803 if (!ans)
9e4abcb5 1804 return 0; /* failed to answer a question */
feba5c1d 1805 }
f6b7dc47 1806
feba5c1d
SK
1807 if (dryrun)
1808 {
1809 dryrun = 0;
1810 goto rerun;
9e4abcb5
SK
1811 }
1812
0a852541
SK
1813 /* create an additional data section, for stuff in SRV and MX record replies. */
1814 for (rec = daemon->mxnames; rec; rec = rec->next)
1815 if (rec->offset != 0)
1816 {
1817 /* squash dupes */
1818 struct mx_srv_record *tmp;
1819 for (tmp = rec->next; tmp; tmp = tmp->next)
1820 if (tmp->offset != 0 && hostname_isequal(rec->target, tmp->target))
1821 tmp->offset = 0;
1822
1823 crecp = NULL;
1824 while ((crecp = cache_find_by_name(crecp, rec->target, now, F_IPV4 | F_IPV6)))
1825 {
0a852541
SK
1826#ifdef HAVE_IPV6
1827 int type = crecp->flags & F_IPV4 ? T_A : T_AAAA;
1828#else
1829 int type = T_A;
1830#endif
1831 if (crecp->flags & F_NEG)
1832 continue;
1833
9009d746
SK
1834 if (add_resource_record(header, limit, NULL, rec->offset, &ansp,
1835 crec_ttl(crecp, now), NULL, type, C_IN,
0a852541
SK
1836 crecp->flags & F_IPV4 ? "4" : "6", &crecp->addr))
1837 addncount++;
1838 }
1839 }
1840
9e4abcb5 1841 /* done all questions, set up header and return length of result */
572b41eb
SK
1842 /* clear authoritative and truncated flags, set QR flag */
1843 header->hb3 = (header->hb3 & ~(HB3_AA | HB3_TC)) | HB3_QR;
1844 /* set RA flag */
1845 header->hb4 |= HB4_RA;
1846
1847 /* authoritive - only hosts and DHCP derived names. */
1848 if (auth)
1849 header->hb3 |= HB3_AA;
1850
1851 /* truncation */
1852 if (trunc)
1853 header->hb3 |= HB3_TC;
1854
9e4abcb5 1855 if (anscount == 0 && nxdomain)
572b41eb 1856 SET_RCODE(header, NXDOMAIN);
9e4abcb5 1857 else
572b41eb 1858 SET_RCODE(header, NOERROR); /* no error */
9e4abcb5
SK
1859 header->ancount = htons(anscount);
1860 header->nscount = htons(0);
0a852541 1861 header->arcount = htons(addncount);
9e4abcb5
SK
1862 return ansp - (unsigned char *)header;
1863}
1864