mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 18:28:25 +00:00
Handle extending EDNS0 OPT RR.
This commit is contained in:
@@ -1117,8 +1117,6 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
|
int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
|
||||||
struct bogus_addr *addr, time_t now);
|
struct bogus_addr *addr, time_t now);
|
||||||
int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bogus_addr *baddr);
|
int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bogus_addr *baddr);
|
||||||
unsigned char *find_pseudoheader(struct dns_header *header, size_t plen,
|
|
||||||
size_t *len, unsigned char **p, int *is_sign);
|
|
||||||
int check_for_local_domain(char *name, time_t now);
|
int check_for_local_domain(char *name, time_t now);
|
||||||
unsigned int questions_crc(struct dns_header *header, size_t plen, char *buff);
|
unsigned int questions_crc(struct dns_header *header, size_t plen, char *buff);
|
||||||
size_t resize_packet(struct dns_header *header, size_t plen,
|
size_t resize_packet(struct dns_header *header, size_t plen,
|
||||||
@@ -1514,6 +1512,8 @@ u16 *rrfilter_desc(int type);
|
|||||||
int expand_workspace(unsigned char ***wkspc, int *szp, int new);
|
int expand_workspace(unsigned char ***wkspc, int *szp, int new);
|
||||||
|
|
||||||
/* edns0.c */
|
/* edns0.c */
|
||||||
|
unsigned char *find_pseudoheader(struct dns_header *header, size_t plen,
|
||||||
|
size_t *len, unsigned char **p, int *is_sign, int *is_last);
|
||||||
size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *limit,
|
size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *limit,
|
||||||
unsigned short udp_sz, int optno, unsigned char *opt, size_t optlen, int set_do);
|
unsigned short udp_sz, int optno, unsigned char *opt, size_t optlen, int set_do);
|
||||||
size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysockaddr *l3);
|
size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysockaddr *l3);
|
||||||
|
|||||||
@@ -2206,7 +2206,7 @@ size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, i
|
|||||||
|
|
||||||
ret = add_do_bit(header, p - (unsigned char *)header, end);
|
ret = add_do_bit(header, p - (unsigned char *)header, end);
|
||||||
|
|
||||||
if (find_pseudoheader(header, ret, NULL, &p, NULL))
|
if (find_pseudoheader(header, ret, NULL, &p, NULL, NULL))
|
||||||
PUTSHORT(edns_pktsz, p);
|
PUTSHORT(edns_pktsz, p);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
109
src/edns0.c
109
src/edns0.c
@@ -16,12 +16,12 @@
|
|||||||
|
|
||||||
#include "dnsmasq.h"
|
#include "dnsmasq.h"
|
||||||
|
|
||||||
unsigned char *find_pseudoheader(struct dns_header *header, size_t plen, size_t *len, unsigned char **p, int *is_sign)
|
unsigned char *find_pseudoheader(struct dns_header *header, size_t plen, size_t *len, unsigned char **p, int *is_sign, int *is_last)
|
||||||
{
|
{
|
||||||
/* See if packet has an RFC2671 pseudoheader, and if so return a pointer to it.
|
/* See if packet has an RFC2671 pseudoheader, and if so return a pointer to it.
|
||||||
also return length of pseudoheader in *len and pointer to the UDP size in *p
|
also return length of pseudoheader in *len and pointer to the UDP size in *p
|
||||||
Finally, check to see if a packet is signed. If it is we cannot change a single bit before
|
Finally, check to see if a packet is signed. If it is we cannot change a single bit before
|
||||||
forwarding. We look for SIG and TSIG in the addition section, and TKEY queries (for GSS-TSIG) */
|
forwarding. We look for TSIG in the addition section, and TKEY queries (for GSS-TSIG) */
|
||||||
|
|
||||||
int i, arcount = ntohs(header->arcount);
|
int i, arcount = ntohs(header->arcount);
|
||||||
unsigned char *ansp = (unsigned char *)(header+1);
|
unsigned char *ansp = (unsigned char *)(header+1);
|
||||||
@@ -76,8 +76,13 @@ unsigned char *find_pseudoheader(struct dns_header *header, size_t plen, size_t
|
|||||||
{
|
{
|
||||||
if (len)
|
if (len)
|
||||||
*len = ansp - start;
|
*len = ansp - start;
|
||||||
|
|
||||||
if (p)
|
if (p)
|
||||||
*p = save;
|
*p = save;
|
||||||
|
|
||||||
|
if (is_last)
|
||||||
|
*is_last = (i == arcount-1);
|
||||||
|
|
||||||
ret = start;
|
ret = start;
|
||||||
}
|
}
|
||||||
else if (is_sign &&
|
else if (is_sign &&
|
||||||
@@ -100,50 +105,31 @@ struct macparm {
|
|||||||
size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *limit,
|
size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *limit,
|
||||||
unsigned short udp_sz, int optno, unsigned char *opt, size_t optlen, int set_do)
|
unsigned short udp_sz, int optno, unsigned char *opt, size_t optlen, int set_do)
|
||||||
{
|
{
|
||||||
unsigned char *lenp, *datap, *p;
|
unsigned char *lenp, *datap, *p, *udp_len, *buff = NULL;
|
||||||
int rdlen, is_sign;
|
int rdlen = 0, is_sign, is_last;
|
||||||
|
unsigned short flags = set_do ? 0x8000 : 0, rcode = 0;
|
||||||
|
|
||||||
if (!(p = find_pseudoheader(header, plen, NULL, NULL, &is_sign)))
|
p = find_pseudoheader(header, plen, NULL, &udp_len, &is_sign, &is_last);
|
||||||
{
|
|
||||||
if (is_sign)
|
|
||||||
return plen;
|
|
||||||
|
|
||||||
/* We are adding the pseudoheader */
|
if (is_sign)
|
||||||
if (!(p = skip_questions(header, plen)) ||
|
return plen;
|
||||||
!(p = skip_section(p,
|
|
||||||
ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount),
|
if (p)
|
||||||
header, plen)))
|
|
||||||
return plen;
|
|
||||||
*p++ = 0; /* empty name */
|
|
||||||
PUTSHORT(T_OPT, p);
|
|
||||||
PUTSHORT(udp_sz, p); /* max packet length, 512 if not given in EDNS0 header */
|
|
||||||
PUTSHORT(0, p); /* extended RCODE and version */
|
|
||||||
PUTSHORT(set_do ? 0x8000 : 0, p); /* DO flag */
|
|
||||||
lenp = p;
|
|
||||||
PUTSHORT(0, p); /* RDLEN */
|
|
||||||
rdlen = 0;
|
|
||||||
if (((ssize_t)optlen) > (limit - (p + 4)))
|
|
||||||
return plen; /* Too big */
|
|
||||||
header->arcount = htons(ntohs(header->arcount) + 1);
|
|
||||||
datap = p;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
|
/* Existing header */
|
||||||
int i;
|
int i;
|
||||||
unsigned short code, len, flags;
|
unsigned short code, len;
|
||||||
|
|
||||||
/* Must be at the end, if exists */
|
p = udp_len;
|
||||||
if (ntohs(header->arcount) != 1 ||
|
GETSHORT(udp_sz, p);
|
||||||
is_sign ||
|
GETSHORT(rcode, p);
|
||||||
(!(p = skip_name(p, header, plen, 10))))
|
|
||||||
return plen;
|
|
||||||
|
|
||||||
p += 6; /* skip UDP length and RCODE */
|
|
||||||
GETSHORT(flags, p);
|
GETSHORT(flags, p);
|
||||||
|
|
||||||
if (set_do)
|
if (set_do)
|
||||||
{
|
{
|
||||||
p -=2;
|
p -=2;
|
||||||
PUTSHORT(flags | 0x8000, p);
|
flags |= 0x8000;
|
||||||
|
PUTSHORT(flags, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
lenp = p;
|
lenp = p;
|
||||||
@@ -166,21 +152,60 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
|
|||||||
p += len;
|
p += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((ssize_t)optlen) > (limit - (p + 4)))
|
/* If we're going to extend the RR, it has to be the last RR in the packet */
|
||||||
return plen; /* Too big */
|
if (!is_last)
|
||||||
|
{
|
||||||
|
/* First, take a copy of the options. */
|
||||||
|
if (rdlen != 0 && (buff = whine_malloc(rdlen)))
|
||||||
|
memcpy(buff, datap, rdlen);
|
||||||
|
|
||||||
|
/* now, delete OPT RR */
|
||||||
|
plen = rrfilter(header, plen, 0);
|
||||||
|
|
||||||
|
/* Now, force addition of a new one */
|
||||||
|
p = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!p)
|
||||||
|
{
|
||||||
|
/* We are (re)adding the pseudoheader */
|
||||||
|
if (!(p = skip_questions(header, plen)) ||
|
||||||
|
!(p = skip_section(p,
|
||||||
|
ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount),
|
||||||
|
header, plen)))
|
||||||
|
return plen;
|
||||||
|
*p++ = 0; /* empty name */
|
||||||
|
PUTSHORT(T_OPT, p);
|
||||||
|
PUTSHORT(udp_sz, p); /* max packet length, 512 if not given in EDNS0 header */
|
||||||
|
PUTSHORT(rcode, p); /* extended RCODE and version */
|
||||||
|
PUTSHORT(flags, p); /* DO flag */
|
||||||
|
lenp = p;
|
||||||
|
PUTSHORT(rdlen, p); /* RDLEN */
|
||||||
|
datap = p;
|
||||||
|
/* Copy back any options */
|
||||||
|
if (buff)
|
||||||
|
{
|
||||||
|
memcpy(p, buff, rdlen);
|
||||||
|
free(buff);
|
||||||
|
p += rdlen;
|
||||||
|
}
|
||||||
|
header->arcount = htons(ntohs(header->arcount) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((ssize_t)optlen) > (limit - (p + 4)))
|
||||||
|
return plen; /* Too big */
|
||||||
|
|
||||||
|
/* Add new option */
|
||||||
if (optno != 0)
|
if (optno != 0)
|
||||||
{
|
{
|
||||||
PUTSHORT(optno, p);
|
PUTSHORT(optno, p);
|
||||||
PUTSHORT(optlen, p);
|
PUTSHORT(optlen, p);
|
||||||
memcpy(p, opt, optlen);
|
memcpy(p, opt, optlen);
|
||||||
p += optlen;
|
p += optlen;
|
||||||
|
PUTSHORT(p - datap, lenp);
|
||||||
}
|
}
|
||||||
|
|
||||||
PUTSHORT(p - datap, lenp);
|
|
||||||
return p - (unsigned char *)header;
|
return p - (unsigned char *)header;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int filter_mac(int family, char *addrp, char *mac, size_t maclen, void *parmv)
|
static int filter_mac(int family, char *addrp, char *mac, size_t maclen, void *parmv)
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
|
blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
|
||||||
plen = forward->stash_len;
|
plen = forward->stash_len;
|
||||||
|
|
||||||
if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign) && !is_sign)
|
if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign, NULL) && !is_sign)
|
||||||
PUTSHORT(SAFE_PKTSZ, pheader);
|
PUTSHORT(SAFE_PKTSZ, pheader);
|
||||||
|
|
||||||
if (forward->sentto->addr.sa.sa_family == AF_INET)
|
if (forward->sentto->addr.sa.sa_family == AF_INET)
|
||||||
@@ -479,7 +479,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
if (option_bool(OPT_DNSSEC_VALID) && !do_bit)
|
if (option_bool(OPT_DNSSEC_VALID) && (forward->flags & FREC_ADDED_PHEADER))
|
||||||
{
|
{
|
||||||
/* Difficult one here. If our client didn't send EDNS0, we will have set the UDP
|
/* Difficult one here. If our client didn't send EDNS0, we will have set the UDP
|
||||||
packet size to 512. But that won't provide space for the RRSIGS in many cases.
|
packet size to 512. But that won't provide space for the RRSIGS in many cases.
|
||||||
@@ -489,7 +489,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
the truncated bit? */
|
the truncated bit? */
|
||||||
unsigned char *pheader;
|
unsigned char *pheader;
|
||||||
int is_sign;
|
int is_sign;
|
||||||
if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign))
|
if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign, NULL) && !is_sign)
|
||||||
PUTSHORT(start->edns_pktsz, pheader);
|
PUTSHORT(start->edns_pktsz, pheader);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -584,7 +584,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign)))
|
if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign, NULL)))
|
||||||
{
|
{
|
||||||
if (check_subnet && !check_source(header, plen, pheader, query_source))
|
if (check_subnet && !check_source(header, plen, pheader, query_source))
|
||||||
{
|
{
|
||||||
@@ -779,7 +779,7 @@ void reply_query(int fd, int family, time_t now)
|
|||||||
int is_sign;
|
int is_sign;
|
||||||
|
|
||||||
/* recreate query from reply */
|
/* recreate query from reply */
|
||||||
pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign);
|
pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign, NULL);
|
||||||
if (!is_sign)
|
if (!is_sign)
|
||||||
{
|
{
|
||||||
header->ancount = htons(0);
|
header->ancount = htons(0);
|
||||||
@@ -1313,7 +1313,7 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (find_pseudoheader(header, (size_t)n, NULL, &pheader, NULL))
|
if (find_pseudoheader(header, (size_t)n, NULL, &pheader, NULL, NULL))
|
||||||
{
|
{
|
||||||
unsigned short flags;
|
unsigned short flags;
|
||||||
|
|
||||||
@@ -1569,7 +1569,7 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
|
|
||||||
do_bit = 0;
|
do_bit = 0;
|
||||||
|
|
||||||
if (find_pseudoheader(header, (size_t)size, NULL, &pheader, NULL))
|
if (find_pseudoheader(header, (size_t)size, NULL, &pheader, NULL, NULL))
|
||||||
{
|
{
|
||||||
unsigned short flags;
|
unsigned short flags;
|
||||||
|
|
||||||
@@ -1578,7 +1578,7 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
GETSHORT(flags, pheader);
|
GETSHORT(flags, pheader);
|
||||||
|
|
||||||
if (flags & 0x8000)
|
if (flags & 0x8000)
|
||||||
do_bit = 1;/* do bit */
|
do_bit = 1; /* do bit */
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_AUTH
|
#ifdef HAVE_AUTH
|
||||||
|
|||||||
Reference in New Issue
Block a user