mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-04 13:48:30 +00:00
Compare commits
17
Commits
v2.65test3
...
v2.66test2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b75c1e61f | ||
|
|
293fd0f700 | ||
|
|
c1be917782 | ||
|
|
bb86e858b6 | ||
|
|
8445f5d2e2 | ||
|
|
72c9c3b11b | ||
|
|
6e3dba3fde | ||
|
|
7558ecd9ac | ||
|
|
1f776932a1 | ||
|
|
4820dce97a | ||
|
|
f8abe0c566 | ||
|
|
9def963c65 | ||
|
|
990123a937 | ||
|
|
1d6c639310 | ||
|
|
429798fd08 | ||
|
|
b5a8dd1dec | ||
|
|
95a0bd3701 |
No files matched your search
+13
@@ -0,0 +1,13 @@
|
|||||||
|
src/*.o
|
||||||
|
src/*.mo
|
||||||
|
src/dnsmasq.pot
|
||||||
|
src/dnsmasq
|
||||||
|
src/.configured
|
||||||
|
contrib/wrt/dhcp_lease_time
|
||||||
|
contrib/wrt/dhcp_release
|
||||||
|
debian/base/
|
||||||
|
debian/daemon/
|
||||||
|
debian/files
|
||||||
|
debian/substvars
|
||||||
|
debian/utils-substvars
|
||||||
|
debian/utils/
|
||||||
@@ -3,6 +3,12 @@ version 2.65
|
|||||||
TCP which are not for A and AAAA and which were directed to
|
TCP which are not for A and AAAA and which were directed to
|
||||||
non-default servers. Thanks to Niax for the bug report.
|
non-default servers. Thanks to Niax for the bug report.
|
||||||
|
|
||||||
|
Fix failure to build with DHCP support excluded. Thanks to
|
||||||
|
Gustavo Zacarias for the patch.
|
||||||
|
|
||||||
|
Fix nasty regression in 2.64 which completely broke cacheing.
|
||||||
|
|
||||||
|
|
||||||
version 2.64
|
version 2.64
|
||||||
Handle DHCP FQDN options with all flag bits zero and
|
Handle DHCP FQDN options with all flag bits zero and
|
||||||
--dhcp-client-update set. Thanks to Bernd Krumbroeck for
|
--dhcp-client-update set. Thanks to Bernd Krumbroeck for
|
||||||
|
|||||||
+1
-1
@@ -17,7 +17,7 @@ elif grep '\$Format:%d\$' $1/VERSION >/dev/null 2>&1; then
|
|||||||
# unsubstituted VERSION, but no git available.
|
# unsubstituted VERSION, but no git available.
|
||||||
echo UNKNOWN
|
echo UNKNOWN
|
||||||
else
|
else
|
||||||
vers=`cat $1/VERSION | sed 's/[(), ]/,/ g' | tr ',' '\n' | grep $v[0-9]`
|
vers=`cat $1/VERSION | sed 's/[(), ]/,/ g' | tr ',' '\n' | grep ^v[0-9]`
|
||||||
|
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
echo "${vers}" | sort | head -n 1 | sed 's/^v//'
|
echo "${vers}" | sort | head -n 1 | sed 's/^v//'
|
||||||
|
|||||||
Vendored
+7
-1
@@ -1,8 +1,14 @@
|
|||||||
|
dnsmasq (2.66-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream.
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Fri, 14 Dec 2012 11:58:41 +0000
|
||||||
|
|
||||||
dnsmasq (2.65-1) unstable; urgency=low
|
dnsmasq (2.65-1) unstable; urgency=low
|
||||||
|
|
||||||
* New upstream.
|
* New upstream.
|
||||||
|
|
||||||
-- Simon Kelley <simon@thekelleys.org.uk> Tue, 4 Dec 2012 20:58:12 +0000
|
-- Simon Kelley <simon@thekelleys.org.uk> Fri, 14 Dec 2012 11:34:12 +0000
|
||||||
|
|
||||||
dnsmasq (2.64-1) unstable; urgency=low
|
dnsmasq (2.64-1) unstable; urgency=low
|
||||||
|
|
||||||
|
|||||||
+6
-2
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#include "dnsmasq.h"
|
#include "dnsmasq.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_AUTH
|
||||||
|
|
||||||
static struct subnet *filter_zone(struct auth_zone *zone, int flag, struct all_addr *addr_u)
|
static struct subnet *filter_zone(struct auth_zone *zone, int flag, struct all_addr *addr_u)
|
||||||
{
|
{
|
||||||
@@ -117,7 +118,10 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
GETSHORT(qclass, p);
|
GETSHORT(qclass, p);
|
||||||
|
|
||||||
if (qclass != C_IN)
|
if (qclass != C_IN)
|
||||||
continue;
|
{
|
||||||
|
auth = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (qtype == T_PTR)
|
if (qtype == T_PTR)
|
||||||
{
|
{
|
||||||
@@ -732,7 +736,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
return ansp - (unsigned char *)header;
|
return ansp - (unsigned char *)header;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -147,7 +147,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
addr->s6_addr[3] = 0;
|
addr->s6_addr[3] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!((*callback)(addr, prefix, scope_id, iface_index, 0, parm)))
|
if (!((*callback)(addr, prefix, scope_id, iface_index, 0, 0, 0, parm)))
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+1
-1
@@ -394,7 +394,7 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
|
|||||||
int freed_all = flags & F_REVERSE;
|
int freed_all = flags & F_REVERSE;
|
||||||
int free_avail = 0;
|
int free_avail = 0;
|
||||||
|
|
||||||
if(daemon->max_cache_ttl < ttl)
|
if (daemon->max_cache_ttl != 0 && daemon->max_cache_ttl < ttl)
|
||||||
ttl = daemon->max_cache_ttl;
|
ttl = daemon->max_cache_ttl;
|
||||||
|
|
||||||
/* Don't log keys */
|
/* Don't log keys */
|
||||||
|
|||||||
+15
-1
@@ -96,12 +96,18 @@ HAVE_CONNTRACK
|
|||||||
a build-dependency on libnetfilter_conntrack, but the resulting binary will
|
a build-dependency on libnetfilter_conntrack, but the resulting binary will
|
||||||
still run happily on a kernel without conntrack support.
|
still run happily on a kernel without conntrack support.
|
||||||
|
|
||||||
|
HAVE_AUTH
|
||||||
|
define this to include the facility to act as an authoritative DNS
|
||||||
|
server for one or more zones.
|
||||||
|
|
||||||
|
|
||||||
NO_IPV6
|
NO_IPV6
|
||||||
NO_TFTP
|
NO_TFTP
|
||||||
NO_DHCP
|
NO_DHCP
|
||||||
NO_DHCP6
|
NO_DHCP6
|
||||||
NO_SCRIPT
|
NO_SCRIPT
|
||||||
NO_LARGEFILE
|
NO_LARGEFILE
|
||||||
|
NO_AUTH
|
||||||
these are avilable to explictly disable compile time options which would
|
these are avilable to explictly disable compile time options which would
|
||||||
otherwise be enabled automatically (HAVE_IPV6, >2Gb file sizes) or
|
otherwise be enabled automatically (HAVE_IPV6, >2Gb file sizes) or
|
||||||
which are enabled by default in the distributed source tree. Building dnsmasq
|
which are enabled by default in the distributed source tree. Building dnsmasq
|
||||||
@@ -123,6 +129,7 @@ RESOLVFILE
|
|||||||
#define HAVE_DHCP6
|
#define HAVE_DHCP6
|
||||||
#define HAVE_TFTP
|
#define HAVE_TFTP
|
||||||
#define HAVE_SCRIPT
|
#define HAVE_SCRIPT
|
||||||
|
#define HAVE_AUTH
|
||||||
/* #define HAVE_LUASCRIPT */
|
/* #define HAVE_LUASCRIPT */
|
||||||
/* #define HAVE_BROKEN_RTC */
|
/* #define HAVE_BROKEN_RTC */
|
||||||
/* #define HAVE_DBUS */
|
/* #define HAVE_DBUS */
|
||||||
@@ -311,6 +318,9 @@ HAVE_SOCKADDR_SA_LEN
|
|||||||
#define HAVE_SCRIPT
|
#define HAVE_SCRIPT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef NO_AUTH
|
||||||
|
#undef HAVE_AUTH
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Define a string indicating which options are in use.
|
/* Define a string indicating which options are in use.
|
||||||
DNSMASQP_COMPILE_OPTS is only defined in dnsmasq.c */
|
DNSMASQP_COMPILE_OPTS is only defined in dnsmasq.c */
|
||||||
@@ -369,7 +379,11 @@ static char *compile_opts =
|
|||||||
#ifndef HAVE_CONNTRACK
|
#ifndef HAVE_CONNTRACK
|
||||||
"no-"
|
"no-"
|
||||||
#endif
|
#endif
|
||||||
"conntrack";
|
"conntrack "
|
||||||
|
#ifndef HAVE_AUTH
|
||||||
|
"no-"
|
||||||
|
#endif
|
||||||
|
"auth";
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+82
-77
@@ -333,83 +333,6 @@ void dhcp_update_configs(struct dhcp_config *configs)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
|
||||||
static int join_multicast_worker(struct in6_addr *local, int prefix,
|
|
||||||
int scope, int if_index, int dad, void *vparam)
|
|
||||||
{
|
|
||||||
char ifrn_name[IFNAMSIZ];
|
|
||||||
struct ipv6_mreq mreq;
|
|
||||||
int fd, i, max = *((int *)vparam);
|
|
||||||
struct iname *tmp;
|
|
||||||
|
|
||||||
(void)prefix;
|
|
||||||
(void)scope;
|
|
||||||
(void)dad;
|
|
||||||
|
|
||||||
/* record which interfaces we join on, so that we do it at most one per
|
|
||||||
interface, even when they have multiple addresses. Use outpacket
|
|
||||||
as an array of int, since it's always allocated here and easy
|
|
||||||
to expand for theoretical vast numbers of interfaces. */
|
|
||||||
for (i = 0; i < max; i++)
|
|
||||||
if (if_index == ((int *)daemon->outpacket.iov_base)[i])
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if ((fd = socket(PF_INET6, SOCK_DGRAM, 0)) == -1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!indextoname(fd, if_index, ifrn_name))
|
|
||||||
{
|
|
||||||
close(fd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
/* Are we doing DHCP on this interface? */
|
|
||||||
if (!iface_check(AF_INET6, (struct all_addr *)local, ifrn_name, NULL))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
|
||||||
if (tmp->name && (strcmp(tmp->name, ifrn_name) == 0))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
mreq.ipv6mr_interface = if_index;
|
|
||||||
|
|
||||||
inet_pton(AF_INET6, ALL_RELAY_AGENTS_AND_SERVERS, &mreq.ipv6mr_multiaddr);
|
|
||||||
|
|
||||||
if (daemon->dhcp6 &&
|
|
||||||
setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
inet_pton(AF_INET6, ALL_SERVERS, &mreq.ipv6mr_multiaddr);
|
|
||||||
|
|
||||||
if (daemon->dhcp6 &&
|
|
||||||
setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
inet_pton(AF_INET6, ALL_ROUTERS, &mreq.ipv6mr_multiaddr);
|
|
||||||
|
|
||||||
if (daemon->ra_contexts &&
|
|
||||||
setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
expand_buf(&daemon->outpacket, (max+1) * sizeof(int));
|
|
||||||
((int *)daemon->outpacket.iov_base)[max++] = if_index;
|
|
||||||
|
|
||||||
*((int *)vparam) = max;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void join_multicast(void)
|
|
||||||
{
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
if (!iface_enumerate(AF_INET6, &count, join_multicast_worker))
|
|
||||||
die(_("failed to join DHCPv6 multicast group: %s"), NULL, EC_BADNET);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_LINUX_NETWORK
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
void bindtodevice(int fd)
|
void bindtodevice(int fd)
|
||||||
{
|
{
|
||||||
@@ -750,4 +673,86 @@ char *option_string(int prot, unsigned int opt, unsigned char *val, int opt_len,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void log_context(int family, struct dhcp_context *context)
|
||||||
|
{
|
||||||
|
/* Cannot use dhcp_buff* for RA contexts */
|
||||||
|
|
||||||
|
void *start = &context->start;
|
||||||
|
void *end = &context->end;
|
||||||
|
char *n = "", *m = "", *p = daemon->namebuff;
|
||||||
|
|
||||||
|
*p = 0;
|
||||||
|
|
||||||
|
#ifdef HAVE_DHCP6
|
||||||
|
if (family == AF_INET6)
|
||||||
|
{
|
||||||
|
struct in6_addr subnet = context->start6;
|
||||||
|
if (!(context->flags & CONTEXT_TEMPLATE))
|
||||||
|
setaddr6part(&subnet, 0);
|
||||||
|
inet_ntop(AF_INET6, &subnet, daemon->addrbuff, ADDRSTRLEN);
|
||||||
|
start = &context->start6;
|
||||||
|
end = &context->end6;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((context->flags & CONTEXT_DHCP) ||
|
||||||
|
!(context->flags & (CONTEXT_CONSTRUCTED | CONTEXT_TEMPLATE)))
|
||||||
|
{
|
||||||
|
if (family != AF_INET && (context->flags & CONTEXT_DEPRECATE))
|
||||||
|
strcpy(daemon->namebuff, _(", prefix deprecated"));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p += sprintf(p, _(", lease time "));
|
||||||
|
m = p;
|
||||||
|
prettyprint_time(p, context->lease_time);
|
||||||
|
p += strlen(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_DHCP6
|
||||||
|
if (context->flags & CONTEXT_CONSTRUCTED)
|
||||||
|
{
|
||||||
|
n = p;
|
||||||
|
p += sprintf(p, ", constructed for %s", context->template_interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context->flags & CONTEXT_TEMPLATE)
|
||||||
|
{
|
||||||
|
n = p;
|
||||||
|
p += sprintf(p, ", template for %s", context->template_interface);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((context->flags & CONTEXT_DHCP) || family == AF_INET)
|
||||||
|
{
|
||||||
|
inet_ntop(family, start, daemon->dhcp_buff, 256);
|
||||||
|
inet_ntop(family, end, daemon->dhcp_buff3, 256);
|
||||||
|
my_syslog(MS_DHCP | LOG_INFO,
|
||||||
|
(context->flags & CONTEXT_RA_STATELESS) ?
|
||||||
|
_("%s stateless on %s%.0s%.0s") :
|
||||||
|
(context->flags & CONTEXT_STATIC) ?
|
||||||
|
_("%s, static leases only on %.0s%s%s") :
|
||||||
|
(context->flags & CONTEXT_PROXY) ?
|
||||||
|
_("%s, proxy on subnet %.0s%s%.0s") :
|
||||||
|
_("%s, IP range %s -- %s%s"),
|
||||||
|
(family != AF_INET) ? "DHCPv6" : "DHCP",
|
||||||
|
daemon->dhcp_buff, daemon->dhcp_buff3, daemon->namebuff);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_DHCP6
|
||||||
|
if (context->flags & CONTEXT_RA_NAME)
|
||||||
|
my_syslog(MS_DHCP | LOG_INFO, _("DHCPv4-derived IPv6 names on %s%s"),
|
||||||
|
daemon->addrbuff, n);
|
||||||
|
|
||||||
|
|
||||||
|
if (context->flags & CONTEXT_RA)
|
||||||
|
my_syslog(MS_DHCP | LOG_INFO, _("router advertisement on %s%s%s"),
|
||||||
|
daemon->addrbuff,
|
||||||
|
(context->flags & (CONTEXT_CONSTRUCTED | CONTEXT_TEMPLATE)) ? "" : ", prefix valid ",
|
||||||
|
(context->flags & (CONTEXT_CONSTRUCTED | CONTEXT_TEMPLATE)) ? n : m);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
+222
-3
@@ -25,7 +25,8 @@ struct iface_param {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static int complete_context6(struct in6_addr *local, int prefix,
|
static int complete_context6(struct in6_addr *local, int prefix,
|
||||||
int scope, int if_index, int dad, void *vparam);
|
int scope, int if_index, int dad,
|
||||||
|
int preferred, int valid, void *vparam);
|
||||||
|
|
||||||
static int make_duid1(int index, unsigned int type, char *mac, size_t maclen, void *parm);
|
static int make_duid1(int index, unsigned int type, char *mac, size_t maclen, void *parm);
|
||||||
|
|
||||||
@@ -181,7 +182,8 @@ void dhcp6_packet(time_t now)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int complete_context6(struct in6_addr *local, int prefix,
|
static int complete_context6(struct in6_addr *local, int prefix,
|
||||||
int scope, int if_index, int dad, void *vparam)
|
int scope, int if_index, int dad, int preferred,
|
||||||
|
int valid, void *vparam)
|
||||||
{
|
{
|
||||||
struct dhcp_context *context;
|
struct dhcp_context *context;
|
||||||
struct iface_param *param = vparam;
|
struct iface_param *param = vparam;
|
||||||
@@ -189,6 +191,8 @@ static int complete_context6(struct in6_addr *local, int prefix,
|
|||||||
|
|
||||||
(void)scope; /* warning */
|
(void)scope; /* warning */
|
||||||
(void)dad;
|
(void)dad;
|
||||||
|
(void)preferred;
|
||||||
|
(void)valid;
|
||||||
|
|
||||||
if (if_index == param->ind &&
|
if (if_index == param->ind &&
|
||||||
!IN6_IS_ADDR_LOOPBACK(local) &&
|
!IN6_IS_ADDR_LOOPBACK(local) &&
|
||||||
@@ -210,7 +214,8 @@ static int complete_context6(struct in6_addr *local, int prefix,
|
|||||||
|
|
||||||
for (context = daemon->dhcp6; context; context = context->next)
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
{
|
{
|
||||||
if (prefix == context->prefix &&
|
if (!(context->flags & CONTEXT_TEMPLATE) &&
|
||||||
|
prefix == context->prefix &&
|
||||||
is_same_net6(local, &context->start6, prefix) &&
|
is_same_net6(local, &context->start6, prefix) &&
|
||||||
is_same_net6(local, &context->end6, prefix))
|
is_same_net6(local, &context->end6, prefix))
|
||||||
{
|
{
|
||||||
@@ -467,6 +472,220 @@ static int make_duid1(int index, unsigned int type, char *mac, size_t maclen, vo
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct cparam {
|
||||||
|
time_t now;
|
||||||
|
int newone;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int construct_worker(struct in6_addr *local, int prefix,
|
||||||
|
int scope, int if_index, int dad,
|
||||||
|
int preferred, int valid, void *vparam)
|
||||||
|
{
|
||||||
|
char ifrn_name[IFNAMSIZ];
|
||||||
|
struct in6_addr start6, end6;
|
||||||
|
struct dhcp_context *template, *context;
|
||||||
|
|
||||||
|
(void)scope;
|
||||||
|
(void)dad;
|
||||||
|
|
||||||
|
struct cparam *param = vparam;
|
||||||
|
|
||||||
|
if (IN6_IS_ADDR_LOOPBACK(local) ||
|
||||||
|
IN6_IS_ADDR_LINKLOCAL(local) ||
|
||||||
|
IN6_IS_ADDR_MULTICAST(local))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (!indextoname(daemon->doing_dhcp6 ? daemon->dhcp6fd : daemon->icmp6fd, if_index, ifrn_name))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (template = daemon->dhcp6; template; template = template->next)
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
template->if_index = if_index;
|
||||||
|
template->local6 = *local;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (strcmp(ifrn_name, template->template_interface) == 0 &&
|
||||||
|
addr6part(local) == addr6part(&template->start6))
|
||||||
|
{
|
||||||
|
start6 = *local;
|
||||||
|
setaddr6part(&start6, addr6part(&template->start6));
|
||||||
|
end6 = *local;
|
||||||
|
setaddr6part(&end6, addr6part(&template->end6));
|
||||||
|
|
||||||
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
|
if ((context->flags & CONTEXT_CONSTRUCTED) &&
|
||||||
|
IN6_ARE_ADDR_EQUAL(&start6, &context->start6) &&
|
||||||
|
IN6_ARE_ADDR_EQUAL(&end6, &context->end6))
|
||||||
|
{
|
||||||
|
context->flags &= ~CONTEXT_GC;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!context && (context = whine_malloc(sizeof (struct dhcp_context))))
|
||||||
|
{
|
||||||
|
*context = *template;
|
||||||
|
context->start6 = start6;
|
||||||
|
context->end6 = end6;
|
||||||
|
context->flags &= ~CONTEXT_TEMPLATE;
|
||||||
|
context->flags |= CONTEXT_CONSTRUCTED;
|
||||||
|
context->if_index = if_index;
|
||||||
|
context->local6 = *local;
|
||||||
|
|
||||||
|
context->next = daemon->dhcp6;
|
||||||
|
daemon->dhcp6 = context;
|
||||||
|
|
||||||
|
ra_start_unsolicted(param->now, context);
|
||||||
|
/* we created a new one, need to call
|
||||||
|
lease_update_file to get periodic functions called */
|
||||||
|
param->newone = 1;
|
||||||
|
|
||||||
|
log_context(AF_INET6, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context)
|
||||||
|
{
|
||||||
|
if (valid == -1)
|
||||||
|
context->valid = valid;
|
||||||
|
else
|
||||||
|
context->valid = valid + param->now;
|
||||||
|
|
||||||
|
if (preferred == -1)
|
||||||
|
context->preferred = preferred;
|
||||||
|
else
|
||||||
|
context->preferred = preferred + param->now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dhcp_construct_contexts(time_t now)
|
||||||
|
{
|
||||||
|
struct dhcp_context *tmp, *context, **up;
|
||||||
|
struct cparam param;
|
||||||
|
param.newone = 0;
|
||||||
|
param.now = now;
|
||||||
|
|
||||||
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
|
if (context->flags & CONTEXT_CONSTRUCTED)
|
||||||
|
{
|
||||||
|
context->flags |= CONTEXT_GC;
|
||||||
|
context->if_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
iface_enumerate(AF_INET6, ¶m, construct_worker);
|
||||||
|
|
||||||
|
for (up = &daemon->dhcp6, context = daemon->dhcp6; context; context = tmp)
|
||||||
|
{
|
||||||
|
tmp = context->next;
|
||||||
|
|
||||||
|
if (context->flags & CONTEXT_GC)
|
||||||
|
{
|
||||||
|
if (daemon->dhcp6 == context)
|
||||||
|
daemon->dhcp6 = context->next;
|
||||||
|
*up = context->next;
|
||||||
|
free(context);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
up = &context->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (param.newone)
|
||||||
|
{
|
||||||
|
if (daemon->dhcp || daemon->doing_dhcp6)
|
||||||
|
lease_update_file(now);
|
||||||
|
else
|
||||||
|
/* Not doing DHCP, so no lease system, manage alarms for ra only */
|
||||||
|
send_alarm(periodic_ra(now), now);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int join_multicast_worker(struct in6_addr *local, int prefix,
|
||||||
|
int scope, int if_index, int dad,
|
||||||
|
int preferred, int valid, void *vparam)
|
||||||
|
{
|
||||||
|
char ifrn_name[IFNAMSIZ];
|
||||||
|
struct ipv6_mreq mreq;
|
||||||
|
int fd, i, max = *((int *)vparam);
|
||||||
|
struct iname *tmp;
|
||||||
|
|
||||||
|
(void)prefix;
|
||||||
|
(void)scope;
|
||||||
|
(void)dad;
|
||||||
|
(void)preferred;
|
||||||
|
(void)valid;
|
||||||
|
|
||||||
|
/* record which interfaces we join on, so that we do it at most one per
|
||||||
|
interface, even when they have multiple addresses. Use outpacket
|
||||||
|
as an array of int, since it's always allocated here and easy
|
||||||
|
to expand for theoretical vast numbers of interfaces. */
|
||||||
|
for (i = 0; i < max; i++)
|
||||||
|
if (if_index == ((int *)daemon->outpacket.iov_base)[i])
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if ((fd = socket(PF_INET6, SOCK_DGRAM, 0)) == -1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!indextoname(fd, if_index, ifrn_name))
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
/* Are we doing DHCP on this interface? */
|
||||||
|
if (!iface_check(AF_INET6, (struct all_addr *)local, ifrn_name, NULL))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||||
|
if (tmp->name && (strcmp(tmp->name, ifrn_name) == 0))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
mreq.ipv6mr_interface = if_index;
|
||||||
|
|
||||||
|
inet_pton(AF_INET6, ALL_RELAY_AGENTS_AND_SERVERS, &mreq.ipv6mr_multiaddr);
|
||||||
|
|
||||||
|
if (daemon->doing_dhcp6 &&
|
||||||
|
setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
inet_pton(AF_INET6, ALL_SERVERS, &mreq.ipv6mr_multiaddr);
|
||||||
|
|
||||||
|
if (daemon->doing_dhcp6 &&
|
||||||
|
setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
inet_pton(AF_INET6, ALL_ROUTERS, &mreq.ipv6mr_multiaddr);
|
||||||
|
|
||||||
|
if (daemon->doing_ra &&
|
||||||
|
setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
expand_buf(&daemon->outpacket, (max+1) * sizeof(int));
|
||||||
|
((int *)daemon->outpacket.iov_base)[max++] = if_index;
|
||||||
|
|
||||||
|
*((int *)vparam) = max;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void join_multicast(void)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
if (!iface_enumerate(AF_INET6, &count, join_multicast_worker))
|
||||||
|
die(_("failed to join DHCPv6 multicast group: %s"), NULL, EC_BADNET);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
+71
-127
@@ -51,6 +51,7 @@ int main (int argc, char **argv)
|
|||||||
cap_user_header_t hdr = NULL;
|
cap_user_header_t hdr = NULL;
|
||||||
cap_user_data_t data = NULL;
|
cap_user_data_t data = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
struct dhcp_context *context;
|
||||||
|
|
||||||
#ifdef LOCALEDIR
|
#ifdef LOCALEDIR
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
@@ -148,6 +149,11 @@ int main (int argc, char **argv)
|
|||||||
die(_("asychronous logging is not available under Android"), NULL, EC_BADCONF);
|
die(_("asychronous logging is not available under Android"), NULL, EC_BADCONF);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_AUTH
|
||||||
|
if (daemon->authserver)
|
||||||
|
die(_("authoritative DNS not available: set HAVE_AUTH in src/config.h"), NULL, EC_BADCONF);
|
||||||
|
#endif
|
||||||
|
|
||||||
rand_init();
|
rand_init();
|
||||||
|
|
||||||
now = dnsmasq_time();
|
now = dnsmasq_time();
|
||||||
@@ -162,63 +168,64 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
if (daemon->dhcp || daemon->dhcp6)
|
if (daemon->dhcp || daemon->dhcp6)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
# ifdef HAVE_DHCP6
|
||||||
|
if (daemon->dhcp6)
|
||||||
|
{
|
||||||
|
daemon->doing_ra = option_bool(OPT_RA);
|
||||||
|
|
||||||
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
|
{
|
||||||
|
if (context->flags & CONTEXT_DHCP)
|
||||||
|
daemon->doing_dhcp6 = 1;
|
||||||
|
if (context->flags & CONTEXT_RA)
|
||||||
|
daemon->doing_ra = 1;
|
||||||
|
#ifndef HAVE_LINUX_NETWORK
|
||||||
|
if (context->flags & CONTEXT_TEMPLATE)
|
||||||
|
die (_("dhcp-range contructor not available on this platform"), NULL, EC_BADCONF);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
/* Note that order matters here, we must call lease_init before
|
/* Note that order matters here, we must call lease_init before
|
||||||
creating any file descriptors which shouldn't be leaked
|
creating any file descriptors which shouldn't be leaked
|
||||||
to the lease-script init process. We need to call common_init
|
to the lease-script init process. We need to call common_init
|
||||||
before lease_init to allocate buffers it uses.*/
|
before lease_init to allocate buffers it uses.*/
|
||||||
dhcp_common_init();
|
if (daemon->dhcp || daemon->doing_dhcp6)
|
||||||
lease_init(now);
|
{
|
||||||
|
dhcp_common_init();
|
||||||
|
lease_init(now);
|
||||||
|
}
|
||||||
|
|
||||||
if (daemon->dhcp)
|
if (daemon->dhcp)
|
||||||
dhcp_init();
|
dhcp_init();
|
||||||
}
|
|
||||||
|
|
||||||
# ifdef HAVE_DHCP6
|
# ifdef HAVE_DHCP6
|
||||||
/* Start RA subsystem if --enable-ra OR dhcp-range=<subnet>, ra-only */
|
if (daemon->doing_ra)
|
||||||
if (daemon->ra_contexts || option_bool(OPT_RA))
|
ra_init(now);
|
||||||
{
|
|
||||||
/* link the DHCP6 contexts to the ra-only ones so we can traverse them all
|
|
||||||
from ->ra_contexts, but only the non-ra-onlies from ->dhcp6 */
|
|
||||||
struct dhcp_context *context;
|
|
||||||
|
|
||||||
if (!daemon->ra_contexts)
|
if (daemon->doing_dhcp6)
|
||||||
daemon->ra_contexts = daemon->dhcp6;
|
dhcp6_init();
|
||||||
else
|
|
||||||
{
|
|
||||||
for (context = daemon->ra_contexts; context->next; context = context->next);
|
|
||||||
context->next = daemon->dhcp6;
|
|
||||||
}
|
|
||||||
ra_init(now);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (daemon->dhcp6)
|
|
||||||
dhcp6_init();
|
|
||||||
|
|
||||||
# endif
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_LINUX_NETWORK
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
/* After lease_init */
|
|
||||||
netlink_init();
|
netlink_init();
|
||||||
|
|
||||||
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
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
/* after netlink_init */
|
/* after netlink_init */
|
||||||
if (daemon->ra_contexts || daemon->dhcp6)
|
if (daemon->doing_dhcp6 || daemon->doing_ra)
|
||||||
join_multicast();
|
join_multicast();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
|
||||||
/* after netlink_init */
|
|
||||||
if (daemon->dhcp || daemon->dhcp6)
|
|
||||||
lease_find_interfaces(now);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!enumerate_interfaces())
|
if (!enumerate_interfaces())
|
||||||
die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
|
die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
|
||||||
|
|
||||||
@@ -623,90 +630,27 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
if (daemon->max_logs != 0)
|
if (daemon->max_logs != 0)
|
||||||
my_syslog(LOG_INFO, _("asynchronous logging enabled, queue limit is %d messages"), daemon->max_logs);
|
my_syslog(LOG_INFO, _("asynchronous logging enabled, queue limit is %d messages"), daemon->max_logs);
|
||||||
|
|
||||||
if (daemon->ra_contexts)
|
|
||||||
my_syslog(MS_DHCP | LOG_INFO, _("IPv6 router advertisement enabled"));
|
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
if (daemon->dhcp || daemon->dhcp6 || daemon->ra_contexts)
|
for (context = daemon->dhcp; context; context = context->next)
|
||||||
{
|
log_context(AF_INET, context);
|
||||||
struct dhcp_context *dhcp_tmp;
|
|
||||||
int family = AF_INET;
|
|
||||||
dhcp_tmp = daemon->dhcp;
|
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
|
||||||
again:
|
|
||||||
#endif
|
|
||||||
for (; dhcp_tmp; dhcp_tmp = dhcp_tmp->next)
|
|
||||||
{
|
|
||||||
void *start = &dhcp_tmp->start;
|
|
||||||
void *end = &dhcp_tmp->end;
|
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
|
||||||
if (family == AF_INET6)
|
|
||||||
{
|
|
||||||
start = &dhcp_tmp->start6;
|
|
||||||
end = &dhcp_tmp->end6;
|
|
||||||
struct in6_addr subnet = dhcp_tmp->start6;
|
|
||||||
setaddr6part(&subnet, 0);
|
|
||||||
inet_ntop(AF_INET6, &subnet, daemon->dhcp_buff2, 256);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (family != AF_INET && (dhcp_tmp->flags & CONTEXT_DEPRECATE))
|
|
||||||
strcpy(daemon->namebuff, _("prefix deprecated"));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char *p = daemon->namebuff;
|
|
||||||
p += sprintf(p, _("lease time "));
|
|
||||||
prettyprint_time(p, dhcp_tmp->lease_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
inet_ntop(family, start, daemon->dhcp_buff, 256);
|
|
||||||
inet_ntop(family, end, daemon->dhcp_buff3, 256);
|
|
||||||
if ((dhcp_tmp->flags & CONTEXT_DHCP) || family == AF_INET)
|
|
||||||
my_syslog(MS_DHCP | LOG_INFO,
|
|
||||||
(dhcp_tmp->flags & CONTEXT_RA_STATELESS) ?
|
|
||||||
_("%s stateless on %s%.0s%.0s") :
|
|
||||||
(dhcp_tmp->flags & CONTEXT_STATIC) ?
|
|
||||||
_("%s, static leases only on %.0s%s, %s") :
|
|
||||||
(dhcp_tmp->flags & CONTEXT_PROXY) ?
|
|
||||||
_("%s, proxy on subnet %.0s%s%.0s") :
|
|
||||||
_("%s, IP range %s -- %s, %s"),
|
|
||||||
(family != AF_INET) ? "DHCPv6" : "DHCP",
|
|
||||||
daemon->dhcp_buff, daemon->dhcp_buff3, daemon->namebuff);
|
|
||||||
|
|
||||||
if (dhcp_tmp->flags & CONTEXT_RA_NAME)
|
# ifdef HAVE_DHCP6
|
||||||
my_syslog(MS_DHCP | LOG_INFO, _("DHCPv4-derived IPv6 names on %s"),
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
daemon->dhcp_buff2);
|
log_context(AF_INET6, context);
|
||||||
if (dhcp_tmp->flags & (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS))
|
|
||||||
{
|
|
||||||
if (!(dhcp_tmp->flags & CONTEXT_DEPRECATE))
|
|
||||||
{
|
|
||||||
char *p = daemon->namebuff;
|
|
||||||
p += sprintf(p, _("prefix valid "));
|
|
||||||
prettyprint_time(p, dhcp_tmp->lease_time > 7200 ? dhcp_tmp->lease_time : 7200);
|
|
||||||
}
|
|
||||||
my_syslog(MS_DHCP | LOG_INFO, _("SLAAC on %s %s"),
|
|
||||||
daemon->dhcp_buff2, daemon->namebuff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
|
||||||
if (family == AF_INET)
|
|
||||||
{
|
|
||||||
family = AF_INET6;
|
|
||||||
if (daemon->ra_contexts)
|
|
||||||
dhcp_tmp = daemon->ra_contexts;
|
|
||||||
else
|
|
||||||
dhcp_tmp = daemon->dhcp6;
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
if (daemon->doing_dhcp6 || daemon->doing_ra)
|
||||||
#endif
|
dhcp_construct_contexts(now);
|
||||||
|
|
||||||
|
if (option_bool(OPT_RA))
|
||||||
|
my_syslog(MS_DHCP | LOG_INFO, _("IPv6 router advertisement enabled"));
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* after dhcp_contruct_contexts */
|
||||||
|
if (daemon->dhcp || daemon->doing_dhcp6)
|
||||||
|
lease_find_interfaces(now);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_TFTP
|
#ifdef HAVE_TFTP
|
||||||
if (option_bool(OPT_TFTP))
|
if (option_bool(OPT_TFTP))
|
||||||
@@ -813,13 +757,13 @@ int main (int argc, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
if (daemon->dhcp6)
|
if (daemon->doing_dhcp6)
|
||||||
{
|
{
|
||||||
FD_SET(daemon->dhcp6fd, &rset);
|
FD_SET(daemon->dhcp6fd, &rset);
|
||||||
bump_maxfd(daemon->dhcp6fd, &maxfd);
|
bump_maxfd(daemon->dhcp6fd, &maxfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (daemon->ra_contexts)
|
if (daemon->doing_ra)
|
||||||
{
|
{
|
||||||
FD_SET(daemon->icmp6fd, &rset);
|
FD_SET(daemon->icmp6fd, &rset);
|
||||||
bump_maxfd(daemon->icmp6fd, &maxfd);
|
bump_maxfd(daemon->icmp6fd, &maxfd);
|
||||||
@@ -883,7 +827,7 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
#ifdef HAVE_LINUX_NETWORK
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
if (FD_ISSET(daemon->netlinkfd, &rset))
|
if (FD_ISSET(daemon->netlinkfd, &rset))
|
||||||
netlink_multicast();
|
netlink_multicast(now);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Check for changes to resolv files once per second max. */
|
/* Check for changes to resolv files once per second max. */
|
||||||
@@ -931,11 +875,11 @@ int main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
if (daemon->dhcp6 && FD_ISSET(daemon->dhcp6fd, &rset))
|
if (daemon->doing_dhcp6 && FD_ISSET(daemon->dhcp6fd, &rset))
|
||||||
dhcp6_packet(now);
|
dhcp6_packet(now);
|
||||||
|
|
||||||
if (daemon->ra_contexts && FD_ISSET(daemon->icmp6fd, &rset))
|
if (daemon->doing_ra && FD_ISSET(daemon->icmp6fd, &rset))
|
||||||
icmp6_packet();
|
icmp6_packet(now);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# ifdef HAVE_SCRIPT
|
# ifdef HAVE_SCRIPT
|
||||||
@@ -1115,13 +1059,13 @@ static void async_event(int pipe, time_t now)
|
|||||||
|
|
||||||
case EVENT_ALARM:
|
case EVENT_ALARM:
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
if (daemon->dhcp || daemon->dhcp6)
|
if (daemon->dhcp || daemon->doing_dhcp6)
|
||||||
{
|
{
|
||||||
lease_prune(NULL, now);
|
lease_prune(NULL, now);
|
||||||
lease_update_file(now);
|
lease_update_file(now);
|
||||||
}
|
}
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
else if (daemon->ra_contexts)
|
else if (daemon->doing_ra)
|
||||||
/* Not doing DHCP, so no lease system, manage alarms for ra only */
|
/* Not doing DHCP, so no lease system, manage alarms for ra only */
|
||||||
send_alarm(periodic_ra(now), now);
|
send_alarm(periodic_ra(now), now);
|
||||||
#endif
|
#endif
|
||||||
@@ -1278,7 +1222,7 @@ void clear_cache_and_reload(time_t now)
|
|||||||
cache_reload();
|
cache_reload();
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
if (daemon->dhcp || daemon->dhcp6)
|
if (daemon->dhcp || daemon->doing_dhcp6)
|
||||||
{
|
{
|
||||||
if (option_bool(OPT_ETHERS))
|
if (option_bool(OPT_ETHERS))
|
||||||
dhcp_read_ethers();
|
dhcp_read_ethers();
|
||||||
@@ -1289,7 +1233,7 @@ void clear_cache_and_reload(time_t now)
|
|||||||
lease_update_dns(1);
|
lease_update_dns(1);
|
||||||
}
|
}
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
else if (daemon->ra_contexts)
|
else if (daemon->doing_ra)
|
||||||
/* Not doing DHCP, so no lease system, manage
|
/* Not doing DHCP, so no lease system, manage
|
||||||
alarms for ra only */
|
alarms for ra only */
|
||||||
send_alarm(periodic_ra(now), now);
|
send_alarm(periodic_ra(now), now);
|
||||||
@@ -1592,7 +1536,7 @@ int icmp_ping(struct in_addr addr)
|
|||||||
set_log_writer(&wset, &maxfd);
|
set_log_writer(&wset, &maxfd);
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
if (daemon->ra_contexts)
|
if (daemon->doing_ra)
|
||||||
{
|
{
|
||||||
FD_SET(daemon->icmp6fd, &rset);
|
FD_SET(daemon->icmp6fd, &rset);
|
||||||
bump_maxfd(daemon->icmp6fd, &maxfd);
|
bump_maxfd(daemon->icmp6fd, &maxfd);
|
||||||
@@ -1611,8 +1555,8 @@ int icmp_ping(struct in_addr addr)
|
|||||||
check_dns_listeners(&rset, now);
|
check_dns_listeners(&rset, now);
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
if (daemon->ra_contexts && FD_ISSET(daemon->icmp6fd, &rset))
|
if (daemon->doing_ra && FD_ISSET(daemon->icmp6fd, &rset))
|
||||||
icmp6_packet();
|
icmp6_packet(now);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_TFTP
|
#ifdef HAVE_TFTP
|
||||||
|
|||||||
+20
-9
@@ -667,7 +667,7 @@ struct cond_domain {
|
|||||||
#endif
|
#endif
|
||||||
int is6;
|
int is6;
|
||||||
struct cond_domain *next;
|
struct cond_domain *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dhcp_context {
|
struct dhcp_context {
|
||||||
unsigned int lease_time, addr_epoch;
|
unsigned int lease_time, addr_epoch;
|
||||||
@@ -678,7 +678,9 @@ struct dhcp_context {
|
|||||||
struct in6_addr start6, end6; /* range of available addresses */
|
struct in6_addr start6, end6; /* range of available addresses */
|
||||||
struct in6_addr local6;
|
struct in6_addr local6;
|
||||||
int prefix, if_index;
|
int prefix, if_index;
|
||||||
time_t ra_time;
|
time_t ra_time, ra_short_period_start;
|
||||||
|
char *template_interface;
|
||||||
|
int valid, preferred; /* times from address for constructed contexts */
|
||||||
#endif
|
#endif
|
||||||
int flags;
|
int flags;
|
||||||
struct dhcp_netid netid, *filter;
|
struct dhcp_netid netid, *filter;
|
||||||
@@ -695,6 +697,11 @@ struct dhcp_context {
|
|||||||
#define CONTEXT_RA_STATELESS 128
|
#define CONTEXT_RA_STATELESS 128
|
||||||
#define CONTEXT_DHCP 256
|
#define CONTEXT_DHCP 256
|
||||||
#define CONTEXT_DEPRECATE 512
|
#define CONTEXT_DEPRECATE 512
|
||||||
|
#define CONTEXT_TEMPLATE 1024 /* create contexts using addresses */
|
||||||
|
#define CONTEXT_CONSTRUCTED 2048
|
||||||
|
#define CONTEXT_GC 4096
|
||||||
|
#define CONTEXT_RA 8192
|
||||||
|
|
||||||
|
|
||||||
struct ping_result {
|
struct ping_result {
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
@@ -755,7 +762,8 @@ extern struct daemon {
|
|||||||
char *lease_file;
|
char *lease_file;
|
||||||
char *username, *groupname, *scriptuser;
|
char *username, *groupname, *scriptuser;
|
||||||
char *luascript;
|
char *luascript;
|
||||||
char *authserver, *authinterface, *hostmaster;
|
char *authserver, *hostmaster;
|
||||||
|
struct iname *authinterface;
|
||||||
struct name_list *secondary_forward_server;
|
struct name_list *secondary_forward_server;
|
||||||
int group_set, osport;
|
int group_set, osport;
|
||||||
char *domain_suffix;
|
char *domain_suffix;
|
||||||
@@ -772,7 +780,7 @@ extern struct daemon {
|
|||||||
int port, query_port, min_port;
|
int port, query_port, min_port;
|
||||||
unsigned long local_ttl, neg_ttl, max_ttl, max_cache_ttl, auth_ttl;
|
unsigned long local_ttl, neg_ttl, max_ttl, max_cache_ttl, auth_ttl;
|
||||||
struct hostsfile *addn_hosts;
|
struct hostsfile *addn_hosts;
|
||||||
struct dhcp_context *dhcp, *dhcp6, *ra_contexts;
|
struct dhcp_context *dhcp, *dhcp6;
|
||||||
struct dhcp_config *dhcp_conf;
|
struct dhcp_config *dhcp_conf;
|
||||||
struct dhcp_opt *dhcp_opts, *dhcp_match, *dhcp_opts6, *dhcp_match6;
|
struct dhcp_opt *dhcp_opts, *dhcp_match, *dhcp_opts6, *dhcp_match6;
|
||||||
struct dhcp_vendor *dhcp_vendors;
|
struct dhcp_vendor *dhcp_vendors;
|
||||||
@@ -783,6 +791,7 @@ extern struct daemon {
|
|||||||
struct addr_list *override_relays;
|
struct addr_list *override_relays;
|
||||||
int override;
|
int override;
|
||||||
int enable_pxe;
|
int enable_pxe;
|
||||||
|
int doing_ra, doing_dhcp6;
|
||||||
struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *dhcp_gen_names;
|
struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *dhcp_gen_names;
|
||||||
struct dhcp_netid_list *force_broadcast, *bootp_dynamic;
|
struct dhcp_netid_list *force_broadcast, *bootp_dynamic;
|
||||||
struct hostsfile *dhcp_hosts_file, *dhcp_opts_file;
|
struct hostsfile *dhcp_hosts_file, *dhcp_opts_file;
|
||||||
@@ -909,7 +918,9 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
|||||||
int in_arpa_name_2_addr(char *namein, struct all_addr *addrp);
|
int in_arpa_name_2_addr(char *namein, struct all_addr *addrp);
|
||||||
|
|
||||||
/* auth.c */
|
/* auth.c */
|
||||||
|
#ifdef HAVE_AUTH
|
||||||
size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t now, union mysockaddr *peer_addr);
|
size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t now, union mysockaddr *peer_addr);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* util.c */
|
/* util.c */
|
||||||
void rand_init(void);
|
void rand_init(void);
|
||||||
@@ -1071,7 +1082,7 @@ void poll_resolv(int force, int do_reload, time_t now);
|
|||||||
/* netlink.c */
|
/* netlink.c */
|
||||||
#ifdef HAVE_LINUX_NETWORK
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
void netlink_init(void);
|
void netlink_init(void);
|
||||||
void netlink_multicast(void);
|
void netlink_multicast(time_t now);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* bpf.c */
|
/* bpf.c */
|
||||||
@@ -1139,6 +1150,8 @@ struct dhcp_config *find_config6(struct dhcp_config *configs,
|
|||||||
struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct in6_addr *net,
|
struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct in6_addr *net,
|
||||||
int prefix, u64 addr);
|
int prefix, u64 addr);
|
||||||
void make_duid(time_t now);
|
void make_duid(time_t now);
|
||||||
|
void dhcp_construct_contexts(time_t now);
|
||||||
|
void join_multicast(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* rfc3315.c */
|
/* rfc3315.c */
|
||||||
@@ -1169,8 +1182,8 @@ void bindtodevice(int fd);
|
|||||||
#endif
|
#endif
|
||||||
# ifdef HAVE_DHCP6
|
# ifdef HAVE_DHCP6
|
||||||
void display_opts6(void);
|
void display_opts6(void);
|
||||||
void join_multicast(void);
|
|
||||||
# endif
|
# endif
|
||||||
|
void log_context(int family, struct dhcp_context *context);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* outpacket.c */
|
/* outpacket.c */
|
||||||
@@ -1189,16 +1202,14 @@ void put_opt6_string(char *s);
|
|||||||
/* radv.c */
|
/* radv.c */
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
void ra_init(time_t now);
|
void ra_init(time_t now);
|
||||||
void icmp6_packet(void);
|
void icmp6_packet(time_t now);
|
||||||
time_t periodic_ra(time_t now);
|
time_t periodic_ra(time_t now);
|
||||||
void ra_start_unsolicted(time_t now, struct dhcp_context *context);
|
void ra_start_unsolicted(time_t now, struct dhcp_context *context);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* slaac.c */
|
/* slaac.c */
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
void build_subnet_map(void);
|
|
||||||
void slaac_add_addrs(struct dhcp_lease *lease, time_t now, int force);
|
void slaac_add_addrs(struct dhcp_lease *lease, time_t now, int force);
|
||||||
time_t periodic_slaac(time_t now, struct dhcp_lease *leases);
|
time_t periodic_slaac(time_t now, struct dhcp_lease *leases);
|
||||||
void slaac_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface, struct dhcp_lease *leases);
|
void slaac_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface, struct dhcp_lease *leases);
|
||||||
void schedule_subnet_map(void);
|
|
||||||
#endif
|
#endif
|
||||||
@@ -812,6 +812,7 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_AUTH
|
||||||
if (auth_dns)
|
if (auth_dns)
|
||||||
{
|
{
|
||||||
m = answer_auth(header, ((char *) header) + PACKETSZ, (size_t)n, now, &source_addr);
|
m = answer_auth(header, ((char *) header) + PACKETSZ, (size_t)n, now, &source_addr);
|
||||||
@@ -820,6 +821,7 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
(char *)header, m, &source_addr, &dst_addr, if_index);
|
(char *)header, m, &source_addr, &dst_addr, if_index);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
m = answer_request(header, ((char *) header) + PACKETSZ, (size_t)n,
|
m = answer_request(header, ((char *) header) + PACKETSZ, (size_t)n,
|
||||||
dst_addr_4, netmask, now);
|
dst_addr_4, netmask, now);
|
||||||
@@ -903,9 +905,11 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
else
|
else
|
||||||
dst_addr_4.s_addr = 0;
|
dst_addr_4.s_addr = 0;
|
||||||
|
|
||||||
|
#ifdef HAVE_AUTH
|
||||||
if (auth_dns)
|
if (auth_dns)
|
||||||
m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr);
|
m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr);
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
/* m > 0 if answered from cache */
|
/* m > 0 if answered from cache */
|
||||||
m = answer_request(header, ((char *) header) + 65536, (size_t)size,
|
m = answer_request(header, ((char *) header) + 65536, (size_t)size,
|
||||||
|
|||||||
+5
-6
@@ -308,7 +308,7 @@ void lease_update_file(time_t now)
|
|||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
/* do timed RAs and determine when the next is, also pings to potential SLAAC addresses */
|
/* do timed RAs and determine when the next is, also pings to potential SLAAC addresses */
|
||||||
if (daemon->ra_contexts)
|
if (daemon->doing_ra)
|
||||||
{
|
{
|
||||||
time_t event;
|
time_t event;
|
||||||
|
|
||||||
@@ -363,12 +363,15 @@ static int find_interface_v4(struct in_addr local, int if_index,
|
|||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
static int find_interface_v6(struct in6_addr *local, int prefix,
|
static int find_interface_v6(struct in6_addr *local, int prefix,
|
||||||
int scope, int if_index, int dad, void *vparam)
|
int scope, int if_index, int dad,
|
||||||
|
int preferred, int valid, void *vparam)
|
||||||
{
|
{
|
||||||
struct dhcp_lease *lease;
|
struct dhcp_lease *lease;
|
||||||
|
|
||||||
(void)scope;
|
(void)scope;
|
||||||
(void)dad;
|
(void)dad;
|
||||||
|
(void)preferred;
|
||||||
|
(void)valid;
|
||||||
|
|
||||||
for (lease = leases; lease; lease = lease->next)
|
for (lease = leases; lease; lease = lease->next)
|
||||||
if ((lease->flags & (LEASE_TA | LEASE_NA)))
|
if ((lease->flags & (LEASE_TA | LEASE_NA)))
|
||||||
@@ -395,10 +398,6 @@ void lease_ping_reply(struct in6_addr *sender, unsigned char *packet, char *inte
|
|||||||
start-time. */
|
start-time. */
|
||||||
void lease_find_interfaces(time_t now)
|
void lease_find_interfaces(time_t now)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_DHCP6
|
|
||||||
build_subnet_map();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
iface_enumerate(AF_INET, &now, find_interface_v4);
|
iface_enumerate(AF_INET, &now, find_interface_v4);
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
iface_enumerate(AF_INET6, &now, find_interface_v6);
|
iface_enumerate(AF_INET6, &now, find_interface_v6);
|
||||||
|
|||||||
+48
-27
@@ -50,10 +50,14 @@ void netlink_init(void)
|
|||||||
addr.nl_pid = 0; /* autobind */
|
addr.nl_pid = 0; /* autobind */
|
||||||
addr.nl_groups = RTMGRP_IPV4_ROUTE;
|
addr.nl_groups = RTMGRP_IPV4_ROUTE;
|
||||||
if (option_bool(OPT_CLEVERBIND))
|
if (option_bool(OPT_CLEVERBIND))
|
||||||
addr.nl_groups |= RTMGRP_IPV4_IFADDR;
|
addr.nl_groups |= RTMGRP_IPV4_IFADDR;
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
addr.nl_groups |= RTMGRP_IPV6_ROUTE;
|
addr.nl_groups |= RTMGRP_IPV6_ROUTE;
|
||||||
if (daemon->ra_contexts || option_bool(OPT_CLEVERBIND))
|
if (option_bool(OPT_CLEVERBIND))
|
||||||
|
addr.nl_groups |= RTMGRP_IPV6_IFADDR;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_DHCP6
|
||||||
|
if (daemon->doing_ra || daemon->doing_dhcp6)
|
||||||
addr.nl_groups |= RTMGRP_IPV6_IFADDR;
|
addr.nl_groups |= RTMGRP_IPV6_IFADDR;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -187,7 +191,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
if (h->nlmsg_seq != seq || h->nlmsg_pid != netlink_pid || h->nlmsg_type == NLMSG_ERROR)
|
if (h->nlmsg_seq != seq || h->nlmsg_pid != netlink_pid || h->nlmsg_type == NLMSG_ERROR)
|
||||||
{
|
{
|
||||||
/* May be multicast arriving async */
|
/* May be multicast arriving async */
|
||||||
if (nl_async(h) && option_bool(OPT_CLEVERBIND))
|
if (nl_async(h))
|
||||||
newaddr = 1;
|
newaddr = 1;
|
||||||
}
|
}
|
||||||
else if (h->nlmsg_type == NLMSG_DONE)
|
else if (h->nlmsg_type == NLMSG_DONE)
|
||||||
@@ -196,10 +200,22 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
after we complete as we're not re-entrant */
|
after we complete as we're not re-entrant */
|
||||||
if (newaddr)
|
if (newaddr)
|
||||||
{
|
{
|
||||||
enumerate_interfaces();
|
time_t now = dnsmasq_time();
|
||||||
create_bound_listeners(0);
|
|
||||||
|
if (option_bool(OPT_CLEVERBIND))
|
||||||
|
{
|
||||||
|
enumerate_interfaces();
|
||||||
|
create_bound_listeners(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_DHCP6
|
||||||
|
if (daemon->doing_dhcp6 || daemon->doing_ra)
|
||||||
|
dhcp_construct_contexts(now);
|
||||||
|
|
||||||
|
if (daemon->doing_dhcp6)
|
||||||
|
lease_find_interfaces(now);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return callback_ok;
|
return callback_ok;
|
||||||
}
|
}
|
||||||
else if (h->nlmsg_type == RTM_NEWADDR && family != AF_UNSPEC && family != AF_LOCAL)
|
else if (h->nlmsg_type == RTM_NEWADDR && family != AF_UNSPEC && family != AF_LOCAL)
|
||||||
@@ -236,17 +252,24 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
else if (ifa->ifa_family == AF_INET6)
|
else if (ifa->ifa_family == AF_INET6)
|
||||||
{
|
{
|
||||||
struct in6_addr *addrp = NULL;
|
struct in6_addr *addrp = NULL;
|
||||||
|
u32 valid = 0, preferred = 0;
|
||||||
while (RTA_OK(rta, len1))
|
while (RTA_OK(rta, len1))
|
||||||
{
|
{
|
||||||
if (rta->rta_type == IFA_ADDRESS)
|
if (rta->rta_type == IFA_ADDRESS)
|
||||||
addrp = ((struct in6_addr *)(rta+1));
|
addrp = ((struct in6_addr *)(rta+1));
|
||||||
|
else if (rta->rta_type == IFA_CACHEINFO)
|
||||||
|
{
|
||||||
|
struct ifa_cacheinfo *ifc = (struct ifa_cacheinfo *)(rta+1);
|
||||||
|
preferred = ifc->ifa_prefered;
|
||||||
|
valid = ifc->ifa_valid;
|
||||||
|
}
|
||||||
rta = RTA_NEXT(rta, len1);
|
rta = RTA_NEXT(rta, len1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addrp && callback_ok)
|
if (addrp && callback_ok)
|
||||||
if (!((*callback)(addrp, (int)(ifa->ifa_prefixlen), (int)(ifa->ifa_scope),
|
if (!((*callback)(addrp, (int)(ifa->ifa_prefixlen), (int)(ifa->ifa_scope),
|
||||||
(int)(ifa->ifa_index), (int)(ifa->ifa_flags & IFA_F_TENTATIVE), parm)))
|
(int)(ifa->ifa_index), (int)(ifa->ifa_flags & IFA_F_TENTATIVE),
|
||||||
|
(int) preferred, (int)valid, parm)))
|
||||||
callback_ok = 0;
|
callback_ok = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -305,7 +328,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void netlink_multicast(void)
|
void netlink_multicast(time_t now)
|
||||||
{
|
{
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
struct nlmsghdr *h;
|
struct nlmsghdr *h;
|
||||||
@@ -318,7 +341,7 @@ void netlink_multicast(void)
|
|||||||
|
|
||||||
if ((len = netlink_recv()) != -1)
|
if ((len = netlink_recv()) != -1)
|
||||||
for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
|
for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
|
||||||
if (nl_async(h) && option_bool(OPT_CLEVERBIND))
|
if (nl_async(h))
|
||||||
newaddr = 1;
|
newaddr = 1;
|
||||||
|
|
||||||
/* restore non-blocking status */
|
/* restore non-blocking status */
|
||||||
@@ -326,8 +349,19 @@ void netlink_multicast(void)
|
|||||||
|
|
||||||
if (newaddr)
|
if (newaddr)
|
||||||
{
|
{
|
||||||
enumerate_interfaces();
|
if (option_bool(OPT_CLEVERBIND))
|
||||||
create_bound_listeners(0);
|
{
|
||||||
|
enumerate_interfaces();
|
||||||
|
create_bound_listeners(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_DHCP6
|
||||||
|
if (daemon->doing_dhcp6 || daemon->doing_ra)
|
||||||
|
dhcp_construct_contexts(now);
|
||||||
|
|
||||||
|
if (daemon->doing_dhcp6)
|
||||||
|
lease_find_interfaces(now);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,21 +405,8 @@ static int nl_async(struct nlmsghdr *h)
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (h->nlmsg_type == RTM_NEWADDR)
|
else if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR)
|
||||||
{
|
return 1; /* clever bind mode - rescan */
|
||||||
#ifdef HAVE_DHCP6
|
|
||||||
/* force RAs to sync new network and pick up new interfaces. */
|
|
||||||
if (daemon->ra_contexts)
|
|
||||||
{
|
|
||||||
schedule_subnet_map();
|
|
||||||
ra_start_unsolicted(dnsmasq_time(), NULL);
|
|
||||||
/* cause lease_update_file to run after we return, in case we were called from
|
|
||||||
iface_enumerate and can't re-enter it now */
|
|
||||||
send_alarm(0, 0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return 1; /* clever bind mode - rescan */
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+40
-22
@@ -114,17 +114,9 @@ int iface_check(int family, struct all_addr *addr, char *name, int *auth)
|
|||||||
|
|
||||||
/* Note: have to check all and not bail out early, so that we set the
|
/* Note: have to check all and not bail out early, so that we set the
|
||||||
"used" flags. */
|
"used" flags. */
|
||||||
|
|
||||||
if (auth)
|
if (auth)
|
||||||
{
|
*auth = 0;
|
||||||
if (daemon->authinterface && strcmp(daemon->authinterface, name) == 0)
|
|
||||||
{
|
|
||||||
*auth = 1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
*auth = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (daemon->if_names || daemon->if_addrs)
|
if (daemon->if_names || daemon->if_addrs)
|
||||||
{
|
{
|
||||||
@@ -134,25 +126,48 @@ int iface_check(int family, struct all_addr *addr, char *name, int *auth)
|
|||||||
if (tmp->name && (strcmp(tmp->name, name) == 0))
|
if (tmp->name && (strcmp(tmp->name, name) == 0))
|
||||||
ret = tmp->used = 1;
|
ret = tmp->used = 1;
|
||||||
|
|
||||||
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
|
if (addr)
|
||||||
if (tmp->addr.sa.sa_family == family)
|
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
|
||||||
{
|
if (tmp->addr.sa.sa_family == family)
|
||||||
if (family == AF_INET &&
|
{
|
||||||
tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
|
if (family == AF_INET &&
|
||||||
ret = tmp->used = 1;
|
tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
|
||||||
|
ret = tmp->used = 1;
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
else if (family == AF_INET6 &&
|
else if (family == AF_INET6 &&
|
||||||
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr,
|
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr,
|
||||||
&addr->addr.addr6))
|
&addr->addr.addr6))
|
||||||
ret = tmp->used = 1;
|
ret = tmp->used = 1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
|
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
|
||||||
if (tmp->name && (strcmp(tmp->name, name) == 0))
|
if (tmp->name && (strcmp(tmp->name, name) == 0))
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
|
|
||||||
|
for (tmp = daemon->authinterface; tmp; tmp = tmp->next)
|
||||||
|
if (tmp->name)
|
||||||
|
{
|
||||||
|
if (strcmp(tmp->name, name) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET &&
|
||||||
|
tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
|
||||||
|
break;
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 &&
|
||||||
|
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr.addr6))
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (tmp && auth)
|
||||||
|
{
|
||||||
|
*auth = 1;
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,7 +289,8 @@ static int iface_allowed(struct irec **irecp, int if_index,
|
|||||||
|
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
static int iface_allowed_v6(struct in6_addr *local, int prefix,
|
static int iface_allowed_v6(struct in6_addr *local, int prefix,
|
||||||
int scope, int if_index, int dad, void *vparam)
|
int scope, int if_index, int dad,
|
||||||
|
int preferred, int valid, void *vparam)
|
||||||
{
|
{
|
||||||
union mysockaddr addr;
|
union mysockaddr addr;
|
||||||
struct in_addr netmask; /* dummy */
|
struct in_addr netmask; /* dummy */
|
||||||
@@ -282,6 +298,8 @@ static int iface_allowed_v6(struct in6_addr *local, int prefix,
|
|||||||
|
|
||||||
(void)prefix; /* warning */
|
(void)prefix; /* warning */
|
||||||
(void)scope; /* warning */
|
(void)scope; /* warning */
|
||||||
|
(void)preferred;
|
||||||
|
(void)valid;
|
||||||
|
|
||||||
memset(&addr, 0, sizeof(addr));
|
memset(&addr, 0, sizeof(addr));
|
||||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||||
|
|||||||
+64
-44
@@ -623,24 +623,6 @@ static void do_usage(void)
|
|||||||
|
|
||||||
#define ret_err(x) do { strcpy(errstr, (x)); return 0; } while (0)
|
#define ret_err(x) do { strcpy(errstr, (x)); return 0; } while (0)
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
|
||||||
|
|
||||||
static int is_tag_prefix(char *arg)
|
|
||||||
{
|
|
||||||
if (arg && (strstr(arg, "net:") == arg || strstr(arg, "tag:") == arg))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *set_prefix(char *arg)
|
|
||||||
{
|
|
||||||
if (strstr(arg, "set:") == arg)
|
|
||||||
return arg+4;
|
|
||||||
|
|
||||||
return arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_addr, char *interface, int *flags)
|
char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_addr, char *interface, int *flags)
|
||||||
{
|
{
|
||||||
int source_port = 0, serv_port = NAMESERVER_PORT;
|
int source_port = 0, serv_port = NAMESERVER_PORT;
|
||||||
@@ -728,6 +710,24 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_DHCP
|
||||||
|
|
||||||
|
static int is_tag_prefix(char *arg)
|
||||||
|
{
|
||||||
|
if (arg && (strstr(arg, "net:") == arg || strstr(arg, "tag:") == arg))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *set_prefix(char *arg)
|
||||||
|
{
|
||||||
|
if (strstr(arg, "set:") == arg)
|
||||||
|
return arg+4;
|
||||||
|
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
|
||||||
/* This is too insanely large to keep in-line in the switch */
|
/* This is too insanely large to keep in-line in the switch */
|
||||||
static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
||||||
{
|
{
|
||||||
@@ -1544,8 +1544,27 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
ret_err(gen_err);
|
ret_err(gen_err);
|
||||||
|
|
||||||
daemon->authserver = opt_string_alloc(arg);
|
daemon->authserver = opt_string_alloc(arg);
|
||||||
daemon->authinterface = opt_string_alloc(comma);
|
arg = comma;
|
||||||
|
do {
|
||||||
|
struct iname *new = opt_malloc(sizeof(struct iname));
|
||||||
|
comma = split(arg);
|
||||||
|
new->name = NULL;
|
||||||
|
unhide_metas(arg);
|
||||||
|
if ((new->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)
|
||||||
|
new->addr.sa.sa_family = AF_INET;
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
else if (inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
|
||||||
|
new->addr.sa.sa_family = AF_INET6;
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
new->name = opt_string_alloc(arg);
|
||||||
|
|
||||||
|
new->next = daemon->authinterface;
|
||||||
|
daemon->authinterface = new;
|
||||||
|
|
||||||
|
arg = comma;
|
||||||
|
} while (arg);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LOPT_AUTHSFS: /* --auth-sec-servers */
|
case LOPT_AUTHSFS: /* --auth-sec-servers */
|
||||||
@@ -1554,7 +1573,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
comma = split(arg);
|
comma = split(arg);
|
||||||
new = safe_malloc(sizeof(struct name_list));
|
new = opt_malloc(sizeof(struct name_list));
|
||||||
new->name = opt_string_alloc(arg);
|
new->name = opt_string_alloc(arg);
|
||||||
new->next = daemon->secondary_forward_server;
|
new->next = daemon->secondary_forward_server;
|
||||||
daemon->secondary_forward_server = new;
|
daemon->secondary_forward_server = new;
|
||||||
@@ -1571,7 +1590,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
if (!comma)
|
if (!comma)
|
||||||
ret_err(gen_err);
|
ret_err(gen_err);
|
||||||
|
|
||||||
new = safe_malloc(sizeof(struct auth_zone));
|
new = opt_malloc(sizeof(struct auth_zone));
|
||||||
new->domain = opt_string_alloc(arg);
|
new->domain = opt_string_alloc(arg);
|
||||||
new->subnet = NULL;
|
new->subnet = NULL;
|
||||||
new->next = daemon->auth_zones;
|
new->next = daemon->auth_zones;
|
||||||
@@ -1581,7 +1600,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
{
|
{
|
||||||
int prefixlen = 0;
|
int prefixlen = 0;
|
||||||
char *prefix;
|
char *prefix;
|
||||||
struct subnet *subnet = safe_malloc(sizeof(struct subnet));
|
struct subnet *subnet = opt_malloc(sizeof(struct subnet));
|
||||||
|
|
||||||
subnet->next = new->subnet;
|
subnet->next = new->subnet;
|
||||||
new->subnet = subnet;
|
new->subnet = subnet;
|
||||||
@@ -1660,7 +1679,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
{
|
{
|
||||||
if (comma)
|
if (comma)
|
||||||
{
|
{
|
||||||
struct cond_domain *new = safe_malloc(sizeof(struct cond_domain));
|
struct cond_domain *new = opt_malloc(sizeof(struct cond_domain));
|
||||||
char *netpart;
|
char *netpart;
|
||||||
|
|
||||||
unhide_metas(comma);
|
unhide_metas(comma);
|
||||||
@@ -2161,7 +2180,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
case 'F': /* --dhcp-range */
|
case 'F': /* --dhcp-range */
|
||||||
{
|
{
|
||||||
int k, leasepos = 2;
|
int k, leasepos = 2;
|
||||||
char *cp, *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
char *cp, *a[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
||||||
struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context));
|
struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context));
|
||||||
|
|
||||||
memset (new, 0, sizeof(*new));
|
memset (new, 0, sizeof(*new));
|
||||||
@@ -2208,7 +2227,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (k = 1; k < 7; k++)
|
for (k = 1; k < 8; k++)
|
||||||
if (!(a[k] = split(a[k-1])))
|
if (!(a[k] = split(a[k-1])))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -2265,28 +2284,25 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
if (strcmp(a[leasepos], "static") == 0)
|
if (strcmp(a[leasepos], "static") == 0)
|
||||||
new->flags |= CONTEXT_STATIC | CONTEXT_DHCP;
|
new->flags |= CONTEXT_STATIC | CONTEXT_DHCP;
|
||||||
else if (strcmp(a[leasepos], "ra-only") == 0 || strcmp(a[leasepos], "slaac") == 0 )
|
else if (strcmp(a[leasepos], "ra-only") == 0 || strcmp(a[leasepos], "slaac") == 0 )
|
||||||
new->flags |= CONTEXT_RA_ONLY;
|
new->flags |= CONTEXT_RA_ONLY | CONTEXT_RA;
|
||||||
else if (strcmp(a[leasepos], "ra-names") == 0)
|
else if (strcmp(a[leasepos], "ra-names") == 0)
|
||||||
new->flags |= CONTEXT_RA_NAME;
|
new->flags |= CONTEXT_RA_NAME | CONTEXT_RA;
|
||||||
else if (strcmp(a[leasepos], "ra-stateless") == 0)
|
else if (strcmp(a[leasepos], "ra-stateless") == 0)
|
||||||
new->flags |= CONTEXT_RA_STATELESS | CONTEXT_DHCP;
|
new->flags |= CONTEXT_RA_STATELESS | CONTEXT_DHCP | CONTEXT_RA;
|
||||||
else if (leasepos == 1 && inet_pton(AF_INET6, a[leasepos], &new->end6))
|
else if (leasepos == 1 && inet_pton(AF_INET6, a[leasepos], &new->end6))
|
||||||
new->flags |= CONTEXT_DHCP;
|
new->flags |= CONTEXT_DHCP;
|
||||||
|
else if (strstr(a[leasepos], "constructor:") == a[leasepos])
|
||||||
|
{
|
||||||
|
new->template_interface = opt_string_alloc(a[leasepos] + 12);
|
||||||
|
new->flags |= CONTEXT_TEMPLATE;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new->flags & CONTEXT_DHCP)
|
new->next = daemon->dhcp6;
|
||||||
{
|
daemon->dhcp6 = new;
|
||||||
new->next = daemon->dhcp6;
|
|
||||||
daemon->dhcp6 = new;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
new->next = daemon->ra_contexts;
|
|
||||||
daemon->ra_contexts = new;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* bare integer < 128 is prefix value */
|
/* bare integer < 128 is prefix value */
|
||||||
if (leasepos < k)
|
if (leasepos < k)
|
||||||
{
|
{
|
||||||
@@ -2298,10 +2314,14 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
{
|
{
|
||||||
new->prefix = pref;
|
new->prefix = pref;
|
||||||
leasepos++;
|
leasepos++;
|
||||||
if ((new->flags & (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)) &&
|
if (new->prefix != 64)
|
||||||
new->prefix != 64)
|
{
|
||||||
ret_err(_("prefix must be exactly 64 for RA subnets"));
|
if ((new->flags & (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)))
|
||||||
else if (new->prefix < 64)
|
ret_err(_("prefix must be exactly 64 for RA subnets"));
|
||||||
|
else if (new->template_interface)
|
||||||
|
ret_err(_("prefix must be exactly 64 for subnet constructors"));
|
||||||
|
}
|
||||||
|
if (new->prefix < 64)
|
||||||
ret_err(_("prefix must be at least 64"));
|
ret_err(_("prefix must be at least 64"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+88
-56
@@ -27,6 +27,7 @@
|
|||||||
#include <netinet/icmp6.h>
|
#include <netinet/icmp6.h>
|
||||||
|
|
||||||
struct ra_param {
|
struct ra_param {
|
||||||
|
time_t now;
|
||||||
int ind, managed, other, found_context, first;
|
int ind, managed, other, found_context, first;
|
||||||
char *if_name;
|
char *if_name;
|
||||||
struct dhcp_netid *tags;
|
struct dhcp_netid *tags;
|
||||||
@@ -37,15 +38,16 @@ struct search_param {
|
|||||||
time_t now; int iface;
|
time_t now; int iface;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void send_ra(int iface, char *iface_name, struct in6_addr *dest);
|
static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *dest);
|
||||||
static int add_prefixes(struct in6_addr *local, int prefix,
|
static int add_prefixes(struct in6_addr *local, int prefix,
|
||||||
int scope, int if_index, int dad, void *vparam);
|
int scope, int if_index, int dad,
|
||||||
|
int preferred, int valid, void *vparam);
|
||||||
static int iface_search(struct in6_addr *local, int prefix,
|
static int iface_search(struct in6_addr *local, int prefix,
|
||||||
int scope, int if_index, int dad, void *vparam);
|
int scope, int if_index, int dad,
|
||||||
|
int prefered, int valid, void *vparam);
|
||||||
static int add_lla(int index, unsigned int type, char *mac, size_t maclen, void *parm);
|
static int add_lla(int index, unsigned int type, char *mac, size_t maclen, void *parm);
|
||||||
|
|
||||||
static int hop_limit;
|
static int hop_limit;
|
||||||
static time_t ra_short_period_start;
|
|
||||||
|
|
||||||
void ra_init(time_t now)
|
void ra_init(time_t now)
|
||||||
{
|
{
|
||||||
@@ -62,7 +64,7 @@ void ra_init(time_t now)
|
|||||||
expand_buf(&daemon->outpacket, sizeof(struct dhcp_packet));
|
expand_buf(&daemon->outpacket, sizeof(struct dhcp_packet));
|
||||||
|
|
||||||
/* See if we're guessing SLAAC addresses, if so we need to recieve ping replies */
|
/* See if we're guessing SLAAC addresses, if so we need to recieve ping replies */
|
||||||
for (context = daemon->ra_contexts; context; context = context->next)
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
if ((context->flags & CONTEXT_RA_NAME))
|
if ((context->flags & CONTEXT_RA_NAME))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -94,18 +96,20 @@ void ra_start_unsolicted(time_t now, struct dhcp_context *context)
|
|||||||
if it's not appropriate to advertise those contexts.
|
if it's not appropriate to advertise those contexts.
|
||||||
This gets re-called on a netlink route-change to re-do the advertisement
|
This gets re-called on a netlink route-change to re-do the advertisement
|
||||||
and pick up new interfaces */
|
and pick up new interfaces */
|
||||||
|
|
||||||
if (context)
|
if (context)
|
||||||
context->ra_time = now;
|
context->ra_short_period_start = context->ra_time = now;
|
||||||
else
|
else
|
||||||
for (context = daemon->ra_contexts; context; context = context->next)
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
context->ra_time = now + (rand16()/13000); /* range 0 - 5 */
|
if (!(context->flags & CONTEXT_TEMPLATE))
|
||||||
|
{
|
||||||
/* re-do frequently for a minute or so, in case the first gets lost. */
|
context->ra_time = now + (rand16()/13000); /* range 0 - 5 */
|
||||||
ra_short_period_start = now;
|
/* re-do frequently for a minute or so, in case the first gets lost. */
|
||||||
|
context->ra_short_period_start = now;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void icmp6_packet(void)
|
void icmp6_packet(time_t now)
|
||||||
{
|
{
|
||||||
char interface[IF_NAMESIZE+1];
|
char interface[IF_NAMESIZE+1];
|
||||||
ssize_t sz;
|
ssize_t sz;
|
||||||
@@ -174,11 +178,11 @@ void icmp6_packet(void)
|
|||||||
|
|
||||||
my_syslog(MS_DHCP | LOG_INFO, "RTR-SOLICIT(%s) %s", interface, mac);
|
my_syslog(MS_DHCP | LOG_INFO, "RTR-SOLICIT(%s) %s", interface, mac);
|
||||||
/* source address may not be valid in solicit request. */
|
/* source address may not be valid in solicit request. */
|
||||||
send_ra(if_index, interface, !IN6_IS_ADDR_UNSPECIFIED(&from.sin6_addr) ? &from.sin6_addr : NULL);
|
send_ra(now, if_index, interface, !IN6_IS_ADDR_UNSPECIFIED(&from.sin6_addr) ? &from.sin6_addr : NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
|
static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *dest)
|
||||||
{
|
{
|
||||||
struct ra_packet *ra;
|
struct ra_packet *ra;
|
||||||
struct ra_param parm;
|
struct ra_param parm;
|
||||||
@@ -206,13 +210,14 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
|
|||||||
parm.found_context = 0;
|
parm.found_context = 0;
|
||||||
parm.if_name = iface_name;
|
parm.if_name = iface_name;
|
||||||
parm.first = 1;
|
parm.first = 1;
|
||||||
|
parm.now = now;
|
||||||
|
|
||||||
/* set tag with name == interface */
|
/* set tag with name == interface */
|
||||||
iface_id.net = iface_name;
|
iface_id.net = iface_name;
|
||||||
iface_id.next = NULL;
|
iface_id.next = NULL;
|
||||||
parm.tags = &iface_id;
|
parm.tags = &iface_id;
|
||||||
|
|
||||||
for (context = daemon->ra_contexts; context; context = context->next)
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
{
|
{
|
||||||
context->flags &= ~CONTEXT_RA_DONE;
|
context->flags &= ~CONTEXT_RA_DONE;
|
||||||
context->netid.next = &context->netid;
|
context->netid.next = &context->netid;
|
||||||
@@ -320,29 +325,34 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int add_prefixes(struct in6_addr *local, int prefix,
|
static int add_prefixes(struct in6_addr *local, int prefix,
|
||||||
int scope, int if_index, int dad, void *vparam)
|
int scope, int if_index, int dad,
|
||||||
|
int preferred, int valid, void *vparam)
|
||||||
{
|
{
|
||||||
struct ra_param *param = vparam;
|
struct ra_param *param = vparam;
|
||||||
|
|
||||||
(void)scope; /* warning */
|
(void)scope; /* warning */
|
||||||
(void)dad;
|
(void)dad;
|
||||||
|
(void)preferred;
|
||||||
|
(void)valid;
|
||||||
|
|
||||||
if (if_index == param->ind)
|
if (if_index == param->ind)
|
||||||
{
|
{
|
||||||
if (IN6_IS_ADDR_LINKLOCAL(local))
|
if (IN6_IS_ADDR_LINKLOCAL(local))
|
||||||
param->link_local = *local;
|
param->link_local = *local;
|
||||||
else if (!IN6_IS_ADDR_LOOPBACK(local) &&
|
else if (!IN6_IS_ADDR_LOOPBACK(local) &&
|
||||||
!IN6_IS_ADDR_LINKLOCAL(local) &&
|
|
||||||
!IN6_IS_ADDR_MULTICAST(local))
|
!IN6_IS_ADDR_MULTICAST(local))
|
||||||
{
|
{
|
||||||
int do_prefix = 0;
|
int do_prefix = 0;
|
||||||
int do_slaac = 0;
|
int do_slaac = 0;
|
||||||
int deprecate = 0;
|
int deprecate = 0;
|
||||||
|
int found_constructed = 0;
|
||||||
unsigned int time = 0xffffffff;
|
unsigned int time = 0xffffffff;
|
||||||
|
int calc_valid = 0, calc_preferred = 0;
|
||||||
struct dhcp_context *context;
|
struct dhcp_context *context;
|
||||||
|
|
||||||
for (context = daemon->ra_contexts; context; context = context->next)
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
if (prefix == context->prefix &&
|
if (!(context->flags & CONTEXT_TEMPLATE) &&
|
||||||
|
prefix == context->prefix &&
|
||||||
is_same_net6(local, &context->start6, prefix) &&
|
is_same_net6(local, &context->start6, prefix) &&
|
||||||
is_same_net6(local, &context->end6, prefix))
|
is_same_net6(local, &context->end6, prefix))
|
||||||
{
|
{
|
||||||
@@ -365,7 +375,18 @@ static int add_prefixes(struct in6_addr *local, int prefix,
|
|||||||
param->managed = 1;
|
param->managed = 1;
|
||||||
param->other = 1;
|
param->other = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (context->flags & CONTEXT_CONSTRUCTED)
|
||||||
|
{
|
||||||
|
found_constructed = 1;
|
||||||
|
calc_valid = context->valid;
|
||||||
|
calc_preferred = context->preferred;
|
||||||
|
if (context->valid != -1)
|
||||||
|
calc_valid -= (int)param->now;
|
||||||
|
if (context->preferred != -1)
|
||||||
|
calc_preferred -= (int)param->now;
|
||||||
|
}
|
||||||
|
|
||||||
/* find floor time */
|
/* find floor time */
|
||||||
if (time > context->lease_time)
|
if (time > context->lease_time)
|
||||||
time = context->lease_time;
|
time = context->lease_time;
|
||||||
@@ -395,6 +416,12 @@ static int add_prefixes(struct in6_addr *local, int prefix,
|
|||||||
param->first = 0;
|
param->first = 0;
|
||||||
param->found_context = 1;
|
param->found_context = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!found_constructed)
|
||||||
|
{
|
||||||
|
calc_valid = time;
|
||||||
|
calc_preferred = deprecate ? 0 : time;
|
||||||
|
}
|
||||||
|
|
||||||
if (do_prefix)
|
if (do_prefix)
|
||||||
{
|
{
|
||||||
@@ -414,8 +441,8 @@ static int add_prefixes(struct in6_addr *local, int prefix,
|
|||||||
opt->prefix_len = prefix;
|
opt->prefix_len = 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(time);
|
opt->valid_lifetime = htonl(calc_valid);
|
||||||
opt->preferred_lifetime = htonl(deprecate ? 0 : time);
|
opt->preferred_lifetime = htonl(calc_preferred);
|
||||||
opt->reserved = 0;
|
opt->reserved = 0;
|
||||||
opt->prefix = *local;
|
opt->prefix = *local;
|
||||||
|
|
||||||
@@ -462,7 +489,7 @@ time_t periodic_ra(time_t now)
|
|||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
/* find overdue events, and time of first future event */
|
/* find overdue events, and time of first future event */
|
||||||
for (next_event = 0, context = daemon->ra_contexts; context; context = context->next)
|
for (next_event = 0, context = daemon->dhcp6; context; context = context->next)
|
||||||
if (context->ra_time != 0)
|
if (context->ra_time != 0)
|
||||||
{
|
{
|
||||||
if (difftime(context->ra_time, now) <= 0.0)
|
if (difftime(context->ra_time, now) <= 0.0)
|
||||||
@@ -492,51 +519,56 @@ time_t periodic_ra(time_t now)
|
|||||||
if (tmp->name && (strcmp(tmp->name, interface) == 0))
|
if (tmp->name && (strcmp(tmp->name, interface) == 0))
|
||||||
break;
|
break;
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
send_ra(param.iface, interface, NULL);
|
send_ra(now, param.iface, interface, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return next_event;
|
return next_event;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iface_search(struct in6_addr *local, int prefix,
|
static int iface_search(struct in6_addr *local, int prefix,
|
||||||
int scope, int if_index, int dad, void *vparam)
|
int scope, int if_index, int dad,
|
||||||
|
int preferred, int valid, void *vparam)
|
||||||
{
|
{
|
||||||
struct search_param *param = vparam;
|
struct search_param *param = vparam;
|
||||||
struct dhcp_context *context;
|
struct dhcp_context *context;
|
||||||
|
|
||||||
(void)scope;
|
(void)scope;
|
||||||
(void)dad;
|
(void)dad;
|
||||||
|
(void)preferred;
|
||||||
|
(void)valid;
|
||||||
|
|
||||||
for (context = daemon->ra_contexts; context; context = context->next)
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
if (prefix == context->prefix &&
|
if (!(context->flags & CONTEXT_TEMPLATE) &&
|
||||||
|
prefix == context->prefix &&
|
||||||
is_same_net6(local, &context->start6, prefix) &&
|
is_same_net6(local, &context->start6, prefix) &&
|
||||||
is_same_net6(local, &context->end6, prefix))
|
is_same_net6(local, &context->end6, prefix) &&
|
||||||
if (context->ra_time != 0 && difftime(context->ra_time, param->now) <= 0.0)
|
context->ra_time != 0 &&
|
||||||
{
|
difftime(context->ra_time, param->now) <= 0.0)
|
||||||
/* found an interface that's overdue for RA determine new
|
{
|
||||||
timeout value and arrange for RA to be sent unless interface is
|
/* found an interface that's overdue for RA determine new
|
||||||
still doing DAD.*/
|
timeout value and arrange for RA to be sent unless interface is
|
||||||
|
still doing DAD.*/
|
||||||
if (!dad)
|
|
||||||
param->iface = if_index;
|
if (!dad)
|
||||||
|
param->iface = if_index;
|
||||||
if (difftime(param->now, ra_short_period_start) < 60.0)
|
|
||||||
/* range 5 - 20 */
|
if (difftime(param->now, context->ra_short_period_start) < 60.0)
|
||||||
context->ra_time = param->now + 5 + (rand16()/4400);
|
/* range 5 - 20 */
|
||||||
else
|
context->ra_time = param->now + 5 + (rand16()/4400);
|
||||||
/* range 450 - 600 */
|
else
|
||||||
context->ra_time = param->now + 450 + (rand16()/440);
|
/* range 450 - 600 */
|
||||||
|
context->ra_time = param->now + 450 + (rand16()/440);
|
||||||
/* zero timers for other contexts on the same subnet, so they don't timeout
|
|
||||||
independently */
|
/* zero timers for other contexts on the same subnet, so they don't timeout
|
||||||
for (context = context->next; context; context = context->next)
|
independently */
|
||||||
if (prefix == context->prefix &&
|
for (context = context->next; context; context = context->next)
|
||||||
is_same_net6(local, &context->start6, prefix) &&
|
if (prefix == context->prefix &&
|
||||||
is_same_net6(local, &context->end6, prefix))
|
is_same_net6(local, &context->start6, prefix) &&
|
||||||
context->ra_time = 0;
|
is_same_net6(local, &context->end6, prefix))
|
||||||
|
context->ra_time = 0;
|
||||||
return 0; /* found, abort */
|
|
||||||
}
|
return 0; /* found, abort */
|
||||||
|
}
|
||||||
|
|
||||||
return 1; /* keep searching */
|
return 1; /* keep searching */
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-56
@@ -20,7 +20,6 @@
|
|||||||
|
|
||||||
#include <netinet/icmp6.h>
|
#include <netinet/icmp6.h>
|
||||||
|
|
||||||
static int map_rebuild = 0;
|
|
||||||
static int ping_id = 0;
|
static int ping_id = 0;
|
||||||
|
|
||||||
void slaac_add_addrs(struct dhcp_lease *lease, time_t now, int force)
|
void slaac_add_addrs(struct dhcp_lease *lease, time_t now, int force)
|
||||||
@@ -38,7 +37,7 @@ void slaac_add_addrs(struct dhcp_lease *lease, time_t now, int force)
|
|||||||
old = lease->slaac_address;
|
old = lease->slaac_address;
|
||||||
lease->slaac_address = NULL;
|
lease->slaac_address = NULL;
|
||||||
|
|
||||||
for (context = daemon->ra_contexts; context; context = context->next)
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
if ((context->flags & CONTEXT_RA_NAME) && lease->last_interface == context->if_index)
|
if ((context->flags & CONTEXT_RA_NAME) && lease->last_interface == context->if_index)
|
||||||
{
|
{
|
||||||
struct in6_addr addr = context->start6;
|
struct in6_addr addr = context->start6;
|
||||||
@@ -123,7 +122,7 @@ time_t periodic_slaac(time_t now, struct dhcp_lease *leases)
|
|||||||
struct slaac_address *slaac;
|
struct slaac_address *slaac;
|
||||||
time_t next_event = 0;
|
time_t next_event = 0;
|
||||||
|
|
||||||
for (context = daemon->ra_contexts; context; context = context->next)
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
if ((context->flags & CONTEXT_RA_NAME))
|
if ((context->flags & CONTEXT_RA_NAME))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -134,12 +133,6 @@ time_t periodic_slaac(time_t now, struct dhcp_lease *leases)
|
|||||||
while (ping_id == 0)
|
while (ping_id == 0)
|
||||||
ping_id = rand16();
|
ping_id = rand16();
|
||||||
|
|
||||||
if (map_rebuild)
|
|
||||||
{
|
|
||||||
map_rebuild = 0;
|
|
||||||
build_subnet_map();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (lease = leases; lease; lease = lease->next)
|
for (lease = leases; lease; lease = lease->next)
|
||||||
for (slaac = lease->slaac_address; slaac; slaac = slaac->next)
|
for (slaac = lease->slaac_address; slaac; slaac = slaac->next)
|
||||||
{
|
{
|
||||||
@@ -211,51 +204,4 @@ void slaac_ping_reply(struct in6_addr *sender, unsigned char *packet, char *inte
|
|||||||
lease_update_dns(gotone);
|
lease_update_dns(gotone);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Build a map from ra-names subnets to corresponding interfaces. This
|
|
||||||
is used to go from DHCPv4 leases to SLAAC addresses,
|
|
||||||
interface->IPv6-subnet, IPv6-subnet + MAC address -> SLAAC.
|
|
||||||
*/
|
|
||||||
static int add_subnet(struct in6_addr *local, int prefix,
|
|
||||||
int scope, int if_index, int dad, void *vparam)
|
|
||||||
{
|
|
||||||
struct dhcp_context *context;
|
|
||||||
|
|
||||||
(void)scope;
|
|
||||||
(void)dad;
|
|
||||||
(void)vparam;
|
|
||||||
|
|
||||||
for (context = daemon->ra_contexts; context; context = context->next)
|
|
||||||
if ((context->flags & CONTEXT_RA_NAME) &&
|
|
||||||
prefix == context->prefix &&
|
|
||||||
is_same_net6(local, &context->start6, prefix) &&
|
|
||||||
is_same_net6(local, &context->end6, prefix))
|
|
||||||
{
|
|
||||||
context->if_index = if_index;
|
|
||||||
context->local6 = *local;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void build_subnet_map(void)
|
|
||||||
{
|
|
||||||
struct dhcp_context *context;
|
|
||||||
int ok = 0;
|
|
||||||
|
|
||||||
for (context = daemon->ra_contexts; context; context = context->next)
|
|
||||||
{
|
|
||||||
context->if_index = 0;
|
|
||||||
if ((context->flags & CONTEXT_RA_NAME))
|
|
||||||
ok = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ra-names configured */
|
|
||||||
if (ok)
|
|
||||||
iface_enumerate(AF_INET6, NULL, add_subnet);
|
|
||||||
}
|
|
||||||
|
|
||||||
void schedule_subnet_map(void)
|
|
||||||
{
|
|
||||||
map_rebuild = 1;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
Reference in new issue
Block a user