]>
git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/rfc1035.c
1 /* dnsmasq is Copyright (c) 2000-2008 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 #define CHECK_LEN(header, pp, plen, len) \
25 ((size_t)((pp) - (unsigned char *)(header) + (len)) <= (plen))
27 #define ADD_RDLEN(header, pp, plen, len) \
28 (!CHECK_LEN(header, pp, plen, len) ? 0 : (int)((pp) += (len)), 1)
30 static int extract_name(HEADER
*header
, size_t plen
, unsigned char **pp
,
31 char *name
, int isExtract
, int extrabytes
)
33 unsigned char *cp
= (unsigned char *)name
, *p
= *pp
, *p1
= NULL
;
34 unsigned int j
, l
, hops
= 0;
42 unsigned int label_type
;
44 if (!CHECK_LEN(header
, p
, plen
, 1))
50 /* check that there are the correct no of bytes after the name */
51 if (!CHECK_LEN(header
, p
, plen
, extrabytes
))
56 if (cp
!= (unsigned char *)name
)
58 *cp
= 0; /* terminate: lose final period */
63 if (p1
) /* we jumped via compression */
71 label_type
= l
& 0xc0;
73 if (label_type
== 0xc0) /* pointer */
75 if (!CHECK_LEN(header
, p
, plen
, 1))
82 if (!p1
) /* first jump, save location to go back to */
85 hops
++; /* break malicious infinite loops */
89 p
= l
+ (unsigned char *)header
;
91 else if (label_type
== 0x80)
92 return 0; /* reserved */
93 else if (label_type
== 0x40)
95 unsigned int count
, digs
;
98 return 0; /* we only understand bitstrings */
101 return 0; /* Cannot compare bitsrings */
106 digs
= ((count
-1)>>2)+1;
108 /* output is \[x<hex>/siz]. which is digs+9 chars */
109 if (cp
- (unsigned char *)name
+ digs
+ 9 >= MAXDNAME
)
111 if (!CHECK_LEN(header
, p
, plen
, (count
-1)>>3))
117 for (j
=0; j
<digs
; j
++)
125 *cp
++ = dig
< 10 ? dig
+ '0' : dig
+ 'A' - 10;
127 cp
+= sprintf((char *)cp
, "/%d]", count
);
128 /* do this here to overwrite the zero char from sprintf */
132 { /* label_type = 0 -> label. */
133 if (cp
- (unsigned char *)name
+ l
+ 1 >= MAXDNAME
)
135 if (!CHECK_LEN(header
, p
, plen
, l
))
138 for(j
=0; j
<l
; j
++, p
++)
148 unsigned char c1
= *cp
, c2
= *p
;
155 if (c1
>= 'A' && c1
<= 'Z')
157 if (c2
>= 'A' && c2
<= 'Z')
167 else if (*cp
!= 0 && *cp
++ != '.')
173 /* Max size of input string (for IPv6) is 75 chars.) */
174 #define MAXARPANAME 75
175 static int in_arpa_name_2_addr(char *namein
, struct all_addr
*addrp
)
178 char name
[MAXARPANAME
+1], *cp1
;
179 unsigned char *addr
= (unsigned char *)addrp
;
180 char *lastchunk
= NULL
, *penchunk
= NULL
;
182 if (strlen(namein
) > MAXARPANAME
)
185 memset(addrp
, 0, sizeof(struct all_addr
));
187 /* turn name into a series of asciiz strings */
188 /* j counts no of labels */
189 for(j
= 1,cp1
= name
; *namein
; cp1
++, namein
++)
192 penchunk
= lastchunk
;
205 if (hostname_isequal(lastchunk
, "arpa") && hostname_isequal(penchunk
, "in-addr"))
208 /* address arives as a name of the form
209 www.xxx.yyy.zzz.in-addr.arpa
210 some of the low order address octets might be missing
211 and should be set to zero. */
212 for (cp1
= name
; cp1
!= penchunk
; cp1
+= strlen(cp1
)+1)
214 /* check for digits only (weeds out things like
215 50.0/24.67.28.64.in-addr.arpa which are used
216 as CNAME targets according to RFC 2317 */
218 for (cp
= cp1
; *cp
; cp
++)
219 if (!isdigit((int)*cp
))
231 else if (hostname_isequal(penchunk
, "ip6") &&
232 (hostname_isequal(lastchunk
, "int") || hostname_isequal(lastchunk
, "arpa")))
235 Address arrives as 0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.ip6.[int|arpa]
236 or \[xfedcba9876543210fedcba9876543210/128].ip6.[int|arpa]
238 Note that most of these the various reprentations are obsolete and
239 left-over from the many DNS-for-IPv6 wars. We support all the formats
240 that we can since there is no reason not to.
243 if (*name
== '\\' && *(name
+1) == '[' &&
244 (*(name
+2) == 'x' || *(name
+2) == 'X'))
246 for (j
= 0, cp1
= name
+3; *cp1
&& isxdigit((int) *cp1
) && j
< 32; cp1
++, j
++)
252 addr
[j
/2] |= strtol(xdig
, NULL
, 16);
254 addr
[j
/2] = strtol(xdig
, NULL
, 16) << 4;
257 if (*cp1
== '/' && j
== 32)
262 for (cp1
= name
; cp1
!= penchunk
; cp1
+= strlen(cp1
)+1)
264 if (*(cp1
+1) || !isxdigit((int)*cp1
))
267 for (j
= sizeof(struct all_addr
)-1; j
>0; j
--)
268 addr
[j
] = (addr
[j
] >> 4) | (addr
[j
-1] << 4);
269 addr
[0] = (addr
[0] >> 4) | (strtol(cp1
, NULL
, 16) << 4);
280 static unsigned char *skip_name(unsigned char *ansp
, HEADER
*header
, size_t plen
, int extrabytes
)
284 unsigned int label_type
;
286 if (!CHECK_LEN(header
, ansp
, plen
, 1))
289 label_type
= (*ansp
) & 0xc0;
291 if (label_type
== 0xc0)
293 /* pointer for compression. */
297 else if (label_type
== 0x80)
298 return NULL
; /* reserved */
299 else if (label_type
== 0x40)
301 /* Extended label type */
304 if (!CHECK_LEN(header
, ansp
, plen
, 2))
307 if (((*ansp
++) & 0x3f) != 1)
308 return NULL
; /* we only understand bitstrings */
310 count
= *(ansp
++); /* Bits in bitstring */
312 if (count
== 0) /* count == 0 means 256 bits */
315 ansp
+= ((count
-1)>>3)+1;
318 { /* label type == 0 Bottom six bits is length */
319 unsigned int len
= (*ansp
++) & 0x3f;
321 if (!ADD_RDLEN(header
, ansp
, plen
, len
))
325 break; /* zero length label marks the end. */
329 if (!CHECK_LEN(header
, ansp
, plen
, extrabytes
))
335 static unsigned char *skip_questions(HEADER
*header
, size_t plen
)
338 unsigned char *ansp
= (unsigned char *)(header
+1);
340 for (q
= ntohs(header
->qdcount
); q
!= 0; q
--)
342 if (!(ansp
= skip_name(ansp
, header
, plen
, 4)))
344 ansp
+= 4; /* class and type */
350 static unsigned char *skip_section(unsigned char *ansp
, int count
, HEADER
*header
, size_t plen
)
354 for (i
= 0; i
< count
; i
++)
356 if (!(ansp
= skip_name(ansp
, header
, plen
, 10)))
358 ansp
+= 8; /* type, class, TTL */
359 GETSHORT(rdlen
, ansp
);
360 if (!ADD_RDLEN(header
, ansp
, plen
, rdlen
))
367 /* CRC the question section. This is used to safely detect query
368 retransmision and to detect answers to questions we didn't ask, which
369 might be poisoning attacks. Note that we decode the name rather
370 than CRC the raw bytes, since replies might be compressed differently.
371 We ignore case in the names for the same reason. Return all-ones
372 if there is not question section. */
373 unsigned int questions_crc(HEADER
*header
, size_t plen
, char *name
)
376 unsigned int crc
= 0xffffffff;
377 unsigned char *p1
, *p
= (unsigned char *)(header
+1);
379 for (q
= ntohs(header
->qdcount
); q
!= 0; q
--)
381 if (!extract_name(header
, plen
, &p
, name
, 1, 4))
382 return crc
; /* bad packet */
384 for (p1
= (unsigned char *)name
; *p1
; p1
++)
389 if (c
>= 'A' && c
<= 'Z')
394 crc
= crc
& 0x80000000 ? (crc
<< 1) ^ 0x04c11db7 : crc
<< 1;
397 /* CRC the class and type as well */
398 for (p1
= p
; p1
< p
+4; p1
++)
403 crc
= crc
& 0x80000000 ? (crc
<< 1) ^ 0x04c11db7 : crc
<< 1;
407 if (!CHECK_LEN(header
, p
, plen
, 0))
408 return crc
; /* bad packet */
415 size_t resize_packet(HEADER
*header
, size_t plen
, unsigned char *pheader
, size_t hlen
)
417 unsigned char *ansp
= skip_questions(header
, plen
);
419 /* if packet is malformed, just return as-is. */
423 if (!(ansp
= skip_section(ansp
, ntohs(header
->ancount
) + ntohs(header
->nscount
) + ntohs(header
->arcount
),
427 /* restore pseudoheader */
428 if (pheader
&& ntohs(header
->arcount
) == 0)
430 /* must use memmove, may overlap */
431 memmove(ansp
, pheader
, hlen
);
432 header
->arcount
= htons(1);
436 return ansp
- (unsigned char *)header
;
439 unsigned char *find_pseudoheader(HEADER
*header
, size_t plen
, size_t *len
, unsigned char **p
, int *is_sign
)
441 /* See if packet has an RFC2671 pseudoheader, and if so return a pointer to it.
442 also return length of pseudoheader in *len and pointer to the UDP size in *p
443 Finally, check to see if a packet is signed. If it is we cannot change a single bit before
444 forwarding. We look for SIG and TSIG in the addition section, and TKEY queries (for GSS-TSIG) */
446 int i
, arcount
= ntohs(header
->arcount
);
447 unsigned char *ansp
= (unsigned char *)(header
+1);
448 unsigned short rdlen
, type
, class;
449 unsigned char *ret
= NULL
;
455 if (header
->opcode
== QUERY
)
457 for (i
= ntohs(header
->qdcount
); i
!= 0; i
--)
459 if (!(ansp
= skip_name(ansp
, header
, plen
, 4)))
462 GETSHORT(type
, ansp
);
463 GETSHORT(class, ansp
);
465 if (class == C_IN
&& type
== T_TKEY
)
472 if (!(ansp
= skip_questions(header
, plen
)))
479 if (!(ansp
= skip_section(ansp
, ntohs(header
->ancount
) + ntohs(header
->nscount
), header
, plen
)))
482 for (i
= 0; i
< arcount
; i
++)
484 unsigned char *save
, *start
= ansp
;
485 if (!(ansp
= skip_name(ansp
, header
, plen
, 10)))
488 GETSHORT(type
, ansp
);
490 GETSHORT(class, ansp
);
492 GETSHORT(rdlen
, ansp
);
493 if (!ADD_RDLEN(header
, ansp
, plen
, rdlen
))
506 (type
== T_SIG
|| type
== T_TSIG
))
514 /* is addr in the non-globally-routed IP space? */
515 static int private_net(struct in_addr addr
)
517 in_addr_t ip_addr
= ntohl(addr
.s_addr
);
520 ((ip_addr
& 0xFF000000) == 0x7F000000) /* 127.0.0.0/8 (loopback) */ ||
521 ((ip_addr
& 0xFFFF0000) == 0xC0A80000) /* 192.168.0.0/16 (private) */ ||
522 ((ip_addr
& 0xFF000000) == 0x0A000000) /* 10.0.0.0/8 (private) */ ||
523 ((ip_addr
& 0xFFF00000) == 0xAC100000) /* 172.16.0.0/12 (private) */ ||
524 ((ip_addr
& 0xFFFF0000) == 0xA9FE0000) /* 169.254.0.0/16 (zeroconf) */ ;
527 static unsigned char *do_doctor(unsigned char *p
, int count
, HEADER
*header
, size_t qlen
)
529 int i
, qtype
, qclass
, rdlen
;
532 for (i
= count
; i
!= 0; i
--)
534 if (!(p
= skip_name(p
, header
, qlen
, 10)))
535 return 0; /* bad packet */
542 if ((qclass
== C_IN
) && (qtype
== T_A
))
544 struct doctor
*doctor
;
547 if (!CHECK_LEN(header
, p
, qlen
, INADDRSZ
))
551 memcpy(&addr
, p
, INADDRSZ
);
553 for (doctor
= daemon
->doctors
; doctor
; doctor
= doctor
->next
)
554 if (is_same_net(doctor
->in
, addr
, doctor
->mask
))
556 addr
.s_addr
&= ~doctor
->mask
.s_addr
;
557 addr
.s_addr
|= (doctor
->out
.s_addr
& doctor
->mask
.s_addr
);
558 /* Since we munged the data, the server it came from is no longer authoritative */
560 memcpy(p
, &addr
, INADDRSZ
);
565 if (!ADD_RDLEN(header
, p
, qlen
, rdlen
))
566 return 0; /* bad packet */
572 static int find_soa(HEADER
*header
, size_t qlen
)
575 int qtype
, qclass
, rdlen
;
576 unsigned long ttl
, minttl
= ULONG_MAX
;
577 int i
, found_soa
= 0;
579 /* first move to NS section and find TTL from any SOA section */
580 if (!(p
= skip_questions(header
, qlen
)) ||
581 !(p
= do_doctor(p
, ntohs(header
->ancount
), header
, qlen
)))
582 return 0; /* bad packet */
584 for (i
= ntohs(header
->nscount
); i
!= 0; i
--)
586 if (!(p
= skip_name(p
, header
, qlen
, 10)))
587 return 0; /* bad packet */
594 if ((qclass
== C_IN
) && (qtype
== T_SOA
))
601 if (!(p
= skip_name(p
, header
, qlen
, 0)))
604 if (!(p
= skip_name(p
, header
, qlen
, 20)))
606 p
+= 16; /* SERIAL REFRESH RETRY EXPIRE */
608 GETLONG(ttl
, p
); /* minTTL */
612 else if (!ADD_RDLEN(header
, p
, qlen
, rdlen
))
613 return 0; /* bad packet */
616 /* rewrite addresses in additioal section too */
617 if (!do_doctor(p
, ntohs(header
->arcount
), header
, qlen
))
621 minttl
= daemon
->neg_ttl
;
626 /* Note that the following code can create CNAME chains that don't point to a real record,
627 either because of lack of memory, or lack of SOA records. These are treated by the cache code as
628 expired and cleaned out that way.
629 Return 1 if we reject an address because it look like parct of dns-rebinding attack. */
630 int extract_addresses(HEADER
*header
, size_t qlen
, char *name
, time_t now
)
632 unsigned char *p
, *p1
, *endrr
, *namep
;
633 int i
, j
, qtype
, qclass
, aqtype
, aqclass
, ardlen
, res
, searched_soa
= 0;
634 unsigned long ttl
= 0;
635 struct all_addr addr
;
637 cache_start_insert();
639 /* find_soa is needed for dns_doctor side-effects, so don't call it lazily if there are any. */
643 ttl
= find_soa(header
, qlen
);
646 /* go through the questions. */
647 p
= (unsigned char *)(header
+1);
649 for (i
= ntohs(header
->qdcount
); i
!= 0; i
--)
651 int found
= 0, cname_count
= 5;
652 struct crec
*cpp
= NULL
;
653 int flags
= header
->rcode
== NXDOMAIN
? F_NXDOMAIN
: 0;
654 unsigned long cttl
= ULONG_MAX
, attl
;
657 if (!extract_name(header
, qlen
, &p
, name
, 1, 4))
658 return 0; /* bad packet */
666 /* PTRs: we chase CNAMEs here, since we have no way to
667 represent them in the cache. */
670 int name_encoding
= in_arpa_name_2_addr(name
, &addr
);
675 if (!(flags
& F_NXDOMAIN
))
678 if (!(p1
= skip_questions(header
, qlen
)))
681 for (j
= ntohs(header
->ancount
); j
!= 0; j
--)
683 unsigned char *tmp
= namep
;
684 /* the loop body overwrites the original name, so get it back here. */
685 if (!extract_name(header
, qlen
, &tmp
, name
, 1, 0) ||
686 !(res
= extract_name(header
, qlen
, &p1
, name
, 0, 10)))
687 return 0; /* bad packet */
689 GETSHORT(aqtype
, p1
);
690 GETSHORT(aqclass
, p1
);
692 GETSHORT(ardlen
, p1
);
695 /* TTL of record is minimum of CNAMES and PTR */
699 if (aqclass
== C_IN
&& res
!= 2 && (aqtype
== T_CNAME
|| aqtype
== T_PTR
))
701 if (!extract_name(header
, qlen
, &p1
, name
, 1, 0))
704 if (aqtype
== T_CNAME
)
707 return 0; /* looped CNAMES */
711 cache_insert(name
, &addr
, now
, cttl
, name_encoding
| F_REVERSE
);
716 if (!CHECK_LEN(header
, p1
, qlen
, 0))
717 return 0; /* bad packet */
721 if (!found
&& !(daemon
->options
& OPT_NO_NEG
))
726 ttl
= find_soa(header
, qlen
);
729 cache_insert(NULL
, &addr
, now
, ttl
, name_encoding
| F_REVERSE
| F_NEG
| flags
);
734 /* everything other than PTR */
744 else if (qtype
== T_AAAA
)
753 if (!(flags
& F_NXDOMAIN
))
756 if (!(p1
= skip_questions(header
, qlen
)))
759 for (j
= ntohs(header
->ancount
); j
!= 0; j
--)
761 if (!(res
= extract_name(header
, qlen
, &p1
, name
, 0, 10)))
762 return 0; /* bad packet */
764 GETSHORT(aqtype
, p1
);
765 GETSHORT(aqclass
, p1
);
767 GETSHORT(ardlen
, p1
);
770 if (aqclass
== C_IN
&& res
!= 2 && (aqtype
== T_CNAME
|| aqtype
== qtype
))
772 if (aqtype
== T_CNAME
)
775 return 0; /* looped CNAMES */
776 newc
= cache_insert(name
, NULL
, now
, attl
, F_CNAME
| F_FORWARD
);
779 cpp
->addr
.cname
.cache
= newc
;
780 cpp
->addr
.cname
.uid
= newc
->uid
;
787 if (!extract_name(header
, qlen
, &p1
, name
, 1, 0))
795 /* copy address into aligned storage */
796 if (!CHECK_LEN(header
, p1
, qlen
, addrlen
))
797 return 0; /* bad packet */
798 memcpy(&addr
, p1
, addrlen
);
800 /* check for returned address in private space */
801 if ((daemon
->options
& OPT_NO_REBIND
) &&
803 private_net(addr
.addr
.addr4
))
806 newc
= cache_insert(name
, &addr
, now
, attl
, flags
| F_FORWARD
);
809 cpp
->addr
.cname
.cache
= newc
;
810 cpp
->addr
.cname
.uid
= newc
->uid
;
817 if (!CHECK_LEN(header
, p1
, qlen
, 0))
818 return 0; /* bad packet */
822 if (!found
&& !(daemon
->options
& OPT_NO_NEG
))
827 ttl
= find_soa(header
, qlen
);
829 /* If there's no SOA to get the TTL from, but there is a CNAME
830 pointing at this, inherit its TTL */
833 newc
= cache_insert(name
, NULL
, now
, ttl
? ttl
: cttl
, F_FORWARD
| F_NEG
| flags
);
836 cpp
->addr
.cname
.cache
= newc
;
837 cpp
->addr
.cname
.uid
= newc
->uid
;
844 /* Don't put stuff from a truncated packet into the cache, but do everything else */
851 /* If the packet holds exactly one query
852 return F_IPV4 or F_IPV6 and leave the name from the query in name.
853 Abuse F_BIGNAME to indicate an NS query - yuck. */
855 unsigned short extract_request(HEADER
*header
, size_t qlen
, char *name
, unsigned short *typep
)
857 unsigned char *p
= (unsigned char *)(header
+1);
863 if (ntohs(header
->qdcount
) != 1 || header
->opcode
!= QUERY
)
864 return 0; /* must be exactly one query. */
866 if (!extract_name(header
, qlen
, &p
, name
, 1, 4))
867 return 0; /* bad packet */
882 return F_IPV4
| F_IPV6
;
883 if (qtype
== T_NS
|| qtype
== T_SOA
)
884 return F_QUERY
| F_BIGNAME
;
891 size_t setup_reply(HEADER
*header
, size_t qlen
,
892 struct all_addr
*addrp
, unsigned short flags
, unsigned long ttl
)
894 unsigned char *p
= skip_questions(header
, qlen
);
896 header
->qr
= 1; /* response */
897 header
->aa
= 0; /* authoritive */
898 header
->ra
= 1; /* recursion if available */
899 header
->tc
= 0; /* not truncated */
900 header
->nscount
= htons(0);
901 header
->arcount
= htons(0);
902 header
->ancount
= htons(0); /* no answers unless changed below */
904 header
->rcode
= SERVFAIL
; /* couldn't get memory */
905 else if (flags
== F_NOERR
)
906 header
->rcode
= NOERROR
; /* empty domain */
907 else if (flags
== F_NXDOMAIN
)
908 header
->rcode
= NXDOMAIN
;
909 else if (p
&& flags
== F_IPV4
)
910 { /* we know the address */
911 header
->rcode
= NOERROR
;
912 header
->ancount
= htons(1);
914 add_resource_record(header
, NULL
, NULL
, sizeof(HEADER
), &p
, ttl
, NULL
, T_A
, C_IN
, "4", addrp
);
917 else if (p
&& flags
== F_IPV6
)
919 header
->rcode
= NOERROR
;
920 header
->ancount
= htons(1);
922 add_resource_record(header
, NULL
, NULL
, sizeof(HEADER
), &p
, ttl
, NULL
, T_AAAA
, C_IN
, "6", addrp
);
925 else /* nowhere to forward to */
926 header
->rcode
= REFUSED
;
928 return p
- (unsigned char *)header
;
931 /* check if name matches local names ie from /etc/hosts or DHCP or local mx names. */
932 int check_for_local_domain(char *name
, time_t now
)
935 struct mx_srv_record
*mx
;
936 struct txt_record
*txt
;
937 struct interface_name
*intr
;
938 struct ptr_record
*ptr
;
940 if ((crecp
= cache_find_by_name(NULL
, name
, now
, F_IPV4
| F_IPV6
)) &&
941 (crecp
->flags
& (F_HOSTS
| F_DHCP
)))
944 for (mx
= daemon
->mxnames
; mx
; mx
= mx
->next
)
945 if (hostname_isequal(name
, mx
->name
))
948 for (txt
= daemon
->txt
; txt
; txt
= txt
->next
)
949 if (hostname_isequal(name
, txt
->name
))
952 for (intr
= daemon
->int_names
; intr
; intr
= intr
->next
)
953 if (hostname_isequal(name
, intr
->name
))
956 for (ptr
= daemon
->ptr
; ptr
; ptr
= ptr
->next
)
957 if (hostname_isequal(name
, ptr
->name
))
963 /* Is the packet a reply with the answer address equal to addr?
964 If so mung is into an NXDOMAIN reply and also put that information
966 int check_for_bogus_wildcard(HEADER
*header
, size_t qlen
, char *name
,
967 struct bogus_addr
*baddr
, time_t now
)
970 int i
, qtype
, qclass
, rdlen
;
972 struct bogus_addr
*baddrp
;
974 /* skip over questions */
975 if (!(p
= skip_questions(header
, qlen
)))
976 return 0; /* bad packet */
978 for (i
= ntohs(header
->ancount
); i
!= 0; i
--)
980 if (!extract_name(header
, qlen
, &p
, name
, 1, 10))
981 return 0; /* bad packet */
988 if (qclass
== C_IN
&& qtype
== T_A
)
990 if (!CHECK_LEN(header
, p
, qlen
, INADDRSZ
))
993 for (baddrp
= baddr
; baddrp
; baddrp
= baddrp
->next
)
994 if (memcmp(&baddrp
->addr
, p
, INADDRSZ
) == 0)
996 /* Found a bogus address. Insert that info here, since there no SOA record
997 to get the ttl from in the normal processing */
998 cache_start_insert();
999 cache_insert(name
, NULL
, now
, ttl
, F_IPV4
| F_FORWARD
| F_NEG
| F_NXDOMAIN
| F_CONFIG
);
1006 if (!ADD_RDLEN(header
, p
, qlen
, rdlen
))
1013 static int add_resource_record(HEADER
*header
, char *limit
, int *truncp
, unsigned int nameoffset
, unsigned char **pp
,
1014 unsigned long ttl
, unsigned int *offset
, unsigned short type
, unsigned short class, char *format
, ...)
1017 unsigned char *sav
, *p
= *pp
;
1019 unsigned short usval
;
1023 if (truncp
&& *truncp
)
1026 PUTSHORT(nameoffset
| 0xc000, p
);
1029 PUTLONG(ttl
, p
); /* TTL */
1031 sav
= p
; /* Save pointer to RDLength field */
1032 PUTSHORT(0, p
); /* Placeholder RDLength */
1034 va_start(ap
, format
); /* make ap point to 1st unamed argument */
1036 for (; *format
; format
++)
1041 sval
= va_arg(ap
, char *);
1042 memcpy(p
, sval
, IN6ADDRSZ
);
1048 sval
= va_arg(ap
, char *);
1049 memcpy(p
, sval
, INADDRSZ
);
1054 usval
= va_arg(ap
, int);
1059 lval
= va_arg(ap
, long);
1064 /* get domain-name answer arg and store it in RDATA field */
1066 *offset
= p
- (unsigned char *)header
;
1067 p
= do_rfc1035_name(p
, va_arg(ap
, char *));
1072 usval
= va_arg(ap
, int);
1073 sval
= va_arg(ap
, char *);
1074 memcpy(p
, sval
, usval
);
1079 sval
= va_arg(ap
, char *);
1080 usval
= sval
? strlen(sval
) : 0;
1083 *p
++ = (unsigned char)usval
;
1084 memcpy(p
, sval
, usval
);
1089 va_end(ap
); /* clean up variable argument pointer */
1092 PUTSHORT(j
, sav
); /* Now, store real RDLength */
1094 /* check for overflow of buffer */
1095 if (limit
&& ((unsigned char *)limit
- p
) < 0)
1106 static unsigned long crec_ttl(struct crec
*crecp
, time_t now
)
1108 /* Return 0 ttl for DHCP entries, which might change
1109 before the lease expires. */
1111 if (crecp
->flags
& (F_IMMORTAL
| F_DHCP
))
1112 return daemon
->local_ttl
;
1114 return crecp
->ttd
- now
;
1118 /* return zero if we can't answer from cache, or packet size if we can */
1119 size_t answer_request(HEADER
*header
, char *limit
, size_t qlen
,
1120 struct in_addr local_addr
, struct in_addr local_netmask
, time_t now
)
1122 char *name
= daemon
->namebuff
;
1123 unsigned char *p
, *ansp
, *pheader
;
1125 struct all_addr addr
;
1126 unsigned int nameoffset
;
1127 unsigned short flag
;
1128 int q
, ans
, anscount
= 0, addncount
= 0;
1129 int dryrun
= 0, sec_reqd
= 0;
1132 int nxdomain
= 0, auth
= 1, trunc
= 0;
1133 struct mx_srv_record
*rec
;
1135 /* If there is an RFC2671 pseudoheader then it will be overwritten by
1136 partial replies, so we have to do a dry run to see if we can answer
1137 the query. We check to see if the do bit is set, if so we always
1138 forward rather than answering from the cache, which doesn't include
1139 security information. */
1141 if (find_pseudoheader(header
, qlen
, NULL
, &pheader
, &is_sign
))
1143 unsigned short udpsz
, ext_rcode
, flags
;
1144 unsigned char *psave
= pheader
;
1146 GETSHORT(udpsz
, pheader
);
1147 GETSHORT(ext_rcode
, pheader
);
1148 GETSHORT(flags
, pheader
);
1150 sec_reqd
= flags
& 0x8000; /* do bit */
1152 /* If our client is advertising a larger UDP packet size
1153 than we allow, trim it so that we don't get an overlarge
1154 response from upstream */
1156 if (!is_sign
&& (udpsz
> daemon
->edns_pktsz
))
1157 PUTSHORT(daemon
->edns_pktsz
, psave
);
1162 if (ntohs(header
->qdcount
) == 0 || header
->opcode
!= QUERY
)
1165 for (rec
= daemon
->mxnames
; rec
; rec
= rec
->next
)
1169 /* determine end of question section (we put answers there) */
1170 if (!(ansp
= skip_questions(header
, qlen
)))
1171 return 0; /* bad packet */
1173 /* now process each question, answers go in RRs after the question */
1174 p
= (unsigned char *)(header
+1);
1176 for (q
= ntohs(header
->qdcount
); q
!= 0; q
--)
1178 /* save pointer to name for copying into answers */
1179 nameoffset
= p
- (unsigned char *)header
;
1181 /* now extract name as .-concatenated string into name */
1182 if (!extract_name(header
, qlen
, &p
, name
, 1, 4))
1183 return 0; /* bad packet */
1186 GETSHORT(qclass
, p
);
1188 ans
= 0; /* have we answered this question */
1190 if (qtype
== T_TXT
|| qtype
== T_ANY
)
1192 struct txt_record
*t
;
1193 for(t
= daemon
->txt
; t
; t
= t
->next
)
1195 if (t
->class == qclass
&& hostname_isequal(name
, t
->name
))
1200 log_query(F_CNAME
| F_FORWARD
| F_CONFIG
| F_NXDOMAIN
, name
, NULL
, "<TXT>");
1201 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
,
1202 daemon
->local_ttl
, NULL
,
1203 T_TXT
, t
->class, "t", t
->len
, t
->txt
))
1213 if (qtype
== T_PTR
|| qtype
== T_ANY
)
1215 /* see if it's w.z.y.z.in-addr.arpa format */
1216 int is_arpa
= in_arpa_name_2_addr(name
, &addr
);
1217 struct ptr_record
*ptr
;
1218 struct interface_name
* intr
= NULL
;
1220 for (ptr
= daemon
->ptr
; ptr
; ptr
= ptr
->next
)
1221 if (hostname_isequal(name
, ptr
->name
))
1224 if (is_arpa
== F_IPV4
)
1225 for (intr
= daemon
->int_names
; intr
; intr
= intr
->next
)
1227 if (addr
.addr
.addr4
.s_addr
== get_ifaddr(intr
->intr
).s_addr
)
1230 while (intr
->next
&& strcmp(intr
->intr
, intr
->next
->intr
) == 0)
1239 log_query(F_IPV4
| F_REVERSE
| F_CONFIG
, intr
->name
, &addr
, NULL
);
1240 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
,
1241 daemon
->local_ttl
, NULL
,
1242 T_PTR
, C_IN
, "d", intr
->name
))
1251 log_query(F_CNAME
| F_FORWARD
| F_CONFIG
| F_NXDOMAIN
, name
, NULL
, "<PTR>");
1252 for (ptr
= daemon
->ptr
; ptr
; ptr
= ptr
->next
)
1253 if (hostname_isequal(name
, ptr
->name
) &&
1254 add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
,
1255 daemon
->local_ttl
, NULL
,
1256 T_PTR
, C_IN
, "d", ptr
->ptr
))
1261 else if ((crecp
= cache_find_by_addr(NULL
, &addr
, now
, is_arpa
)))
1264 /* don't answer wildcard queries with data not from /etc/hosts or dhcp leases */
1265 if (qtype
== T_ANY
&& !(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
1268 if (crecp
->flags
& F_NEG
)
1272 if (crecp
->flags
& F_NXDOMAIN
)
1275 log_query(crecp
->flags
& ~F_FORWARD
, name
, &addr
, NULL
);
1277 else if ((crecp
->flags
& (F_HOSTS
| F_DHCP
)) || !sec_reqd
)
1280 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
1284 log_query(crecp
->flags
& ~F_FORWARD
, cache_get_name(crecp
), &addr
,
1285 record_source(daemon
->addn_hosts
, crecp
->uid
));
1287 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
,
1288 crec_ttl(crecp
, now
), NULL
,
1289 T_PTR
, C_IN
, "d", cache_get_name(crecp
)))
1293 } while ((crecp
= cache_find_by_addr(crecp
, &addr
, now
, is_arpa
)));
1294 else if (is_arpa
== F_IPV4
&&
1295 (daemon
->options
& OPT_BOGUSPRIV
) &&
1296 private_net(addr
.addr
.addr4
))
1298 /* if not in cache, enabled and private IPV4 address, return NXDOMAIN */
1302 log_query(F_CONFIG
| F_REVERSE
| F_IPV4
| F_NEG
| F_NXDOMAIN
,
1307 for (flag
= F_IPV4
; flag
; flag
= (flag
== F_IPV4
) ? F_IPV6
: 0)
1309 unsigned short type
= T_A
;
1318 if (qtype
!= type
&& qtype
!= T_ANY
)
1321 /* Check for "A for A" queries */
1322 if (qtype
== T_A
&& (addr
.addr
.addr4
.s_addr
= inet_addr(name
)) != (in_addr_t
) -1)
1327 log_query(F_FORWARD
| F_CONFIG
| F_IPV4
, name
, &addr
, NULL
);
1328 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
,
1329 daemon
->local_ttl
, NULL
, type
, C_IN
, "4", &addr
))
1335 /* interface name stuff */
1338 struct interface_name
*intr
;
1340 for (intr
= daemon
->int_names
; intr
; intr
= intr
->next
)
1341 if (hostname_isequal(name
, intr
->name
))
1349 if ((addr
.addr
.addr4
= get_ifaddr(intr
->intr
)).s_addr
== (in_addr_t
) -1)
1350 log_query(F_FORWARD
| F_CONFIG
| F_IPV4
| F_NEG
, name
, NULL
, NULL
);
1353 log_query(F_FORWARD
| F_CONFIG
| F_IPV4
, name
, &addr
, NULL
);
1354 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
,
1355 daemon
->local_ttl
, NULL
, type
, C_IN
, "4", &addr
))
1364 if ((crecp
= cache_find_by_name(NULL
, name
, now
, flag
| F_CNAME
)))
1368 /* See if a putative address is on the network from which we recieved
1369 the query, is so we'll filter other answers. */
1370 if (local_addr
.s_addr
!= 0 && (daemon
->options
& OPT_LOCALISE
) && flag
== F_IPV4
)
1372 struct crec
*save
= crecp
;
1374 if ((crecp
->flags
& F_HOSTS
) &&
1375 is_same_net(*((struct in_addr
*)&crecp
->addr
), local_addr
, local_netmask
))
1380 } while ((crecp
= cache_find_by_name(crecp
, name
, now
, flag
| F_CNAME
)));
1386 /* don't answer wildcard queries with data not from /etc/hosts
1388 if (qtype
== T_ANY
&& !(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
1391 if (crecp
->flags
& F_CNAME
)
1395 log_query(crecp
->flags
, name
, NULL
, record_source(daemon
->addn_hosts
, crecp
->uid
));
1396 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
,
1397 crec_ttl(crecp
, now
), &nameoffset
,
1398 T_CNAME
, C_IN
, "d", cache_get_name(crecp
->addr
.cname
.cache
)))
1402 strcpy(name
, cache_get_name(crecp
->addr
.cname
.cache
));
1406 if (crecp
->flags
& F_NEG
)
1410 if (crecp
->flags
& F_NXDOMAIN
)
1413 log_query(crecp
->flags
, name
, NULL
, NULL
);
1415 else if ((crecp
->flags
& (F_HOSTS
| F_DHCP
)) || !sec_reqd
)
1417 /* If we are returning local answers depending on network,
1420 (crecp
->flags
& F_HOSTS
) &&
1421 !is_same_net(*((struct in_addr
*)&crecp
->addr
), local_addr
, local_netmask
))
1424 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
1430 log_query(crecp
->flags
& ~F_REVERSE
, name
, &crecp
->addr
.addr
,
1431 record_source(daemon
->addn_hosts
, crecp
->uid
));
1433 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
,
1434 crec_ttl(crecp
, now
), NULL
, type
, C_IN
,
1435 type
== T_A
? "4" : "6", &crecp
->addr
))
1439 } while ((crecp
= cache_find_by_name(crecp
, name
, now
, flag
| F_CNAME
)));
1443 if (qtype
== T_MX
|| qtype
== T_ANY
)
1446 for (rec
= daemon
->mxnames
; rec
; rec
= rec
->next
)
1447 if (!rec
->issrv
&& hostname_isequal(name
, rec
->name
))
1452 unsigned int offset
;
1453 log_query(F_CNAME
| F_FORWARD
| F_CONFIG
| F_NXDOMAIN
, name
, NULL
, "<MX>");
1454 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
, daemon
->local_ttl
,
1455 &offset
, T_MX
, C_IN
, "sd", rec
->weight
, rec
->target
))
1459 rec
->offset
= offset
;
1464 if (!found
&& (daemon
->options
& (OPT_SELFMX
| OPT_LOCALMX
)) &&
1465 cache_find_by_name(NULL
, name
, now
, F_HOSTS
| F_DHCP
))
1470 log_query(F_CNAME
| F_FORWARD
| F_CONFIG
| F_NXDOMAIN
, name
, NULL
, "<MX>");
1471 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
, daemon
->local_ttl
, NULL
,
1472 T_MX
, C_IN
, "sd", 1,
1473 (daemon
->options
& OPT_SELFMX
) ? name
: daemon
->mxtarget
))
1479 if (qtype
== T_SRV
|| qtype
== T_ANY
)
1483 for (rec
= daemon
->mxnames
; rec
; rec
= rec
->next
)
1484 if (rec
->issrv
&& hostname_isequal(name
, rec
->name
))
1489 unsigned int offset
;
1490 log_query(F_CNAME
| F_FORWARD
| F_CONFIG
| F_NXDOMAIN
, name
, NULL
, "<SRV>");
1491 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
, daemon
->local_ttl
,
1492 &offset
, T_SRV
, C_IN
, "sssd",
1493 rec
->priority
, rec
->weight
, rec
->srvport
, rec
->target
))
1497 rec
->offset
= offset
;
1502 if (!found
&& (daemon
->options
& OPT_FILTER
) && (qtype
== T_SRV
|| (qtype
== T_ANY
&& strchr(name
, '_'))))
1506 log_query(F_CONFIG
| F_NEG
, name
, NULL
, NULL
);
1510 if (qtype
== T_NAPTR
|| qtype
== T_ANY
)
1513 for (na
= daemon
->naptr
; na
; na
= na
->next
)
1514 if (hostname_isequal(name
, na
->name
))
1519 log_query(F_CNAME
| F_FORWARD
| F_CONFIG
| F_NXDOMAIN
, name
, NULL
, "<NAPTR>");
1520 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
, daemon
->local_ttl
,
1521 NULL
, T_NAPTR
, C_IN
, "sszzzd",
1522 na
->order
, na
->pref
, na
->flags
, na
->services
, na
->regexp
, na
->replace
))
1528 if (qtype
== T_MAILB
)
1529 ans
= 1, nxdomain
= 1;
1531 if (qtype
== T_SOA
&& (daemon
->options
& OPT_FILTER
))
1535 log_query(F_CONFIG
| F_NEG
, name
, &addr
, NULL
);
1540 return 0; /* failed to answer a question */
1549 /* create an additional data section, for stuff in SRV and MX record replies. */
1550 for (rec
= daemon
->mxnames
; rec
; rec
= rec
->next
)
1551 if (rec
->offset
!= 0)
1554 struct mx_srv_record
*tmp
;
1555 for (tmp
= rec
->next
; tmp
; tmp
= tmp
->next
)
1556 if (tmp
->offset
!= 0 && hostname_isequal(rec
->target
, tmp
->target
))
1560 while ((crecp
= cache_find_by_name(crecp
, rec
->target
, now
, F_IPV4
| F_IPV6
)))
1563 int type
= crecp
->flags
& F_IPV4
? T_A
: T_AAAA
;
1567 if (crecp
->flags
& F_NEG
)
1570 if (add_resource_record(header
, limit
, NULL
, rec
->offset
, &ansp
,
1571 crec_ttl(crecp
, now
), NULL
, type
, C_IN
,
1572 crecp
->flags
& F_IPV4
? "4" : "6", &crecp
->addr
))
1577 /* done all questions, set up header and return length of result */
1578 header
->qr
= 1; /* response */
1579 header
->aa
= auth
; /* authoritive - only hosts and DHCP derived names. */
1580 header
->ra
= 1; /* recursion if available */
1581 header
->tc
= trunc
; /* truncation */
1582 if (anscount
== 0 && nxdomain
)
1583 header
->rcode
= NXDOMAIN
;
1585 header
->rcode
= NOERROR
; /* no error */
1586 header
->ancount
= htons(anscount
);
1587 header
->nscount
= htons(0);
1588 header
->arcount
= htons(addncount
);
1589 return ansp
- (unsigned char *)header
;