Commit c352dd8f authored by Simon Kelley's avatar Simon Kelley

Merge branch 'master' into dnssec

parents 3a237152 56ad6c9b
...@@ -32,7 +32,24 @@ version 2.68 ...@@ -32,7 +32,24 @@ version 2.68
the prefix is deleted (rather than replaced), it doesn't the prefix is deleted (rather than replaced), it doesn't
get advertised with zero preferred time. Thanks to Tsachi get advertised with zero preferred time. Thanks to Tsachi
for the bug report. for the bug report.
Fix segfault with some locally configured CNAMEs. Thanks
to Andrew Childs for spotting the problem.
Fix memory leak on re-reading /etc/hosts and friends,
introduced in 2.67.
Check the arrival interface of incoming DNS and TFTP
requests via IPv6, even in --bind-interfaces mode. This
isn't possible for IPv4 and can generate scary warnings,
but as it's always possible for IPv6 (the API always
exists) then we should do it always.
Tweak the rules on prefix-lengths in --dhcp-range for
IPv6. The new rule is that the specified prefix length
must be larger than or equal to the prefix length of the
corresponding address on the local interface.
version 2.67 version 2.67
Fix crash if upstream server returns SERVFAIL when Fix crash if upstream server returns SERVFAIL when
......
dnsmasq (2.68-1) unstable; urgency=low
* New upstream. (closes: #730553)
-- Simon Kelley <simon@thekelleys.org.uk> Sun, 8 Dec 2013 15:57:32 +0000
dnsmasq (2.67-1) unstable; urgency=low dnsmasq (2.67-1) unstable; urgency=low
* New upstream. * New upstream.
......
...@@ -514,11 +514,13 @@ record (which is always in the C_IN class). The value of the record is ...@@ -514,11 +514,13 @@ record (which is always in the C_IN class). The value of the record is
given by the hex data, which may be of the form 01:23:45 or 01 23 45 or given by the hex data, which may be of the form 01:23:45 or 01 23 45 or
012345 or any mixture of these. 012345 or any mixture of these.
.TP .TP
.B --interface-name=<name>,<interface> .B --interface-name=<name>,<interface>[/4|/6]
Return a DNS record associating the name with the primary address on Return a DNS record associating the name with the primary address on
the given interface. This flag specifies an A record for the given the given interface. This flag specifies an A or AAAA record for the given
name in the same way as an /etc/hosts line, except that the address is name in the same way as an /etc/hosts line, except that the address is
not constant, but taken from the given interface. If the interface is not constant, but taken from the given interface. The interface may be
followed by "/4" or "/6" to specify that only IPv4 or IPv6 addresses
of the interface should be used. If the interface is
down, not configured or non-existent, an empty record is returned. The down, not configured or non-existent, an empty record is returned. The
matching PTR record is also created, mapping the interface address to matching PTR record is also created, mapping the interface address to
the name. More than one name may be associated with an interface the name. More than one name may be associated with an interface
...@@ -593,8 +595,10 @@ needed for a client to do validation itself. ...@@ -593,8 +595,10 @@ needed for a client to do validation itself.
.TP .TP
.B --auth-zone=<domain>[,<subnet>[/<prefix length>][,<subnet>[/<prefix length>].....]] .B --auth-zone=<domain>[,<subnet>[/<prefix length>][,<subnet>[/<prefix length>].....]]
Define a DNS zone for which dnsmasq acts as authoritative server. Locally defined DNS records which are in the domain Define a DNS zone for which dnsmasq acts as authoritative server. Locally defined DNS records which are in the domain
will be served. A and AAAA records must be in one of the will be served. If subnet(s) are given, A and AAAA records must be in one of the
specified subnets. As alternative to directly specifying the subnets, it's possible to specified subnets.
As alternative to directly specifying the subnets, it's possible to
give the name of an interface, in which case the subnets implied by give the name of an interface, in which case the subnets implied by
that interface's configured addresses and netmask/prefix-length are that interface's configured addresses and netmask/prefix-length are
used; this is useful when using constructed DHCP ranges as the actual used; this is useful when using constructed DHCP ranges as the actual
...@@ -611,7 +615,8 @@ ipv6.arpa domains which are served for reverse-DNS queries. If not ...@@ -611,7 +615,8 @@ ipv6.arpa domains which are served for reverse-DNS queries. If not
specified, the prefix length defaults to 24 for IPv4 and 64 for IPv6. specified, the prefix length defaults to 24 for IPv4 and 64 for IPv6.
For IPv4 subnets, the prefix length should be have the value 8, 16 or 24 For IPv4 subnets, the prefix length should be have the value 8, 16 or 24
unless you are familiar with RFC 2317 and have arranged the unless you are familiar with RFC 2317 and have arranged the
in-addr.arpa delegation accordingly. in-addr.arpa delegation accordingly. Note that if no subnets are
specified, then no reverse queries are answered.
.TP .TP
.B --auth-soa=<serial>[,<hostmaster>[,<refresh>[,<retry>[,<expiry>]]]] .B --auth-soa=<serial>[,<hostmaster>[,<refresh>[,<retry>[,<expiry>]]]]
Specify fields in the SOA record associated with authoritative Specify fields in the SOA record associated with authoritative
...@@ -668,7 +673,8 @@ always optional. It is always ...@@ -668,7 +673,8 @@ always optional. It is always
allowed to have more than one dhcp-range in a single subnet. allowed to have more than one dhcp-range in a single subnet.
For IPv6, the parameters are slightly different: instead of netmask For IPv6, the parameters are slightly different: instead of netmask
and broadcast address, there is an optional prefix length. If not and broadcast address, there is an optional prefix length which must
be equal to or larger then the prefix length on the local interface. If not
given, this defaults to 64. Unlike the IPv4 case, the prefix length is not given, this defaults to 64. Unlike the IPv4 case, the prefix length is not
automatically derived from the interface configuration. The mimimum automatically derived from the interface configuration. The mimimum
size of the prefix length is 64. size of the prefix length is 64.
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#ifdef HAVE_AUTH #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; struct addrlist *subnet;
...@@ -45,6 +45,15 @@ static struct addrlist *filter_zone(struct auth_zone *zone, int flag, struct all ...@@ -45,6 +45,15 @@ static struct addrlist *filter_zone(struct auth_zone *zone, int flag, struct all
return NULL; 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) int in_zone(struct auth_zone *zone, char *name, char **cut)
{ {
size_t namelen = strlen(name); 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 ...@@ -130,7 +139,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
if (!local_query) if (!local_query)
{ {
for (zone = daemon->auth_zones; zone; zone = zone->next) for (zone = daemon->auth_zones; zone; zone = zone->next)
if ((subnet = filter_zone(zone, flag, &addr))) if ((subnet = find_subnet(zone, flag, &addr)))
break; break;
if (!zone) if (!zone)
......
...@@ -320,7 +320,7 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign ...@@ -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)) if (is_expired(now, crecp) || is_outdated_cname_pointer(crecp))
{ {
*up = crecp->hash_next; *up = crecp->hash_next;
if (!(crecp->flags & (F_HOSTS | F_DHCP))) if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
{ {
cache_unlink(crecp); cache_unlink(crecp);
cache_free(crecp); cache_free(crecp);
...@@ -354,13 +354,13 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign ...@@ -354,13 +354,13 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign
if (is_expired(now, crecp)) if (is_expired(now, crecp))
{ {
*up = crecp->hash_next; *up = crecp->hash_next;
if (!(crecp->flags & (F_HOSTS | F_DHCP))) if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
{ {
cache_unlink(crecp); cache_unlink(crecp);
cache_free(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_REVERSE) &&
(flags & crecp->flags & (F_IPV4 | F_IPV6)) && (flags & crecp->flags & (F_IPV4 | F_IPV6)) &&
memcmp(&crecp->addr.addr, addr, addrlen) == 0) 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 ...@@ -558,7 +558,7 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi
(crecp->flags & prot) && (crecp->flags & prot) &&
hostname_isequal(cache_get_name(crecp), name)) 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;
chainp = &crecp->next; chainp = &crecp->next;
...@@ -599,7 +599,7 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi ...@@ -599,7 +599,7 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi
{ {
/* expired entry, free it */ /* expired entry, free it */
*up = crecp->hash_next; *up = crecp->hash_next;
if (!(crecp->flags & (F_HOSTS | F_DHCP))) if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
{ {
cache_unlink(crecp); cache_unlink(crecp);
cache_free(crecp); cache_free(crecp);
...@@ -649,7 +649,7 @@ struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr, ...@@ -649,7 +649,7 @@ struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr,
if ((crecp->flags & prot) && if ((crecp->flags & prot) &&
memcmp(&crecp->addr.addr, addr, addrlen) == 0) 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;
chainp = &crecp->next; chainp = &crecp->next;
...@@ -665,7 +665,7 @@ struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr, ...@@ -665,7 +665,7 @@ struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr,
else else
{ {
*up = crecp->hash_next; *up = crecp->hash_next;
if (!(crecp->flags & (F_HOSTS | F_DHCP))) if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
{ {
cache_unlink(crecp); cache_unlink(crecp);
cache_free(crecp); cache_free(crecp);
...@@ -923,7 +923,7 @@ void cache_reload(void) ...@@ -923,7 +923,7 @@ void cache_reload(void)
for (cache = hash_table[i], up = &hash_table[i]; cache; cache = tmp) for (cache = hash_table[i], up = &hash_table[i]; cache; cache = tmp)
{ {
tmp = cache->hash_next; tmp = cache->hash_next;
if (cache->flags & F_HOSTS) if (cache->flags & (F_HOSTS | F_CONFIG))
{ {
*up = cache->hash_next; *up = cache->hash_next;
free(cache); free(cache);
...@@ -945,15 +945,15 @@ void cache_reload(void) ...@@ -945,15 +945,15 @@ void cache_reload(void)
/* Add CNAMEs to interface_names to the cache */ /* Add CNAMEs to interface_names to the cache */
for (a = daemon->cnames; a; a = a->next) for (a = daemon->cnames; a; a = a->next)
for (intr = daemon->int_names; intr; intr = intr->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)); cache->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG;
aliasc->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG; cache->name.namep = a->alias;
aliasc->name.namep = a->alias; cache->addr.cname.target.int_name = intr;
aliasc->addr.cname.target.int_name = intr; cache->addr.cname.uid = -1;
aliasc->addr.cname.uid = -1; cache_hash(cache);
cache_hash(aliasc); add_hosts_cname(cache); /* handle chains */
add_hosts_cname(aliasc); /* handle chains */
} }
/* borrow the packet buffer for a temporary by-address hash */ /* borrow the packet buffer for a temporary by-address hash */
...@@ -1083,7 +1083,7 @@ void cache_add_dhcp_entry(char *host_name, int prot, ...@@ -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))) while ((crec = cache_find_by_name(crec, host_name, 0, flags | F_CNAME)))
{ {
/* check all addresses associated with name */ /* check all addresses associated with name */
if (crec->flags & F_HOSTS) if (crec->flags & (F_HOSTS | F_CONFIG))
{ {
if (crec->flags & F_CNAME) if (crec->flags & F_CNAME)
my_syslog(MS_DHCP | LOG_WARNING, my_syslog(MS_DHCP | LOG_WARNING,
......
...@@ -190,10 +190,6 @@ HAVE_SOLARIS_NETWORK ...@@ -190,10 +190,6 @@ HAVE_SOLARIS_NETWORK
HAVE_GETOPT_LONG HAVE_GETOPT_LONG
defined when GNU-style getopt_long available. 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 HAVE_SOCKADDR_SA_LEN
defined if struct sockaddr has sa_len field (*BSD) defined if struct sockaddr has sa_len field (*BSD)
*/ */
...@@ -202,7 +198,6 @@ HAVE_SOCKADDR_SA_LEN ...@@ -202,7 +198,6 @@ HAVE_SOCKADDR_SA_LEN
#if defined(__uClinux__) #if defined(__uClinux__)
#define HAVE_LINUX_NETWORK #define HAVE_LINUX_NETWORK
#define HAVE_GETOPT_LONG #define HAVE_GETOPT_LONG
#undef HAVE_ARC4RANDOM
#undef HAVE_SOCKADDR_SA_LEN #undef HAVE_SOCKADDR_SA_LEN
/* Never use fork() on uClinux. Note that this is subtly different from the /* Never use fork() on uClinux. Note that this is subtly different from the
--keep-in-foreground option, since it also suppresses forking new --keep-in-foreground option, since it also suppresses forking new
...@@ -216,7 +211,6 @@ HAVE_SOCKADDR_SA_LEN ...@@ -216,7 +211,6 @@ HAVE_SOCKADDR_SA_LEN
((__UCLIBC_MAJOR__==0) && (__UCLIBC_MINOR__==9) && (__UCLIBC_SUBLEVEL__<21)) ((__UCLIBC_MAJOR__==0) && (__UCLIBC_MINOR__==9) && (__UCLIBC_SUBLEVEL__<21))
# define HAVE_GETOPT_LONG # define HAVE_GETOPT_LONG
#endif #endif
#undef HAVE_ARC4RANDOM
#undef HAVE_SOCKADDR_SA_LEN #undef HAVE_SOCKADDR_SA_LEN
#if !defined(__ARCH_HAS_MMU__) && !defined(__UCLIBC_HAS_MMU__) #if !defined(__ARCH_HAS_MMU__) && !defined(__UCLIBC_HAS_MMU__)
# define NO_FORK # define NO_FORK
...@@ -231,7 +225,6 @@ HAVE_SOCKADDR_SA_LEN ...@@ -231,7 +225,6 @@ HAVE_SOCKADDR_SA_LEN
#elif defined(__linux__) #elif defined(__linux__)
#define HAVE_LINUX_NETWORK #define HAVE_LINUX_NETWORK
#define HAVE_GETOPT_LONG #define HAVE_GETOPT_LONG
#undef HAVE_ARC4RANDOM
#undef HAVE_SOCKADDR_SA_LEN #undef HAVE_SOCKADDR_SA_LEN
#elif defined(__FreeBSD__) || \ #elif defined(__FreeBSD__) || \
...@@ -243,15 +236,11 @@ HAVE_SOCKADDR_SA_LEN ...@@ -243,15 +236,11 @@ HAVE_SOCKADDR_SA_LEN
#if defined(optional_argument) && defined(required_argument) #if defined(optional_argument) && defined(required_argument)
# define HAVE_GETOPT_LONG # define HAVE_GETOPT_LONG
#endif #endif
#if !defined(__FreeBSD_kernel__)
# define HAVE_ARC4RANDOM
#endif
#define HAVE_SOCKADDR_SA_LEN #define HAVE_SOCKADDR_SA_LEN
#elif defined(__APPLE__) #elif defined(__APPLE__)
#define HAVE_BSD_NETWORK #define HAVE_BSD_NETWORK
#define HAVE_GETOPT_LONG #define HAVE_GETOPT_LONG
#define HAVE_ARC4RANDOM
#define HAVE_SOCKADDR_SA_LEN #define HAVE_SOCKADDR_SA_LEN
/* Define before sys/socket.h is included so we get socklen_t */ /* Define before sys/socket.h is included so we get socklen_t */
#define _BSD_SOCKLEN_T_ #define _BSD_SOCKLEN_T_
...@@ -262,13 +251,11 @@ HAVE_SOCKADDR_SA_LEN ...@@ -262,13 +251,11 @@ HAVE_SOCKADDR_SA_LEN
#elif defined(__NetBSD__) #elif defined(__NetBSD__)
#define HAVE_BSD_NETWORK #define HAVE_BSD_NETWORK
#define HAVE_GETOPT_LONG #define HAVE_GETOPT_LONG
#undef HAVE_ARC4RANDOM
#define HAVE_SOCKADDR_SA_LEN #define HAVE_SOCKADDR_SA_LEN
#elif defined(__sun) || defined(__sun__) #elif defined(__sun) || defined(__sun__)
#define HAVE_SOLARIS_NETWORK #define HAVE_SOLARIS_NETWORK
#define HAVE_GETOPT_LONG #define HAVE_GETOPT_LONG
#undef HAVE_ARC4RANDOM
#undef HAVE_SOCKADDR_SA_LEN #undef HAVE_SOCKADDR_SA_LEN
#define ETHER_ADDR_LEN 6 #define ETHER_ADDR_LEN 6
......
...@@ -330,9 +330,9 @@ static int complete_context6(struct in6_addr *local, int prefix, ...@@ -330,9 +330,9 @@ static int complete_context6(struct in6_addr *local, int prefix,
{ {
if ((context->flags & CONTEXT_DHCP) && if ((context->flags & CONTEXT_DHCP) &&
!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) && !(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
prefix == context->prefix && prefix <= context->prefix &&
is_same_net6(local, &context->start6, prefix) && is_same_net6(local, &context->start6, context->prefix) &&
is_same_net6(local, &context->end6, prefix)) is_same_net6(local, &context->end6, context->prefix))
{ {
...@@ -631,9 +631,9 @@ static int construct_worker(struct in6_addr *local, int prefix, ...@@ -631,9 +631,9 @@ static int construct_worker(struct in6_addr *local, int prefix,
if (!(template->flags & CONTEXT_TEMPLATE)) if (!(template->flags & CONTEXT_TEMPLATE))
{ {
/* non-template entries, just fill in interface and local addresses */ /* non-template entries, just fill in interface and local addresses */
if (prefix == template->prefix && if (prefix <= template->prefix &&
is_same_net6(local, &template->start6, prefix) && is_same_net6(local, &template->start6, template->prefix) &&
is_same_net6(local, &template->end6, prefix)) is_same_net6(local, &template->end6, template->prefix))
{ {
template->if_index = if_index; template->if_index = if_index;
template->local6 = *local; template->local6 = *local;
...@@ -641,7 +641,7 @@ static int construct_worker(struct in6_addr *local, int prefix, ...@@ -641,7 +641,7 @@ static int construct_worker(struct in6_addr *local, int prefix,
} }
else if (wildcard_match(template->template_interface, ifrn_name) && else if (wildcard_match(template->template_interface, ifrn_name) &&
template->prefix == prefix) template->prefix >= prefix)
{ {
start6 = *local; start6 = *local;
setaddr6part(&start6, addr6part(&template->start6)); setaddr6part(&start6, addr6part(&template->start6));
...@@ -661,6 +661,7 @@ static int construct_worker(struct in6_addr *local, int prefix, ...@@ -661,6 +661,7 @@ static int construct_worker(struct in6_addr *local, int prefix,
log_context(AF_INET6, context); log_context(AF_INET6, context);
/* fast RAs for a while */ /* fast RAs for a while */
ra_start_unsolicted(param->now, context); ra_start_unsolicted(param->now, context);
param->newone = 1;
/* Add address to name again */ /* Add address to name again */
if (context->flags & CONTEXT_RA_NAME) if (context->flags & CONTEXT_RA_NAME)
param->newname = 1; param->newname = 1;
......
...@@ -637,7 +637,10 @@ int main (int argc, char **argv) ...@@ -637,7 +637,10 @@ int main (int argc, char **argv)
if (bind_fallback) if (bind_fallback)
my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations")); 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)) if (!option_bool(OPT_NOWILD))
for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next) for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
......
...@@ -325,6 +325,7 @@ struct host_record { ...@@ -325,6 +325,7 @@ struct host_record {
struct interface_name { struct interface_name {
char *name; /* domain name */ char *name; /* domain name */
char *intr; /* interface name */ char *intr; /* interface name */
int family; /* AF_INET, AF_INET6 or zero for both */
struct addrlist *addr; struct addrlist *addr;
struct interface_name *next; struct interface_name *next;
}; };
...@@ -462,7 +463,7 @@ struct ipsets { ...@@ -462,7 +463,7 @@ struct ipsets {
struct irec { struct irec {
union mysockaddr addr; union mysockaddr addr;
struct in_addr netmask; /* only valid for IPv4 */ 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; char *name;
struct irec *next; struct irec *next;
}; };
...@@ -1108,6 +1109,7 @@ int enumerate_interfaces(int reset); ...@@ -1108,6 +1109,7 @@ int enumerate_interfaces(int reset);
void create_wildcard_listeners(void); void create_wildcard_listeners(void);
void create_bound_listeners(int die); void create_bound_listeners(int die);
void warn_bound_listeners(void); void warn_bound_listeners(void);
void warn_int_names(void);
int is_dad_listeners(void); int is_dad_listeners(void);
int iface_check(int family, struct all_addr *addr, char *name, int *auth_dns); 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); int loopback_exception(int fd, int family, struct all_addr *addr, char *name);
......
...@@ -785,8 +785,10 @@ void receive_query(struct listener *listen, time_t now) ...@@ -785,8 +785,10 @@ void receive_query(struct listener *listen, time_t now)
struct in_addr netmask, dst_addr_4; struct in_addr netmask, dst_addr_4;
size_t m; size_t m;
ssize_t n; ssize_t n;
int if_index = 0; int if_index = 0, auth_dns = 0;
int local_auth = 0, auth_dns = 0; #ifdef HAVE_AUTH
int local_auth = 0;
#endif
struct iovec iov[1]; struct iovec iov[1];
struct msghdr msg; struct msghdr msg;
struct cmsghdr *cmptr; struct cmsghdr *cmptr;
...@@ -805,7 +807,13 @@ void receive_query(struct listener *listen, time_t now) ...@@ -805,7 +807,13 @@ void receive_query(struct listener *listen, time_t now)
CMSG_SPACE(sizeof(struct sockaddr_dl))]; CMSG_SPACE(sizeof(struct sockaddr_dl))];
#endif #endif
} control_u; } 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 */ /* packet buffer overwritten */
daemon->srv_save = NULL; daemon->srv_save = NULL;
...@@ -848,7 +856,7 @@ void receive_query(struct listener *listen, time_t now) ...@@ -848,7 +856,7 @@ void receive_query(struct listener *listen, time_t now)
source_addr.in6.sin6_flowinfo = 0; source_addr.in6.sin6_flowinfo = 0;
#endif #endif
if (!option_bool(OPT_NOWILD)) if (check_dst)
{ {
struct ifreq ifr; struct ifreq ifr;
...@@ -1026,7 +1034,9 @@ unsigned char *tcp_request(int confd, time_t now, ...@@ -1026,7 +1034,9 @@ unsigned char *tcp_request(int confd, time_t now,
{ {
size_t size = 0; size_t size = 0;
int norebind = 0; int norebind = 0;
#ifdef HAVE_AUTH
int local_auth = 0; int local_auth = 0;
#endif
int checking_disabled, check_subnet; int checking_disabled, check_subnet;
size_t m; size_t m;
unsigned short qtype; unsigned short qtype;
......
...@@ -252,6 +252,8 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label, ...@@ -252,6 +252,8 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
struct iname *tmp; struct iname *tmp;
#endif #endif
(void)prefixlen;
if (!indextoname(param->fd, if_index, ifr.ifr_name) || if (!indextoname(param->fd, if_index, ifr.ifr_name) ||
ioctl(param->fd, SIOCGIFFLAGS, &ifr) == -1) ioctl(param->fd, SIOCGIFFLAGS, &ifr) == -1)
return 0; return 0;
...@@ -318,7 +320,8 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label, ...@@ -318,7 +320,8 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
{ {
al->next = zone->subnet; al->next = zone->subnet;
zone->subnet = al; 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; al->flags = ADDRLIST_IPV6;
} }
} }
...@@ -330,7 +333,8 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label, ...@@ -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 /* Update addresses from interface_names. These are a set independent
of the set we're listening on. */ of the set we're listening on. */
for (int_name = daemon->int_names; int_name; int_name = int_name->next) 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) if (param->spare)
{ {
...@@ -367,6 +371,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label, ...@@ -367,6 +371,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
if (sockaddr_isequal(&iface->addr, addr)) if (sockaddr_isequal(&iface->addr, addr))
{ {
iface->dad = dad; iface->dad = dad;
iface->found = 1; /* for garbage collection */
return 1; return 1;
} }
...@@ -441,6 +446,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label, ...@@ -441,6 +446,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
iface->dns_auth = auth_dns; iface->dns_auth = auth_dns;
iface->mtu = mtu; iface->mtu = mtu;
iface->dad = dad; iface->dad = dad;
iface->found = 1;
iface->done = iface->multicast_done = iface->warned = 0; iface->done = iface->multicast_done = iface->warned = 0;
iface->index = if_index; iface->index = if_index;
if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1))) 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, ...@@ -478,8 +484,12 @@ static int iface_allowed_v6(struct in6_addr *local, int prefix,
addr.in6.sin6_family = AF_INET6; addr.in6.sin6_family = AF_INET6;
addr.in6.sin6_addr = *local; addr.in6.sin6_addr = *local;
addr.in6.sin6_port = htons(daemon->port); 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)); return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, !!(flags & IFACE_TENTATIVE));
} }
#endif #endif
...@@ -513,6 +523,7 @@ int enumerate_interfaces(int reset) ...@@ -513,6 +523,7 @@ int enumerate_interfaces(int reset)
int errsave, ret = 1; int errsave, ret = 1;
struct addrlist *addr, *tmp; struct addrlist *addr, *tmp;
struct interface_name *intname; struct interface_name *intname;
struct irec *iface;
#ifdef HAVE_AUTH #ifdef HAVE_AUTH
struct auth_zone *zone; struct auth_zone *zone;
#endif #endif
...@@ -537,6 +548,10 @@ int enumerate_interfaces(int reset) ...@@ -537,6 +548,10 @@ int enumerate_interfaces(int reset)
if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1) if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
return 0; return 0;
/* Mark interfaces for garbage collection */
for (iface = daemon->interfaces; iface; iface = iface->next)
iface->found = 0;
/* remove addresses stored against interface_names */ /* remove addresses stored against interface_names */
for (intname = daemon->int_names; intname; intname = intname->next) for (intname = daemon->int_names; intname; intname = intname->next)
{ {
...@@ -583,11 +598,47 @@ int enumerate_interfaces(int reset) ...@@ -583,11 +598,47 @@ int enumerate_interfaces(int reset)
errsave = errno; errsave = errno;
close(param.fd); 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; errno = errsave;
spare = param.spare; spare = param.spare;
active = 0; active = 0;
return ret; return ret;
} }
...@@ -610,7 +661,7 @@ static int make_sock(union mysockaddr *addr, int type, int dienow) ...@@ -610,7 +661,7 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
if ((fd = socket(family, type, 0)) == -1) if ((fd = socket(family, type, 0)) == -1)
{ {
int port; int port, errsav;
char *s; char *s;
/* No error if the kernel just doesn't support this IP flavour */ /* 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) ...@@ -620,6 +671,7 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
return -1; return -1;
err: err:
errsav = errno;
port = prettyprint_addr(addr, daemon->addrbuff); port = prettyprint_addr(addr, daemon->addrbuff);
if (!option_bool(OPT_NOWILD) && !option_bool(OPT_CLEVERBIND)) if (!option_bool(OPT_NOWILD) && !option_bool(OPT_CLEVERBIND))
sprintf(daemon->addrbuff, "port %d", port); sprintf(daemon->addrbuff, "port %d", port);
...@@ -627,6 +679,8 @@ static int make_sock(union mysockaddr *addr, int type, int dienow) ...@@ -627,6 +679,8 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
if (fd != -1) if (fd != -1)
close (fd); close (fd);
errno = errsav;
if (dienow) if (dienow)
{ {
...@@ -657,9 +711,9 @@ static int make_sock(union mysockaddr *addr, int type, int dienow) ...@@ -657,9 +711,9 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
if (listen(fd, 5) == -1) if (listen(fd, 5) == -1)
goto err; 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 defined(HAVE_LINUX_NETWORK)
if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1) 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) ...@@ -670,11 +724,11 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
goto err; goto err;
#endif #endif
} }
}
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
else if (!set_ipv6pktinfo(fd)) else if (!set_ipv6pktinfo(fd))
goto err; goto err;
#endif #endif
}
return fd; return fd;
} }
...@@ -822,7 +876,8 @@ static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, in ...@@ -822,7 +876,8 @@ static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, in
l->family = addr->sa.sa_family; l->family = addr->sa.sa_family;
l->fd = fd; l->fd = fd;
l->tcpfd = tcpfd; l->tcpfd = tcpfd;
l->tftpfd = tftpfd; l->tftpfd = tftpfd;
l->iface = NULL;
} }
return l; return l;
...@@ -869,7 +924,7 @@ void create_bound_listeners(int dienow) ...@@ -869,7 +924,7 @@ void create_bound_listeners(int dienow)
struct iname *if_tmp; struct iname *if_tmp;
for (iface = daemon->interfaces; iface; iface = iface->next) 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 = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
{ {
new->iface = iface; new->iface = iface;
...@@ -893,7 +948,6 @@ void create_bound_listeners(int dienow) ...@@ -893,7 +948,6 @@ void create_bound_listeners(int dienow)
if (!if_tmp->used && if (!if_tmp->used &&
(new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow))) (new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow)))
{ {
new->iface = NULL;
new->next = daemon->listeners; new->next = daemon->listeners;
daemon->listeners = new; daemon->listeners = new;
} }
...@@ -907,6 +961,9 @@ void create_bound_listeners(int dienow) ...@@ -907,6 +961,9 @@ void create_bound_listeners(int dienow)
The fix is to use --bind-dynamic, which actually checks the arrival interface too. The fix is to use --bind-dynamic, which actually checks the arrival interface too.
Tough if your platform doesn't support this. 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) void warn_bound_listeners(void)
...@@ -915,43 +972,34 @@ void warn_bound_listeners(void) ...@@ -915,43 +972,34 @@ void warn_bound_listeners(void)
int advice = 0; int advice = 0;
for (iface = daemon->interfaces; iface; iface = iface->next) 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 (iface->addr.sa.sa_family == AF_INET)
{ {
if (!private_net(iface->addr.in.sin_addr, 1)) if (!private_net(iface->addr.in.sin_addr, 1))
{ {
inet_ntop(AF_INET, &iface->addr.in.sin_addr, daemon->addrbuff, ADDRSTRLEN); 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) 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) int is_dad_listeners(void)
{ {
struct irec *iface; struct irec *iface;
......
...@@ -3381,6 +3381,19 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma ...@@ -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)); for (up = &daemon->int_names; *up; up = &((*up)->next));
*up = new; *up = new;
new->name = domain; 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); new->intr = opt_string_alloc(comma);
break; break;
} }
...@@ -3474,7 +3487,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma ...@@ -3474,7 +3487,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; size_t len = len;
char *data; char *data;
int val; int val;
......
...@@ -430,7 +430,7 @@ static int add_prefixes(struct in6_addr *local, int prefix, ...@@ -430,7 +430,7 @@ static int add_prefixes(struct in6_addr *local, int prefix,
else if (!IN6_IS_ADDR_LOOPBACK(local) && else if (!IN6_IS_ADDR_LOOPBACK(local) &&
!IN6_IS_ADDR_MULTICAST(local)) !IN6_IS_ADDR_MULTICAST(local))
{ {
int do_prefix = 0; int real_prefix = 0;
int do_slaac = 0; int do_slaac = 0;
int deprecate = 0; int deprecate = 0;
int constructed = 0; int constructed = 0;
...@@ -439,9 +439,9 @@ static int add_prefixes(struct in6_addr *local, int prefix, ...@@ -439,9 +439,9 @@ static int add_prefixes(struct in6_addr *local, int prefix,
for (context = daemon->dhcp6; context; context = context->next) for (context = daemon->dhcp6; context; context = context->next)
if (!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) && if (!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
prefix == context->prefix && prefix <= context->prefix &&
is_same_net6(local, &context->start6, prefix) && is_same_net6(local, &context->start6, context->prefix) &&
is_same_net6(local, &context->end6, prefix)) is_same_net6(local, &context->end6, context->prefix))
{ {
context->saved_valid = valid; context->saved_valid = valid;
...@@ -496,7 +496,7 @@ static int add_prefixes(struct in6_addr *local, int prefix, ...@@ -496,7 +496,7 @@ static int add_prefixes(struct in6_addr *local, int prefix,
if (!param->first) if (!param->first)
context->ra_time = 0; context->ra_time = 0;
context->flags |= CONTEXT_RA_DONE; context->flags |= CONTEXT_RA_DONE;
do_prefix = 1; real_prefix = context->prefix;
} }
param->first = 0; param->first = 0;
...@@ -523,18 +523,18 @@ static int add_prefixes(struct in6_addr *local, int prefix, ...@@ -523,18 +523,18 @@ static int add_prefixes(struct in6_addr *local, int prefix,
param->link_global = *local; param->link_global = *local;
} }
if (do_prefix) if (real_prefix != 0)
{ {
struct prefix_opt *opt; struct prefix_opt *opt;
if ((opt = expand(sizeof(struct prefix_opt)))) if ((opt = expand(sizeof(struct prefix_opt))))
{ {
/* zero net part of address */ /* 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->type = ICMP6_OPT_PREFIX;
opt->len = 4; opt->len = 4;
opt->prefix_len = prefix; opt->prefix_len = real_prefix;
/* autonomous only if we're not doing dhcp, always set "on-link" */ /* autonomous only if we're not doing dhcp, always set "on-link" */
opt->flags = do_slaac ? 0xC0 : 0x80; opt->flags = do_slaac ? 0xC0 : 0x80;
opt->valid_lifetime = htonl(valid); opt->valid_lifetime = htonl(valid);
...@@ -645,9 +645,9 @@ static int iface_search(struct in6_addr *local, int prefix, ...@@ -645,9 +645,9 @@ static int iface_search(struct in6_addr *local, int prefix,
for (context = daemon->dhcp6; context; context = context->next) for (context = daemon->dhcp6; context; context = context->next)
if (!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) && if (!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
prefix == context->prefix && prefix <= context->prefix &&
is_same_net6(local, &context->start6, prefix) && is_same_net6(local, &context->start6, context->prefix) &&
is_same_net6(local, &context->end6, prefix) && is_same_net6(local, &context->end6, context->prefix) &&
context->ra_time != 0 && context->ra_time != 0 &&
difftime(context->ra_time, param->now) <= 0.0) difftime(context->ra_time, param->now) <= 0.0)
{ {
...@@ -670,9 +670,9 @@ static int iface_search(struct in6_addr *local, int prefix, ...@@ -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 /* zero timers for other contexts on the same subnet, so they don't timeout
independently */ independently */
for (context = context->next; context; context = context->next) for (context = context->next; context; context = context->next)
if (prefix == context->prefix && if (prefix <= context->prefix &&
is_same_net6(local, &context->start6, prefix) && is_same_net6(local, &context->start6, context->prefix) &&
is_same_net6(local, &context->end6, prefix)) is_same_net6(local, &context->end6, context->prefix))
context->ra_time = 0; context->ra_time = 0;
return 0; /* found, abort */ return 0; /* found, abort */
......
...@@ -92,7 +92,10 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index, ...@@ -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_netid known_id, iface_id, cpewan_id;
struct dhcp_opt *o; struct dhcp_opt *o;
unsigned char pxe_uuid[17]; 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; 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, ...@@ -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); unsigned char *y = option_ptr(opt, offset + elen + 5);
oui = option_find1(x, y, 1, 1); oui = option_find1(x, y, 1, 1);
serial = option_find1(x, y, 2, 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 /* If TR069-id is present set the tag "cpewan-id" to facilitate echoing
the gateway id back. Note that the device class is optional */ the gateway id back. Note that the device class is optional */
if (oui && serial) if (oui && serial)
......
...@@ -60,7 +60,12 @@ void tftp_request(struct listener *listen, time_t now) ...@@ -60,7 +60,12 @@ void tftp_request(struct listener *listen, time_t now)
char *prefix = daemon->tftp_prefix; char *prefix = daemon->tftp_prefix;
struct tftp_prefix *pref; struct tftp_prefix *pref;
struct all_addr addra; 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 { union {
struct cmsghdr align; /* this ensures alignment */ struct cmsghdr align; /* this ensures alignment */
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
...@@ -91,8 +96,9 @@ void tftp_request(struct listener *listen, time_t now) ...@@ -91,8 +96,9 @@ void tftp_request(struct listener *listen, time_t now)
if ((len = recvmsg(listen->tftpfd, &msg, 0)) < 2) if ((len = recvmsg(listen->tftpfd, &msg, 0)) < 2)
return; return;
if (option_bool(OPT_NOWILD)) /* Can always get recvd interface for IPv6 */
if (!check_dest)
{ {
if (listen->iface) if (listen->iface)
{ {
......
...@@ -28,28 +28,6 @@ ...@@ -28,28 +28,6 @@
#include <idna.h> #include <idna.h>
#endif #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 */ /* SURF random number generator */
static u32 seed[32]; static u32 seed[32];
...@@ -119,8 +97,6 @@ u64 rand64(void) ...@@ -119,8 +97,6 @@ u64 rand64(void)
return (u64)out[outleft+1] + (((u64)out[outleft]) << 32); return (u64)out[outleft+1] + (((u64)out[outleft]) << 32);
} }
#endif
static int check_name(char *in) static int check_name(char *in)
{ {
/* remove trailing . /* remove trailing .
...@@ -482,7 +458,7 @@ int parse_hex(char *in, unsigned char *out, int maxlen, ...@@ -482,7 +458,7 @@ int parse_hex(char *in, unsigned char *out, int maxlen,
int j, bytes = (1 + (r - in))/2; int j, bytes = (1 + (r - in))/2;
for (j = 0; j < bytes; j++) for (j = 0; j < bytes; j++)
{ {
char sav; char sav = sav;
if (j < bytes - 1) if (j < bytes - 1)
{ {
sav = in[(j+1)*2]; sav = in[(j+1)*2];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment