]>
git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/rfc1035.c
1 /* dnsmasq is Copyright (c) 2000-2009 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 : (long)((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
++)
141 unsigned char c
= *p
;
142 if (isascii(c
) && !iscntrl(c
) && c
!= '.')
149 unsigned char c1
= *cp
, c2
= *p
;
156 if (c1
>= 'A' && c1
<= 'Z')
158 if (c2
>= 'A' && c2
<= 'Z')
168 else if (*cp
!= 0 && *cp
++ != '.')
174 /* Max size of input string (for IPv6) is 75 chars.) */
175 #define MAXARPANAME 75
176 static int in_arpa_name_2_addr(char *namein
, struct all_addr
*addrp
)
179 char name
[MAXARPANAME
+1], *cp1
;
180 unsigned char *addr
= (unsigned char *)addrp
;
181 char *lastchunk
= NULL
, *penchunk
= NULL
;
183 if (strlen(namein
) > MAXARPANAME
)
186 memset(addrp
, 0, sizeof(struct all_addr
));
188 /* turn name into a series of asciiz strings */
189 /* j counts no of labels */
190 for(j
= 1,cp1
= name
; *namein
; cp1
++, namein
++)
193 penchunk
= lastchunk
;
206 if (hostname_isequal(lastchunk
, "arpa") && hostname_isequal(penchunk
, "in-addr"))
209 /* address arives as a name of the form
210 www.xxx.yyy.zzz.in-addr.arpa
211 some of the low order address octets might be missing
212 and should be set to zero. */
213 for (cp1
= name
; cp1
!= penchunk
; cp1
+= strlen(cp1
)+1)
215 /* check for digits only (weeds out things like
216 50.0/24.67.28.64.in-addr.arpa which are used
217 as CNAME targets according to RFC 2317 */
219 for (cp
= cp1
; *cp
; cp
++)
220 if (!isdigit((int)*cp
))
232 else if (hostname_isequal(penchunk
, "ip6") &&
233 (hostname_isequal(lastchunk
, "int") || hostname_isequal(lastchunk
, "arpa")))
236 Address arrives as 0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.ip6.[int|arpa]
237 or \[xfedcba9876543210fedcba9876543210/128].ip6.[int|arpa]
239 Note that most of these the various reprentations are obsolete and
240 left-over from the many DNS-for-IPv6 wars. We support all the formats
241 that we can since there is no reason not to.
244 if (*name
== '\\' && *(name
+1) == '[' &&
245 (*(name
+2) == 'x' || *(name
+2) == 'X'))
247 for (j
= 0, cp1
= name
+3; *cp1
&& isxdigit((int) *cp1
) && j
< 32; cp1
++, j
++)
253 addr
[j
/2] |= strtol(xdig
, NULL
, 16);
255 addr
[j
/2] = strtol(xdig
, NULL
, 16) << 4;
258 if (*cp1
== '/' && j
== 32)
263 for (cp1
= name
; cp1
!= penchunk
; cp1
+= strlen(cp1
)+1)
265 if (*(cp1
+1) || !isxdigit((int)*cp1
))
268 for (j
= sizeof(struct all_addr
)-1; j
>0; j
--)
269 addr
[j
] = (addr
[j
] >> 4) | (addr
[j
-1] << 4);
270 addr
[0] = (addr
[0] >> 4) | (strtol(cp1
, NULL
, 16) << 4);
281 static unsigned char *skip_name(unsigned char *ansp
, HEADER
*header
, size_t plen
, int extrabytes
)
285 unsigned int label_type
;
287 if (!CHECK_LEN(header
, ansp
, plen
, 1))
290 label_type
= (*ansp
) & 0xc0;
292 if (label_type
== 0xc0)
294 /* pointer for compression. */
298 else if (label_type
== 0x80)
299 return NULL
; /* reserved */
300 else if (label_type
== 0x40)
302 /* Extended label type */
305 if (!CHECK_LEN(header
, ansp
, plen
, 2))
308 if (((*ansp
++) & 0x3f) != 1)
309 return NULL
; /* we only understand bitstrings */
311 count
= *(ansp
++); /* Bits in bitstring */
313 if (count
== 0) /* count == 0 means 256 bits */
316 ansp
+= ((count
-1)>>3)+1;
319 { /* label type == 0 Bottom six bits is length */
320 unsigned int len
= (*ansp
++) & 0x3f;
322 if (!ADD_RDLEN(header
, ansp
, plen
, len
))
326 break; /* zero length label marks the end. */
330 if (!CHECK_LEN(header
, ansp
, plen
, extrabytes
))
336 static unsigned char *skip_questions(HEADER
*header
, size_t plen
)
339 unsigned char *ansp
= (unsigned char *)(header
+1);
341 for (q
= ntohs(header
->qdcount
); q
!= 0; q
--)
343 if (!(ansp
= skip_name(ansp
, header
, plen
, 4)))
345 ansp
+= 4; /* class and type */
351 static unsigned char *skip_section(unsigned char *ansp
, int count
, HEADER
*header
, size_t plen
)
355 for (i
= 0; i
< count
; i
++)
357 if (!(ansp
= skip_name(ansp
, header
, plen
, 10)))
359 ansp
+= 8; /* type, class, TTL */
360 GETSHORT(rdlen
, ansp
);
361 if (!ADD_RDLEN(header
, ansp
, plen
, rdlen
))
368 /* CRC the question section. This is used to safely detect query
369 retransmision and to detect answers to questions we didn't ask, which
370 might be poisoning attacks. Note that we decode the name rather
371 than CRC the raw bytes, since replies might be compressed differently.
372 We ignore case in the names for the same reason. Return all-ones
373 if there is not question section. */
374 unsigned int questions_crc(HEADER
*header
, size_t plen
, char *name
)
377 unsigned int crc
= 0xffffffff;
378 unsigned char *p1
, *p
= (unsigned char *)(header
+1);
380 for (q
= ntohs(header
->qdcount
); q
!= 0; q
--)
382 if (!extract_name(header
, plen
, &p
, name
, 1, 4))
383 return crc
; /* bad packet */
385 for (p1
= (unsigned char *)name
; *p1
; p1
++)
390 if (c
>= 'A' && c
<= 'Z')
395 crc
= crc
& 0x80000000 ? (crc
<< 1) ^ 0x04c11db7 : crc
<< 1;
398 /* CRC the class and type as well */
399 for (p1
= p
; p1
< p
+4; p1
++)
404 crc
= crc
& 0x80000000 ? (crc
<< 1) ^ 0x04c11db7 : crc
<< 1;
408 if (!CHECK_LEN(header
, p
, plen
, 0))
409 return crc
; /* bad packet */
416 size_t resize_packet(HEADER
*header
, size_t plen
, unsigned char *pheader
, size_t hlen
)
418 unsigned char *ansp
= skip_questions(header
, plen
);
420 /* if packet is malformed, just return as-is. */
424 if (!(ansp
= skip_section(ansp
, ntohs(header
->ancount
) + ntohs(header
->nscount
) + ntohs(header
->arcount
),
428 /* restore pseudoheader */
429 if (pheader
&& ntohs(header
->arcount
) == 0)
431 /* must use memmove, may overlap */
432 memmove(ansp
, pheader
, hlen
);
433 header
->arcount
= htons(1);
437 return ansp
- (unsigned char *)header
;
440 unsigned char *find_pseudoheader(HEADER
*header
, size_t plen
, size_t *len
, unsigned char **p
, int *is_sign
)
442 /* See if packet has an RFC2671 pseudoheader, and if so return a pointer to it.
443 also return length of pseudoheader in *len and pointer to the UDP size in *p
444 Finally, check to see if a packet is signed. If it is we cannot change a single bit before
445 forwarding. We look for SIG and TSIG in the addition section, and TKEY queries (for GSS-TSIG) */
447 int i
, arcount
= ntohs(header
->arcount
);
448 unsigned char *ansp
= (unsigned char *)(header
+1);
449 unsigned short rdlen
, type
, class;
450 unsigned char *ret
= NULL
;
456 if (header
->opcode
== QUERY
)
458 for (i
= ntohs(header
->qdcount
); i
!= 0; i
--)
460 if (!(ansp
= skip_name(ansp
, header
, plen
, 4)))
463 GETSHORT(type
, ansp
);
464 GETSHORT(class, ansp
);
466 if (class == C_IN
&& type
== T_TKEY
)
473 if (!(ansp
= skip_questions(header
, plen
)))
480 if (!(ansp
= skip_section(ansp
, ntohs(header
->ancount
) + ntohs(header
->nscount
), header
, plen
)))
483 for (i
= 0; i
< arcount
; i
++)
485 unsigned char *save
, *start
= ansp
;
486 if (!(ansp
= skip_name(ansp
, header
, plen
, 10)))
489 GETSHORT(type
, ansp
);
491 GETSHORT(class, ansp
);
493 GETSHORT(rdlen
, ansp
);
494 if (!ADD_RDLEN(header
, ansp
, plen
, rdlen
))
507 (type
== T_SIG
|| type
== T_TSIG
))
515 /* is addr in the non-globally-routed IP space? */
516 static int private_net(struct in_addr addr
)
518 in_addr_t ip_addr
= ntohl(addr
.s_addr
);
521 ((ip_addr
& 0xFF000000) == 0x7F000000) /* 127.0.0.0/8 (loopback) */ ||
522 ((ip_addr
& 0xFFFF0000) == 0xC0A80000) /* 192.168.0.0/16 (private) */ ||
523 ((ip_addr
& 0xFF000000) == 0x0A000000) /* 10.0.0.0/8 (private) */ ||
524 ((ip_addr
& 0xFFF00000) == 0xAC100000) /* 172.16.0.0/12 (private) */ ||
525 ((ip_addr
& 0xFFFF0000) == 0xA9FE0000) /* 169.254.0.0/16 (zeroconf) */ ;
528 static unsigned char *do_doctor(unsigned char *p
, int count
, HEADER
*header
, size_t qlen
)
530 int i
, qtype
, qclass
, rdlen
;
533 for (i
= count
; i
!= 0; i
--)
535 if (!(p
= skip_name(p
, header
, qlen
, 10)))
536 return 0; /* bad packet */
543 if ((qclass
== C_IN
) && (qtype
== T_A
))
545 struct doctor
*doctor
;
548 if (!CHECK_LEN(header
, p
, qlen
, INADDRSZ
))
552 memcpy(&addr
, p
, INADDRSZ
);
554 for (doctor
= daemon
->doctors
; doctor
; doctor
= doctor
->next
)
556 if (doctor
->end
.s_addr
== 0)
558 if (!is_same_net(doctor
->in
, addr
, doctor
->mask
))
561 else if (ntohl(doctor
->in
.s_addr
) > ntohl(addr
.s_addr
) ||
562 ntohl(doctor
->end
.s_addr
) < ntohl(addr
.s_addr
))
565 addr
.s_addr
&= ~doctor
->mask
.s_addr
;
566 addr
.s_addr
|= (doctor
->out
.s_addr
& doctor
->mask
.s_addr
);
567 /* Since we munged the data, the server it came from is no longer authoritative */
569 memcpy(p
, &addr
, INADDRSZ
);
574 if (!ADD_RDLEN(header
, p
, qlen
, rdlen
))
575 return 0; /* bad packet */
581 static int find_soa(HEADER
*header
, size_t qlen
)
584 int qtype
, qclass
, rdlen
;
585 unsigned long ttl
, minttl
= ULONG_MAX
;
586 int i
, found_soa
= 0;
588 /* first move to NS section and find TTL from any SOA section */
589 if (!(p
= skip_questions(header
, qlen
)) ||
590 !(p
= do_doctor(p
, ntohs(header
->ancount
), header
, qlen
)))
591 return 0; /* bad packet */
593 for (i
= ntohs(header
->nscount
); i
!= 0; i
--)
595 if (!(p
= skip_name(p
, header
, qlen
, 10)))
596 return 0; /* bad packet */
603 if ((qclass
== C_IN
) && (qtype
== T_SOA
))
610 if (!(p
= skip_name(p
, header
, qlen
, 0)))
613 if (!(p
= skip_name(p
, header
, qlen
, 20)))
615 p
+= 16; /* SERIAL REFRESH RETRY EXPIRE */
617 GETLONG(ttl
, p
); /* minTTL */
621 else if (!ADD_RDLEN(header
, p
, qlen
, rdlen
))
622 return 0; /* bad packet */
625 /* rewrite addresses in additioal section too */
626 if (!do_doctor(p
, ntohs(header
->arcount
), header
, qlen
))
630 minttl
= daemon
->neg_ttl
;
635 /* Note that the following code can create CNAME chains that don't point to a real record,
636 either because of lack of memory, or lack of SOA records. These are treated by the cache code as
637 expired and cleaned out that way.
638 Return 1 if we reject an address because it look like parct of dns-rebinding attack. */
639 int extract_addresses(HEADER
*header
, size_t qlen
, char *name
, time_t now
)
641 unsigned char *p
, *p1
, *endrr
, *namep
;
642 int i
, j
, qtype
, qclass
, aqtype
, aqclass
, ardlen
, res
, searched_soa
= 0;
643 unsigned long ttl
= 0;
644 struct all_addr addr
;
646 cache_start_insert();
648 /* find_soa is needed for dns_doctor side-effects, so don't call it lazily if there are any. */
652 ttl
= find_soa(header
, qlen
);
655 /* go through the questions. */
656 p
= (unsigned char *)(header
+1);
658 for (i
= ntohs(header
->qdcount
); i
!= 0; i
--)
660 int found
= 0, cname_count
= 5;
661 struct crec
*cpp
= NULL
;
662 int flags
= header
->rcode
== NXDOMAIN
? F_NXDOMAIN
: 0;
663 unsigned long cttl
= ULONG_MAX
, attl
;
666 if (!extract_name(header
, qlen
, &p
, name
, 1, 4))
667 return 0; /* bad packet */
675 /* PTRs: we chase CNAMEs here, since we have no way to
676 represent them in the cache. */
679 int name_encoding
= in_arpa_name_2_addr(name
, &addr
);
684 if (!(flags
& F_NXDOMAIN
))
687 if (!(p1
= skip_questions(header
, qlen
)))
690 for (j
= ntohs(header
->ancount
); j
!= 0; j
--)
692 unsigned char *tmp
= namep
;
693 /* the loop body overwrites the original name, so get it back here. */
694 if (!extract_name(header
, qlen
, &tmp
, name
, 1, 0) ||
695 !(res
= extract_name(header
, qlen
, &p1
, name
, 0, 10)))
696 return 0; /* bad packet */
698 GETSHORT(aqtype
, p1
);
699 GETSHORT(aqclass
, p1
);
701 GETSHORT(ardlen
, p1
);
704 /* TTL of record is minimum of CNAMES and PTR */
708 if (aqclass
== C_IN
&& res
!= 2 && (aqtype
== T_CNAME
|| aqtype
== T_PTR
))
710 if (!extract_name(header
, qlen
, &p1
, name
, 1, 0))
713 if (aqtype
== T_CNAME
)
716 return 0; /* looped CNAMES */
720 cache_insert(name
, &addr
, now
, cttl
, name_encoding
| F_REVERSE
);
725 if (!CHECK_LEN(header
, p1
, qlen
, 0))
726 return 0; /* bad packet */
730 if (!found
&& !(daemon
->options
& OPT_NO_NEG
))
735 ttl
= find_soa(header
, qlen
);
738 cache_insert(NULL
, &addr
, now
, ttl
, name_encoding
| F_REVERSE
| F_NEG
| flags
);
743 /* everything other than PTR */
753 else if (qtype
== T_AAAA
)
762 if (!(flags
& F_NXDOMAIN
))
765 if (!(p1
= skip_questions(header
, qlen
)))
768 for (j
= ntohs(header
->ancount
); j
!= 0; j
--)
770 if (!(res
= extract_name(header
, qlen
, &p1
, name
, 0, 10)))
771 return 0; /* bad packet */
773 GETSHORT(aqtype
, p1
);
774 GETSHORT(aqclass
, p1
);
776 GETSHORT(ardlen
, p1
);
779 if (aqclass
== C_IN
&& res
!= 2 && (aqtype
== T_CNAME
|| aqtype
== qtype
))
781 if (aqtype
== T_CNAME
)
784 return 0; /* looped CNAMES */
785 newc
= cache_insert(name
, NULL
, now
, attl
, F_CNAME
| F_FORWARD
);
788 cpp
->addr
.cname
.cache
= newc
;
789 cpp
->addr
.cname
.uid
= newc
->uid
;
796 if (!extract_name(header
, qlen
, &p1
, name
, 1, 0))
804 /* copy address into aligned storage */
805 if (!CHECK_LEN(header
, p1
, qlen
, addrlen
))
806 return 0; /* bad packet */
807 memcpy(&addr
, p1
, addrlen
);
809 /* check for returned address in private space */
810 if ((daemon
->options
& OPT_NO_REBIND
) &&
812 private_net(addr
.addr
.addr4
))
815 newc
= cache_insert(name
, &addr
, now
, attl
, flags
| F_FORWARD
);
818 cpp
->addr
.cname
.cache
= newc
;
819 cpp
->addr
.cname
.uid
= newc
->uid
;
826 if (!CHECK_LEN(header
, p1
, qlen
, 0))
827 return 0; /* bad packet */
831 if (!found
&& !(daemon
->options
& OPT_NO_NEG
))
836 ttl
= find_soa(header
, qlen
);
838 /* If there's no SOA to get the TTL from, but there is a CNAME
839 pointing at this, inherit its TTL */
842 newc
= cache_insert(name
, NULL
, now
, ttl
? ttl
: cttl
, F_FORWARD
| F_NEG
| flags
);
845 cpp
->addr
.cname
.cache
= newc
;
846 cpp
->addr
.cname
.uid
= newc
->uid
;
853 /* Don't put stuff from a truncated packet into the cache, but do everything else */
860 /* If the packet holds exactly one query
861 return F_IPV4 or F_IPV6 and leave the name from the query in name.
862 Abuse F_BIGNAME to indicate an NS query - yuck. */
864 unsigned short extract_request(HEADER
*header
, size_t qlen
, char *name
, unsigned short *typep
)
866 unsigned char *p
= (unsigned char *)(header
+1);
872 if (ntohs(header
->qdcount
) != 1 || header
->opcode
!= QUERY
)
873 return 0; /* must be exactly one query. */
875 if (!extract_name(header
, qlen
, &p
, name
, 1, 4))
876 return 0; /* bad packet */
891 return F_IPV4
| F_IPV6
;
892 if (qtype
== T_NS
|| qtype
== T_SOA
)
893 return F_QUERY
| F_BIGNAME
;
900 size_t setup_reply(HEADER
*header
, size_t qlen
,
901 struct all_addr
*addrp
, unsigned short flags
, unsigned long ttl
)
903 unsigned char *p
= skip_questions(header
, qlen
);
905 header
->qr
= 1; /* response */
906 header
->aa
= 0; /* authoritive */
907 header
->ra
= 1; /* recursion if available */
908 header
->tc
= 0; /* not truncated */
909 header
->nscount
= htons(0);
910 header
->arcount
= htons(0);
911 header
->ancount
= htons(0); /* no answers unless changed below */
913 header
->rcode
= SERVFAIL
; /* couldn't get memory */
914 else if (flags
== F_NOERR
)
915 header
->rcode
= NOERROR
; /* empty domain */
916 else if (flags
== F_NXDOMAIN
)
917 header
->rcode
= NXDOMAIN
;
918 else if (p
&& flags
== F_IPV4
)
919 { /* we know the address */
920 header
->rcode
= NOERROR
;
921 header
->ancount
= htons(1);
923 add_resource_record(header
, NULL
, NULL
, sizeof(HEADER
), &p
, ttl
, NULL
, T_A
, C_IN
, "4", addrp
);
926 else if (p
&& flags
== F_IPV6
)
928 header
->rcode
= NOERROR
;
929 header
->ancount
= htons(1);
931 add_resource_record(header
, NULL
, NULL
, sizeof(HEADER
), &p
, ttl
, NULL
, T_AAAA
, C_IN
, "6", addrp
);
934 else /* nowhere to forward to */
935 header
->rcode
= REFUSED
;
937 return p
- (unsigned char *)header
;
940 /* check if name matches local names ie from /etc/hosts or DHCP or local mx names. */
941 int check_for_local_domain(char *name
, time_t now
)
944 struct mx_srv_record
*mx
;
945 struct txt_record
*txt
;
946 struct interface_name
*intr
;
947 struct ptr_record
*ptr
;
949 if ((crecp
= cache_find_by_name(NULL
, name
, now
, F_IPV4
| F_IPV6
)) &&
950 (crecp
->flags
& (F_HOSTS
| F_DHCP
)))
953 for (mx
= daemon
->mxnames
; mx
; mx
= mx
->next
)
954 if (hostname_isequal(name
, mx
->name
))
957 for (txt
= daemon
->txt
; txt
; txt
= txt
->next
)
958 if (hostname_isequal(name
, txt
->name
))
961 for (intr
= daemon
->int_names
; intr
; intr
= intr
->next
)
962 if (hostname_isequal(name
, intr
->name
))
965 for (ptr
= daemon
->ptr
; ptr
; ptr
= ptr
->next
)
966 if (hostname_isequal(name
, ptr
->name
))
972 /* Is the packet a reply with the answer address equal to addr?
973 If so mung is into an NXDOMAIN reply and also put that information
975 int check_for_bogus_wildcard(HEADER
*header
, size_t qlen
, char *name
,
976 struct bogus_addr
*baddr
, time_t now
)
979 int i
, qtype
, qclass
, rdlen
;
981 struct bogus_addr
*baddrp
;
983 /* skip over questions */
984 if (!(p
= skip_questions(header
, qlen
)))
985 return 0; /* bad packet */
987 for (i
= ntohs(header
->ancount
); i
!= 0; i
--)
989 if (!extract_name(header
, qlen
, &p
, name
, 1, 10))
990 return 0; /* bad packet */
997 if (qclass
== C_IN
&& qtype
== T_A
)
999 if (!CHECK_LEN(header
, p
, qlen
, INADDRSZ
))
1002 for (baddrp
= baddr
; baddrp
; baddrp
= baddrp
->next
)
1003 if (memcmp(&baddrp
->addr
, p
, INADDRSZ
) == 0)
1005 /* Found a bogus address. Insert that info here, since there no SOA record
1006 to get the ttl from in the normal processing */
1007 cache_start_insert();
1008 cache_insert(name
, NULL
, now
, ttl
, F_IPV4
| F_FORWARD
| F_NEG
| F_NXDOMAIN
| F_CONFIG
);
1015 if (!ADD_RDLEN(header
, p
, qlen
, rdlen
))
1022 static int add_resource_record(HEADER
*header
, char *limit
, int *truncp
, unsigned int nameoffset
, unsigned char **pp
,
1023 unsigned long ttl
, unsigned int *offset
, unsigned short type
, unsigned short class, char *format
, ...)
1026 unsigned char *sav
, *p
= *pp
;
1028 unsigned short usval
;
1032 if (truncp
&& *truncp
)
1035 PUTSHORT(nameoffset
| 0xc000, p
);
1038 PUTLONG(ttl
, p
); /* TTL */
1040 sav
= p
; /* Save pointer to RDLength field */
1041 PUTSHORT(0, p
); /* Placeholder RDLength */
1043 va_start(ap
, format
); /* make ap point to 1st unamed argument */
1045 for (; *format
; format
++)
1050 sval
= va_arg(ap
, char *);
1051 memcpy(p
, sval
, IN6ADDRSZ
);
1057 sval
= va_arg(ap
, char *);
1058 memcpy(p
, sval
, INADDRSZ
);
1063 usval
= va_arg(ap
, int);
1068 lval
= va_arg(ap
, long);
1073 /* get domain-name answer arg and store it in RDATA field */
1075 *offset
= p
- (unsigned char *)header
;
1076 p
= do_rfc1035_name(p
, va_arg(ap
, char *));
1081 usval
= va_arg(ap
, int);
1082 sval
= va_arg(ap
, char *);
1083 memcpy(p
, sval
, usval
);
1088 sval
= va_arg(ap
, char *);
1089 usval
= sval
? strlen(sval
) : 0;
1092 *p
++ = (unsigned char)usval
;
1093 memcpy(p
, sval
, usval
);
1098 va_end(ap
); /* clean up variable argument pointer */
1101 PUTSHORT(j
, sav
); /* Now, store real RDLength */
1103 /* check for overflow of buffer */
1104 if (limit
&& ((unsigned char *)limit
- p
) < 0)
1115 static unsigned long crec_ttl(struct crec
*crecp
, time_t now
)
1117 /* Return 0 ttl for DHCP entries, which might change
1118 before the lease expires. */
1120 if (crecp
->flags
& (F_IMMORTAL
| F_DHCP
))
1121 return daemon
->local_ttl
;
1123 return crecp
->ttd
- now
;
1127 /* return zero if we can't answer from cache, or packet size if we can */
1128 size_t answer_request(HEADER
*header
, char *limit
, size_t qlen
,
1129 struct in_addr local_addr
, struct in_addr local_netmask
, time_t now
)
1131 char *name
= daemon
->namebuff
;
1132 unsigned char *p
, *ansp
, *pheader
;
1134 struct all_addr addr
;
1135 unsigned int nameoffset
;
1136 unsigned short flag
;
1137 int q
, ans
, anscount
= 0, addncount
= 0;
1138 int dryrun
= 0, sec_reqd
= 0;
1141 int nxdomain
= 0, auth
= 1, trunc
= 0;
1142 struct mx_srv_record
*rec
;
1144 /* If there is an RFC2671 pseudoheader then it will be overwritten by
1145 partial replies, so we have to do a dry run to see if we can answer
1146 the query. We check to see if the do bit is set, if so we always
1147 forward rather than answering from the cache, which doesn't include
1148 security information. */
1150 if (find_pseudoheader(header
, qlen
, NULL
, &pheader
, &is_sign
))
1152 unsigned short udpsz
, ext_rcode
, flags
;
1153 unsigned char *psave
= pheader
;
1155 GETSHORT(udpsz
, pheader
);
1156 GETSHORT(ext_rcode
, pheader
);
1157 GETSHORT(flags
, pheader
);
1159 sec_reqd
= flags
& 0x8000; /* do bit */
1161 /* If our client is advertising a larger UDP packet size
1162 than we allow, trim it so that we don't get an overlarge
1163 response from upstream */
1165 if (!is_sign
&& (udpsz
> daemon
->edns_pktsz
))
1166 PUTSHORT(daemon
->edns_pktsz
, psave
);
1171 if (ntohs(header
->qdcount
) == 0 || header
->opcode
!= QUERY
)
1174 for (rec
= daemon
->mxnames
; rec
; rec
= rec
->next
)
1178 /* determine end of question section (we put answers there) */
1179 if (!(ansp
= skip_questions(header
, qlen
)))
1180 return 0; /* bad packet */
1182 /* now process each question, answers go in RRs after the question */
1183 p
= (unsigned char *)(header
+1);
1185 for (q
= ntohs(header
->qdcount
); q
!= 0; q
--)
1187 /* save pointer to name for copying into answers */
1188 nameoffset
= p
- (unsigned char *)header
;
1190 /* now extract name as .-concatenated string into name */
1191 if (!extract_name(header
, qlen
, &p
, name
, 1, 4))
1192 return 0; /* bad packet */
1195 GETSHORT(qclass
, p
);
1197 ans
= 0; /* have we answered this question */
1199 if (qtype
== T_TXT
|| qtype
== T_ANY
)
1201 struct txt_record
*t
;
1202 for(t
= daemon
->txt
; t
; t
= t
->next
)
1204 if (t
->class == qclass
&& hostname_isequal(name
, t
->name
))
1209 log_query(F_CNAME
| F_FORWARD
| F_CONFIG
| F_NXDOMAIN
, name
, NULL
, "<TXT>");
1210 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
,
1211 daemon
->local_ttl
, NULL
,
1212 T_TXT
, t
->class, "t", t
->len
, t
->txt
))
1222 if (qtype
== T_PTR
|| qtype
== T_ANY
)
1224 /* see if it's w.z.y.z.in-addr.arpa format */
1225 int is_arpa
= in_arpa_name_2_addr(name
, &addr
);
1226 struct ptr_record
*ptr
;
1227 struct interface_name
* intr
= NULL
;
1229 for (ptr
= daemon
->ptr
; ptr
; ptr
= ptr
->next
)
1230 if (hostname_isequal(name
, ptr
->name
))
1233 if (is_arpa
== F_IPV4
)
1234 for (intr
= daemon
->int_names
; intr
; intr
= intr
->next
)
1236 if (addr
.addr
.addr4
.s_addr
== get_ifaddr(intr
->intr
).s_addr
)
1239 while (intr
->next
&& strcmp(intr
->intr
, intr
->next
->intr
) == 0)
1248 log_query(F_IPV4
| F_REVERSE
| F_CONFIG
, intr
->name
, &addr
, NULL
);
1249 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
,
1250 daemon
->local_ttl
, NULL
,
1251 T_PTR
, C_IN
, "d", intr
->name
))
1260 log_query(F_CNAME
| F_FORWARD
| F_CONFIG
| F_NXDOMAIN
, name
, NULL
, "<PTR>");
1261 for (ptr
= daemon
->ptr
; ptr
; ptr
= ptr
->next
)
1262 if (hostname_isequal(name
, ptr
->name
) &&
1263 add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
,
1264 daemon
->local_ttl
, NULL
,
1265 T_PTR
, C_IN
, "d", ptr
->ptr
))
1270 else if ((crecp
= cache_find_by_addr(NULL
, &addr
, now
, is_arpa
)))
1273 /* don't answer wildcard queries with data not from /etc/hosts or dhcp leases */
1274 if (qtype
== T_ANY
&& !(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
1277 if (crecp
->flags
& F_NEG
)
1281 if (crecp
->flags
& F_NXDOMAIN
)
1284 log_query(crecp
->flags
& ~F_FORWARD
, name
, &addr
, NULL
);
1286 else if ((crecp
->flags
& (F_HOSTS
| F_DHCP
)) || !sec_reqd
)
1289 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
1293 log_query(crecp
->flags
& ~F_FORWARD
, cache_get_name(crecp
), &addr
,
1294 record_source(crecp
->uid
));
1296 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
,
1297 crec_ttl(crecp
, now
), NULL
,
1298 T_PTR
, C_IN
, "d", cache_get_name(crecp
)))
1302 } while ((crecp
= cache_find_by_addr(crecp
, &addr
, now
, is_arpa
)));
1303 else if (is_arpa
== F_IPV4
&&
1304 (daemon
->options
& OPT_BOGUSPRIV
) &&
1305 private_net(addr
.addr
.addr4
))
1307 /* if not in cache, enabled and private IPV4 address, return NXDOMAIN */
1311 log_query(F_CONFIG
| F_REVERSE
| F_IPV4
| F_NEG
| F_NXDOMAIN
,
1316 for (flag
= F_IPV4
; flag
; flag
= (flag
== F_IPV4
) ? F_IPV6
: 0)
1318 unsigned short type
= T_A
;
1327 if (qtype
!= type
&& qtype
!= T_ANY
)
1330 /* Check for "A for A" queries */
1331 if (qtype
== T_A
&& (addr
.addr
.addr4
.s_addr
= inet_addr(name
)) != (in_addr_t
) -1)
1336 log_query(F_FORWARD
| F_CONFIG
| F_IPV4
, name
, &addr
, NULL
);
1337 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
,
1338 daemon
->local_ttl
, NULL
, type
, C_IN
, "4", &addr
))
1344 /* interface name stuff */
1347 struct interface_name
*intr
;
1349 for (intr
= daemon
->int_names
; intr
; intr
= intr
->next
)
1350 if (hostname_isequal(name
, intr
->name
))
1358 if ((addr
.addr
.addr4
= get_ifaddr(intr
->intr
)).s_addr
== (in_addr_t
) -1)
1359 log_query(F_FORWARD
| F_CONFIG
| F_IPV4
| F_NEG
, name
, NULL
, NULL
);
1362 log_query(F_FORWARD
| F_CONFIG
| F_IPV4
, name
, &addr
, NULL
);
1363 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
,
1364 daemon
->local_ttl
, NULL
, type
, C_IN
, "4", &addr
))
1373 if ((crecp
= cache_find_by_name(NULL
, name
, now
, flag
| F_CNAME
)))
1377 /* See if a putative address is on the network from which we recieved
1378 the query, is so we'll filter other answers. */
1379 if (local_addr
.s_addr
!= 0 && (daemon
->options
& OPT_LOCALISE
) && flag
== F_IPV4
)
1381 struct crec
*save
= crecp
;
1383 if ((crecp
->flags
& F_HOSTS
) &&
1384 is_same_net(*((struct in_addr
*)&crecp
->addr
), local_addr
, local_netmask
))
1389 } while ((crecp
= cache_find_by_name(crecp
, name
, now
, flag
| F_CNAME
)));
1395 /* don't answer wildcard queries with data not from /etc/hosts
1397 if (qtype
== T_ANY
&& !(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
1400 if (crecp
->flags
& F_CNAME
)
1404 log_query(crecp
->flags
, name
, NULL
, record_source(crecp
->uid
));
1405 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
,
1406 crec_ttl(crecp
, now
), &nameoffset
,
1407 T_CNAME
, C_IN
, "d", cache_get_name(crecp
->addr
.cname
.cache
)))
1411 strcpy(name
, cache_get_name(crecp
->addr
.cname
.cache
));
1415 if (crecp
->flags
& F_NEG
)
1419 if (crecp
->flags
& F_NXDOMAIN
)
1422 log_query(crecp
->flags
, name
, NULL
, NULL
);
1424 else if ((crecp
->flags
& (F_HOSTS
| F_DHCP
)) || !sec_reqd
)
1426 /* If we are returning local answers depending on network,
1429 (crecp
->flags
& F_HOSTS
) &&
1430 !is_same_net(*((struct in_addr
*)&crecp
->addr
), local_addr
, local_netmask
))
1433 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
1439 log_query(crecp
->flags
& ~F_REVERSE
, name
, &crecp
->addr
.addr
,
1440 record_source(crecp
->uid
));
1442 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
,
1443 crec_ttl(crecp
, now
), NULL
, type
, C_IN
,
1444 type
== T_A
? "4" : "6", &crecp
->addr
))
1448 } while ((crecp
= cache_find_by_name(crecp
, name
, now
, flag
| F_CNAME
)));
1452 if (qtype
== T_MX
|| qtype
== T_ANY
)
1455 for (rec
= daemon
->mxnames
; rec
; rec
= rec
->next
)
1456 if (!rec
->issrv
&& hostname_isequal(name
, rec
->name
))
1461 unsigned int offset
;
1462 log_query(F_CNAME
| F_FORWARD
| F_CONFIG
| F_NXDOMAIN
, name
, NULL
, "<MX>");
1463 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
, daemon
->local_ttl
,
1464 &offset
, T_MX
, C_IN
, "sd", rec
->weight
, rec
->target
))
1468 rec
->offset
= offset
;
1473 if (!found
&& (daemon
->options
& (OPT_SELFMX
| OPT_LOCALMX
)) &&
1474 cache_find_by_name(NULL
, name
, now
, F_HOSTS
| F_DHCP
))
1479 log_query(F_CNAME
| F_FORWARD
| F_CONFIG
| F_NXDOMAIN
, name
, NULL
, "<MX>");
1480 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
, daemon
->local_ttl
, NULL
,
1481 T_MX
, C_IN
, "sd", 1,
1482 (daemon
->options
& OPT_SELFMX
) ? name
: daemon
->mxtarget
))
1488 if (qtype
== T_SRV
|| qtype
== T_ANY
)
1492 for (rec
= daemon
->mxnames
; rec
; rec
= rec
->next
)
1493 if (rec
->issrv
&& hostname_isequal(name
, rec
->name
))
1498 unsigned int offset
;
1499 log_query(F_CNAME
| F_FORWARD
| F_CONFIG
| F_NXDOMAIN
, name
, NULL
, "<SRV>");
1500 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
, daemon
->local_ttl
,
1501 &offset
, T_SRV
, C_IN
, "sssd",
1502 rec
->priority
, rec
->weight
, rec
->srvport
, rec
->target
))
1506 rec
->offset
= offset
;
1511 if (!found
&& (daemon
->options
& OPT_FILTER
) && (qtype
== T_SRV
|| (qtype
== T_ANY
&& strchr(name
, '_'))))
1515 log_query(F_CONFIG
| F_NEG
, name
, NULL
, NULL
);
1519 if (qtype
== T_NAPTR
|| qtype
== T_ANY
)
1522 for (na
= daemon
->naptr
; na
; na
= na
->next
)
1523 if (hostname_isequal(name
, na
->name
))
1528 log_query(F_CNAME
| F_FORWARD
| F_CONFIG
| F_NXDOMAIN
, name
, NULL
, "<NAPTR>");
1529 if (add_resource_record(header
, limit
, &trunc
, nameoffset
, &ansp
, daemon
->local_ttl
,
1530 NULL
, T_NAPTR
, C_IN
, "sszzzd",
1531 na
->order
, na
->pref
, na
->flags
, na
->services
, na
->regexp
, na
->replace
))
1537 if (qtype
== T_MAILB
)
1538 ans
= 1, nxdomain
= 1;
1540 if (qtype
== T_SOA
&& (daemon
->options
& OPT_FILTER
))
1544 log_query(F_CONFIG
| F_NEG
, name
, &addr
, NULL
);
1549 return 0; /* failed to answer a question */
1558 /* create an additional data section, for stuff in SRV and MX record replies. */
1559 for (rec
= daemon
->mxnames
; rec
; rec
= rec
->next
)
1560 if (rec
->offset
!= 0)
1563 struct mx_srv_record
*tmp
;
1564 for (tmp
= rec
->next
; tmp
; tmp
= tmp
->next
)
1565 if (tmp
->offset
!= 0 && hostname_isequal(rec
->target
, tmp
->target
))
1569 while ((crecp
= cache_find_by_name(crecp
, rec
->target
, now
, F_IPV4
| F_IPV6
)))
1572 int type
= crecp
->flags
& F_IPV4
? T_A
: T_AAAA
;
1576 if (crecp
->flags
& F_NEG
)
1579 if (add_resource_record(header
, limit
, NULL
, rec
->offset
, &ansp
,
1580 crec_ttl(crecp
, now
), NULL
, type
, C_IN
,
1581 crecp
->flags
& F_IPV4
? "4" : "6", &crecp
->addr
))
1586 /* done all questions, set up header and return length of result */
1587 header
->qr
= 1; /* response */
1588 header
->aa
= auth
; /* authoritive - only hosts and DHCP derived names. */
1589 header
->ra
= 1; /* recursion if available */
1590 header
->tc
= trunc
; /* truncation */
1591 if (anscount
== 0 && nxdomain
)
1592 header
->rcode
= NXDOMAIN
;
1594 header
->rcode
= NOERROR
; /* no error */
1595 header
->ancount
= htons(anscount
);
1596 header
->nscount
= htons(0);
1597 header
->arcount
= htons(addncount
);
1598 return ansp
- (unsigned char *)header
;