Compare commits

...
12 Commits
10 changed files with 89 additions and 57 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
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
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)
{
if (addr->sa.sa_family == arp->family)
{
if (arp->addr.addr.addr4.s_addr != addr->in.sin_addr.s_addr)
continue;
}
if (addr->sa.sa_family != arp->family)
continue;
if (arp->family == AF_INET &&
arp->addr.addr.addr4.s_addr != addr->in.sin_addr.s_addr)
continue;
#ifdef HAVE_IPV6
else
{
if (!IN6_ARE_ADDR_EQUAL(&arp->addr.addr.addr6, &addr->in6.sin6_addr))
continue;
}
if (arp->family == AF_INET6 &&
!IN6_ARE_ADDR_EQUAL(&arp->addr.addr.addr6, &addr->in6.sin6_addr))
continue;
#endif
/* 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
dispersal even with similarly-valued "strings". */
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 (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();
else
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 (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;
p++; /* flags */
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 = p;
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, '.')));
if (!closest_encloser)
if (!closest_encloser || !next_closest)
return 0;
/* 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;
}
/* replace == 2 ->delete existing option only. */
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)
{
@@ -151,7 +153,7 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
if (code == optno)
{
if (!replace)
if (replace == 0)
return plen;
/* 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 */
/* Add new option */
if (optno != 0)
if (optno != 0 && replace != 2)
{
PUTSHORT(optno, 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)
{
int maclen;
int maclen, replace = 2; /* can't get mac address, just delete any incoming. */
unsigned char mac[DHCP_CHADDR_MAX];
char encode[18]; /* handle 6 byte MACs */
if ((maclen = find_mac(l3, mac, 1, now)) == 6)
{
replace = 1;
if (option_bool(OPT_MAC_HEX))
print_mac(encode, mac, maclen);
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);
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. */
if (errno == EINVAL || errno == ENOENT)
return NULL;
{
free(buf);
return NULL;
}
else
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);
}
}
closedir(dir_stream);
}
}
+27 -18
View File
@@ -532,13 +532,14 @@ static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
{
union mysockaddr addr;
int prefix, bit;
(void)broadcast; /* warning */
memset(&addr, 0, sizeof(addr));
#ifdef HAVE_SOCKADDR_SA_LEN
addr.in.sin_len = sizeof(addr.in);
#endif
addr.in.sin_family = AF_INET;
addr.in.sin_addr = broadcast; /* warning */
addr.in.sin_addr = local;
addr.in.sin_port = htons(daemon->port);
@@ -809,10 +810,11 @@ int tcp_interface(int fd, int af)
int opt = 1;
struct cmsghdr *cmptr;
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_controllen = daemon->packet_buff_sz;
msg.msg_controllen = len = daemon->packet_buff_sz;
/* we overwrote the buffer... */
daemon->srv_save = NULL;
@@ -820,18 +822,21 @@ int tcp_interface(int fd, int af)
if (af == AF_INET)
{
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)
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
{
union {
unsigned char *c;
struct in_pktinfo *p;
} p;
p.c = CMSG_DATA(cmptr);
if_index = p.p->ipi_ifindex;
}
getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, &len) != -1)
{
msg.msg_controllen = len;
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
{
union {
unsigned char *c;
struct in_pktinfo *p;
} p;
p.c = CMSG_DATA(cmptr);
if_index = p.p->ipi_ifindex;
}
}
}
#ifdef HAVE_IPV6
else
@@ -849,9 +854,10 @@ int tcp_interface(int fd, int af)
#endif
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)
{
union {
@@ -1403,7 +1409,6 @@ void add_update_server(int flags,
serv->domain = domain_str;
serv->next = next;
serv->queries = serv->failed_queries = 0;
serv->edns_pktsz = daemon->edns_pktsz;
#ifdef HAVE_LOOP
serv->uid = rand32();
#endif
@@ -1441,6 +1446,10 @@ void check_servers(void)
{
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
if (option_bool(OPT_DNSSEC_VALID))
{
+14 -17
View File
@@ -1199,7 +1199,8 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
cp = comma;
comma = split(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)
{
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)))
option = '?';
if (k == 3)
inet_pton(AF_INET, a[2], &new->mask);
if (k == 3 && !inet_pton(AF_INET, a[2], &new->mask))
option = '?';
if (dash &&
(!(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 */
{
struct txt_record *new;
size_t len = len;
size_t len = 0;
char *data;
int val;
@@ -4611,21 +4612,17 @@ void read_opts(int argc, char **argv, char *compile_opts)
{
struct server *tmp;
for (tmp = daemon->servers; tmp; tmp = tmp->next)
{
tmp->edns_pktsz = daemon->edns_pktsz;
if (!(tmp->flags & SERV_HAS_SOURCE))
{
if (tmp->source_addr.sa.sa_family == AF_INET)
tmp->source_addr.in.sin_port = htons(daemon->query_port);
if (!(tmp->flags & SERV_HAS_SOURCE))
{
if (tmp->source_addr.sa.sa_family == AF_INET)
tmp->source_addr.in.sin_port = htons(daemon->query_port);
#ifdef HAVE_IPV6
else if (tmp->source_addr.sa.sa_family == AF_INET6)
tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
else if (tmp->source_addr.sa.sa_family == AF_INET6)
tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
#endif
}
}
}
}
}
if (daemon->host_records)
{
struct host_record *hr;
+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))
{
/* 32 bytes for IP, UDP and TFTP headers, 52 bytes for IPv6 */
int overhead = (listen->family == AF_INET) ? 32 : 52;
transfer->blocksize = atoi(opt);
if (transfer->blocksize < 1)
transfer->blocksize = 1;
if (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 - 32)
transfer->blocksize = (unsigned)mtu - 32;
if (mtu != 0 && transfer->blocksize > (unsigned)mtu - overhead)
transfer->blocksize = (unsigned)mtu - overhead;
transfer->opt_blocksize = 1;
transfer->block = 0;
}