Compare commits

...
6 Commits
10 changed files with 165 additions and 44 deletions

No files matched your search

+10
View File
@@ -1,3 +1,13 @@
version 2.69
Implement dynamic interface discovery on *BSD. This allows
the contructor: syntax to be used in dhcp-range for DHCPv6
on the BSD platform. Thanks to Matthias Andree for
valuable research on how to implement this.
Fix infinite loop associated with some --bogus-nxdomain
configs. Thanks fogobogo for the bug report.
version 2.68 version 2.68
Use random addresses for DHCPv6 temporary address Use random addresses for DHCPv6 temporary address
allocations, instead of algorithmically determined stable allocations, instead of algorithmically determined stable
+102 -4
View File
@@ -19,9 +19,9 @@
#if defined(HAVE_BSD_NETWORK) || defined(HAVE_SOLARIS_NETWORK) #if defined(HAVE_BSD_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
#include <ifaddrs.h> #include <ifaddrs.h>
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
#include <sys/param.h> #include <sys/param.h>
#include <sys/sysctl.h> #include <sys/sysctl.h>
#include <net/if.h>
#include <net/route.h> #include <net/route.h>
#include <net/if_dl.h> #include <net/if_dl.h>
#include <netinet/if_ether.h> #include <netinet/if_ether.h>
@@ -29,7 +29,9 @@
# include <net/if_var.h> # include <net/if_var.h>
#endif #endif
#include <netinet/in_var.h> #include <netinet/in_var.h>
#include <netinet6/in6_var.h> #ifdef HAVE_IPV6
# include <netinet6/in6_var.h>
#endif
#ifndef SA_SIZE #ifndef SA_SIZE
#define SA_SIZE(sa) \ #define SA_SIZE(sa) \
@@ -38,6 +40,13 @@
1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(long) - 1) ) ) 1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(long) - 1) ) )
#endif #endif
#ifdef HAVE_BSD_NETWORK
static int del_family = 0;
static struct all_addr del_addr;
#endif
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
int arp_enumerate(void *parm, int (*callback)()) int arp_enumerate(void *parm, int (*callback)())
{ {
int mib[6]; int mib[6];
@@ -88,7 +97,7 @@ int arp_enumerate(void *parm, int (*callback)())
return 1; return 1;
} }
#endif #endif /* defined(HAVE_BSD_NETWORK) && !defined(__APPLE__) */
int iface_enumerate(int family, void *parm, int (*callback)()) int iface_enumerate(int family, void *parm, int (*callback)())
@@ -129,6 +138,10 @@ int iface_enumerate(int family, void *parm, int (*callback)())
{ {
struct in_addr addr, netmask, broadcast; struct in_addr addr, netmask, broadcast;
addr = ((struct sockaddr_in *) addrs->ifa_addr)->sin_addr; addr = ((struct sockaddr_in *) addrs->ifa_addr)->sin_addr;
#ifdef HAVE_BSD_NETWORK
if (del_family == AF_INET && del_addr.addr.addr4.s_addr == addr.s_addr)
continue;
#endif
netmask = ((struct sockaddr_in *) addrs->ifa_netmask)->sin_addr; netmask = ((struct sockaddr_in *) addrs->ifa_netmask)->sin_addr;
if (addrs->ifa_broadaddr) if (addrs->ifa_broadaddr)
broadcast = ((struct sockaddr_in *) addrs->ifa_broadaddr)->sin_addr; broadcast = ((struct sockaddr_in *) addrs->ifa_broadaddr)->sin_addr;
@@ -146,6 +159,10 @@ int iface_enumerate(int family, void *parm, int (*callback)())
int i, j, prefix = 0; int i, j, prefix = 0;
u32 valid = 0xffffffff, preferred = 0xffffffff; u32 valid = 0xffffffff, preferred = 0xffffffff;
int flags = 0; int flags = 0;
#ifdef HAVE_BSD_NETWORK
if (del_family == AF_INET6 && IN6_ARE_ADDR_EQUAL(&del_addr.addr.addr6, addr))
continue;
#endif
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__) #if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
struct in6_ifreq ifr6; struct in6_ifreq ifr6;
@@ -226,7 +243,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
return ret; return ret;
} }
#endif #endif /* defined(HAVE_BSD_NETWORK) || defined(HAVE_SOLARIS_NETWORK) */
#if defined(HAVE_BSD_NETWORK) && defined(HAVE_DHCP) #if defined(HAVE_BSD_NETWORK) && defined(HAVE_DHCP)
@@ -345,6 +362,87 @@ void send_via_bpf(struct dhcp_packet *mess, size_t len,
while (writev(daemon->dhcp_raw_fd, iov, 4) == -1 && retry_send()); while (writev(daemon->dhcp_raw_fd, iov, 4) == -1 && retry_send());
} }
#endif /* defined(HAVE_BSD_NETWORK) && defined(HAVE_DHCP) */
#ifdef HAVE_BSD_NETWORK
void route_init(void)
{
/* AF_UNSPEC: all addr families */
daemon->routefd = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
if (daemon->routefd == -1 || !fix_fd(daemon->routefd))
die(_("cannot create PF_ROUTE socket: %s"), NULL, EC_BADNET);
}
void route_sock(time_t now)
{
struct if_msghdr *msg;
int rc = recv(daemon->routefd, daemon->packet, daemon->packet_buff_sz, 0);
if (rc < 4)
return;
msg = (struct if_msghdr *)daemon->packet;
if (rc < msg->ifm_msglen)
return;
if (msg->ifm_version != RTM_VERSION)
{
static int warned = 0;
if (!warned)
{
my_syslog(LOG_WARNING, _("Unknown protocol version from route socket"));
warned = 1;
}
}
else if (msg->ifm_type == RTM_NEWADDR)
{
del_family = 0;
newaddress(now);
}
else if (msg->ifm_type == RTM_DELADDR)
{
/* There's a race in the kernel, such that if we run iface_enumerate() immediately
we get a DELADDR event, the deleted address still appears. Here we store the deleted address
in a static variable, and omit it from the set returned by iface_enumerate() */
int mask = ((struct ifa_msghdr *)msg)->ifam_addrs;
int maskvec[] = { RTA_DST, RTA_GATEWAY, RTA_NETMASK, RTA_GENMASK,
RTA_IFP, RTA_IFA, RTA_AUTHOR, RTA_BRD };
int of;
unsigned int i;
for (i = 0, of = sizeof(struct ifa_msghdr); of < rc && i < sizeof(maskvec)/sizeof(maskvec[0]); i++)
if (mask & maskvec[i])
{
struct sockaddr *sa = (struct sockaddr *)((char *)msg + of);
size_t diff = (sa->sa_len != 0) ? sa->sa_len : sizeof(long);
if (maskvec[i] == RTA_IFA)
{
del_family = sa->sa_family;
if (del_family == AF_INET)
del_addr.addr.addr4 = ((struct sockaddr_in *)sa)->sin_addr;
#ifdef HAVE_IPV6
else if (del_family == AF_INET6)
del_addr.addr.addr6 = ((struct sockaddr_in6 *)sa)->sin6_addr;
#endif #endif
else
del_family = 0;
}
of += diff;
/* round up as needed */
if (diff & (sizeof(long) - 1))
of += sizeof(long) - (diff & (sizeof(long) - 1));
}
newaddress(now);
}
}
#endif /* HAVE_BSD_NETWORK */
-1
View File
@@ -720,7 +720,6 @@ void dhcp_construct_contexts(time_t now)
if (context->flags & CONTEXT_GC && !(context->flags & CONTEXT_OLD)) if (context->flags & CONTEXT_GC && !(context->flags & CONTEXT_OLD))
{ {
if ((context->flags & (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)) || if ((context->flags & (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)) ||
option_bool(OPT_RA)) option_bool(OPT_RA))
{ {
+13 -5
View File
@@ -182,7 +182,7 @@ int main (int argc, char **argv)
daemon->doing_dhcp6 = 1; daemon->doing_dhcp6 = 1;
if (context->flags & CONTEXT_RA) if (context->flags & CONTEXT_RA)
daemon->doing_ra = 1; daemon->doing_ra = 1;
#ifndef HAVE_LINUX_NETWORK #if !defined(HAVE_LINUX_NETWORK) && !defined(HAVE_BSD_NETWORK)
if (context->flags & CONTEXT_TEMPLATE) if (context->flags & CONTEXT_TEMPLATE)
die (_("dhcp-range constructor not available on this platform"), NULL, EC_BADCONF); die (_("dhcp-range constructor not available on this platform"), NULL, EC_BADCONF);
#endif #endif
@@ -220,12 +220,14 @@ int main (int argc, char **argv)
ipset_init(); ipset_init();
#endif #endif
#ifdef HAVE_LINUX_NETWORK #if defined(HAVE_LINUX_NETWORK)
netlink_init(); netlink_init();
#elif defined(HAVE_BSD_NETWORK)
route_init();
#endif
if (option_bool(OPT_NOWILD) && option_bool(OPT_CLEVERBIND)) if (option_bool(OPT_NOWILD) && option_bool(OPT_CLEVERBIND))
die(_("cannot set --bind-interfaces and --bind-dynamic"), NULL, EC_BADCONF); die(_("cannot set --bind-interfaces and --bind-dynamic"), NULL, EC_BADCONF);
#endif
if (!enumerate_interfaces(1) || !enumerate_interfaces(0)) if (!enumerate_interfaces(1) || !enumerate_interfaces(0))
die(_("failed to find list of interfaces: %s"), NULL, EC_MISC); die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
@@ -808,9 +810,12 @@ int main (int argc, char **argv)
} }
#endif #endif
#ifdef HAVE_LINUX_NETWORK #if defined(HAVE_LINUX_NETWORK)
FD_SET(daemon->netlinkfd, &rset); FD_SET(daemon->netlinkfd, &rset);
bump_maxfd(daemon->netlinkfd, &maxfd); bump_maxfd(daemon->netlinkfd, &maxfd);
#elif defined(HAVE_BSD_NETWORK)
FD_SET(daemon->routefd, &rset);
bump_maxfd(daemon->routefd, &maxfd);
#endif #endif
FD_SET(piperead, &rset); FD_SET(piperead, &rset);
@@ -867,9 +872,12 @@ int main (int argc, char **argv)
warn_bound_listeners(); warn_bound_listeners();
} }
#ifdef HAVE_LINUX_NETWORK #if defined(HAVE_LINUX_NETWORK)
if (FD_ISSET(daemon->netlinkfd, &rset)) if (FD_ISSET(daemon->netlinkfd, &rset))
netlink_multicast(now); netlink_multicast(now);
#elif defined(HAVE_BSD_NETWORK)
if (FD_ISSET(daemon->routefd, &rset))
route_sock(now);
#endif #endif
/* Check for changes to resolv files once per second max. */ /* Check for changes to resolv files once per second max. */
+8 -2
View File
@@ -561,7 +561,7 @@ struct dhcp_lease {
struct in6_addr addr6; struct in6_addr addr6;
int iaid; int iaid;
struct slaac_address { struct slaac_address {
struct in6_addr addr, local; struct in6_addr addr;
time_t ping_time; time_t ping_time;
int backoff; /* zero -> confirmed */ int backoff; /* zero -> confirmed */
struct slaac_address *next; struct slaac_address *next;
@@ -900,7 +900,7 @@ extern struct daemon {
#if defined(HAVE_LINUX_NETWORK) #if defined(HAVE_LINUX_NETWORK)
int netlinkfd; int netlinkfd;
#elif defined(HAVE_BSD_NETWORK) #elif defined(HAVE_BSD_NETWORK)
int dhcp_raw_fd, dhcp_icmp_fd; int dhcp_raw_fd, dhcp_icmp_fd, routefd;
#endif #endif
struct iovec dhcp_packet; struct iovec dhcp_packet;
char *dhcp_buff, *dhcp_buff2, *dhcp_buff3; char *dhcp_buff, *dhcp_buff2, *dhcp_buff3;
@@ -1090,6 +1090,10 @@ int set_ipv6pktinfo(int fd);
#ifdef HAVE_DHCP6 #ifdef HAVE_DHCP6
void join_multicast(int dienow); void join_multicast(int dienow);
#endif #endif
#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_BSD_NETWORK)
void newaddress(time_t now);
#endif
/* dhcp.c */ /* dhcp.c */
#ifdef HAVE_DHCP #ifdef HAVE_DHCP
@@ -1177,6 +1181,8 @@ void netlink_multicast(time_t now);
void init_bpf(void); void init_bpf(void);
void send_via_bpf(struct dhcp_packet *mess, size_t len, void send_via_bpf(struct dhcp_packet *mess, size_t len,
struct in_addr iface_addr, struct ifreq *ifr); struct in_addr iface_addr, struct ifreq *ifr);
void route_init(void);
void route_sock(time_t now);
#endif #endif
/* bpf.c or netlink.c */ /* bpf.c or netlink.c */
+2 -27
View File
@@ -39,7 +39,6 @@ static struct iovec iov;
static u32 netlink_pid; static u32 netlink_pid;
static int nl_async(struct nlmsghdr *h); static int nl_async(struct nlmsghdr *h);
static void nl_newaddress(time_t now);
void netlink_init(void) void netlink_init(void)
{ {
@@ -203,7 +202,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
/* handle async new interface address arrivals, these have to be done /* handle async new interface address arrivals, these have to be done
after we complete as we're not re-entrant */ after we complete as we're not re-entrant */
if (newaddr) if (newaddr)
nl_newaddress(dnsmasq_time()); newaddress(dnsmasq_time());
return callback_ok; return callback_ok;
} }
@@ -351,7 +350,7 @@ void netlink_multicast(time_t now)
fcntl(daemon->netlinkfd, F_SETFL, flags); fcntl(daemon->netlinkfd, F_SETFL, flags);
if (newaddr) if (newaddr)
nl_newaddress(now); newaddress(now);
} }
static int nl_async(struct nlmsghdr *h) static int nl_async(struct nlmsghdr *h)
@@ -399,30 +398,6 @@ static int nl_async(struct nlmsghdr *h)
return 0; return 0;
} }
static void nl_newaddress(time_t now)
{
(void)now;
if (option_bool(OPT_CLEVERBIND) || daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
enumerate_interfaces(0);
if (option_bool(OPT_CLEVERBIND))
create_bound_listeners(0);
#ifdef HAVE_DHCP6
if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
join_multicast(0);
if (daemon->doing_dhcp6 || daemon->doing_ra)
dhcp_construct_contexts(now);
if (daemon->doing_dhcp6)
lease_find_interfaces(now);
#endif
}
#endif #endif
+24
View File
@@ -1470,7 +1470,31 @@ int reload_servers(char *fname)
return gotone; return gotone;
} }
#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_BSD_NETWORK)
/* Called when addresses are added or deleted from an interface */
void newaddress(time_t now)
{
(void)now;
if (option_bool(OPT_CLEVERBIND) || daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
enumerate_interfaces(0);
if (option_bool(OPT_CLEVERBIND))
create_bound_listeners(0);
#ifdef HAVE_DHCP6
if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
join_multicast(0);
if (daemon->doing_dhcp6 || daemon->doing_ra)
dhcp_construct_contexts(now);
if (daemon->doing_dhcp6)
lease_find_interfaces(now);
#endif
}
#endif
+5 -3
View File
@@ -2732,7 +2732,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
else else
{ {
char *cp, *lastp = NULL, last = 0; char *cp, *lastp = NULL, last = 0;
int fac = 1; int fac = 1, isdig = 0;
if (strlen(a[j]) > 1) if (strlen(a[j]) > 1)
{ {
@@ -2763,7 +2763,9 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
} }
for (cp = a[j]; *cp; cp++) for (cp = a[j]; *cp; cp++)
if (!isdigit((unsigned char)*cp) && *cp != ' ') if (isdigit((unsigned char)*cp))
isdig = 1;
else if (*cp != ' ')
break; break;
if (*cp) if (*cp)
@@ -2787,7 +2789,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
new->domain = strip_hostname(new->hostname); new->domain = strip_hostname(new->hostname);
} }
} }
else else if (isdig)
{ {
new->lease_time = atoi(a[j]) * fac; new->lease_time = atoi(a[j]) * fac;
/* Leases of a minute or less confuse /* Leases of a minute or less confuse
+1 -1
View File
@@ -1283,7 +1283,7 @@ int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
/* Found a bogus address. Insert that info here, since there no SOA record /* Found a bogus address. Insert that info here, since there no SOA record
to get the ttl from in the normal processing */ to get the ttl from in the normal processing */
cache_start_insert(); cache_start_insert();
cache_insert(name, NULL, now, ttl, F_IPV4 | F_FORWARD | F_NEG | F_NXDOMAIN | F_CONFIG); cache_insert(name, NULL, now, ttl, F_IPV4 | F_FORWARD | F_NEG | F_NXDOMAIN);
cache_end_insert(); cache_end_insert();
return 1; return 1;
-1
View File
@@ -93,7 +93,6 @@ void slaac_add_addrs(struct dhcp_lease *lease, time_t now, int force)
slaac->ping_time = now; slaac->ping_time = now;
slaac->backoff = 1; slaac->backoff = 1;
slaac->addr = addr; slaac->addr = addr;
slaac->local = context->local6;
/* Do RA's to prod it */ /* Do RA's to prod it */
ra_start_unsolicted(now, context); ra_start_unsolicted(now, context);
} }