Compare commits

..
10 changed files with 86 additions and 54 deletions

No files matched your search

+9
View File
@@ -56,6 +56,15 @@ version 2.76
Add --tftp-mtu option. Thanks to Patrick McLean for the Add --tftp-mtu option. Thanks to Patrick McLean for the
initial patch. initial patch.
Check return-code of inet_pton() when parsing dhcp-option.
Bad addresses could fail to generate errors and result in
garbage dhcp-options being sent. Thanks to Marc Branchaud
for spotting this.
Fix wrong value for EDNS UDP packet size when using
--servers-file to define upstream DNS servers. Thanks to
Scott Bonar for the bug report.
version 2.75 version 2.75
Fix reversion on 2.74 which caused 100% CPU use when a Fix reversion on 2.74 which caused 100% CPU use when a
+10 -10
View File
@@ -129,17 +129,17 @@ int find_mac(union mysockaddr *addr, unsigned char *mac, int lazy, time_t now)
for (arp = arps; arp; arp = arp->next) for (arp = arps; arp; arp = arp->next)
{ {
if (addr->sa.sa_family == arp->family) if (addr->sa.sa_family != arp->family)
{ continue;
if (arp->addr.addr.addr4.s_addr != addr->in.sin_addr.s_addr)
continue; if (arp->family == AF_INET &&
} arp->addr.addr.addr4.s_addr != addr->in.sin_addr.s_addr)
continue;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
else if (arp->family == AF_INET6 &&
{ !IN6_ARE_ADDR_EQUAL(&arp->addr.addr.addr6, &addr->in6.sin6_addr))
if (!IN6_ARE_ADDR_EQUAL(&arp->addr.addr.addr6, &addr->in6.sin6_addr)) continue;
continue;
}
#endif #endif
/* Only accept positive entries unless in lazy mode. */ /* Only accept positive entries unless in lazy mode. */
+1 -1
View File
@@ -651,7 +651,7 @@ int address_allocate(struct dhcp_context *context,
/* hash hwaddr: use the SDBM hashing algorithm. Seems to give good /* hash hwaddr: use the SDBM hashing algorithm. Seems to give good
dispersal even with similarly-valued "strings". */ dispersal even with similarly-valued "strings". */
for (j = 0, i = 0; i < hw_len; i++) for (j = 0, i = 0; i < hw_len; i++)
j += hwaddr[i] + (j << 6) + (j << 16) - j; j = hwaddr[i] + (j << 6) + (j << 16) - j;
for (pass = 0; pass <= 1; pass++) for (pass = 0; pass <= 1; pass++)
for (c = context; c; c = c->current) for (c = context; c; c = c->current)
+1 -1
View File
@@ -420,7 +420,7 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned c
j = rand64(); j = rand64();
else else
for (j = iaid, i = 0; i < clid_len; i++) for (j = iaid, i = 0; i < clid_len; i++)
j += clid[i] + (j << 6) + (j << 16) - j; j = clid[i] + (j << 6) + (j << 16) - j;
for (pass = 0; pass <= plain_range ? 1 : 0; pass++) for (pass = 0; pass <= plain_range ? 1 : 0; pass++)
for (c = context; c; c = c->current) for (c = context; c; c = c->current)
+9 -1
View File
@@ -1697,7 +1697,15 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
return 0; return 0;
p++; /* flags */ p++; /* flags */
GETSHORT (iterations, p); GETSHORT (iterations, p);
/* Upper-bound iterations, to avoid DoS.
Strictly, there are lower bounds for small keys, but
since we don't have key size info here, at least limit
to the largest bound, for 4096-bit keys. RFC 5155 10.3 */
if (iterations > 2500)
return 0;
salt_len = *p++; salt_len = *p++;
salt = p; salt = p;
if (!CHECK_LEN(header, salt, plen, salt_len)) if (!CHECK_LEN(header, salt, plen, salt_len))
@@ -1783,7 +1791,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
} }
while ((closest_encloser = strchr(closest_encloser, '.'))); while ((closest_encloser = strchr(closest_encloser, '.')));
if (!closest_encloser) if (!closest_encloser || !next_closest)
return 0; return 0;
/* Look for NSEC3 that proves the non-existence of the next-closest encloser */ /* Look for NSEC3 that proves the non-existence of the next-closest encloser */
+8 -5
View File
@@ -95,6 +95,8 @@ unsigned char *find_pseudoheader(struct dns_header *header, size_t plen, size_t
return ret; return ret;
} }
/* replace == 2 ->delete existing option only. */
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, int replace) unsigned short udp_sz, int optno, unsigned char *opt, size_t optlen, int set_do, int replace)
{ {
@@ -151,7 +153,7 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
if (code == optno) if (code == optno)
{ {
if (!replace) if (replace == 0)
return plen; return plen;
/* delete option if we're to replace it. */ /* delete option if we're to replace it. */
@@ -213,7 +215,7 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
return plen; /* Too big */ return plen; /* Too big */
/* Add new option */ /* Add new option */
if (optno != 0) if (optno != 0 && replace != 2)
{ {
PUTSHORT(optno, p); PUTSHORT(optno, p);
PUTSHORT(optlen, p); PUTSHORT(optlen, p);
@@ -244,12 +246,14 @@ static void encoder(unsigned char *in, char *out)
static size_t add_dns_client(struct dns_header *header, size_t plen, unsigned char *limit, union mysockaddr *l3, time_t now) static size_t add_dns_client(struct dns_header *header, size_t plen, unsigned char *limit, union mysockaddr *l3, time_t now)
{ {
int maclen; 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;
if (option_bool(OPT_MAC_HEX)) if (option_bool(OPT_MAC_HEX))
print_mac(encode, mac, maclen); print_mac(encode, mac, maclen);
else else
@@ -258,10 +262,9 @@ static size_t add_dns_client(struct dns_header *header, size_t plen, unsigned ch
encoder(mac+3, encode+4); encoder(mac+3, encode+4);
encode[8] = 0; encode[8] = 0;
} }
plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMDEVICEID, (unsigned char *)encode, strlen(encode), 0, 1);
} }
return plen; return add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMDEVICEID, (unsigned char *)encode, strlen(encode), 0, replace);
} }
+6 -1
View File
@@ -54,7 +54,10 @@ static char *my_readlink(char *path)
{ {
/* Not link or doesn't exist. */ /* Not link or doesn't exist. */
if (errno == EINVAL || errno == ENOENT) if (errno == EINVAL || errno == ENOENT)
return NULL; {
free(buf);
return NULL;
}
else else
die(_("cannot access path %s: %s"), path, EC_MISC); die(_("cannot access path %s: %s"), path, EC_MISC);
} }
@@ -200,6 +203,8 @@ void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revh
free(path); free(path);
} }
} }
closedir(dir_stream);
} }
} }
+26 -17
View File
@@ -533,12 +533,13 @@ static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
union mysockaddr addr; union mysockaddr addr;
int prefix, bit; int prefix, bit;
(void)broadcast; /* warning */
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
#ifdef HAVE_SOCKADDR_SA_LEN #ifdef HAVE_SOCKADDR_SA_LEN
addr.in.sin_len = sizeof(addr.in); addr.in.sin_len = sizeof(addr.in);
#endif #endif
addr.in.sin_family = AF_INET; addr.in.sin_family = AF_INET;
addr.in.sin_addr = broadcast; /* warning */
addr.in.sin_addr = local; addr.in.sin_addr = local;
addr.in.sin_port = htons(daemon->port); addr.in.sin_port = htons(daemon->port);
@@ -809,10 +810,11 @@ int tcp_interface(int fd, int af)
int opt = 1; int opt = 1;
struct cmsghdr *cmptr; struct cmsghdr *cmptr;
struct msghdr msg; struct msghdr msg;
socklen_t len;
/* use mshdr do that the CMSDG_* macros are available */ /* use mshdr so that the CMSDG_* macros are available */
msg.msg_control = daemon->packet; msg.msg_control = daemon->packet;
msg.msg_controllen = daemon->packet_buff_sz; msg.msg_controllen = len = daemon->packet_buff_sz;
/* we overwrote the buffer... */ /* we overwrote the buffer... */
daemon->srv_save = NULL; daemon->srv_save = NULL;
@@ -820,18 +822,21 @@ int tcp_interface(int fd, int af)
if (af == AF_INET) if (af == AF_INET)
{ {
if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) != -1 && if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) != -1 &&
getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1) getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, &len) != -1)
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) {
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO) msg.msg_controllen = len;
{ for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
union { if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
unsigned char *c; {
struct in_pktinfo *p; union {
} p; unsigned char *c;
struct in_pktinfo *p;
} p;
p.c = CMSG_DATA(cmptr); p.c = CMSG_DATA(cmptr);
if_index = p.p->ipi_ifindex; if_index = p.p->ipi_ifindex;
} }
}
} }
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
else else
@@ -849,9 +854,10 @@ int tcp_interface(int fd, int af)
#endif #endif
if (set_ipv6pktinfo(fd) && if (set_ipv6pktinfo(fd) &&
getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1) getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, &len) != -1)
{ {
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) msg.msg_controllen = len;
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo) if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
{ {
union { union {
@@ -1403,7 +1409,6 @@ void add_update_server(int flags,
serv->domain = domain_str; serv->domain = domain_str;
serv->next = next; serv->next = next;
serv->queries = serv->failed_queries = 0; serv->queries = serv->failed_queries = 0;
serv->edns_pktsz = daemon->edns_pktsz;
#ifdef HAVE_LOOP #ifdef HAVE_LOOP
serv->uid = rand32(); serv->uid = rand32();
#endif #endif
@@ -1441,6 +1446,10 @@ void check_servers(void)
{ {
if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND))) if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
{ {
/* Init edns_pktsz for newly created server records. */
if (serv->edns_pktsz == 0)
serv->edns_pktsz = daemon->edns_pktsz;
#ifdef HAVE_DNSSEC #ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID)) if (option_bool(OPT_DNSSEC_VALID))
{ {
+12 -15
View File
@@ -1199,7 +1199,8 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
cp = comma; cp = comma;
comma = split(cp); comma = split(cp);
slash = split_chr(cp, '/'); slash = split_chr(cp, '/');
inet_pton(AF_INET, cp, &in); if (!inet_pton(AF_INET, cp, &in))
ret_err(_("bad IPv4 address"));
if (!slash) if (!slash)
{ {
memcpy(op, &in, INADDRSZ); memcpy(op, &in, INADDRSZ);
@@ -3658,8 +3659,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
(!(inet_pton(AF_INET, a[1], &new->out) > 0))) (!(inet_pton(AF_INET, a[1], &new->out) > 0)))
option = '?'; option = '?';
if (k == 3) if (k == 3 && !inet_pton(AF_INET, a[2], &new->mask))
inet_pton(AF_INET, a[2], &new->mask); option = '?';
if (dash && if (dash &&
(!(inet_pton(AF_INET, dash, &new->end) > 0) || (!(inet_pton(AF_INET, dash, &new->end) > 0) ||
@@ -3799,7 +3800,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
case LOPT_RR: /* dns-rr */ case LOPT_RR: /* dns-rr */
{ {
struct txt_record *new; struct txt_record *new;
size_t len = len; size_t len = 0;
char *data; char *data;
int val; int val;
@@ -4611,19 +4612,15 @@ void read_opts(int argc, char **argv, char *compile_opts)
{ {
struct server *tmp; struct server *tmp;
for (tmp = daemon->servers; tmp; tmp = tmp->next) for (tmp = daemon->servers; tmp; tmp = tmp->next)
{ if (!(tmp->flags & SERV_HAS_SOURCE))
tmp->edns_pktsz = daemon->edns_pktsz; {
if (tmp->source_addr.sa.sa_family == AF_INET)
if (!(tmp->flags & SERV_HAS_SOURCE)) tmp->source_addr.in.sin_port = htons(daemon->query_port);
{
if (tmp->source_addr.sa.sa_family == AF_INET)
tmp->source_addr.in.sin_port = htons(daemon->query_port);
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
else if (tmp->source_addr.sa.sa_family == AF_INET6) else if (tmp->source_addr.sa.sa_family == AF_INET6)
tmp->source_addr.in6.sin6_port = htons(daemon->query_port); tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
#endif #endif
} }
}
} }
if (daemon->host_records) if (daemon->host_records)
+4 -3
View File
@@ -346,14 +346,15 @@ void tftp_request(struct listener *listen, time_t now)
{ {
if ((opt = next(&p, end)) && !option_bool(OPT_TFTP_NOBLOCK)) if ((opt = next(&p, end)) && !option_bool(OPT_TFTP_NOBLOCK))
{ {
/* 32 bytes for IP, UDP and TFTP headers, 52 bytes for IPv6 */
int overhead = (listen->family == AF_INET) ? 32 : 52;
transfer->blocksize = atoi(opt); transfer->blocksize = atoi(opt);
if (transfer->blocksize < 1) if (transfer->blocksize < 1)
transfer->blocksize = 1; transfer->blocksize = 1;
if (transfer->blocksize > (unsigned)daemon->packet_buff_sz - 4) if (transfer->blocksize > (unsigned)daemon->packet_buff_sz - 4)
transfer->blocksize = (unsigned)daemon->packet_buff_sz - 4; transfer->blocksize = (unsigned)daemon->packet_buff_sz - 4;
/* 32 bytes for IP, UDP and TFTP headers */ if (mtu != 0 && transfer->blocksize > (unsigned)mtu - overhead)
if (mtu != 0 && transfer->blocksize > (unsigned)mtu - 32) transfer->blocksize = (unsigned)mtu - overhead;
transfer->blocksize = (unsigned)mtu - 32;
transfer->opt_blocksize = 1; transfer->opt_blocksize = 1;
transfer->block = 0; transfer->block = 0;
} }