Compare commits

...

12 Commits

Author SHA1 Message Date
Simon Kelley
2c0c36f54b Fix problem with IPv6 in new ARP-search code. 2016-05-01 20:57:08 +01:00
Simon Kelley
d6b749af91 Fix typo in SDBM hash function.
Thanks to Luis Carvalho for spotting the error.
2016-04-25 17:05:15 +01:00
Simon Kelley
14ffa0770b Fix init of per server EDNS UDP packet size. 2016-04-25 16:36:44 +01:00
Simon Kelley
87985855ad Remove pre-existing EDNS0_OPTION_NOMDEVICEID if MAC address unknown. 2016-04-25 15:33:30 +01:00
Simon Kelley
a2bc254bed Check return-code of inet_pton when parsing DHCPv4 options. 2016-04-21 22:41:31 +01:00
Simon Kelley
a7b27e84fa NULL pointer check. 2016-03-16 19:11:52 +00:00
Simon Kelley
529b030228 Tidy code. 2016-03-16 19:00:45 +00:00
Simon Kelley
4caa86dd7d Tidy. 2016-03-16 18:44:16 +00:00
Simon Kelley
e1abeeeec2 Fix memory leak in inotify code. 2016-03-16 18:12:35 +00:00
Simon Kelley
40205a053e Bound hash-iterations in DNSSEC NSEC3 checking. 2016-03-14 21:24:00 +00:00
Simon Kelley
b8ac466209 Tidy code. 2016-03-10 18:40:53 +00:00
Simon Kelley
d1377fa3c4 Account for TFTP packet headers in IPv6 correctly. 2016-03-04 21:32:21 +00:00
10 changed files with 89 additions and 57 deletions

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

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. */

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)

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)

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 */

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);
}

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);
}
}

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))
{

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;

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;
}