"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/edns0.c" between
dnsmasq-2.82.tar.xz and dnsmasq-2.83.tar.xz

About: Dnsmasq is a lightweight caching DNS forwarder and DHCP server.

edns0.c  (dnsmasq-2.82.tar.xz):edns0.c  (dnsmasq-2.83.tar.xz)
skipping to change at line 266 skipping to change at line 266
} }
static void encoder(unsigned char *in, char *out) static void encoder(unsigned char *in, char *out)
{ {
out[0] = char64(in[0]>>2); out[0] = char64(in[0]>>2);
out[1] = char64((in[0]<<4) | (in[1]>>4)); out[1] = char64((in[0]<<4) | (in[1]>>4));
out[2] = char64((in[1]<<2) | (in[2]>>6)); out[2] = char64((in[1]<<2) | (in[2]>>6));
out[3] = char64(in[2]); out[3] = char64(in[2]);
} }
static size_t add_dns_client(struct dns_header *header, size_t plen, unsigned ch static size_t add_dns_client(struct dns_header *header, size_t plen, unsigned ch
ar *limit, union mysockaddr *l3, time_t now) ar *limit,
union mysockaddr *l3, time_t now, int *cacheablep)
{ {
int maclen, replace = 2; /* can't get mac address, just delete any incoming. * / int maclen, replace = 2; /* can't get mac address, just delete any incoming. * /
unsigned char mac[DHCP_CHADDR_MAX]; unsigned char mac[DHCP_CHADDR_MAX];
char encode[18]; /* handle 6 byte MACs */ char encode[18]; /* handle 6 byte MACs */
if ((maclen = find_mac(l3, mac, 1, now)) == 6) if ((maclen = find_mac(l3, mac, 1, now)) == 6)
{ {
replace = 1; replace = 1;
*cacheablep = 0;
if (option_bool(OPT_MAC_HEX)) if (option_bool(OPT_MAC_HEX))
print_mac(encode, mac, maclen); print_mac(encode, mac, maclen);
else else
{ {
encoder(mac, encode); encoder(mac, encode);
encoder(mac+3, encode+4); encoder(mac+3, encode+4);
encode[8] = 0; encode[8] = 0;
} }
} }
return add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMDEVICEI D, (unsigned char *)encode, strlen(encode), 0, replace); return add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMDEVICEI D, (unsigned char *)encode, strlen(encode), 0, replace);
} }
static size_t add_mac(struct dns_header *header, size_t plen, unsigned char *lim static size_t add_mac(struct dns_header *header, size_t plen, unsigned char *lim
it, union mysockaddr *l3, time_t now) it,
union mysockaddr *l3, time_t now, int *cacheablep)
{ {
int maclen; int maclen;
unsigned char mac[DHCP_CHADDR_MAX]; unsigned char mac[DHCP_CHADDR_MAX];
if ((maclen = find_mac(l3, mac, 1, now)) != 0) if ((maclen = find_mac(l3, mac, 1, now)) != 0)
plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_MAC, mac {
, maclen, 0, 0); *cacheablep = 0;
plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_MAC, m
ac, maclen, 0, 0);
}
return plen; return plen;
} }
struct subnet_opt { struct subnet_opt {
u16 family; u16 family;
u8 source_netmask, scope_netmask; u8 source_netmask, scope_netmask;
u8 addr[IN6ADDRSZ]; u8 addr[IN6ADDRSZ];
}; };
static void *get_addrp(union mysockaddr *addr, const short family) static void *get_addrp(union mysockaddr *addr, const short family)
{ {
if (family == AF_INET6) if (family == AF_INET6)
return &addr->in6.sin6_addr; return &addr->in6.sin6_addr;
return &addr->in.sin_addr; return &addr->in.sin_addr;
} }
static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source) static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source, int *cacheablep)
{ {
/* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */ /* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
int len; int len;
void *addrp = NULL; void *addrp = NULL;
int sa_family = source->sa.sa_family; int sa_family = source->sa.sa_family;
int cacheable = 0;
opt->source_netmask = 0; opt->source_netmask = 0;
opt->scope_netmask = 0; opt->scope_netmask = 0;
if (source->sa.sa_family == AF_INET6 && daemon->add_subnet6) if (source->sa.sa_family == AF_INET6 && daemon->add_subnet6)
{ {
opt->source_netmask = daemon->add_subnet6->mask; opt->source_netmask = daemon->add_subnet6->mask;
if (daemon->add_subnet6->addr_used) if (daemon->add_subnet6->addr_used)
{ {
sa_family = daemon->add_subnet6->addr.sa.sa_family; sa_family = daemon->add_subnet6->addr.sa.sa_family;
addrp = get_addrp(&daemon->add_subnet6->addr, sa_family); addrp = get_addrp(&daemon->add_subnet6->addr, sa_family);
cacheable = 1;
} }
else else
addrp = &source->in6.sin6_addr; addrp = &source->in6.sin6_addr;
} }
if (source->sa.sa_family == AF_INET && daemon->add_subnet4) if (source->sa.sa_family == AF_INET && daemon->add_subnet4)
{ {
opt->source_netmask = daemon->add_subnet4->mask; opt->source_netmask = daemon->add_subnet4->mask;
if (daemon->add_subnet4->addr_used) if (daemon->add_subnet4->addr_used)
{ {
sa_family = daemon->add_subnet4->addr.sa.sa_family; sa_family = daemon->add_subnet4->addr.sa.sa_family;
addrp = get_addrp(&daemon->add_subnet4->addr, sa_family); addrp = get_addrp(&daemon->add_subnet4->addr, sa_family);
cacheable = 1; /* Address is constant */
} }
else else
addrp = &source->in.sin_addr; addrp = &source->in.sin_addr;
} }
opt->family = htons(sa_family == AF_INET6 ? 2 : 1); opt->family = htons(sa_family == AF_INET6 ? 2 : 1);
len = 0;
if (addrp && opt->source_netmask != 0) if (addrp && opt->source_netmask != 0)
{ {
len = ((opt->source_netmask - 1) >> 3) + 1; len = ((opt->source_netmask - 1) >> 3) + 1;
memcpy(opt->addr, addrp, len); memcpy(opt->addr, addrp, len);
if (opt->source_netmask & 7) if (opt->source_netmask & 7)
opt->addr[len-1] &= 0xff << (8 - (opt->source_netmask & 7)); opt->addr[len-1] &= 0xff << (8 - (opt->source_netmask & 7));
} }
else
{
cacheable = 1; /* No address ever supplied. */
len = 0;
}
if (cacheablep)
*cacheablep = cacheable;
return len + 4; return len + 4;
} }
static size_t add_source_addr(struct dns_header *header, size_t plen, unsigned c har *limit, union mysockaddr *source) static size_t add_source_addr(struct dns_header *header, size_t plen, unsigned c har *limit, union mysockaddr *source, int *cacheable)
{ {
/* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */ /* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
int len; int len;
struct subnet_opt opt; struct subnet_opt opt;
len = calc_subnet_opt(&opt, source); len = calc_subnet_opt(&opt, source, cacheable);
return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_ OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0, 0); return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_ OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0, 0);
} }
int check_source(struct dns_header *header, size_t plen, unsigned char *pseudohe ader, union mysockaddr *peer) int check_source(struct dns_header *header, size_t plen, unsigned char *pseudohe ader, union mysockaddr *peer)
{ {
/* Section 9.2, Check that subnet option in reply matches. */ /* Section 9.2, Check that subnet option in reply matches. */
int len, calc_len; int len, calc_len;
struct subnet_opt opt; struct subnet_opt opt;
unsigned char *p; unsigned char *p;
int code, i, rdlen; int code, i, rdlen;
calc_len = calc_subnet_opt(&opt, peer); calc_len = calc_subnet_opt(&opt, peer, NULL);
if (!(p = skip_name(pseudoheader, header, plen, 10))) if (!(p = skip_name(pseudoheader, header, plen, 10)))
return 1; return 1;
p += 8; /* skip UDP length and RCODE */ p += 8; /* skip UDP length and RCODE */
GETSHORT(rdlen, p); GETSHORT(rdlen, p);
if (!CHECK_LEN(header, p, plen, rdlen)) if (!CHECK_LEN(header, p, plen, rdlen))
return 1; /* bad packet */ return 1; /* bad packet */
/* check if option there */ /* check if option there */
for (i = 0; i + 4 < rdlen; i += len + 4) for (i = 0; i + 4 < rdlen; i += len + 4)
{ {
GETSHORT(code, p); GETSHORT(code, p);
GETSHORT(len, p); GETSHORT(len, p);
if (code == EDNS0_OPTION_CLIENT_SUBNET) if (code == EDNS0_OPTION_CLIENT_SUBNET)
{ {
/* make sure this doesn't mismatch. */ /* make sure this doesn't mismatch. */
opt.scope_netmask = p[3]; opt.scope_netmask = p[3];
if (len != calc_len || memcmp(p, &opt, len) != 0) if (len != calc_len || memcmp(p, &opt, len) != 0)
return 0; return 0;
} }
p += len; p += len;
} }
return 1; return 1;
} }
/* Set *check_subnet if we add a client subnet option, which needs to checked
in the reply. Set *cacheable to zero if we add an option which the answer
may depend on. */
size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *l imit, size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *l imit,
union mysockaddr *source, time_t now, int *check_subnet) union mysockaddr *source, time_t now, int *check_subnet, int *cacheable)
{ {
*check_subnet = 0; *check_subnet = 0;
*cacheable = 1;
if (option_bool(OPT_ADD_MAC)) if (option_bool(OPT_ADD_MAC))
plen = add_mac(header, plen, limit, source, now); plen = add_mac(header, plen, limit, source, now, cacheable);
if (option_bool(OPT_MAC_B64) || option_bool(OPT_MAC_HEX)) if (option_bool(OPT_MAC_B64) || option_bool(OPT_MAC_HEX))
plen = add_dns_client(header, plen, limit, source, now); plen = add_dns_client(header, plen, limit, source, now, cacheable);
if (daemon->dns_client_id) if (daemon->dns_client_id)
plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMCPEID , plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMCPEID ,
(unsigned char *)daemon->dns_client_id, strlen(daemon ->dns_client_id), 0, 1); (unsigned char *)daemon->dns_client_id, strlen(daemon ->dns_client_id), 0, 1);
if (option_bool(OPT_CLIENT_SUBNET)) if (option_bool(OPT_CLIENT_SUBNET))
{ {
plen = add_source_addr(header, plen, limit, source); plen = add_source_addr(header, plen, limit, source, cacheable);
*check_subnet = 1; *check_subnet = 1;
} }
return plen; return plen;
} }
 End of changes. 23 change blocks. 
23 lines changed or deleted 42 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)