More flexible RA configuration.

This commit is contained in:
Simon Kelley
2012-03-25 20:44:38 +01:00
parent 7dbe98147d
commit 30cd96663f
5 changed files with 99 additions and 72 deletions

View File

@@ -229,7 +229,7 @@ int address6_allocate(struct dhcp_context *context, unsigned char *clid, int cl
for (pass = 0; pass <= 1; pass++) for (pass = 0; pass <= 1; pass++)
for (c = context; c; c = c->current) for (c = context; c; c = c->current)
if (c->flags & (CONTEXT_STATIC | CONTEXT_PROXY)) if (c->flags & (CONTEXT_STATIC | CONTEXT_RA_STATELESS))
continue; continue;
else if (!match_netid(c->filter, netids, pass)) else if (!match_netid(c->filter, netids, pass))
continue; continue;

View File

@@ -549,23 +549,30 @@ int main (int argc, char **argv)
{ {
start = &dhcp_tmp->start6; start = &dhcp_tmp->start6;
end = &dhcp_tmp->end6; end = &dhcp_tmp->end6;
struct in6_addr subnet = dhcp_tmp->start6;
setaddr6part(&subnet, 0);
inet_ntop(AF_INET6, &subnet, daemon->dhcp_buff2, 256);
} }
#endif #endif
prettyprint_time(daemon->dhcp_buff2, dhcp_tmp->lease_time); prettyprint_time(daemon->namebuff, dhcp_tmp->lease_time);
inet_ntop(family, start, daemon->dhcp_buff, 256); inet_ntop(family, start, daemon->dhcp_buff, 256);
inet_ntop(family, end, daemon->dhcp_buff3, 256); inet_ntop(family, end, daemon->dhcp_buff3, 256);
my_syslog(MS_DHCP | LOG_INFO, if ((dhcp_tmp->flags & CONTEXT_DHCP) || family == AF_INET)
(dhcp_tmp->flags & CONTEXT_STATIC) ? my_syslog(MS_DHCP | LOG_INFO,
_("DHCP, static leases only on %.0s%s, lease time %s") : (dhcp_tmp->flags & CONTEXT_STATIC) ?
(dhcp_tmp->flags & CONTEXT_RA_NAME) ? _("DHCP, static leases only on %.0s%s, lease time %s") :
_("router advertisement with DHCPv4-derived names on %.0s%s, lifetime %s") : (dhcp_tmp->flags & CONTEXT_RA_STATELESS) ?
(dhcp_tmp->flags & CONTEXT_RA_ONLY) ? _("SLAAC and stateless DHCPv6 on %.0s%s%.0s") :
_("router advertisement only on %.0s%s, lifetime %s") : (dhcp_tmp->flags & CONTEXT_PROXY) ?
(dhcp_tmp->flags & CONTEXT_PROXY) ? _("DHCP, proxy on subnet %.0s%s%.0s") :
_("DHCP, proxy on subnet %.0s%s%.0s") : _("DHCP, IP range %s -- %s, lease time %s"),
_("DHCP, IP range %s -- %s, lease time %s"), daemon->dhcp_buff, daemon->dhcp_buff3, daemon->namebuff);
daemon->dhcp_buff, daemon->dhcp_buff3, daemon->dhcp_buff2); if (dhcp_tmp->flags & CONTEXT_RA_NAME)
my_syslog(MS_DHCP | LOG_INFO, _("SLAAC and DHCPv4-derived names on %s"), daemon->dhcp_buff2);
if (dhcp_tmp->flags & CONTEXT_RA_ONLY)
my_syslog(MS_DHCP | LOG_INFO, _("SLAAC on %s"), daemon->dhcp_buff2);
} }
#ifdef HAVE_DHCP6 #ifdef HAVE_DHCP6

View File

@@ -646,13 +646,15 @@ struct dhcp_context {
struct dhcp_context *next, *current; struct dhcp_context *next, *current;
}; };
#define CONTEXT_STATIC 1 #define CONTEXT_STATIC 1
#define CONTEXT_NETMASK 2 #define CONTEXT_NETMASK 2
#define CONTEXT_BRDCAST 4 #define CONTEXT_BRDCAST 4
#define CONTEXT_PROXY 8 #define CONTEXT_PROXY 8
#define CONTEXT_RA_ONLY 16 #define CONTEXT_RA_ONLY 16
#define CONTEXT_RA_DONE 32 #define CONTEXT_RA_DONE 32
#define CONTEXT_RA_NAME 64 #define CONTEXT_RA_NAME 64
#define CONTEXT_RA_STATELESS 128
#define CONTEXT_DHCP 256
struct ping_result { struct ping_result {
struct in_addr addr; struct in_addr addr;

View File

@@ -1959,7 +1959,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
case 'F': /* --dhcp-range */ case 'F': /* --dhcp-range */
{ {
int k, leasepos = 2; int k, leasepos = 2;
char *cp, *a[5] = { NULL, NULL, NULL, NULL, NULL }; char *cp, *a[7] = { 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));
@@ -2010,7 +2010,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
} }
} }
for (k = 1; k < 5; k++) for (k = 1; k < 7; k++)
if (!(a[k] = split(a[k-1]))) if (!(a[k] = split(a[k-1])))
break; break;
@@ -2020,17 +2020,12 @@ static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
{ {
new->next = daemon->dhcp; new->next = daemon->dhcp;
daemon->dhcp = new; daemon->dhcp = new;
new->end = new->start;
if (strcmp(a[1], "static") == 0) if (strcmp(a[1], "static") == 0)
{ new->flags |= CONTEXT_STATIC;
new->end = new->start;
new->flags |= CONTEXT_STATIC;
}
else if (strcmp(a[1], "proxy") == 0) else if (strcmp(a[1], "proxy") == 0)
{ new->flags |= CONTEXT_PROXY;
new->end = new->start; else if (!inet_pton(AF_INET, a[1], &new->end))
new->flags |= CONTEXT_PROXY;
}
else if ((new->end.s_addr = inet_addr(a[1])) == (in_addr_t)-1)
option = '?'; option = '?';
if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr)) if (ntohl(new->start.s_addr) > ntohl(new->end.s_addr))
@@ -2060,53 +2055,54 @@ static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
else if (inet_pton(AF_INET6, a[0], &new->start6)) else if (inet_pton(AF_INET6, a[0], &new->start6))
{ {
new->prefix = 64; /* default */ new->prefix = 64; /* default */
new->end6 = new->start6;
for (leasepos = 1; leasepos < k; leasepos++)
{
if (strcmp(a[leasepos], "static") == 0)
new->flags |= CONTEXT_STATIC | CONTEXT_DHCP;
else if (strcmp(a[leasepos], "ra-only") == 0 || strcmp(a[leasepos], "slaac") == 0 )
new->flags |= CONTEXT_RA_ONLY;
else if (strcmp(a[leasepos], "ra-names") == 0)
new->flags |= CONTEXT_RA_NAME;
else if (strcmp(a[leasepos], "ra-stateless") == 0)
new->flags |= CONTEXT_RA_STATELESS | CONTEXT_DHCP;
else if (leasepos == 1 && inet_pton(AF_INET6, a[leasepos], &new->end6))
new->flags |= CONTEXT_DHCP;
else
break;
}
if (strcmp(a[1], "static") == 0) if (new->flags & CONTEXT_DHCP)
{
memcpy(&new->end6, &new->start6, IN6ADDRSZ);
new->flags |= CONTEXT_STATIC;
}
else if (strcmp(a[1], "ra-only") == 0)
{
memcpy(&new->end6, &new->start6, IN6ADDRSZ);
new->flags |= CONTEXT_RA_ONLY;
}
else if (strcmp(a[1], "ra-names") == 0)
{
memcpy(&new->end6, &new->start6, IN6ADDRSZ);
new->flags |= CONTEXT_RA_NAME | CONTEXT_RA_ONLY;
}
else if (!inet_pton(AF_INET6, a[1], &new->end6))
option = '?';
if (new->flags & CONTEXT_RA_ONLY)
{
new->next = daemon->ra_contexts;
daemon->ra_contexts = new;
}
else
{ {
new->next = daemon->dhcp6; new->next = daemon->dhcp6;
daemon->dhcp6 = new; 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 (option != '?' && k >= 3) if (option != '?' && leasepos < k)
{ {
int pref; int pref;
for (cp = a[2]; *cp; cp++) for (cp = a[leasepos]; *cp; cp++)
if (!(*cp >= '0' && *cp <= '9')) if (!(*cp >= '0' && *cp <= '9'))
break; break;
if (!*cp && (pref = atoi(a[2])) <= 128) if (!*cp && (pref = atoi(a[leasepos])) <= 128)
{ {
new->prefix = pref; new->prefix = pref;
leasepos = 3; leasepos++;
if ((new->flags & CONTEXT_RA_ONLY) && new->prefix != 64) if ((new->flags & (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)) &&
new->prefix != 64)
problem = _("prefix must be exactly 64 for RA subnets"); problem = _("prefix must be exactly 64 for RA subnets");
else if (new->prefix < 64) else if (new->prefix < 64)
problem = _("prefix must be at least 64"); problem = _("prefix must be at least 64");
} }
} }
if (!problem && !is_same_net6(&new->start6, &new->end6, new->prefix)) if (!problem && !is_same_net6(&new->start6, &new->end6, new->prefix))
problem = _("inconsistent DHCPv6 range"); problem = _("inconsistent DHCPv6 range");
else if (addr6part(&new->start6) > addr6part(&new->end6)) else if (addr6part(&new->start6) > addr6part(&new->end6))
@@ -2118,7 +2114,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
} }
#endif #endif
if (k >= leasepos+1) if (leasepos < k)
{ {
if (strcmp(a[leasepos], "infinite") == 0) if (strcmp(a[leasepos], "infinite") == 0)
new->lease_time = 0xffffffff; new->lease_time = 0xffffffff;

View File

@@ -27,7 +27,7 @@
#include <netinet/icmp6.h> #include <netinet/icmp6.h>
struct ra_param { struct ra_param {
int ind, managed, found_context, first; int ind, managed, other, found_context, first;
char *if_name; char *if_name;
struct in6_addr link_local; struct in6_addr link_local;
}; };
@@ -213,6 +213,7 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
parm.ind = iface; parm.ind = iface;
parm.managed = 0; parm.managed = 0;
parm.other = 0;
parm.found_context = 0; parm.found_context = 0;
parm.if_name = iface_name; parm.if_name = iface_name;
parm.first = 1; parm.first = 1;
@@ -246,8 +247,10 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
/* set managed bits unless we're providing only RA on this link */ /* set managed bits unless we're providing only RA on this link */
if (parm.managed) if (parm.managed)
ra->flags = 0xc0; /* M flag, managed, O flag, other */ ra->flags |= 0x80; /* M flag, managed, */
if (parm.other)
ra->flags |= 0x40; /* O flag, other */
/* decide where we're sending */ /* decide where we're sending */
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
#ifdef HAVE_SOCKADDR_SA_LEN #ifdef HAVE_SOCKADDR_SA_LEN
@@ -295,14 +298,20 @@ static int add_prefixes(struct in6_addr *local, int prefix,
{ {
int do_slaac = 0; int do_slaac = 0;
if (context->flags & CONTEXT_RA_ONLY) if ((context->flags &
do_slaac = 1; (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)))
{
do_slaac = 1;
if (context->flags & CONTEXT_RA_STATELESS)
param->other = 1;
}
else else
{ {
/* don't do RA for non-ra-only unless --enable-ra is set */ /* don't do RA for non-ra-only unless --enable-ra is set */
if (!option_bool(OPT_RA)) if (!option_bool(OPT_RA))
continue; continue;
param->managed = 1; param->managed = 1;
param->other = 1;
} }
if (context->flags & CONTEXT_RA_DONE) if (context->flags & CONTEXT_RA_DONE)
@@ -321,14 +330,27 @@ static int add_prefixes(struct in6_addr *local, int prefix,
is_same_net6(local, &tmp->start6, prefix) && is_same_net6(local, &tmp->start6, prefix) &&
is_same_net6(local, &tmp->end6, prefix)) is_same_net6(local, &tmp->end6, prefix))
{ {
/* if any dhcp-range with ra-only on this subnet
set the "do_slaac" bit */
if (tmp->flags & CONTEXT_RA_ONLY)
do_slaac = 1;
tmp->flags |= CONTEXT_RA_DONE; tmp->flags |= CONTEXT_RA_DONE;
context->ra_time = 0; context->ra_time = 0;
/* if any dhcp-range with ra-only on this subnet
set the "do_slaac" bit */
if (tmp->flags &
(CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS))
{
do_slaac = 1;
if (context->flags & CONTEXT_RA_STATELESS)
param->other = 1;
}
else
{
/* don't do RA for non-ra-only unless --enable-ra is set */
if (!option_bool(OPT_RA))
continue;
param->managed = 1;
param->other = 1;
}
} }
if ((opt = expand(sizeof(struct prefix_opt)))) if ((opt = expand(sizeof(struct prefix_opt))))
{ {
u64 addrpart = addr6part(&context->start6); u64 addrpart = addr6part(&context->start6);