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