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