]>
git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/rfc1035.c
1 /* dnsmasq is Copyright (c) 2000-2007 Simon Kelley
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.
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.
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/>.
19 static int add_resource_record(HEADER
*header
, char *limit
, int *truncp
,
20 unsigned int nameoffset
, unsigned char **pp
,
21 unsigned long ttl
, unsigned int *offset
, unsigned short type
,
22 unsigned short class, char *format
, ...);
24 static int extract_name(HEADER
*header
, size_t plen
, unsigned char **pp
,
25 char *name
, int isExtract
)
27 unsigned char *cp
= (unsigned char *)name
, *p
= *pp
, *p1
= NULL
;
28 unsigned int j
, l
, hops
= 0;
36 unsigned int label_type
= l
& 0xc0;
37 if (label_type
== 0xc0) /* pointer */
39 if ((size_t)(p
- (unsigned char *)header
) >= plen
)
48 if (!p1
) /* first jump, save location to go back to */
51 hops
++; /* break malicious infinite loops */
55 p
= l
+ (unsigned char *)header
;
57 else if (label_type
== 0x80)
58 return 0; /* reserved */
59 else if (label_type
== 0x40)
61 unsigned int count
, digs
;
64 return 0; /* we only understand bitstrings */
67 return 0; /* Cannot compare bitsrings */
72 digs
= ((count
-1)>>2)+1;
74 /* output is \[x<hex>/siz]. which is digs+9 chars */
75 if (cp
- (unsigned char *)name
+ digs
+ 9 >= MAXDNAME
)
77 if ((size_t)(p
- (unsigned char *)header
+ ((count
-1)>>3)) >= plen
)
83 for (j
=0; j
<digs
; j
++)
91 *cp
++ = dig
< 10 ? dig
+ '0' : dig
+ 'A' - 10;
93 cp
+= sprintf((char *)cp
, "/%d]", count
);
94 /* do this here to overwrite the zero char from sprintf */
98 { /* label_type = 0 -> label. */
99 if (cp
- (unsigned char *)name
+ l
+ 1 >= MAXDNAME
)
101 if ((size_t)(p
- (unsigned char *)header
) >= plen
)
103 for(j
=0; j
<l
; j
++, p
++)
113 unsigned char c1
= *cp
, c2
= *p
;
120 if (c1
>= 'A' && c1
<= 'Z')
122 if (c2
>= 'A' && c2
<= 'Z')
132 else if (*cp
!= 0 && *cp
++ != '.')
136 if ((unsigned int)(p
- (unsigned char *)header
) >= plen
)
142 if (cp
!= (unsigned char *)name
)
144 *cp
= 0; /* terminate: lose final period */
149 if (p1
) /* we jumped via compression */
157 /* Max size of input string (for IPv6) is 75 chars.) */
158 #define MAXARPANAME 75
159 static int in_arpa_name_2_addr(char *namein
, struct all_addr
*addrp
)
162 char name
[MAXARPANAME
+1], *cp1
;
163 unsigned char *addr
= (unsigned char *)addrp
;
164 char *lastchunk
= NULL
, *penchunk
= NULL
;
166 if (strlen(namein
) > MAXARPANAME
)
169 memset(addrp
, 0, sizeof(struct all_addr
));
171 /* turn name into a series of asciiz strings */
172 /* j counts no of labels */
173 for(j
= 1,cp1
= name
; *namein
; cp1
++, namein
++)
176 penchunk
= lastchunk
;
189 if (hostname_isequal(lastchunk
, "arpa") && hostname_isequal(penchunk
, "in-addr"))
192 /* address arives as a name of the form
193 www.xxx.yyy.zzz.in-addr.arpa
194 some of the low order address octets might be missing
195 and should be set to zero. */
196 for (cp1
= name
; cp1
!= penchunk
; cp1
+= strlen(cp1
)+1)
198 /* check for digits only (weeds out things like
199 50.0/24.67.28.64.in-addr.arpa which are used
200 as CNAME targets according to RFC 2317 */
202 for (cp
= cp1
; *cp
; cp
++)
203 if (!isdigit((int)*cp
))
215 else if (hostname_isequal(penchunk
, "ip6") &&
216 (hostname_isequal(lastchunk
, "int") || hostname_isequal(lastchunk
, "arpa")))
219 Address arrives as 0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.ip6.[int|arpa]
220 or \[xfedcba9876543210fedcba9876543210/128].ip6.[int|arpa]
222 Note that most of these the various reprentations are obsolete and
223 left-over from the many DNS-for-IPv6 wars. We support all the formats
224 that we can since there is no reason not to.
227 if (*name
== '\\' && *(name
+1) == '[' &&
228 (*(name
+2) == 'x' || *(name
+2) == 'X'))
230 for (j
= 0, cp1
= name
+3; *cp1
&& isxdigit((int) *cp1
) && j
< 32; cp1
++, j
++)
236 addr
[j
/2] |= strtol(xdig
, NULL
, 16);
238 addr
[j
/2] = strtol(xdig
, NULL
, 16) << 4;
241 if (*cp1
== '/' && j
== 32)
246 for (cp1
= name
; cp1
!= penchunk
; cp1
+= strlen(cp1
)+1)
248 if (*(cp1
+1) || !isxdigit((int)*cp1
))
251 for (j
= sizeof(struct all_addr
)-1; j
>0; j
--)
252 addr
[j
] = (addr
[j
] >> 4) | (addr
[j
-1] << 4);
253 addr
[0] = (addr
[0] >> 4) | (strtol(cp1
, NULL
, 16) << 4);
264 static unsigned char *skip_name(unsigned char *ansp
, HEADER
*header
, size_t plen
)
268 unsigned int label_type
= (*ansp
) & 0xc0;
270 if ((unsigned int)(ansp
- (unsigned char *)header
) >= plen
)
273 if (label_type
== 0xc0)
275 /* pointer for compression. */
279 else if (label_type
== 0x80)
280 return NULL
; /* reserved */
281 else if (label_type
== 0x40)
283 /* Extended label type */
286 if (((*ansp
++) & 0x3f) != 1)
287 return NULL
; /* we only understand bitstrings */
289 count
= *(ansp
++); /* Bits in bitstring */
291 if (count
== 0) /* count == 0 means 256 bits */
294 ansp
+= ((count
-1)>>3)+1;
297 { /* label type == 0 Bottom six bits is length */
298 unsigned int len
= (*ansp
++) & 0x3f;
300 break; /* zero length label marks the end. */
309 static unsigned char *skip_questions(HEADER
*header
, size_t plen
)
312 unsigned char *ansp
= (unsigned char *)(header
+1);
314 for (q
= ntohs(header
->qdcount
); q
!= 0; q
--)
316 if (!(ansp
= skip_name(ansp
, header
, plen
)))
318 ansp
+= 4; /* class and type */
320 if ((unsigned int)(ansp
- (unsigned char *)header
) > plen
)
326 static unsigned char *skip_section(unsigned char *ansp
, int count
, HEADER
*header
, size_t plen
)
330 for (i
= 0; i
< count
; i
++)
332 if (!(ansp
= skip_name(ansp
, header
, plen
)))
334 ansp
+= 8; /* type, class, TTL */
335 GETSHORT(rdlen
, ansp
);
336 if ((unsigned int)(ansp
+ rdlen
- (unsigned char *)header
) > plen
)
344 /* CRC the question section. This is used to safely detect query
345 retransmision and to detect answers to questions we didn't ask, which
346 might be poisoning attacks. Note that we decode the name rather
347 than CRC the raw bytes, since replies might be compressed differently.
348 We ignore case in the names for the same reason. Return all-ones
349 if there is not question section. */
350 unsigned int questions_crc(HEADER
*header
, size_t plen
, char *name
)
353 unsigned int crc
= 0xffffffff;
354 unsigned char *p1
, *p
= (unsigned char *)(header
+1);
356 for (q
= ntohs(header
->qdcount
); q
!= 0; q
--)
358 if (!extract_name(header
, plen
, &p
, name
, 1))
359 return crc
; /* bad packet */
361 for (p1
= (unsigned char *)name
; *p1
; p1
++)
366 if (c
>= 'A' && c
<= 'Z')
371 crc
= crc
& 0x80000000 ? (crc
<< 1) ^ 0x04c11db7 : crc
<< 1;
374 /* CRC the class and type as well */
375 for (p1
= p
; p1
< p
+4; p1
++)
380 crc
= crc
& 0x80000000 ? (crc
<< 1) ^ 0x04c11db7 : crc
<< 1;
384 if ((unsigned int)(p
- (unsigned char *)header
) > plen
)
385 return crc
; /* bad packet */
392 size_t resize_packet(HEADER
*header
, size_t plen
, unsigned char *pheader
, size_t hlen
)
394 unsigned char *ansp
= skip_questions(header
, plen
);
399 if (!(ansp
= skip_section(ansp
, ntohs(header
->ancount
) + ntohs(header
->nscount
) + ntohs(header
->arcount
),
403 /* restore pseudoheader */
404 if (pheader
&& ntohs(header
->arcount
) == 0)
406 /* must use memmove, may overlap */
407 memmove(ansp
, pheader
, hlen
);
408 header
->arcount
= htons(1);
412 return ansp
- (unsigned char *)header
;
415 unsigned char *find_pseudoheader(HEADER
*header
, size_t plen
, size_t *len
, unsigned char **p
, int *is_sign
)
417 /* See if packet has an RFC2671 pseudoheader, and if so return a pointer to it.
418 also return length of pseudoheader in *len and pointer to the UDP size in *p
419 Finally, check to see if a packet is signed. If it is we cannot change a single bit before
420 forwarding. We look for SIG and TSIG in the addition section, and TKEY queries (for GSS-TSIG) */
422 int i
, arcount
= ntohs(header
->arcount
);
423 unsigned char *ansp
= (unsigned char *)(header
+1);
424 unsigned short rdlen
, type
, class;
425 unsigned char *ret
= NULL
;
431 if (header
->opcode
== QUERY
)
433 for (i
= ntohs(header
->qdcount
); i
!= 0; i
--)
435 if (!(ansp
= skip_name(ansp
, header
, plen
)))
438 GETSHORT(type
, ansp
);
439 GETSHORT(class, ansp
);
441 if (class == C_IN
&& type
== T_TKEY
)
448 if (!(ansp
= skip_questions(header
, plen
)))
455 if (!(ansp
= skip_section(ansp
, ntohs(header
->ancount
) + ntohs(header
->nscount
), header
, plen
)))
458 for (i
= 0; i
< arcount
; i
++)
460 unsigned char *save
, *start
= ansp
;
461 if (!(ansp
= skip_name(ansp
, header
, plen
)))
464 GETSHORT(type
, ansp
);
466 GETSHORT(class, ansp
);
468 GETSHORT(rdlen
, ansp
);
469 if ((size_t)(ansp
+ rdlen
- (unsigned char *)header
) > plen
)
483 (type
== T_SIG
|| type
== T_TSIG
))
491 /* is addr in the non-globally-routed IP space? */
492 static int private_net(struct in_addr addr
)
494 in_addr_t ip_addr
= ntohl(addr
.s_addr
);
497 ((ip_addr
& 0xFF000000) == 0x7F000000) /* 127.0.0.0/8 (loopback) */ ||
498 ((ip_addr
& 0xFFFF0000) == 0xC0A80000) /* 192.168.0.0/16 (private) */ ||
499 ((ip_addr
& 0xFF000000) == 0x0A000000) /* 10.0.0.0/8 (private) */ ||
500 ((ip_addr
& 0xFFF00000) == 0xAC100000) /* 172.16.0.0/12 (private) */ ||
501 ((ip_addr
& 0xFFFF0000) == 0xA9FE0000) /* 169.254.0.0/16 (zeroconf) */ ;
504 static unsigned char *do_doctor(unsigned char *p
, int count
, HEADER
*header
, size_t qlen
)
506 int i
, qtype
, qclass
, rdlen
;
509 for (i
= count
; i
!= 0; i
--)
511 if (!(p
= skip_name(p
, header
, qlen
)))
512 return 0; /* bad packet */
519 if ((qclass
== C_IN
) && (qtype
== T_A
))
521 struct doctor
*doctor
;
525 memcpy(&addr
, p
, INADDRSZ
);
527 for (doctor
= daemon
->doctors
; doctor
; doctor
= doctor
->next
)
528 if (is_same_net(doctor
->in
, addr
, doctor
->mask
))
530 addr
.s_addr
&= ~doctor
->mask
.s_addr
;
531 addr
.s_addr
|= (doctor
->out
.s_addr
& doctor
->mask
.s_addr
);
532 /* Since we munged the data, the server it came from is no longer authoritative */
534 memcpy(p
, &addr
, INADDRSZ
);
541 if ((size_t)(p
- (unsigned char *)header
) > qlen
)
542 return 0; /* bad packet */
548 static int find_soa(HEADER
*header
, size_t qlen
)
551 int qtype
, qclass
, rdlen
;
552 unsigned long ttl
, minttl
= ULONG_MAX
;
553 int i
, found_soa
= 0;
555 /* first move to NS section and find TTL from any SOA section */
556 if (!(p
= skip_questions(header
, qlen
)) ||
557 !(p
= do_doctor(p
, ntohs(header
->ancount
), header
, qlen
)))
558 return 0; /* bad packet */
560 for (i
= ntohs(header
->nscount
); i
!= 0; i
--)
562 if (!(p
= skip_name(p
, header
, qlen
)))
563 return 0; /* bad packet */
570 if ((qclass
== C_IN
) && (qtype
== T_SOA
))
577 if (!(p
= skip_name(p
, header
, qlen
)))
580 if (!(p
= skip_name(p
, header
, qlen
)))
582 p
+= 16; /* SERIAL REFRESH RETRY EXPIRE */
584 GETLONG(ttl
, p
); /* minTTL */
591 if ((size_t)(p
- (unsigned char *)header
) > qlen
)
592 return 0; /* bad packet */
595 /* rewrite addresses in additioal section too */
596 if (!do_doctor(p
, ntohs(header
->arcount
), header
, qlen
))
600 minttl
= daemon
->neg_ttl
;
605 /* Note that the following code can create CNAME chains that don't point to a real record,
606 either because of lack of memory, or lack of SOA records. These are treated by the cache code as
607 expired and cleaned out that way.
608 Return 1 if we reject an address because it look like parct of dns-rebinding attack. */
609 int extract_addresses(HEADER
*header
, size_t qlen
, char *name
, time_t now
)
611 unsigned char *p
, *p1
, *endrr
, *namep
;
612 int i
, j
, qtype
, qclass
, aqtype
, aqclass
, ardlen
, res
, searched_soa
= 0;
613 unsigned long ttl
= 0;
614 struct all_addr addr
;
616 cache_start_insert();
618 /* find_soa is needed for dns_doctor side-effects, so don't call it lazily if there are any. */
622 ttl
= find_soa(header
, qlen
);
625 /* go through the questions. */
626 p
= (unsigned char *)(header
+1);
628 for (i
= ntohs(header
->qdcount
); i
!= 0; i
--)
630 int found
= 0, cname_count
= 5;
631 struct crec
*cpp
= NULL
;
632 int flags
= header
->rcode
== NXDOMAIN
? F_NXDOMAIN
: 0;
633 unsigned long cttl
= ULONG_MAX
, attl
;
636 if (!extract_name(header
, qlen
, &p
, name
, 1))
637 return 0; /* bad packet */
645 /* PTRs: we chase CNAMEs here, since we have no way to
646 represent them in the cache. */
649 int name_encoding
= in_arpa_name_2_addr(name
, &addr
);
654 if (!(flags
& F_NXDOMAIN
))
657 if (!(p1
= skip_questions(header
, qlen
)))
660 for (j
= ntohs(header
->ancount
); j
!= 0; j
--)
662 unsigned char *tmp
= namep
;
663 /* the loop body overwrites the original name, so get it back here. */
664 if (!extract_name(header
, qlen
, &tmp
, name
, 1) ||
665 !(res
= extract_name(header
, qlen
, &p1
, name
, 0)))
666 return 0; /* bad packet */
668 GETSHORT(aqtype
, p1
);
669 GETSHORT(aqclass
, p1
);
671 GETSHORT(ardlen
, p1
);
674 /* TTL of record is minimum of CNAMES and PTR */
678 if (aqclass
== C_IN
&& res
!= 2 && (aqtype
== T_CNAME
|| aqtype
== T_PTR
))
680 if (!extract_name(header
, qlen
, &p1
, name
, 1))
683 if (aqtype
== T_CNAME
)
686 return 0; /* looped CNAMES */
690 cache_insert(name
, &addr
, now
, cttl
, name_encoding
| F_REVERSE
);
695 if ((size_t)(p1
- (unsigned char *)header
) > qlen
)
696 return 0; /* bad packet */
700 if (!found
&& !(daemon
->options
& OPT_NO_NEG
))
705 ttl
= find_soa(header
, qlen
);
708 cache_insert(NULL
, &addr
, now
, ttl
, name_encoding
| F_REVERSE
| F_NEG
| flags
);
713 /* everything other than PTR */
723 else if (qtype
== T_AAAA
)
732 if (!(flags
& F_NXDOMAIN
))
735 if (!(p1
= skip_questions(header
, qlen
)))
738 for (j
= ntohs(header
->ancount
); j
!= 0; j
--)
740 if (!(res
= extract_name(header
, qlen
, &p1
, name
, 0)))
741 return 0; /* bad packet */
743 GETSHORT(aqtype
, p1
);
744 GETSHORT(aqclass
, p1
);
746 GETSHORT(ardlen
, p1
);
749 if (aqclass
== C_IN
&& res
!= 2 && (aqtype
== T_CNAME
|| aqtype
== qtype
))
751 if (aqtype
== T_CNAME
)
754 return 0; /* looped CNAMES */
755 newc
= cache_insert(name
, NULL
, now
, attl
, F_CNAME
| F_FORWARD
);
758 cpp
->addr
.cname
.cache
= newc
;
759 cpp
->addr
.cname
.uid
= newc
->uid
;
766 if (!extract_name(header
, qlen
, &p1
, name
, 1))
773 /* copy address into aligned storage */
774 memcpy(&addr
, p1
, addrlen
);
776 /* check for returned address in private space */
777 if ((daemon
->options
& OPT_NO_REBIND
) &&
779 private_net(addr
.addr
.addr4
))
782 newc
= cache_insert(name
, &addr
, now
, attl
, flags
| F_FORWARD
);
785 cpp
->addr
.cname
.cache
= newc
;
786 cpp
->addr
.cname
.uid
= newc
->uid
;
793 if ((size_t)(p1
- (unsigned char *)header
) > qlen
)
794 return 0; /* bad packet */
798 if (!found
&& !(daemon
->options
& OPT_NO_NEG
))
803 ttl
= find_soa(header
, qlen
);
805 /* If there's no SOA to get the TTL from, but there is a CNAME
806 pointing at this, inherit its TTL */
809 newc
= cache_insert(name
, NULL
, now
, ttl
? ttl
: cttl
, F_FORWARD
| F_NEG
| flags
);
812 cpp
->addr
.cname
.cache
= newc
;
813 cpp
->addr
.cname
.uid
= newc
->uid
;
820 /* Don't put stuff from a truncated packet into the cache, but do everything else */
827 /* If the packet holds exactly one query
828 return F_IPV4 or F_IPV6 and leave the name from the query in name.
829 Abuse F_BIGNAME to indicate an NS query - yuck. */
831 unsigned short extract_request(HEADER
*header
, size_t qlen
, char *name
, unsigned short *typep
)
833 unsigned char *p
= (unsigned char *)(header
+1);
839 if (ntohs(header
->qdcount
) != 1 || header
->opcode
!= QUERY
)
840 return 0; /* must be exactly one query. */
842 if (!extract_name(header
, qlen
, &p
, name
, 1))
843 return 0; /* bad packet */
858 return F_IPV4
| F_IPV6
;
859 if (qtype
== T_NS
|| qtype
== T_SOA
)
860 return F_QUERY
| F_BIGNAME
;
867 size_t setup_reply(HEADER
*header
, size_t qlen
,
868 struct all_addr
*addrp
, unsigned short flags
, unsigned long ttl
)
870 unsigned char *p
= skip_questions(header
, qlen
);
872 header
->qr
= 1; /* response */
873 header
->aa
= 0; /* authoritive */
874 header
->ra
= 1; /* recursion if available */
875 header
->tc
= 0; /* not truncated */
876 header
->nscount
= htons(0);
877 header
->arcount
= htons(0);
878 header
->ancount
= htons(0); /* no answers unless changed below */
880 header
->rcode
= SERVFAIL
; /* couldn't get memory */
881 else if (flags
== F_NOERR
)
882 header
->rcode
= NOERROR
; /* empty domain */
883 else if (flags
== F_NXDOMAIN
)
884 header
->rcode
= NXDOMAIN
;
885 else if (p
&& flags
== F_IPV4
)
886 { /* we know the address */
887 header
->rcode
= NOERROR
;
888 header
->ancount
= htons(1);
890 add_resource_record(header
, NULL
, NULL
, sizeof(HEADER
), &p
, ttl
, NULL
, T_A
, C_IN
, "4", addrp
);
893 else if (p
&& flags
== F_IPV6
)
895 header
->rcode
= NOERROR
;
896 header
->ancount
= htons(1);
898 add_resource_record(header
, NULL
, NULL
, sizeof(HEADER
), &p
, ttl
, NULL
, T_AAAA
, C_IN
, "6", addrp
);
901 else /* nowhere to forward to */
902 header
->rcode
= REFUSED
;
904 return p
- (unsigned char *)header
;
907 /* check if name matches local names ie from /etc/hosts or DHCP or local mx names. */
908 int check_for_local_domain(char *name
, time_t now
)
911 struct mx_srv_record
*mx
;
912 struct txt_record
*txt
;
913 struct interface_name
*intr
;
914 struct ptr_record
*ptr
;
916 if ((crecp
= cache_find_by_name(NULL
, name
, now
, F_IPV4
| F_IPV6
)) &&
917 (crecp
->flags
& (F_HOSTS
| F_DHCP
)))
920 for (mx
= daemon
->mxnames
; mx
; mx
= mx
->next
)
921 if (hostname_isequal(name
, mx
->name
))
924 for (txt
= daemon
->txt
; txt
; txt
= txt
->next
)
925 if (hostname_isequal(name
, txt
->name
))
928 for (intr
= daemon
->int_names
; intr
; intr
= intr
->next
)
929 if (hostname_isequal(name
, intr
->name
))
932 for (ptr
= daemon
->ptr
; ptr
; ptr
= ptr
->next
)
933 if (hostname_isequal(name
, ptr
->name
))
939 /* Is the packet a reply with the answer address equal to addr?
940 If so mung is into an NXDOMAIN reply and also put that information
942 int check_for_bogus_wildcard(HEADER
*header
, size_t qlen
, char *name
,
943 struct bogus_addr
*baddr
, time_t now
)
946 int i
, qtype
, qclass
, rdlen
;
948 struct bogus_addr
*baddrp
;
950 /* skip over questions */
951 if (!(p
= skip_questions(header
, qlen
)))
952 return 0; /* bad packet */
954 for (i
= ntohs(header
->ancount
); i
!= 0; i
--)
956 if (!extract_name(header
, qlen
, &p
, name
, 1))
957 return 0; /* bad packet */
964 if (qclass
== C_IN
&& qtype
== T_A
)
965 for (baddrp
= baddr
; baddrp
; baddrp
= baddrp
->next
)
966 if (memcmp(&baddrp
->addr
, p
, INADDRSZ
) == 0)
968 /* Found a bogus address. Insert that info here, since there no SOA record
969 to get the ttl from in the normal processing */
970 cache_start_insert();
971 cache_insert(name
, NULL
, now
, ttl
, F_IPV4
| F_FORWARD
| F_NEG
| F_NXDOMAIN
| F_CONFIG
);
983 static int add_resource_record(HEADER
*header
, char *limit
, int *truncp
, unsigned int nameoffset
, unsigned char **pp
,
984 unsigned long ttl
, unsigned int *offset
, unsigned short type
, unsigned short class, char *format
, ...)
987 unsigned char *sav
, *p
= *pp
;
989 unsigned short usval
;
993 if (truncp
&& *truncp
)
996 PUTSHORT(nameoffset
| 0xc000, p
);
999 PUTLONG(ttl
, p
); /* TTL */
1001 sav
= p
; /* Save pointer to RDLength field */
1002 PUTSHORT(0, p
); /* Placeholder RDLength */
1004 va_start(ap
, format
); /* make ap point to 1st unamed argument */
1006 for (; *format
; format
++)
1011 sval
= va_arg(ap
, char *);
1012 memcpy(p
, sval
, IN6ADDRSZ
);
1018 sval
= va_arg(ap
, char *);
1019 memcpy(p
, sval
, INADDRSZ
);
1024 usval
= va_arg(ap
, int);
1029 lval
= va_arg(ap
, long);
1034 /* get domain-name answer arg and store it in RDATA field */
1036 *offset
= p
- (unsigned char *)header
;
1037 p
= do_rfc1035_name(p
, va_arg(ap
, char *));
1042 usval
= va_arg(ap
, int);
1043 sval
= va_arg(ap
, char *);
1044 memcpy(p
, sval
, usval
);
1049 va_end(ap
); /* clean up variable argument pointer */
1052 PUTSHORT(j
, sav
); /* Now, store real RDLength */
1054 /* check for overflow of buffer */
1055 if (limit
&& ((unsigned char *)limit
- p
) < 0)
1066 /* return zero if we can't answer from cache, or packet size if we can */
1067 size_t answer_request(HEADER
*header
, char *limit
, size_t qlen
,
1068 struct in_addr local_addr
, struct in_addr local_netmask
, time_t now
)
1070 char *name
= daemon
->namebuff
;
1071 unsigned char *p
, *ansp
, *pheader
;
1073 struct all_addr addr
;
1074 unsigned int nameoffset
;
1075 unsigned short flag
;
1076 int q
, ans
, anscount
= 0, addncount
= 0;
1077 int dryrun
= 0, sec_reqd
= 0;
1080 int nxdomain
= 0, auth
= 1, trunc
= 0;
1081 struct mx_srv_record
*rec
;
1083 /* If there is an RFC2671 pseudoheader then it will be overwritten by
1084 partial replies, so we have to do a dry run to see if we can answer
1085 the query. We check to see if the do bit is set, if so we always
1086 forward rather than answering from the cache, which doesn't include
1087 security information. */
1089 if (find_pseudoheader(header
, qlen
, NULL
, &pheader
, &is_sign
))
1091 unsigned short udpsz
, ext_rcode
, flags
;
1092 unsigned char *psave
= pheader
;
1094 GETSHORT(udpsz
, pheader
);
1095 GETSHORT(ext_rcode
, pheader
);
1096 GETSHORT(flags
, pheader
);
1098 sec_reqd
= flags
& 0x8000; /* do bit */
1100 /* If our client is advertising a larger UDP packet size
1101 than we allow, trim it so that we don't get an overlarge
1102 response from upstream */
1104 if (!is_sign
&& (udpsz
> daemon
->edns_pktsz
))
1105 PUTSHORT(daemon
->edns_pktsz
, psave
);
1110 if (ntohs(header
->qdcount
) == 0 || header
->opcode
!= QUERY
)
1113 for (rec
= daemon
->mxnames
; rec
; rec
= rec
->next
)
1117 /* determine end of question section (we put answers there) */
1118 if (!(ansp
= skip_questions(header
, qlen
)))
1119 return 0; /* bad packet */
1121 /* now process each question, answers go in RRs after the question */
1122 p
= (unsigned char *)(header
+1);
1124 for (q
= ntohs(header
->qdcount
); q
!= 0; q
--)
1126 /* save pointer to name for copying into answers */
1127 nameoffset
= p
- (unsigned char *)header
;
1129 /* now extract name as .-concatenated string into name */
1130 if (!extract_name(header
, qlen
, &p
, name
, 1))
1131 return 0; /* bad packet */
1134 GETSHORT(qclass
, p
);
1136 ans
= 0; /* have we answered this question */
1138 if (qtype
== T_TXT
|| qtype
== T_ANY
)
1140 struct txt_record
*t
;
1141 for(t
= daemon
->txt
; t
; t
= t
->next
)
1143 if (t
->class == qclass
&& hostname_isequal(name
, t
->name
))
1148 log_query(F_CNAME
| F_FORWARD
| F_CONFIG
| F_NXDOMAIN
, name
, NULL
, 0, NULL
, 0);
1149 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
,
1150 daemon
->local_ttl
, NULL
,
1151 T_TXT
, t
->class, "t", t
->len
, t
->txt
))
1161 if (qtype
== T_PTR
|| qtype
== T_ANY
)
1163 /* see if it's w.z.y.z.in-addr.arpa format */
1164 int is_arpa
= in_arpa_name_2_addr(name
, &addr
);
1165 struct ptr_record
*ptr
;
1166 struct interface_name
* intr
= NULL
;
1168 for (ptr
= daemon
->ptr
; ptr
; ptr
= ptr
->next
)
1169 if (hostname_isequal(name
, ptr
->name
))
1172 if (is_arpa
== F_IPV4
)
1173 for (intr
= daemon
->int_names
; intr
; intr
= intr
->next
)
1175 if (addr
.addr
.addr4
.s_addr
== get_ifaddr(intr
->intr
).s_addr
)
1178 while (intr
->next
&& strcmp(intr
->intr
, intr
->next
->intr
) == 0)
1187 log_query(F_IPV4
| F_REVERSE
| F_CONFIG
, intr
->name
, &addr
, 0, NULL
, 0);
1188 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
,
1189 daemon
->local_ttl
, NULL
,
1190 T_PTR
, C_IN
, "d", intr
->name
))
1199 log_query(F_CNAME
| F_FORWARD
| F_CONFIG
| F_BIGNAME
, name
, NULL
, 0, NULL
, 0);
1200 for (ptr
= daemon
->ptr
; ptr
; ptr
= ptr
->next
)
1201 if (hostname_isequal(name
, ptr
->name
) &&
1202 add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
,
1203 daemon
->local_ttl
, NULL
,
1204 T_PTR
, C_IN
, "d", ptr
->ptr
))
1209 else if ((crecp
= cache_find_by_addr(NULL
, &addr
, now
, is_arpa
)))
1212 /* don't answer wildcard queries with data not from /etc/hosts or dhcp leases */
1213 if (qtype
== T_ANY
&& !(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
1216 if (crecp
->flags
& F_NEG
)
1220 if (crecp
->flags
& F_NXDOMAIN
)
1223 log_query(crecp
->flags
& ~F_FORWARD
, name
, &addr
, 0, NULL
, 0);
1225 else if ((crecp
->flags
& (F_HOSTS
| F_DHCP
)) || !sec_reqd
)
1228 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
1233 /* Return 0 ttl for DHCP entries, which might change
1234 before the lease expires. */
1235 if (crecp
->flags
& (F_IMMORTAL
| F_DHCP
))
1236 ttl
= daemon
->local_ttl
;
1238 ttl
= crecp
->ttd
- now
;
1240 log_query(crecp
->flags
& ~F_FORWARD
, cache_get_name(crecp
), &addr
,
1241 0, daemon
->addn_hosts
, crecp
->uid
);
1243 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
, ttl
, NULL
,
1244 T_PTR
, C_IN
, "d", cache_get_name(crecp
)))
1248 } while ((crecp
= cache_find_by_addr(crecp
, &addr
, now
, is_arpa
)));
1249 else if (is_arpa
== F_IPV4
&&
1250 (daemon
->options
& OPT_BOGUSPRIV
) &&
1251 private_net(addr
.addr
.addr4
))
1253 /* if not in cache, enabled and private IPV4 address, return NXDOMAIN */
1257 log_query(F_CONFIG
| F_REVERSE
| F_IPV4
| F_NEG
| F_NXDOMAIN
,
1258 name
, &addr
, 0, NULL
, 0);
1262 for (flag
= F_IPV4
; flag
; flag
= (flag
== F_IPV4
) ? F_IPV6
: 0)
1264 unsigned short type
= T_A
;
1273 if (qtype
!= type
&& qtype
!= T_ANY
)
1276 /* Check for "A for A" queries */
1277 if (qtype
== T_A
&& (addr
.addr
.addr4
.s_addr
= inet_addr(name
)) != (in_addr_t
) -1)
1282 log_query(F_FORWARD
| F_CONFIG
| F_IPV4
, name
, &addr
, 0, NULL
, 0);
1283 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
,
1284 daemon
->local_ttl
, NULL
, type
, C_IN
, "4", &addr
))
1290 /* interface name stuff */
1293 struct interface_name
*intr
;
1295 for (intr
= daemon
->int_names
; intr
; intr
= intr
->next
)
1296 if (hostname_isequal(name
, intr
->name
))
1304 if ((addr
.addr
.addr4
= get_ifaddr(intr
->intr
)).s_addr
== (in_addr_t
) -1)
1305 log_query(F_FORWARD
| F_CONFIG
| F_IPV4
| F_NEG
, name
, NULL
, 0, NULL
, 0);
1308 log_query(F_FORWARD
| F_CONFIG
| F_IPV4
, name
, &addr
, 0, NULL
, 0);
1309 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
,
1310 daemon
->local_ttl
, NULL
, type
, C_IN
, "4", &addr
))
1319 if ((crecp
= cache_find_by_name(NULL
, name
, now
, flag
| F_CNAME
)))
1323 /* See if a putative address is on the network from which we recieved
1324 the query, is so we'll filter other answers. */
1325 if (local_addr
.s_addr
!= 0 && (daemon
->options
& OPT_LOCALISE
) && flag
== F_IPV4
)
1327 struct crec
*save
= crecp
;
1329 if ((crecp
->flags
& F_HOSTS
) &&
1330 is_same_net(*((struct in_addr
*)&crecp
->addr
), local_addr
, local_netmask
))
1335 } while ((crecp
= cache_find_by_name(crecp
, name
, now
, flag
| F_CNAME
)));
1341 /* don't answer wildcard queries with data not from /etc/hosts
1343 if (qtype
== T_ANY
&& !(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
1346 if (crecp
->flags
& F_CNAME
)
1350 log_query(crecp
->flags
, name
, NULL
, 0, daemon
->addn_hosts
, crecp
->uid
);
1351 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
, crecp
->ttd
- now
, &nameoffset
,
1352 T_CNAME
, C_IN
, "d", cache_get_name(crecp
->addr
.cname
.cache
)))
1356 strcpy(name
, cache_get_name(crecp
->addr
.cname
.cache
));
1360 if (crecp
->flags
& F_NEG
)
1364 if (crecp
->flags
& F_NXDOMAIN
)
1367 log_query(crecp
->flags
, name
, NULL
, 0, NULL
, 0);
1369 else if ((crecp
->flags
& (F_HOSTS
| F_DHCP
)) || !sec_reqd
)
1371 /* If we are returning local answers depending on network,
1374 (crecp
->flags
& F_HOSTS
) &&
1375 !is_same_net(*((struct in_addr
*)&crecp
->addr
), local_addr
, local_netmask
))
1378 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
1386 if (crecp
->flags
& (F_IMMORTAL
| F_DHCP
))
1387 ttl
= daemon
->local_ttl
;
1389 ttl
= crecp
->ttd
- now
;
1391 log_query(crecp
->flags
& ~F_REVERSE
, name
, &crecp
->addr
.addr
,
1392 0, daemon
->addn_hosts
, crecp
->uid
);
1394 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
, ttl
, NULL
, type
, C_IN
,
1395 type
== T_A
? "4" : "6", &crecp
->addr
))
1399 } while ((crecp
= cache_find_by_name(crecp
, name
, now
, flag
| F_CNAME
)));
1403 if (qtype
== T_MX
|| qtype
== T_ANY
)
1406 for (rec
= daemon
->mxnames
; rec
; rec
= rec
->next
)
1407 if (!rec
->issrv
&& hostname_isequal(name
, rec
->name
))
1412 unsigned int offset
;
1413 log_query(F_CNAME
| F_FORWARD
| F_CONFIG
| F_IPV4
, name
, NULL
, 0, NULL
, 0);
1414 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
, daemon
->local_ttl
,
1415 &offset
, T_MX
, C_IN
, "sd", rec
->weight
, rec
->target
))
1419 rec
->offset
= offset
;
1424 if (!found
&& (daemon
->options
& (OPT_SELFMX
| OPT_LOCALMX
)) &&
1425 cache_find_by_name(NULL
, name
, now
, F_HOSTS
| F_DHCP
))
1430 log_query(F_CNAME
| F_FORWARD
| F_CONFIG
| F_IPV4
, name
, NULL
, 0, NULL
, 0);
1431 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
, daemon
->local_ttl
, NULL
,
1432 T_MX
, C_IN
, "sd", 1,
1433 (daemon
->options
& OPT_SELFMX
) ? name
: daemon
->mxtarget
))
1439 if (qtype
== T_SRV
|| qtype
== T_ANY
)
1443 for (rec
= daemon
->mxnames
; rec
; rec
= rec
->next
)
1444 if (rec
->issrv
&& hostname_isequal(name
, rec
->name
))
1449 unsigned int offset
;
1450 log_query(F_CNAME
| F_FORWARD
| F_CONFIG
| F_IPV6
, name
, NULL
, 0, NULL
, 0);
1451 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
, daemon
->local_ttl
,
1452 &offset
, T_SRV
, C_IN
, "sssd",
1453 rec
->priority
, rec
->weight
, rec
->srvport
, rec
->target
))
1457 rec
->offset
= offset
;
1462 if (!found
&& (daemon
->options
& OPT_FILTER
) && (qtype
== T_SRV
|| (qtype
== T_ANY
&& strchr(name
, '_'))))
1466 log_query(F_CONFIG
| F_NEG
, name
, NULL
, 0, NULL
, 0);
1470 if (qtype
== T_MAILB
)
1471 ans
= 1, nxdomain
= 1;
1473 if (qtype
== T_SOA
&& (daemon
->options
& OPT_FILTER
))
1477 log_query(F_CONFIG
| F_NEG
, name
, &addr
, 0, NULL
, 0);
1482 return 0; /* failed to answer a question */
1491 /* create an additional data section, for stuff in SRV and MX record replies. */
1492 for (rec
= daemon
->mxnames
; rec
; rec
= rec
->next
)
1493 if (rec
->offset
!= 0)
1496 struct mx_srv_record
*tmp
;
1497 for (tmp
= rec
->next
; tmp
; tmp
= tmp
->next
)
1498 if (tmp
->offset
!= 0 && hostname_isequal(rec
->target
, tmp
->target
))
1502 while ((crecp
= cache_find_by_name(crecp
, rec
->target
, now
, F_IPV4
| F_IPV6
)))
1506 int type
= crecp
->flags
& F_IPV4
? T_A
: T_AAAA
;
1510 if (crecp
->flags
& F_NEG
)
1513 if (crecp
->flags
& (F_IMMORTAL
| F_DHCP
))
1514 ttl
= daemon
->local_ttl
;
1516 ttl
= crecp
->ttd
- now
;
1518 if (add_resource_record(header
, limit
, NULL
, rec
->offset
, &ansp
, ttl
, NULL
, type
, C_IN
,
1519 crecp
->flags
& F_IPV4
? "4" : "6", &crecp
->addr
))
1524 /* done all questions, set up header and return length of result */
1525 header
->qr
= 1; /* response */
1526 header
->aa
= auth
; /* authoritive - only hosts and DHCP derived names. */
1527 header
->ra
= 1; /* recursion if available */
1528 header
->tc
= trunc
; /* truncation */
1529 if (anscount
== 0 && nxdomain
)
1530 header
->rcode
= NXDOMAIN
;
1532 header
->rcode
= NOERROR
; /* no error */
1533 header
->ancount
= htons(anscount
);
1534 header
->nscount
= htons(0);
1535 header
->arcount
= htons(addncount
);
1536 return ansp
- (unsigned char *)header
;