Merge branch 'master' into dnssec

This commit is contained in:
Simon Kelley
2013-12-12 12:16:17 +00:00
26 changed files with 4308 additions and 3728 deletions

View File

@@ -18,7 +18,7 @@
#ifdef HAVE_AUTH
static struct addrlist *filter_zone(struct auth_zone *zone, int flag, struct all_addr *addr_u)
static struct addrlist *find_subnet(struct auth_zone *zone, int flag, struct all_addr *addr_u)
{
struct addrlist *subnet;
@@ -45,6 +45,15 @@ static struct addrlist *filter_zone(struct auth_zone *zone, int flag, struct all
return NULL;
}
static int filter_zone(struct auth_zone *zone, int flag, struct all_addr *addr_u)
{
/* No zones specified, no filter */
if (!zone->subnet)
return 1;
return find_subnet(zone, flag, addr_u) != NULL;
}
int in_zone(struct auth_zone *zone, char *name, char **cut)
{
size_t namelen = strlen(name);
@@ -130,7 +139,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
if (!local_query)
{
for (zone = daemon->auth_zones; zone; zone = zone->next)
if ((subnet = filter_zone(zone, flag, &addr)))
if ((subnet = find_subnet(zone, flag, &addr)))
break;
if (!zone)

View File

@@ -320,7 +320,7 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign
if (is_expired(now, crecp) || is_outdated_cname_pointer(crecp))
{
*up = crecp->hash_next;
if (!(crecp->flags & (F_HOSTS | F_DHCP)))
if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
{
cache_unlink(crecp);
cache_free(crecp);
@@ -354,13 +354,13 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign
if (is_expired(now, crecp))
{
*up = crecp->hash_next;
if (!(crecp->flags & (F_HOSTS | F_DHCP)))
if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
{
cache_unlink(crecp);
cache_free(crecp);
}
}
else if (!(crecp->flags & (F_HOSTS | F_DHCP)) &&
else if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) &&
(flags & crecp->flags & F_REVERSE) &&
(flags & crecp->flags & (F_IPV4 | F_IPV6)) &&
memcmp(&crecp->addr.addr, addr, addrlen) == 0)
@@ -558,7 +558,7 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi
(crecp->flags & prot) &&
hostname_isequal(cache_get_name(crecp), name))
{
if (crecp->flags & (F_HOSTS | F_DHCP))
if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
{
*chainp = crecp;
chainp = &crecp->next;
@@ -599,7 +599,7 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi
{
/* expired entry, free it */
*up = crecp->hash_next;
if (!(crecp->flags & (F_HOSTS | F_DHCP)))
if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
{
cache_unlink(crecp);
cache_free(crecp);
@@ -649,7 +649,7 @@ struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr,
if ((crecp->flags & prot) &&
memcmp(&crecp->addr.addr, addr, addrlen) == 0)
{
if (crecp->flags & (F_HOSTS | F_DHCP))
if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
{
*chainp = crecp;
chainp = &crecp->next;
@@ -665,7 +665,7 @@ struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr,
else
{
*up = crecp->hash_next;
if (!(crecp->flags & (F_HOSTS | F_DHCP)))
if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
{
cache_unlink(crecp);
cache_free(crecp);
@@ -923,7 +923,7 @@ void cache_reload(void)
for (cache = hash_table[i], up = &hash_table[i]; cache; cache = tmp)
{
tmp = cache->hash_next;
if (cache->flags & F_HOSTS)
if (cache->flags & (F_HOSTS | F_CONFIG))
{
*up = cache->hash_next;
free(cache);
@@ -945,15 +945,15 @@ void cache_reload(void)
/* Add CNAMEs to interface_names to the cache */
for (a = daemon->cnames; a; a = a->next)
for (intr = daemon->int_names; intr; intr = intr->next)
if (hostname_isequal(a->target, intr->name))
if (hostname_isequal(a->target, intr->name) &&
((cache = whine_malloc(sizeof(struct crec)))))
{
struct crec *aliasc = safe_malloc(sizeof(struct crec));
aliasc->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG;
aliasc->name.namep = a->alias;
aliasc->addr.cname.target.int_name = intr;
aliasc->addr.cname.uid = -1;
cache_hash(aliasc);
add_hosts_cname(aliasc); /* handle chains */
cache->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG;
cache->name.namep = a->alias;
cache->addr.cname.target.int_name = intr;
cache->addr.cname.uid = -1;
cache_hash(cache);
add_hosts_cname(cache); /* handle chains */
}
/* borrow the packet buffer for a temporary by-address hash */
@@ -1083,7 +1083,7 @@ void cache_add_dhcp_entry(char *host_name, int prot,
while ((crec = cache_find_by_name(crec, host_name, 0, flags | F_CNAME)))
{
/* check all addresses associated with name */
if (crec->flags & F_HOSTS)
if (crec->flags & (F_HOSTS | F_CONFIG))
{
if (crec->flags & F_CNAME)
my_syslog(MS_DHCP | LOG_WARNING,

View File

@@ -190,10 +190,6 @@ HAVE_SOLARIS_NETWORK
HAVE_GETOPT_LONG
defined when GNU-style getopt_long available.
HAVE_ARC4RANDOM
defined if arc4random() available to get better security from DNS spoofs
by using really random ids (OpenBSD)
HAVE_SOCKADDR_SA_LEN
defined if struct sockaddr has sa_len field (*BSD)
*/
@@ -202,7 +198,6 @@ HAVE_SOCKADDR_SA_LEN
#if defined(__uClinux__)
#define HAVE_LINUX_NETWORK
#define HAVE_GETOPT_LONG
#undef HAVE_ARC4RANDOM
#undef HAVE_SOCKADDR_SA_LEN
/* Never use fork() on uClinux. Note that this is subtly different from the
--keep-in-foreground option, since it also suppresses forking new
@@ -216,7 +211,6 @@ HAVE_SOCKADDR_SA_LEN
((__UCLIBC_MAJOR__==0) && (__UCLIBC_MINOR__==9) && (__UCLIBC_SUBLEVEL__<21))
# define HAVE_GETOPT_LONG
#endif
#undef HAVE_ARC4RANDOM
#undef HAVE_SOCKADDR_SA_LEN
#if !defined(__ARCH_HAS_MMU__) && !defined(__UCLIBC_HAS_MMU__)
# define NO_FORK
@@ -231,7 +225,6 @@ HAVE_SOCKADDR_SA_LEN
#elif defined(__linux__)
#define HAVE_LINUX_NETWORK
#define HAVE_GETOPT_LONG
#undef HAVE_ARC4RANDOM
#undef HAVE_SOCKADDR_SA_LEN
#elif defined(__FreeBSD__) || \
@@ -243,15 +236,11 @@ HAVE_SOCKADDR_SA_LEN
#if defined(optional_argument) && defined(required_argument)
# define HAVE_GETOPT_LONG
#endif
#if !defined(__FreeBSD_kernel__)
# define HAVE_ARC4RANDOM
#endif
#define HAVE_SOCKADDR_SA_LEN
#elif defined(__APPLE__)
#define HAVE_BSD_NETWORK
#define HAVE_GETOPT_LONG
#define HAVE_ARC4RANDOM
#define HAVE_SOCKADDR_SA_LEN
/* Define before sys/socket.h is included so we get socklen_t */
#define _BSD_SOCKLEN_T_
@@ -262,13 +251,11 @@ HAVE_SOCKADDR_SA_LEN
#elif defined(__NetBSD__)
#define HAVE_BSD_NETWORK
#define HAVE_GETOPT_LONG
#undef HAVE_ARC4RANDOM
#define HAVE_SOCKADDR_SA_LEN
#elif defined(__sun) || defined(__sun__)
#define HAVE_SOLARIS_NETWORK
#define HAVE_GETOPT_LONG
#undef HAVE_ARC4RANDOM
#undef HAVE_SOCKADDR_SA_LEN
#define ETHER_ADDR_LEN 6

View File

@@ -330,9 +330,9 @@ static int complete_context6(struct in6_addr *local, int prefix,
{
if ((context->flags & CONTEXT_DHCP) &&
!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
prefix == context->prefix &&
is_same_net6(local, &context->start6, prefix) &&
is_same_net6(local, &context->end6, prefix))
prefix <= context->prefix &&
is_same_net6(local, &context->start6, context->prefix) &&
is_same_net6(local, &context->end6, context->prefix))
{
@@ -631,9 +631,9 @@ static int construct_worker(struct in6_addr *local, int prefix,
if (!(template->flags & CONTEXT_TEMPLATE))
{
/* non-template entries, just fill in interface and local addresses */
if (prefix == template->prefix &&
is_same_net6(local, &template->start6, prefix) &&
is_same_net6(local, &template->end6, prefix))
if (prefix <= template->prefix &&
is_same_net6(local, &template->start6, template->prefix) &&
is_same_net6(local, &template->end6, template->prefix))
{
template->if_index = if_index;
template->local6 = *local;
@@ -641,7 +641,7 @@ static int construct_worker(struct in6_addr *local, int prefix,
}
else if (wildcard_match(template->template_interface, ifrn_name) &&
template->prefix == prefix)
template->prefix >= prefix)
{
start6 = *local;
setaddr6part(&start6, addr6part(&template->start6));
@@ -661,6 +661,7 @@ static int construct_worker(struct in6_addr *local, int prefix,
log_context(AF_INET6, context);
/* fast RAs for a while */
ra_start_unsolicted(param->now, context);
param->newone = 1;
/* Add address to name again */
if (context->flags & CONTEXT_RA_NAME)
param->newname = 1;

View File

@@ -637,7 +637,10 @@ int main (int argc, char **argv)
if (bind_fallback)
my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
warn_bound_listeners();
if (option_bool(OPT_NOWILD))
warn_bound_listeners();
warn_int_names();
if (!option_bool(OPT_NOWILD))
for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)

View File

@@ -325,6 +325,7 @@ struct host_record {
struct interface_name {
char *name; /* domain name */
char *intr; /* interface name */
int family; /* AF_INET, AF_INET6 or zero for both */
struct addrlist *addr;
struct interface_name *next;
};
@@ -462,7 +463,7 @@ struct ipsets {
struct irec {
union mysockaddr addr;
struct in_addr netmask; /* only valid for IPv4 */
int tftp_ok, dhcp_ok, mtu, done, warned, dad, dns_auth, index, multicast_done;
int tftp_ok, dhcp_ok, mtu, done, warned, dad, dns_auth, index, multicast_done, found;
char *name;
struct irec *next;
};
@@ -1108,6 +1109,7 @@ int enumerate_interfaces(int reset);
void create_wildcard_listeners(void);
void create_bound_listeners(int die);
void warn_bound_listeners(void);
void warn_int_names(void);
int is_dad_listeners(void);
int iface_check(int family, struct all_addr *addr, char *name, int *auth_dns);
int loopback_exception(int fd, int family, struct all_addr *addr, char *name);

View File

@@ -785,8 +785,10 @@ void receive_query(struct listener *listen, time_t now)
struct in_addr netmask, dst_addr_4;
size_t m;
ssize_t n;
int if_index = 0;
int local_auth = 0, auth_dns = 0;
int if_index = 0, auth_dns = 0;
#ifdef HAVE_AUTH
int local_auth = 0;
#endif
struct iovec iov[1];
struct msghdr msg;
struct cmsghdr *cmptr;
@@ -805,7 +807,13 @@ void receive_query(struct listener *listen, time_t now)
CMSG_SPACE(sizeof(struct sockaddr_dl))];
#endif
} control_u;
#ifdef HAVE_IPV6
/* Can always get recvd interface for IPv6 */
int check_dst = !option_bool(OPT_NOWILD) || listen->family == AF_INET6;
#else
int check_dst = !option_bool(OPT_NOWILD);
#endif
/* packet buffer overwritten */
daemon->srv_save = NULL;
@@ -848,7 +856,7 @@ void receive_query(struct listener *listen, time_t now)
source_addr.in6.sin6_flowinfo = 0;
#endif
if (!option_bool(OPT_NOWILD))
if (check_dst)
{
struct ifreq ifr;
@@ -1026,7 +1034,9 @@ unsigned char *tcp_request(int confd, time_t now,
{
size_t size = 0;
int norebind = 0;
#ifdef HAVE_AUTH
int local_auth = 0;
#endif
int checking_disabled, check_subnet;
size_t m;
unsigned short qtype;

View File

@@ -252,6 +252,8 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
struct iname *tmp;
#endif
(void)prefixlen;
if (!indextoname(param->fd, if_index, ifr.ifr_name) ||
ioctl(param->fd, SIOCGIFFLAGS, &ifr) == -1)
return 0;
@@ -318,7 +320,8 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
{
al->next = zone->subnet;
zone->subnet = al;
al->prefixlen = prefixlen;al->addr.addr.addr6 = addr->in6.sin6_addr;
al->prefixlen = prefixlen;
al->addr.addr.addr6 = addr->in6.sin6_addr;
al->flags = ADDRLIST_IPV6;
}
}
@@ -330,7 +333,8 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
/* Update addresses from interface_names. These are a set independent
of the set we're listening on. */
for (int_name = daemon->int_names; int_name; int_name = int_name->next)
if (strncmp(label, int_name->intr, IF_NAMESIZE) == 0)
if (strncmp(label, int_name->intr, IF_NAMESIZE) == 0 &&
(addr->sa.sa_family == int_name->family || int_name->family == 0))
{
if (param->spare)
{
@@ -367,6 +371,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
if (sockaddr_isequal(&iface->addr, addr))
{
iface->dad = dad;
iface->found = 1; /* for garbage collection */
return 1;
}
@@ -441,6 +446,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
iface->dns_auth = auth_dns;
iface->mtu = mtu;
iface->dad = dad;
iface->found = 1;
iface->done = iface->multicast_done = iface->warned = 0;
iface->index = if_index;
if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
@@ -478,8 +484,12 @@ static int iface_allowed_v6(struct in6_addr *local, int prefix,
addr.in6.sin6_family = AF_INET6;
addr.in6.sin6_addr = *local;
addr.in6.sin6_port = htons(daemon->port);
addr.in6.sin6_scope_id = if_index;
/* FreeBSD insists this is zero for non-linklocal addresses */
if (IN6_IS_ADDR_LINKLOCAL(local))
addr.in6.sin6_scope_id = if_index;
else
addr.in6.sin6_scope_id = 0;
return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, !!(flags & IFACE_TENTATIVE));
}
#endif
@@ -513,6 +523,7 @@ int enumerate_interfaces(int reset)
int errsave, ret = 1;
struct addrlist *addr, *tmp;
struct interface_name *intname;
struct irec *iface;
#ifdef HAVE_AUTH
struct auth_zone *zone;
#endif
@@ -537,6 +548,10 @@ int enumerate_interfaces(int reset)
if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
return 0;
/* Mark interfaces for garbage collection */
for (iface = daemon->interfaces; iface; iface = iface->next)
iface->found = 0;
/* remove addresses stored against interface_names */
for (intname = daemon->int_names; intname; intname = intname->next)
{
@@ -583,11 +598,47 @@ int enumerate_interfaces(int reset)
errsave = errno;
close(param.fd);
if (option_bool(OPT_CLEVERBIND))
{
/* Garbage-collect listeners listening on addresses that no longer exist.
Does nothing when not binding interfaces or for listeners on localhost,
since the ->iface field is NULL. Note that this needs the protections
against re-entrancy, hence it's here. It also means there's a possibility,
in OPT_CLEVERBIND mode, that at listener will just disappear after
a call to enumerate_interfaces, this is checked OK on all calls. */
struct listener *l, *tmp, **up;
for (up = &daemon->listeners, l = daemon->listeners; l; l = tmp)
{
tmp = l->next;
if (!l->iface || l->iface->found)
up = &l->next;
else
{
*up = l->next;
/* In case it ever returns */
l->iface->done = 0;
if (l->fd != -1)
close(l->fd);
if (l->tcpfd != -1)
close(l->tcpfd);
if (l->tftpfd != -1)
close(l->tftpfd);
free(l);
}
}
}
errno = errsave;
spare = param.spare;
active = 0;
return ret;
}
@@ -610,7 +661,7 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
if ((fd = socket(family, type, 0)) == -1)
{
int port;
int port, errsav;
char *s;
/* No error if the kernel just doesn't support this IP flavour */
@@ -620,6 +671,7 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
return -1;
err:
errsav = errno;
port = prettyprint_addr(addr, daemon->addrbuff);
if (!option_bool(OPT_NOWILD) && !option_bool(OPT_CLEVERBIND))
sprintf(daemon->addrbuff, "port %d", port);
@@ -627,6 +679,8 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
if (fd != -1)
close (fd);
errno = errsav;
if (dienow)
{
@@ -657,9 +711,9 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
if (listen(fd, 5) == -1)
goto err;
}
else if (!option_bool(OPT_NOWILD))
else if (family == AF_INET)
{
if (family == AF_INET)
if (!option_bool(OPT_NOWILD))
{
#if defined(HAVE_LINUX_NETWORK)
if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1)
@@ -670,11 +724,11 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
goto err;
#endif
}
#ifdef HAVE_IPV6
else if (!set_ipv6pktinfo(fd))
goto err;
#endif
}
#ifdef HAVE_IPV6
else if (!set_ipv6pktinfo(fd))
goto err;
#endif
return fd;
}
@@ -822,7 +876,8 @@ static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, in
l->family = addr->sa.sa_family;
l->fd = fd;
l->tcpfd = tcpfd;
l->tftpfd = tftpfd;
l->tftpfd = tftpfd;
l->iface = NULL;
}
return l;
@@ -869,7 +924,7 @@ void create_bound_listeners(int dienow)
struct iname *if_tmp;
for (iface = daemon->interfaces; iface; iface = iface->next)
if (!iface->done && !iface->dad &&
if (!iface->done && !iface->dad && iface->found &&
(new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
{
new->iface = iface;
@@ -893,7 +948,6 @@ void create_bound_listeners(int dienow)
if (!if_tmp->used &&
(new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow)))
{
new->iface = NULL;
new->next = daemon->listeners;
daemon->listeners = new;
}
@@ -907,6 +961,9 @@ void create_bound_listeners(int dienow)
The fix is to use --bind-dynamic, which actually checks the arrival interface too.
Tough if your platform doesn't support this.
Note that checking the arrival interface is supported in the standard IPv6 API and
always done, so we don't warn about any IPv6 addresses here.
*/
void warn_bound_listeners(void)
@@ -915,43 +972,34 @@ void warn_bound_listeners(void)
int advice = 0;
for (iface = daemon->interfaces; iface; iface = iface->next)
if (option_bool(OPT_NOWILD) && !iface->dns_auth)
if (!iface->dns_auth)
{
int warn = 0;
if (iface->addr.sa.sa_family == AF_INET)
{
if (!private_net(iface->addr.in.sin_addr, 1))
{
inet_ntop(AF_INET, &iface->addr.in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
warn = 1;
iface->warned = advice = 1;
my_syslog(LOG_WARNING,
_("LOUD WARNING: listening on %s may accept requests via interfaces other than %s"),
daemon->addrbuff, iface->name);
}
}
#ifdef HAVE_IPV6
else
{
if (!IN6_IS_ADDR_LINKLOCAL(&iface->addr.in6.sin6_addr) &&
!IN6_IS_ADDR_SITELOCAL(&iface->addr.in6.sin6_addr) &&
!IN6_IS_ADDR_ULA(&iface->addr.in6.sin6_addr) &&
!IN6_IS_ADDR_LOOPBACK(&iface->addr.in6.sin6_addr))
{
inet_ntop(AF_INET6, &iface->addr.in6.sin6_addr, daemon->addrbuff, ADDRSTRLEN);
warn = 1;
}
}
#endif
if (warn)
{
iface->warned = advice = 1;
my_syslog(LOG_WARNING,
_("LOUD WARNING: listening on %s may accept requests via interfaces other than %s. "),
daemon->addrbuff, iface->name);
}
}
if (advice)
my_syslog(LOG_WARNING, _("LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid DNS amplification attacks via these interface(s)."));
my_syslog(LOG_WARNING, _("LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid DNS amplification attacks via these interface(s)"));
}
void warn_int_names(void)
{
struct interface_name *intname;
for (intname = daemon->int_names; intname; intname = intname->next)
if (!intname->addr)
my_syslog(LOG_WARNING, _("warning: no addresses found for interface %s"), intname->intr);
}
int is_dad_listeners(void)
{
struct irec *iface;

View File

@@ -3381,6 +3381,19 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
for (up = &daemon->int_names; *up; up = &((*up)->next));
*up = new;
new->name = domain;
new->family = 0;
arg = split_chr(comma, '/');
if (arg)
{
if (strcmp(arg, "4") == 0)
new->family = AF_INET;
#ifdef HAVE_IPV6
else if (strcmp(arg, "6") == 0)
new->family = AF_INET6;
#endif
else
ret_err(gen_err);
}
new->intr = opt_string_alloc(comma);
break;
}
@@ -3474,7 +3487,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;
size_t len = len;
char *data;
int val;

View File

@@ -430,7 +430,7 @@ static int add_prefixes(struct in6_addr *local, int prefix,
else if (!IN6_IS_ADDR_LOOPBACK(local) &&
!IN6_IS_ADDR_MULTICAST(local))
{
int do_prefix = 0;
int real_prefix = 0;
int do_slaac = 0;
int deprecate = 0;
int constructed = 0;
@@ -439,9 +439,9 @@ static int add_prefixes(struct in6_addr *local, int prefix,
for (context = daemon->dhcp6; context; context = context->next)
if (!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
prefix == context->prefix &&
is_same_net6(local, &context->start6, prefix) &&
is_same_net6(local, &context->end6, prefix))
prefix <= context->prefix &&
is_same_net6(local, &context->start6, context->prefix) &&
is_same_net6(local, &context->end6, context->prefix))
{
context->saved_valid = valid;
@@ -496,7 +496,7 @@ static int add_prefixes(struct in6_addr *local, int prefix,
if (!param->first)
context->ra_time = 0;
context->flags |= CONTEXT_RA_DONE;
do_prefix = 1;
real_prefix = context->prefix;
}
param->first = 0;
@@ -523,18 +523,18 @@ static int add_prefixes(struct in6_addr *local, int prefix,
param->link_global = *local;
}
if (do_prefix)
if (real_prefix != 0)
{
struct prefix_opt *opt;
if ((opt = expand(sizeof(struct prefix_opt))))
{
/* zero net part of address */
setaddr6part(local, addr6part(local) & ~((prefix == 64) ? (u64)-1LL : (1LLU << (128 - prefix)) - 1LLU));
setaddr6part(local, addr6part(local) & ~((real_prefix == 64) ? (u64)-1LL : (1LLU << (128 - real_prefix)) - 1LLU));
opt->type = ICMP6_OPT_PREFIX;
opt->len = 4;
opt->prefix_len = prefix;
opt->prefix_len = real_prefix;
/* autonomous only if we're not doing dhcp, always set "on-link" */
opt->flags = do_slaac ? 0xC0 : 0x80;
opt->valid_lifetime = htonl(valid);
@@ -645,9 +645,9 @@ static int iface_search(struct in6_addr *local, int prefix,
for (context = daemon->dhcp6; context; context = context->next)
if (!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
prefix == context->prefix &&
is_same_net6(local, &context->start6, prefix) &&
is_same_net6(local, &context->end6, prefix) &&
prefix <= context->prefix &&
is_same_net6(local, &context->start6, context->prefix) &&
is_same_net6(local, &context->end6, context->prefix) &&
context->ra_time != 0 &&
difftime(context->ra_time, param->now) <= 0.0)
{
@@ -670,9 +670,9 @@ static int iface_search(struct in6_addr *local, int prefix,
/* zero timers for other contexts on the same subnet, so they don't timeout
independently */
for (context = context->next; context; context = context->next)
if (prefix == context->prefix &&
is_same_net6(local, &context->start6, prefix) &&
is_same_net6(local, &context->end6, prefix))
if (prefix <= context->prefix &&
is_same_net6(local, &context->start6, context->prefix) &&
is_same_net6(local, &context->end6, context->prefix))
context->ra_time = 0;
return 0; /* found, abort */

View File

@@ -92,7 +92,10 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
struct dhcp_netid known_id, iface_id, cpewan_id;
struct dhcp_opt *o;
unsigned char pxe_uuid[17];
unsigned char *oui = NULL, *serial = NULL, *class = NULL;
unsigned char *oui = NULL, *serial = NULL;
#ifdef HAVE_SCRIPT
unsigned char *class = NULL;
#endif
subnet_addr.s_addr = override.s_addr = 0;
@@ -156,8 +159,9 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
unsigned char *y = option_ptr(opt, offset + elen + 5);
oui = option_find1(x, y, 1, 1);
serial = option_find1(x, y, 2, 1);
class = option_find1(x, y, 3, 1);
#ifdef HAVE_SCRIPT
class = option_find1(x, y, 3, 1);
#endif
/* If TR069-id is present set the tag "cpewan-id" to facilitate echoing
the gateway id back. Note that the device class is optional */
if (oui && serial)

View File

@@ -60,7 +60,12 @@ void tftp_request(struct listener *listen, time_t now)
char *prefix = daemon->tftp_prefix;
struct tftp_prefix *pref;
struct all_addr addra;
#ifdef HAVE_IPV6
/* Can always get recvd interface for IPv6 */
int check_dest = !option_bool(OPT_NOWILD) || listen->family == AF_INET6;
#else
int check_dest = !option_bool(OPT_NOWILD);
#endif
union {
struct cmsghdr align; /* this ensures alignment */
#ifdef HAVE_IPV6
@@ -91,8 +96,9 @@ void tftp_request(struct listener *listen, time_t now)
if ((len = recvmsg(listen->tftpfd, &msg, 0)) < 2)
return;
if (option_bool(OPT_NOWILD))
/* Can always get recvd interface for IPv6 */
if (!check_dest)
{
if (listen->iface)
{

View File

@@ -28,28 +28,6 @@
#include <idna.h>
#endif
#ifdef HAVE_ARC4RANDOM
void rand_init(void)
{
return;
}
unsigned short rand16(void)
{
return (unsigned short) (arc4random() >> 15);
}
u64 rand64(void)
{
u64 ret;
arc4random_buf(&ret, sizeof(ret));
return ret;
}
#else
/* SURF random number generator */
static u32 seed[32];
@@ -119,8 +97,6 @@ u64 rand64(void)
return (u64)out[outleft+1] + (((u64)out[outleft]) << 32);
}
#endif
static int check_name(char *in)
{
/* remove trailing .
@@ -482,7 +458,7 @@ int parse_hex(char *in, unsigned char *out, int maxlen,
int j, bytes = (1 + (r - in))/2;
for (j = 0; j < bytes; j++)
{
char sav;
char sav = sav;
if (j < bytes - 1)
{
sav = in[(j+1)*2];