]> git.ipfire.org Git - people/ms/dnsmasq.git/blame - src/rfc1035.c
import of dnsmasq-2.53.tar.gz
[people/ms/dnsmasq.git] / src / rfc1035.c
CommitLineData
316e2730 1/* dnsmasq is Copyright (c) 2000-2010 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
SK
19static int add_resource_record(HEADER *header, char *limit, int *truncp,
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) \
73a08a24 28 (!CHECK_LEN(header, pp, plen, len) ? 0 : (long)((pp) += (len)), 1)
9009d746 29
cdeda28f 30static int extract_name(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++)
220 if (!isdigit((int)*cp))
221 return 0;
222
223 addr[3] = addr[2];
224 addr[2] = addr[1];
225 addr[1] = addr[0];
226 addr[0] = atoi(cp1);
227 }
228
229 return F_IPV4;
230 }
231#ifdef HAVE_IPV6
232 else if (hostname_isequal(penchunk, "ip6") &&
233 (hostname_isequal(lastchunk, "int") || hostname_isequal(lastchunk, "arpa")))
234 {
235 /* IP v6:
236 Address arrives as 0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.ip6.[int|arpa]
237 or \[xfedcba9876543210fedcba9876543210/128].ip6.[int|arpa]
238
239 Note that most of these the various reprentations are obsolete and
240 left-over from the many DNS-for-IPv6 wars. We support all the formats
241 that we can since there is no reason not to.
242 */
243
244 if (*name == '\\' && *(name+1) == '[' &&
245 (*(name+2) == 'x' || *(name+2) == 'X'))
246 {
9e038946 247 for (j = 0, cp1 = name+3; *cp1 && isxdigit((int) *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 {
265 if (*(cp1+1) || !isxdigit((int)*cp1))
266 return 0;
267
268 for (j = sizeof(struct all_addr)-1; j>0; j--)
269 addr[j] = (addr[j] >> 4) | (addr[j-1] << 4);
270 addr[0] = (addr[0] >> 4) | (strtol(cp1, NULL, 16) << 4);
271 }
272
273 return F_IPV6;
274 }
275 }
276#endif
277
278 return 0;
279}
280
9009d746 281static unsigned char *skip_name(unsigned char *ansp, 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
cdeda28f 336static unsigned char *skip_questions(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
cdeda28f 351static unsigned char *skip_section(unsigned char *ansp, int count, 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. */
cdeda28f 374unsigned int questions_crc(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
cdeda28f 416size_t resize_packet(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
832af0ba 440unsigned char *find_pseudoheader(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
456 if (header->opcode == 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
SK
512}
513
514
9e4abcb5 515/* is addr in the non-globally-routed IP space? */
8ef5ada2 516static int private_net(struct in_addr addr, int ban_localhost)
9e4abcb5 517{
f2621c7f
SK
518 in_addr_t ip_addr = ntohl(addr.s_addr);
519
520 return
8ef5ada2 521 (((ip_addr & 0xFF000000) == 0x7F000000) && ban_localhost) /* 127.0.0.0/8 (loopback) */ ||
f2621c7f
SK
522 ((ip_addr & 0xFFFF0000) == 0xC0A80000) /* 192.168.0.0/16 (private) */ ||
523 ((ip_addr & 0xFF000000) == 0x0A000000) /* 10.0.0.0/8 (private) */ ||
524 ((ip_addr & 0xFFF00000) == 0xAC100000) /* 172.16.0.0/12 (private) */ ||
525 ((ip_addr & 0xFFFF0000) == 0xA9FE0000) /* 169.254.0.0/16 (zeroconf) */ ;
9e4abcb5 526}
fd9fa481 527
8ef5ada2 528static unsigned char *do_doctor(unsigned char *p, int count, HEADER *header, size_t qlen, char *name)
824af85b
SK
529{
530 int i, qtype, qclass, rdlen;
531 unsigned long ttl;
532
533 for (i = count; i != 0; i--)
534 {
8ef5ada2
SK
535 if (name && (daemon->options & OPT_LOG))
536 {
537 if (!extract_name(header, qlen, &p, name, 1, 10))
538 return 0;
539 }
540 else if (!(p = skip_name(p, header, qlen, 10)))
824af85b
SK
541 return 0; /* bad packet */
542
543 GETSHORT(qtype, p);
544 GETSHORT(qclass, p);
545 GETLONG(ttl, p);
546 GETSHORT(rdlen, p);
547
8ef5ada2 548 if (qclass == C_IN && qtype == T_A)
824af85b
SK
549 {
550 struct doctor *doctor;
551 struct in_addr addr;
552
9009d746
SK
553 if (!CHECK_LEN(header, p, qlen, INADDRSZ))
554 return 0;
8ef5ada2
SK
555
556 /* alignment */
824af85b
SK
557 memcpy(&addr, p, INADDRSZ);
558
559 for (doctor = daemon->doctors; doctor; doctor = doctor->next)
73a08a24
SK
560 {
561 if (doctor->end.s_addr == 0)
562 {
563 if (!is_same_net(doctor->in, addr, doctor->mask))
564 continue;
565 }
566 else if (ntohl(doctor->in.s_addr) > ntohl(addr.s_addr) ||
567 ntohl(doctor->end.s_addr) < ntohl(addr.s_addr))
568 continue;
8ef5ada2 569
73a08a24
SK
570 addr.s_addr &= ~doctor->mask.s_addr;
571 addr.s_addr |= (doctor->out.s_addr & doctor->mask.s_addr);
572 /* Since we munged the data, the server it came from is no longer authoritative */
573 header->aa = 0;
574 memcpy(p, &addr, INADDRSZ);
575 break;
576 }
824af85b 577 }
8ef5ada2
SK
578 else if (qtype == T_TXT && name && (daemon->options & OPT_LOG))
579 {
580 unsigned char *p1 = p;
581 if (!CHECK_LEN(header, p1, qlen, rdlen))
582 return 0;
583 while ((p1 - p) < rdlen)
584 {
585 unsigned int i, len = *p1;
586 unsigned char *p2 = p1;
587 /* make counted string zero-term and sanitise */
588 for (i = 0; i < len; i++)
589 if (isprint(*(p2+1)))
590 {
591 *p2 = *(p2+1);
592 p2++;
593 }
594 *p2 = 0;
595 my_syslog(LOG_DEBUG, "reply %s is %s", name, p1);
596 /* restore */
597 memmove(p1 + 1, p1, len);
598 *p1 = len;
599 p1 += len+1;
600 }
601 }
824af85b 602
9009d746
SK
603 if (!ADD_RDLEN(header, p, qlen, rdlen))
604 return 0; /* bad packet */
824af85b
SK
605 }
606
607 return p;
608}
609
8ef5ada2 610static int find_soa(HEADER *header, size_t qlen, char *name)
9e4abcb5
SK
611{
612 unsigned char *p;
9e4abcb5 613 int qtype, qclass, rdlen;
fd9fa481
SK
614 unsigned long ttl, minttl = ULONG_MAX;
615 int i, found_soa = 0;
9e4abcb5 616
fd9fa481
SK
617 /* first move to NS section and find TTL from any SOA section */
618 if (!(p = skip_questions(header, qlen)) ||
8ef5ada2 619 !(p = do_doctor(p, ntohs(header->ancount), header, qlen, name)))
824af85b 620 return 0; /* bad packet */
9e4abcb5 621
5aabfc78 622 for (i = ntohs(header->nscount); i != 0; i--)
9e4abcb5 623 {
9009d746 624 if (!(p = skip_name(p, header, qlen, 10)))
fd9fa481
SK
625 return 0; /* bad packet */
626
9e4abcb5
SK
627 GETSHORT(qtype, p);
628 GETSHORT(qclass, p);
629 GETLONG(ttl, p);
630 GETSHORT(rdlen, p);
fd9fa481 631
9e4abcb5
SK
632 if ((qclass == C_IN) && (qtype == T_SOA))
633 {
fd9fa481
SK
634 found_soa = 1;
635 if (ttl < minttl)
636 minttl = ttl;
637
9e4abcb5 638 /* MNAME */
9009d746 639 if (!(p = skip_name(p, header, qlen, 0)))
fd9fa481 640 return 0;
9e4abcb5 641 /* RNAME */
9009d746 642 if (!(p = skip_name(p, header, qlen, 20)))
fd9fa481
SK
643 return 0;
644 p += 16; /* SERIAL REFRESH RETRY EXPIRE */
645
9e4abcb5
SK
646 GETLONG(ttl, p); /* minTTL */
647 if (ttl < minttl)
648 minttl = ttl;
649 }
9009d746 650 else if (!ADD_RDLEN(header, p, qlen, rdlen))
fd9fa481 651 return 0; /* bad packet */
9e4abcb5 652 }
9009d746 653
824af85b 654 /* rewrite addresses in additioal section too */
8ef5ada2 655 if (!do_doctor(p, ntohs(header->arcount), header, qlen, NULL))
824af85b
SK
656 return 0;
657
658 if (!found_soa)
659 minttl = daemon->neg_ttl;
660
661 return minttl;
1cff166d
SK
662}
663
fd9fa481
SK
664/* Note that the following code can create CNAME chains that don't point to a real record,
665 either because of lack of memory, or lack of SOA records. These are treated by the cache code as
824af85b 666 expired and cleaned out that way.
8ef5ada2
SK
667 Return 1 if we reject an address because it look like part of dns-rebinding attack. */
668int extract_addresses(HEADER *header, size_t qlen, char *name, time_t now, int is_sign, int check_rebind)
9e4abcb5 669{
824af85b 670 unsigned char *p, *p1, *endrr, *namep;
fd9fa481 671 int i, j, qtype, qclass, aqtype, aqclass, ardlen, res, searched_soa = 0;
0a852541 672 unsigned long ttl = 0;
5aabfc78 673 struct all_addr addr;
0a852541 674
9e4abcb5 675 cache_start_insert();
0a852541 676
8ef5ada2
SK
677 /* find_soa is needed for dns_doctor and logging side-effects, so don't call it lazily if there are any. */
678 if (daemon->doctors || (daemon->options & OPT_LOG))
0a852541
SK
679 {
680 searched_soa = 1;
8ef5ada2 681 ttl = find_soa(header, qlen, name);
0a852541 682 }
9e4abcb5 683
fd9fa481
SK
684 /* go through the questions. */
685 p = (unsigned char *)(header+1);
9e4abcb5 686
5aabfc78 687 for (i = ntohs(header->qdcount); i != 0; i--)
9e4abcb5 688 {
fd9fa481
SK
689 int found = 0, cname_count = 5;
690 struct crec *cpp = NULL;
691 int flags = header->rcode == NXDOMAIN ? F_NXDOMAIN : 0;
0a852541 692 unsigned long cttl = ULONG_MAX, attl;
fd9fa481 693
824af85b 694 namep = p;
9009d746 695 if (!extract_name(header, qlen, &p, name, 1, 4))
824af85b 696 return 0; /* bad packet */
fd9fa481 697
9e4abcb5
SK
698 GETSHORT(qtype, p);
699 GETSHORT(qclass, p);
9e4abcb5
SK
700
701 if (qclass != C_IN)
fd9fa481 702 continue;
9e4abcb5 703
fd9fa481
SK
704 /* PTRs: we chase CNAMEs here, since we have no way to
705 represent them in the cache. */
706 if (qtype == T_PTR)
707 {
9e4abcb5 708 int name_encoding = in_arpa_name_2_addr(name, &addr);
fd9fa481
SK
709
710 if (!name_encoding)
711 continue;
712
713 if (!(flags & F_NXDOMAIN))
9e4abcb5 714 {
fd9fa481
SK
715 cname_loop:
716 if (!(p1 = skip_questions(header, qlen)))
824af85b 717 return 0;
fd9fa481 718
5aabfc78 719 for (j = ntohs(header->ancount); j != 0; j--)
fd9fa481 720 {
824af85b
SK
721 unsigned char *tmp = namep;
722 /* the loop body overwrites the original name, so get it back here. */
9009d746
SK
723 if (!extract_name(header, qlen, &tmp, name, 1, 0) ||
724 !(res = extract_name(header, qlen, &p1, name, 0, 10)))
824af85b 725 return 0; /* bad packet */
fd9fa481
SK
726
727 GETSHORT(aqtype, p1);
728 GETSHORT(aqclass, p1);
729 GETLONG(attl, p1);
8ef5ada2
SK
730 if ((daemon->max_ttl != 0) && (attl > daemon->max_ttl) && !is_sign)
731 {
732 (p1) -= NS_INT32SZ;
733 PUTLONG(daemon->max_ttl, p1);
734 }
fd9fa481
SK
735 GETSHORT(ardlen, p1);
736 endrr = p1+ardlen;
737
738 /* TTL of record is minimum of CNAMES and PTR */
739 if (attl < cttl)
740 cttl = attl;
741
742 if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == T_PTR))
743 {
9009d746 744 if (!extract_name(header, qlen, &p1, name, 1, 0))
824af85b 745 return 0;
fd9fa481
SK
746
747 if (aqtype == T_CNAME)
748 {
749 if (!cname_count--)
824af85b 750 return 0; /* looped CNAMES */
fd9fa481
SK
751 goto cname_loop;
752 }
753
754 cache_insert(name, &addr, now, cttl, name_encoding | F_REVERSE);
755 found = 1;
756 }
757
758 p1 = endrr;
9009d746 759 if (!CHECK_LEN(header, p1, qlen, 0))
824af85b 760 return 0; /* bad packet */
fd9fa481
SK
761 }
762 }
763
764 if (!found && !(daemon->options & OPT_NO_NEG))
765 {
766 if (!searched_soa)
767 {
768 searched_soa = 1;
8ef5ada2 769 ttl = find_soa(header, qlen, NULL);
fd9fa481
SK
770 }
771 if (ttl)
5aabfc78 772 cache_insert(NULL, &addr, now, ttl, name_encoding | F_REVERSE | F_NEG | flags);
9e4abcb5
SK
773 }
774 }
fd9fa481 775 else
9e4abcb5 776 {
fd9fa481
SK
777 /* everything other than PTR */
778 struct crec *newc;
5aabfc78
SK
779 int addrlen;
780
fd9fa481 781 if (qtype == T_A)
5aabfc78
SK
782 {
783 addrlen = INADDRSZ;
784 flags |= F_IPV4;
785 }
fd9fa481
SK
786#ifdef HAVE_IPV6
787 else if (qtype == T_AAAA)
5aabfc78
SK
788 {
789 addrlen = IN6ADDRSZ;
790 flags |= F_IPV6;
791 }
fd9fa481
SK
792#endif
793 else
794 continue;
795
796 if (!(flags & F_NXDOMAIN))
9e4abcb5 797 {
fd9fa481
SK
798 cname_loop1:
799 if (!(p1 = skip_questions(header, qlen)))
824af85b 800 return 0;
9e4abcb5 801
5aabfc78 802 for (j = ntohs(header->ancount); j != 0; j--)
9e4abcb5 803 {
9009d746 804 if (!(res = extract_name(header, qlen, &p1, name, 0, 10)))
824af85b 805 return 0; /* bad packet */
fd9fa481
SK
806
807 GETSHORT(aqtype, p1);
808 GETSHORT(aqclass, p1);
809 GETLONG(attl, p1);
8ef5ada2
SK
810 if ((daemon->max_ttl != 0) && (attl > daemon->max_ttl) && !is_sign)
811 {
812 (p1) -= NS_INT32SZ;
813 PUTLONG(daemon->max_ttl, p1);
814 }
fd9fa481
SK
815 GETSHORT(ardlen, p1);
816 endrr = p1+ardlen;
817
818 if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == qtype))
819 {
820 if (aqtype == T_CNAME)
821 {
822 if (!cname_count--)
824af85b 823 return 0; /* looped CNAMES */
fd9fa481 824 newc = cache_insert(name, NULL, now, attl, F_CNAME | F_FORWARD);
26128d27 825 if (newc && cpp)
fd9fa481
SK
826 {
827 cpp->addr.cname.cache = newc;
828 cpp->addr.cname.uid = newc->uid;
829 }
9e4abcb5 830
fd9fa481
SK
831 cpp = newc;
832 if (attl < cttl)
833 cttl = attl;
834
9009d746 835 if (!extract_name(header, qlen, &p1, name, 1, 0))
824af85b 836 return 0;
fd9fa481
SK
837 goto cname_loop1;
838 }
839 else
840 {
841 found = 1;
9009d746 842
5aabfc78 843 /* copy address into aligned storage */
9009d746
SK
844 if (!CHECK_LEN(header, p1, qlen, addrlen))
845 return 0; /* bad packet */
5aabfc78 846 memcpy(&addr, p1, addrlen);
824af85b
SK
847
848 /* check for returned address in private space */
8ef5ada2 849 if (check_rebind &&
824af85b 850 (flags & F_IPV4) &&
8ef5ada2 851 private_net(addr.addr.addr4, !(daemon->options & OPT_LOCAL_REBIND)))
824af85b
SK
852 return 1;
853
5aabfc78 854 newc = cache_insert(name, &addr, now, attl, flags | F_FORWARD);
26128d27 855 if (newc && cpp)
fd9fa481
SK
856 {
857 cpp->addr.cname.cache = newc;
858 cpp->addr.cname.uid = newc->uid;
859 }
860 cpp = NULL;
861 }
862 }
863
864 p1 = endrr;
9009d746 865 if (!CHECK_LEN(header, p1, qlen, 0))
824af85b 866 return 0; /* bad packet */
fd9fa481
SK
867 }
868 }
869
870 if (!found && !(daemon->options & OPT_NO_NEG))
871 {
872 if (!searched_soa)
1cff166d 873 {
fd9fa481 874 searched_soa = 1;
8ef5ada2 875 ttl = find_soa(header, qlen, NULL);
1cff166d 876 }
fd9fa481 877 /* If there's no SOA to get the TTL from, but there is a CNAME
824af85b 878 pointing at this, inherit its TTL */
fd9fa481 879 if (ttl || cpp)
9e4abcb5 880 {
5aabfc78 881 newc = cache_insert(name, NULL, now, ttl ? ttl : cttl, F_FORWARD | F_NEG | flags);
26128d27 882 if (newc && cpp)
9e4abcb5 883 {
fd9fa481
SK
884 cpp->addr.cname.cache = newc;
885 cpp->addr.cname.uid = newc->uid;
886 }
9e4abcb5 887 }
9e4abcb5 888 }
fd9fa481 889 }
9e4abcb5 890 }
fd9fa481 891
824af85b
SK
892 /* Don't put stuff from a truncated packet into the cache, but do everything else */
893 if (!header->tc)
894 cache_end_insert();
895
896 return 0;
9e4abcb5
SK
897}
898
899/* If the packet holds exactly one query
832af0ba
SK
900 return F_IPV4 or F_IPV6 and leave the name from the query in name.
901 Abuse F_BIGNAME to indicate an NS query - yuck. */
9e4abcb5 902
cdeda28f 903unsigned short extract_request(HEADER *header, size_t qlen, char *name, unsigned short *typep)
9e4abcb5
SK
904{
905 unsigned char *p = (unsigned char *)(header+1);
906 int qtype, qclass;
907
c1bb8504
SK
908 if (typep)
909 *typep = 0;
910
9e4abcb5
SK
911 if (ntohs(header->qdcount) != 1 || header->opcode != QUERY)
912 return 0; /* must be exactly one query. */
913
9009d746 914 if (!extract_name(header, qlen, &p, name, 1, 4))
9e4abcb5
SK
915 return 0; /* bad packet */
916
917 GETSHORT(qtype, p);
918 GETSHORT(qclass, p);
919
0a852541
SK
920 if (typep)
921 *typep = qtype;
922
9e4abcb5
SK
923 if (qclass == C_IN)
924 {
925 if (qtype == T_A)
926 return F_IPV4;
927 if (qtype == T_AAAA)
928 return F_IPV6;
929 if (qtype == T_ANY)
930 return F_IPV4 | F_IPV6;
832af0ba
SK
931 if (qtype == T_NS || qtype == T_SOA)
932 return F_QUERY | F_BIGNAME;
9e4abcb5
SK
933 }
934
935 return F_QUERY;
936}
937
938
cdeda28f 939size_t setup_reply(HEADER *header, size_t qlen,
9e4abcb5
SK
940 struct all_addr *addrp, unsigned short flags, unsigned long ttl)
941{
942 unsigned char *p = skip_questions(header, qlen);
943
944 header->qr = 1; /* response */
945 header->aa = 0; /* authoritive */
946 header->ra = 1; /* recursion if available */
947 header->tc = 0; /* not truncated */
948 header->nscount = htons(0);
949 header->arcount = htons(0);
feba5c1d 950 header->ancount = htons(0); /* no answers unless changed below */
9e4abcb5
SK
951 if (flags == F_NEG)
952 header->rcode = SERVFAIL; /* couldn't get memory */
824af85b 953 else if (flags == F_NOERR)
9e4abcb5
SK
954 header->rcode = NOERROR; /* empty domain */
955 else if (flags == F_NXDOMAIN)
956 header->rcode = NXDOMAIN;
957 else if (p && flags == F_IPV4)
958 { /* we know the address */
959 header->rcode = NOERROR;
960 header->ancount = htons(1);
961 header->aa = 1;
f6b7dc47 962 add_resource_record(header, NULL, NULL, sizeof(HEADER), &p, ttl, NULL, T_A, C_IN, "4", addrp);
9e4abcb5
SK
963 }
964#ifdef HAVE_IPV6
965 else if (p && flags == F_IPV6)
966 {
967 header->rcode = NOERROR;
968 header->ancount = htons(1);
969 header->aa = 1;
f6b7dc47 970 add_resource_record(header, NULL, NULL, sizeof(HEADER), &p, ttl, NULL, T_AAAA, C_IN, "6", addrp);
9e4abcb5
SK
971 }
972#endif
973 else /* nowhere to forward to */
974 header->rcode = REFUSED;
975
976 return p - (unsigned char *)header;
977}
36717eee
SK
978
979/* check if name matches local names ie from /etc/hosts or DHCP or local mx names. */
5aabfc78 980int check_for_local_domain(char *name, time_t now)
36717eee
SK
981{
982 struct crec *crecp;
0a852541
SK
983 struct mx_srv_record *mx;
984 struct txt_record *txt;
f2621c7f
SK
985 struct interface_name *intr;
986 struct ptr_record *ptr;
987
26128d27 988 if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6)) &&
36717eee
SK
989 (crecp->flags & (F_HOSTS | F_DHCP)))
990 return 1;
991
f6b7dc47 992 for (mx = daemon->mxnames; mx; mx = mx->next)
0a852541 993 if (hostname_isequal(name, mx->name))
36717eee 994 return 1;
f6b7dc47 995
0a852541
SK
996 for (txt = daemon->txt; txt; txt = txt->next)
997 if (hostname_isequal(name, txt->name))
f6b7dc47 998 return 1;
f2621c7f
SK
999
1000 for (intr = daemon->int_names; intr; intr = intr->next)
1001 if (hostname_isequal(name, intr->name))
1002 return 1;
1003
1004 for (ptr = daemon->ptr; ptr; ptr = ptr->next)
1005 if (hostname_isequal(name, ptr->name))
1006 return 1;
1007
36717eee
SK
1008 return 0;
1009}
9e4abcb5
SK
1010
1011/* Is the packet a reply with the answer address equal to addr?
1012 If so mung is into an NXDOMAIN reply and also put that information
1013 in the cache. */
cdeda28f 1014int check_for_bogus_wildcard(HEADER *header, size_t qlen, char *name,
9e4abcb5
SK
1015 struct bogus_addr *baddr, time_t now)
1016{
1017 unsigned char *p;
1018 int i, qtype, qclass, rdlen;
1019 unsigned long ttl;
1020 struct bogus_addr *baddrp;
1021
1022 /* skip over questions */
1023 if (!(p = skip_questions(header, qlen)))
1024 return 0; /* bad packet */
1025
5aabfc78 1026 for (i = ntohs(header->ancount); i != 0; i--)
9e4abcb5 1027 {
9009d746 1028 if (!extract_name(header, qlen, &p, name, 1, 10))
9e4abcb5
SK
1029 return 0; /* bad packet */
1030
1031 GETSHORT(qtype, p);
1032 GETSHORT(qclass, p);
1033 GETLONG(ttl, p);
1034 GETSHORT(rdlen, p);
1035
1036 if (qclass == C_IN && qtype == T_A)
9009d746
SK
1037 {
1038 if (!CHECK_LEN(header, p, qlen, INADDRSZ))
1039 return 0;
1040
1041 for (baddrp = baddr; baddrp; baddrp = baddrp->next)
1042 if (memcmp(&baddrp->addr, p, INADDRSZ) == 0)
1043 {
1044 /* Found a bogus address. Insert that info here, since there no SOA record
1045 to get the ttl from in the normal processing */
1046 cache_start_insert();
1047 cache_insert(name, NULL, now, ttl, F_IPV4 | F_FORWARD | F_NEG | F_NXDOMAIN | F_CONFIG);
1048 cache_end_insert();
1049
1050 return 1;
1051 }
1052 }
9e4abcb5 1053
9009d746
SK
1054 if (!ADD_RDLEN(header, p, qlen, rdlen))
1055 return 0;
9e4abcb5
SK
1056 }
1057
1058 return 0;
1059}
1060
f6b7dc47 1061static int add_resource_record(HEADER *header, char *limit, int *truncp, unsigned int nameoffset, unsigned char **pp,
3d8df260 1062 unsigned long ttl, unsigned int *offset, unsigned short type, unsigned short class, char *format, ...)
f6b7dc47
SK
1063{
1064 va_list ap;
1065 unsigned char *sav, *p = *pp;
1066 int j;
1067 unsigned short usval;
1068 long lval;
1069 char *sval;
1070
1071 if (truncp && *truncp)
1072 return 0;
1073
1074 PUTSHORT(nameoffset | 0xc000, p);
1075 PUTSHORT(type, p);
1076 PUTSHORT(class, p);
1077 PUTLONG(ttl, p); /* TTL */
1078
1079 sav = p; /* Save pointer to RDLength field */
1080 PUTSHORT(0, p); /* Placeholder RDLength */
1081
1082 va_start(ap, format); /* make ap point to 1st unamed argument */
1083
1084 for (; *format; format++)
1085 switch (*format)
1086 {
1087#ifdef HAVE_IPV6
1088 case '6':
1089 sval = va_arg(ap, char *);
1090 memcpy(p, sval, IN6ADDRSZ);
1091 p += IN6ADDRSZ;
1092 break;
1093#endif
1094
1095 case '4':
1096 sval = va_arg(ap, char *);
1097 memcpy(p, sval, INADDRSZ);
1098 p += INADDRSZ;
1099 break;
1100
1101 case 's':
1102 usval = va_arg(ap, int);
1103 PUTSHORT(usval, p);
1104 break;
1105
1106 case 'l':
1107 lval = va_arg(ap, long);
1108 PUTLONG(lval, p);
1109 break;
1110
1111 case 'd':
1112 /* get domain-name answer arg and store it in RDATA field */
0a852541
SK
1113 if (offset)
1114 *offset = p - (unsigned char *)header;
3d8df260 1115 p = do_rfc1035_name(p, va_arg(ap, char *));
f6b7dc47
SK
1116 *p++ = 0;
1117 break;
3d8df260 1118
f6b7dc47 1119 case 't':
0a852541 1120 usval = va_arg(ap, int);
f6b7dc47 1121 sval = va_arg(ap, char *);
0a852541
SK
1122 memcpy(p, sval, usval);
1123 p += usval;
f6b7dc47 1124 break;
1a6bca81
SK
1125
1126 case 'z':
1127 sval = va_arg(ap, char *);
1128 usval = sval ? strlen(sval) : 0;
1129 if (usval > 255)
1130 usval = 255;
1131 *p++ = (unsigned char)usval;
1132 memcpy(p, sval, usval);
1133 p += usval;
1134 break;
f6b7dc47
SK
1135 }
1136
1137 va_end(ap); /* clean up variable argument pointer */
1138
1139 j = p - sav - 2;
1140 PUTSHORT(j, sav); /* Now, store real RDLength */
1141
f6b7dc47
SK
1142 /* check for overflow of buffer */
1143 if (limit && ((unsigned char *)limit - p) < 0)
1144 {
1145 if (truncp)
1146 *truncp = 1;
1147 return 0;
1148 }
1149
1150 *pp = p;
1151 return 1;
1152}
1153
9009d746
SK
1154static unsigned long crec_ttl(struct crec *crecp, time_t now)
1155{
1156 /* Return 0 ttl for DHCP entries, which might change
1157 before the lease expires. */
1158
1159 if (crecp->flags & (F_IMMORTAL | F_DHCP))
1160 return daemon->local_ttl;
1161
8ef5ada2
SK
1162 /* Return the Max TTL value if it is lower then the actual TTL */
1163 if (daemon->max_ttl == 0 || ((unsigned)(crecp->ttd - now) < daemon->max_ttl))
1164 return crecp->ttd - now;
1165 else
1166 return daemon->max_ttl;
9009d746
SK
1167}
1168
1169
9e4abcb5 1170/* return zero if we can't answer from cache, or packet size if we can */
5aabfc78 1171size_t answer_request(HEADER *header, char *limit, size_t qlen,
cdeda28f 1172 struct in_addr local_addr, struct in_addr local_netmask, time_t now)
9e4abcb5 1173{
3be34541 1174 char *name = daemon->namebuff;
feba5c1d 1175 unsigned char *p, *ansp, *pheader;
832af0ba 1176 int qtype, qclass;
9e4abcb5
SK
1177 struct all_addr addr;
1178 unsigned int nameoffset;
feba5c1d 1179 unsigned short flag;
0a852541 1180 int q, ans, anscount = 0, addncount = 0;
feba5c1d 1181 int dryrun = 0, sec_reqd = 0;
832af0ba 1182 int is_sign;
9e4abcb5 1183 struct crec *crecp;
f6b7dc47 1184 int nxdomain = 0, auth = 1, trunc = 0;
0a852541
SK
1185 struct mx_srv_record *rec;
1186
feba5c1d
SK
1187 /* If there is an RFC2671 pseudoheader then it will be overwritten by
1188 partial replies, so we have to do a dry run to see if we can answer
1189 the query. We check to see if the do bit is set, if so we always
1190 forward rather than answering from the cache, which doesn't include
1191 security information. */
1192
832af0ba 1193 if (find_pseudoheader(header, qlen, NULL, &pheader, &is_sign))
feba5c1d
SK
1194 {
1195 unsigned short udpsz, ext_rcode, flags;
1196 unsigned char *psave = pheader;
1197
1198 GETSHORT(udpsz, pheader);
1199 GETSHORT(ext_rcode, pheader);
1200 GETSHORT(flags, pheader);
1201
1202 sec_reqd = flags & 0x8000; /* do bit */
1203
1204 /* If our client is advertising a larger UDP packet size
1205 than we allow, trim it so that we don't get an overlarge
1206 response from upstream */
1207
832af0ba 1208 if (!is_sign && (udpsz > daemon->edns_pktsz))
3be34541 1209 PUTSHORT(daemon->edns_pktsz, psave);
feba5c1d
SK
1210
1211 dryrun = 1;
1212 }
1213
5aabfc78 1214 if (ntohs(header->qdcount) == 0 || header->opcode != QUERY )
832af0ba
SK
1215 return 0;
1216
0a852541
SK
1217 for (rec = daemon->mxnames; rec; rec = rec->next)
1218 rec->offset = 0;
1219
feba5c1d 1220 rerun:
9e4abcb5
SK
1221 /* determine end of question section (we put answers there) */
1222 if (!(ansp = skip_questions(header, qlen)))
1223 return 0; /* bad packet */
1224
1225 /* now process each question, answers go in RRs after the question */
1226 p = (unsigned char *)(header+1);
feba5c1d 1227
5aabfc78 1228 for (q = ntohs(header->qdcount); q != 0; q--)
9e4abcb5
SK
1229 {
1230 /* save pointer to name for copying into answers */
1231 nameoffset = p - (unsigned char *)header;
1232
1233 /* now extract name as .-concatenated string into name */
9009d746 1234 if (!extract_name(header, qlen, &p, name, 1, 4))
9e4abcb5 1235 return 0; /* bad packet */
832af0ba 1236
9e4abcb5
SK
1237 GETSHORT(qtype, p);
1238 GETSHORT(qclass, p);
1239
1240 ans = 0; /* have we answered this question */
1241
0a852541 1242 if (qtype == T_TXT || qtype == T_ANY)
9e4abcb5 1243 {
0a852541
SK
1244 struct txt_record *t;
1245 for(t = daemon->txt; t ; t = t->next)
9e4abcb5 1246 {
0a852541
SK
1247 if (t->class == qclass && hostname_isequal(name, t->name))
1248 {
1249 ans = 1;
e17fb629
SK
1250 if (!dryrun)
1251 {
1a6bca81 1252 log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL, "<TXT>");
e17fb629
SK
1253 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1254 daemon->local_ttl, NULL,
1255 T_TXT, t->class, "t", t->len, t->txt))
1256 anscount++;
1257
1258 }
0a852541 1259 }
9e4abcb5 1260 }
0a852541 1261 }
f6b7dc47 1262
0a852541 1263 if (qclass == C_IN)
9e4abcb5 1264 {
f6b7dc47 1265 if (qtype == T_PTR || qtype == T_ANY)
c1bb8504 1266 {
832af0ba
SK
1267 /* see if it's w.z.y.z.in-addr.arpa format */
1268 int is_arpa = in_arpa_name_2_addr(name, &addr);
1269 struct ptr_record *ptr;
f2621c7f 1270 struct interface_name* intr = NULL;
832af0ba
SK
1271
1272 for (ptr = daemon->ptr; ptr; ptr = ptr->next)
1273 if (hostname_isequal(name, ptr->name))
1274 break;
1275
f2621c7f
SK
1276 if (is_arpa == F_IPV4)
1277 for (intr = daemon->int_names; intr; intr = intr->next)
5aabfc78
SK
1278 {
1279 if (addr.addr.addr4.s_addr == get_ifaddr(intr->intr).s_addr)
1280 break;
1281 else
1282 while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
1283 intr = intr->next;
1284 }
f2621c7f
SK
1285
1286 if (intr)
1287 {
1288 ans = 1;
1289 if (!dryrun)
f6b7dc47 1290 {
1a6bca81 1291 log_query(F_IPV4 | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
f2621c7f
SK
1292 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1293 daemon->local_ttl, NULL,
1294 T_PTR, C_IN, "d", intr->name))
1295 anscount++;
9e4abcb5 1296 }
9e4abcb5 1297 }
832af0ba
SK
1298 else if (ptr)
1299 {
1300 ans = 1;
1301 if (!dryrun)
1302 {
1a6bca81 1303 log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL, "<PTR>");
832af0ba 1304 for (ptr = daemon->ptr; ptr; ptr = ptr->next)
f2621c7f
SK
1305 if (hostname_isequal(name, ptr->name) &&
1306 add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1307 daemon->local_ttl, NULL,
1308 T_PTR, C_IN, "d", ptr->ptr))
1309 anscount++;
1310
1311 }
1312 }
1313 else if ((crecp = cache_find_by_addr(NULL, &addr, now, is_arpa)))
1314 do
1315 {
1316 /* don't answer wildcard queries with data not from /etc/hosts or dhcp leases */
1317 if (qtype == T_ANY && !(crecp->flags & (F_HOSTS | F_DHCP)))
1318 continue;
1319
1320 if (crecp->flags & F_NEG)
1321 {
1322 ans = 1;
1323 auth = 0;
1324 if (crecp->flags & F_NXDOMAIN)
1325 nxdomain = 1;
1326 if (!dryrun)
1a6bca81 1327 log_query(crecp->flags & ~F_FORWARD, name, &addr, NULL);
f2621c7f
SK
1328 }
1329 else if ((crecp->flags & (F_HOSTS | F_DHCP)) || !sec_reqd)
1330 {
1331 ans = 1;
1332 if (!(crecp->flags & (F_HOSTS | F_DHCP)))
1333 auth = 0;
1334 if (!dryrun)
832af0ba 1335 {
1a6bca81 1336 log_query(crecp->flags & ~F_FORWARD, cache_get_name(crecp), &addr,
7622fc06 1337 record_source(crecp->uid));
f2621c7f 1338
9009d746
SK
1339 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1340 crec_ttl(crecp, now), NULL,
f2621c7f 1341 T_PTR, C_IN, "d", cache_get_name(crecp)))
832af0ba
SK
1342 anscount++;
1343 }
f2621c7f
SK
1344 }
1345 } while ((crecp = cache_find_by_addr(crecp, &addr, now, is_arpa)));
1346 else if (is_arpa == F_IPV4 &&
1347 (daemon->options & OPT_BOGUSPRIV) &&
8ef5ada2 1348 private_net(addr.addr.addr4, 1))
f2621c7f
SK
1349 {
1350 /* if not in cache, enabled and private IPV4 address, return NXDOMAIN */
1351 ans = 1;
1352 nxdomain = 1;
1353 if (!dryrun)
1354 log_query(F_CONFIG | F_REVERSE | F_IPV4 | F_NEG | F_NXDOMAIN,
1a6bca81 1355 name, &addr, NULL);
832af0ba 1356 }
f6b7dc47 1357 }
f2621c7f 1358
f6b7dc47
SK
1359 for (flag = F_IPV4; flag; flag = (flag == F_IPV4) ? F_IPV6 : 0)
1360 {
1361 unsigned short type = T_A;
f2621c7f 1362
f6b7dc47 1363 if (flag == F_IPV6)
feba5c1d 1364#ifdef HAVE_IPV6
3d8df260 1365 type = T_AAAA;
feba5c1d 1366#else
3d8df260 1367 break;
feba5c1d 1368#endif
f6b7dc47
SK
1369
1370 if (qtype != type && qtype != T_ANY)
1371 continue;
1372
316e2730
SK
1373 /* Check for "A for A" queries; be rather conservative
1374 about what looks like dotted-quad. */
1375 if (qtype == T_A)
3d8df260 1376 {
316e2730
SK
1377 char *cp;
1378 unsigned int i, a;
1379 int x;
1380
1381 for (cp = name, i = 0, a = 0; *cp; i++)
3d8df260 1382 {
316e2730
SK
1383 if (!isdigit(*cp) || (x = strtol(cp, &cp, 10)) > 255)
1384 {
1385 i = 5;
1386 break;
1387 }
1388
1389 a = (a << 8) + x;
1390
1391 if (*cp == '.')
1392 cp++;
1393 }
1394
1395 if (i == 4)
1396 {
1397 ans = 1;
1398 if (!dryrun)
1399 {
1400 addr.addr.addr4.s_addr = htonl(a);
1401 log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL);
1402 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1403 daemon->local_ttl, NULL, type, C_IN, "4", &addr))
1404 anscount++;
1405 }
1406 continue;
3d8df260 1407 }
3d8df260
SK
1408 }
1409
f2621c7f
SK
1410 /* interface name stuff */
1411 if (qtype == T_A)
1412 {
1413 struct interface_name *intr;
1414
1415 for (intr = daemon->int_names; intr; intr = intr->next)
1416 if (hostname_isequal(name, intr->name))
1417 break;
1418
1419 if (intr)
1420 {
1421 ans = 1;
1422 if (!dryrun)
1423 {
5aabfc78 1424 if ((addr.addr.addr4 = get_ifaddr(intr->intr)).s_addr == (in_addr_t) -1)
1a6bca81 1425 log_query(F_FORWARD | F_CONFIG | F_IPV4 | F_NEG, name, NULL, NULL);
f2621c7f
SK
1426 else
1427 {
1a6bca81 1428 log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL);
f2621c7f
SK
1429 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1430 daemon->local_ttl, NULL, type, C_IN, "4", &addr))
1431 anscount++;
1432 }
1433 }
1434 continue;
1435 }
1436 }
1437
f6b7dc47
SK
1438 cname_restart:
1439 if ((crecp = cache_find_by_name(NULL, name, now, flag | F_CNAME)))
1440 {
1441 int localise = 0;
feba5c1d 1442
f6b7dc47
SK
1443 /* See if a putative address is on the network from which we recieved
1444 the query, is so we'll filter other answers. */
1445 if (local_addr.s_addr != 0 && (daemon->options & OPT_LOCALISE) && flag == F_IPV4)
1446 {
1447 struct crec *save = crecp;
1448 do {
1449 if ((crecp->flags & F_HOSTS) &&
1450 is_same_net(*((struct in_addr *)&crecp->addr), local_addr, local_netmask))
1451 {
1452 localise = 1;
1453 break;
1454 }
1455 } while ((crecp = cache_find_by_name(crecp, name, now, flag | F_CNAME)));
1456 crecp = save;
1457 }
1458
1459 do
9e4abcb5 1460 {
26128d27
SK
1461 /* don't answer wildcard queries with data not from /etc/hosts
1462 or DHCP leases */
1463 if (qtype == T_ANY && !(crecp->flags & (F_HOSTS | F_DHCP)))
1464 break;
1465
fd9fa481
SK
1466 if (crecp->flags & F_CNAME)
1467 {
fd9fa481
SK
1468 if (!dryrun)
1469 {
7622fc06 1470 log_query(crecp->flags, name, NULL, record_source(crecp->uid));
9009d746
SK
1471 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1472 crec_ttl(crecp, now), &nameoffset,
f6b7dc47
SK
1473 T_CNAME, C_IN, "d", cache_get_name(crecp->addr.cname.cache)))
1474 anscount++;
fd9fa481 1475 }
f6b7dc47 1476
fd9fa481
SK
1477 strcpy(name, cache_get_name(crecp->addr.cname.cache));
1478 goto cname_restart;
1479 }
f6b7dc47 1480
9e4abcb5
SK
1481 if (crecp->flags & F_NEG)
1482 {
feba5c1d 1483 ans = 1;
f6b7dc47
SK
1484 auth = 0;
1485 if (crecp->flags & F_NXDOMAIN)
1486 nxdomain = 1;
feba5c1d 1487 if (!dryrun)
1a6bca81 1488 log_query(crecp->flags, name, NULL, NULL);
9e4abcb5 1489 }
feba5c1d 1490 else if ((crecp->flags & (F_HOSTS | F_DHCP)) || !sec_reqd)
9e4abcb5 1491 {
f6b7dc47
SK
1492 /* If we are returning local answers depending on network,
1493 filter here. */
1494 if (localise &&
1495 (crecp->flags & F_HOSTS) &&
1496 !is_same_net(*((struct in_addr *)&crecp->addr), local_addr, local_netmask))
1497 continue;
1498
1499 if (!(crecp->flags & (F_HOSTS | F_DHCP)))
1500 auth = 0;
1501
feba5c1d
SK
1502 ans = 1;
1503 if (!dryrun)
1504 {
fd9fa481 1505 log_query(crecp->flags & ~F_REVERSE, name, &crecp->addr.addr,
7622fc06 1506 record_source(crecp->uid));
feba5c1d 1507
9009d746
SK
1508 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
1509 crec_ttl(crecp, now), NULL, type, C_IN,
f6b7dc47
SK
1510 type == T_A ? "4" : "6", &crecp->addr))
1511 anscount++;
feba5c1d 1512 }
9e4abcb5 1513 }
f6b7dc47 1514 } while ((crecp = cache_find_by_name(crecp, name, now, flag | F_CNAME)));
9e4abcb5 1515 }
f6b7dc47
SK
1516 }
1517
1518 if (qtype == T_MX || qtype == T_ANY)
1519 {
1520 int found = 0;
0a852541
SK
1521 for (rec = daemon->mxnames; rec; rec = rec->next)
1522 if (!rec->issrv && hostname_isequal(name, rec->name))
f6b7dc47
SK
1523 {
1524 ans = found = 1;
1525 if (!dryrun)
feba5c1d 1526 {
3d8df260 1527 unsigned int offset;
1a6bca81 1528 log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL, "<MX>");
0a852541
SK
1529 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
1530 &offset, T_MX, C_IN, "sd", rec->weight, rec->target))
1531 {
1532 anscount++;
1533 if (rec->target)
1534 rec->offset = offset;
1535 }
feba5c1d 1536 }
f6b7dc47
SK
1537 }
1538
1539 if (!found && (daemon->options & (OPT_SELFMX | OPT_LOCALMX)) &&
1540 cache_find_by_name(NULL, name, now, F_HOSTS | F_DHCP))
1541 {
1542 ans = 1;
1543 if (!dryrun)
1544 {
1a6bca81 1545 log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL, "<MX>");
f6b7dc47
SK
1546 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, NULL,
1547 T_MX, C_IN, "sd", 1,
1548 (daemon->options & OPT_SELFMX) ? name : daemon->mxtarget))
1549 anscount++;
9e4abcb5
SK
1550 }
1551 }
f6b7dc47
SK
1552 }
1553
1554 if (qtype == T_SRV || qtype == T_ANY)
1555 {
1556 int found = 0;
9e4abcb5 1557
0a852541
SK
1558 for (rec = daemon->mxnames; rec; rec = rec->next)
1559 if (rec->issrv && hostname_isequal(name, rec->name))
f6b7dc47
SK
1560 {
1561 found = ans = 1;
1562 if (!dryrun)
1563 {
3d8df260 1564 unsigned int offset;
1a6bca81 1565 log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL, "<SRV>");
f6b7dc47 1566 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
0a852541
SK
1567 &offset, T_SRV, C_IN, "sssd",
1568 rec->priority, rec->weight, rec->srvport, rec->target))
1569 {
1570 anscount++;
1571 if (rec->target)
1572 rec->offset = offset;
1573 }
f6b7dc47
SK
1574 }
1575 }
feba5c1d 1576
f6b7dc47
SK
1577 if (!found && (daemon->options & OPT_FILTER) && (qtype == T_SRV || (qtype == T_ANY && strchr(name, '_'))))
1578 {
1579 ans = 1;
1580 if (!dryrun)
1a6bca81 1581 log_query(F_CONFIG | F_NEG, name, NULL, NULL);
f6b7dc47
SK
1582 }
1583 }
1a6bca81
SK
1584
1585 if (qtype == T_NAPTR || qtype == T_ANY)
1586 {
1587 struct naptr *na;
1588 for (na = daemon->naptr; na; na = na->next)
1589 if (hostname_isequal(name, na->name))
1590 {
1591 ans = 1;
1592 if (!dryrun)
1593 {
1594 log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL, "<NAPTR>");
1595 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
1596 NULL, T_NAPTR, C_IN, "sszzzd",
1597 na->order, na->pref, na->flags, na->services, na->regexp, na->replace))
1598 anscount++;
1599 }
1600 }
1601 }
f6b7dc47
SK
1602
1603 if (qtype == T_MAILB)
1604 ans = 1, nxdomain = 1;
1605
1606 if (qtype == T_SOA && (daemon->options & OPT_FILTER))
1607 {
1608 ans = 1;
1609 if (!dryrun)
1a6bca81 1610 log_query(F_CONFIG | F_NEG, name, &addr, NULL);
feba5c1d 1611 }
9e4abcb5 1612 }
f6b7dc47
SK
1613
1614 if (!ans)
9e4abcb5 1615 return 0; /* failed to answer a question */
feba5c1d 1616 }
f6b7dc47 1617
feba5c1d
SK
1618 if (dryrun)
1619 {
1620 dryrun = 0;
1621 goto rerun;
9e4abcb5
SK
1622 }
1623
0a852541
SK
1624 /* create an additional data section, for stuff in SRV and MX record replies. */
1625 for (rec = daemon->mxnames; rec; rec = rec->next)
1626 if (rec->offset != 0)
1627 {
1628 /* squash dupes */
1629 struct mx_srv_record *tmp;
1630 for (tmp = rec->next; tmp; tmp = tmp->next)
1631 if (tmp->offset != 0 && hostname_isequal(rec->target, tmp->target))
1632 tmp->offset = 0;
1633
1634 crecp = NULL;
1635 while ((crecp = cache_find_by_name(crecp, rec->target, now, F_IPV4 | F_IPV6)))
1636 {
0a852541
SK
1637#ifdef HAVE_IPV6
1638 int type = crecp->flags & F_IPV4 ? T_A : T_AAAA;
1639#else
1640 int type = T_A;
1641#endif
1642 if (crecp->flags & F_NEG)
1643 continue;
1644
9009d746
SK
1645 if (add_resource_record(header, limit, NULL, rec->offset, &ansp,
1646 crec_ttl(crecp, now), NULL, type, C_IN,
0a852541
SK
1647 crecp->flags & F_IPV4 ? "4" : "6", &crecp->addr))
1648 addncount++;
1649 }
1650 }
1651
9e4abcb5
SK
1652 /* done all questions, set up header and return length of result */
1653 header->qr = 1; /* response */
1654 header->aa = auth; /* authoritive - only hosts and DHCP derived names. */
1655 header->ra = 1; /* recursion if available */
f6b7dc47 1656 header->tc = trunc; /* truncation */
9e4abcb5
SK
1657 if (anscount == 0 && nxdomain)
1658 header->rcode = NXDOMAIN;
1659 else
1660 header->rcode = NOERROR; /* no error */
1661 header->ancount = htons(anscount);
1662 header->nscount = htons(0);
0a852541 1663 header->arcount = htons(addncount);
9e4abcb5
SK
1664 return ansp - (unsigned char *)header;
1665}
1666
1667
1668
1669
1670