From: Roy Marples Date: Mon, 3 Jun 2013 22:02:51 +0000 (+0000) Subject: Allow ia_pd interfaces to be specified without a SLA. X-Git-Tag: v5.99.7~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5985c4e2a6cc9cd91daf683640727dc7561fce64;p=thirdparty%2Fdhcpcd.git Allow ia_pd interfaces to be specified without a SLA. --- diff --git a/dhcp6.c b/dhcp6.c index af98fd64..7c307da9 100644 --- a/dhcp6.c +++ b/dhcp6.c @@ -1495,10 +1495,39 @@ dhcp6_startinit(struct interface *ifp) dhcp6_startdiscover(ifp); } -static struct dhcp6_state * -dhcp6_getstate(struct interface *ifp) +static uint32_t +dhcp6_findsla(void) +{ + uint32_t sla; + const struct interface *ifp; + const struct dhcp6_state *state; + + /* Slow, but finding the lowest free SLA is needed if we get a + * /62 or /63 prefix from upstream */ + for (sla = 0; sla < UINT32_MAX; sla++) { + TAILQ_FOREACH(ifp, ifaces, next) { + state = D6_CSTATE(ifp); + if (state && state->sla_set && state->sla == sla) + break; + } + if (ifp == NULL) + return sla; + } + + errno = E2BIG; + return 0; +} + +static struct ipv6_addr * +dhcp6_delegate_addr(struct interface *ifp, const struct ipv6_addr *prefix, + const struct if_sla *sla, struct interface *ifs) { struct dhcp6_state *state; + struct if_sla asla; + struct in6_addr addr; + struct ipv6_addr *a, *ap; + char iabuf[INET6_ADDRSTRLEN]; + const char *ia; state = D6_STATE(ifp); if (state == NULL) { @@ -1513,18 +1542,24 @@ dhcp6_getstate(struct interface *ifp) state->state = DH6S_DELEGATED; state->reason = "DELEGATED6"; } - return state; -} -static struct ipv6_addr * -dhcp6_delegate_addr(struct interface *ifp, const struct ipv6_addr *prefix, - const struct if_sla *sla, struct interface *ifs) -{ - struct in6_addr addr; - struct dhcp6_state *state; - struct ipv6_addr *a, *ap; - char iabuf[INET6_ADDRSTRLEN]; - const char *ia; + if (sla == NULL || sla->sla_set == 0) { + if (!state->sla_set) { + errno = 0; + state->sla = dhcp6_findsla(); + if (errno) { + syslog(LOG_ERR, "%s: dhcp6_find_sla: %m", + ifp->name); + return NULL; + } + syslog(LOG_DEBUG, "%s: set SLA %d", + ifp->name, state->sla); + state->sla_set = 1; + } + asla.sla = state->sla; + asla.prefix_len = 64; + sla = &asla; + } if (ipv6_userprefix(&prefix->prefix, prefix->prefix_len, sla->sla, &addr, sla->prefix_len) == -1) @@ -1537,10 +1572,6 @@ dhcp6_delegate_addr(struct interface *ifp, const struct ipv6_addr *prefix, return NULL; } - state = dhcp6_getstate(ifp); - if (state == NULL) - return NULL; - a = calloc(1, sizeof(*a)); if (a == NULL) { syslog(LOG_ERR, "%s: %m", __func__); @@ -1580,29 +1611,6 @@ dhcp6_delegate_addr(struct interface *ifp, const struct ipv6_addr *prefix, return a; } -static uint32_t -dhcp6_findsla(void) -{ - uint32_t sla; - const struct interface *ifp; - const struct dhcp6_state *state; - - /* Slow, but finding the lowest free SLA is needed if we get a - * /62 or /63 prefix from upstream */ - for (sla = 0; sla < UINT32_MAX; sla++) { - TAILQ_FOREACH(ifp, ifaces, next) { - state = D6_CSTATE(ifp); - if (state && state->sla_set && state->sla == sla) - break; - } - if (ifp == NULL) - return sla; - } - - errno = E2BIG; - return 0; -} - static void dhcp6_delegate_prefix(struct interface *ifp) { @@ -1611,11 +1619,10 @@ dhcp6_delegate_prefix(struct interface *ifp) struct ipv6_addr *ap; size_t i, j, k; struct if_iaid *iaid; - struct if_sla *sla, asla; + struct if_sla *sla; struct interface *ifd; uint8_t carrier_warned; - asla.prefix_len = 64; ifo = ifp->options; state = D6_STATE(ifp); TAILQ_FOREACH(ifd, ifaces, next) { @@ -1637,25 +1644,6 @@ dhcp6_delegate_prefix(struct interface *ifp) * automate it */ if (ifp == ifd) continue; - ifd_state = dhcp6_getstate(ifd); - if (ifd_state == NULL) - return; - if (!ifd_state->sla_set) { - errno = 0; - ifd_state->sla = - dhcp6_findsla(); - if (errno) { - syslog(LOG_ERR, - "%s: dhcp6_find_sla:" - " %m", ifd->name); - continue; - } - syslog(LOG_DEBUG, - "%s: set SLA %d", - ifd->name, ifd_state->sla); - ifd_state->sla_set = 1; - } - asla.sla = ifd_state->sla; if (ifd->carrier == LINK_DOWN) { syslog(LOG_DEBUG, "%s: has no carrier, cannot" @@ -1665,7 +1653,7 @@ dhcp6_delegate_prefix(struct interface *ifp) break; } if (dhcp6_delegate_addr(ifd, ap, - &asla, ifp)) + NULL, ifp)) k++; } for (j = 0; j < iaid->sla_len; j++) { diff --git a/dhcpcd.conf.5.in b/dhcpcd.conf.5.in index 6db7c5b5..414c2054 100644 --- a/dhcpcd.conf.5.in +++ b/dhcpcd.conf.5.in @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd June 1, 2013 +.Dd June 3, 2013 .Dt DHCPCD.CONF 5 SMM .Os .Sh NAME @@ -144,7 +144,7 @@ otherwise the interface index is used. .It Ic ia_ta Op Ar iaid Request a DHCPv6 Temporary Address for .Ar iaid . -.It Ic ia_pd Op Ar iaid Op Ar interface / Ar sla_id Op / Ar prefix_len +.It Ic ia_pd Op Ar iaid Op Ar interface Op / Ar sla_id Op / Ar prefix_len Request a DHCPv6 Delegated Prefix for .Ar iaid . If no @@ -175,7 +175,7 @@ IPv6RS should be disabled globally when requesting a Prefix Delegation like so: .D1 noipv6rs .Pp .D1 interface eth0 -.D1 ia_pd 1 eth1/0 eth2/1 +.D1 ia_pd 1 eth1/0 eth2/0 .It Ic ipv4only Only configure IPv4. .It Ic ipv6only diff --git a/if-options.c b/if-options.c index 11b5e80b..69a5a45c 100644 --- a/if-options.c +++ b/if-options.c @@ -435,7 +435,7 @@ parse_option(struct if_options *ifo, int opt, const char *arg) uint32_t u32; struct if_iaid *iaid; uint8_t _iaid[4]; - struct if_sla *sla; + struct if_sla *sla, *slap; i = 0; switch(opt) { @@ -1035,6 +1035,7 @@ got_iaid: *np++ = '\0'; errno = 0; sla->sla = atoint(p); + sla->sla_set = 1; if (errno) return -1; if (np) { @@ -1044,6 +1045,25 @@ got_iaid: return -1; } else sla->prefix_len = 64; + } else { + sla->sla_set = 0; + /* Sanity - check there are no more + * unspecified SLA's */ + for (sl = 0; sl < iaid->sla_len - 1; sl++) { + slap = &iaid->sla[sl]; + if (slap->sla_set == 0 && + strcmp(slap->ifname, sla->ifname) + == 0) + { + syslog(LOG_WARNING, + "%s: cannot specify the " + "same interface twice with " + "an automatic SLA", + sla->ifname); + iaid->sla_len--; + break; + } + } } } break; diff --git a/if-options.h b/if-options.h index 7b2a74bb..1efb6e47 100644 --- a/if-options.h +++ b/if-options.h @@ -97,6 +97,7 @@ struct if_sla { char ifname[IF_NAMESIZE]; uint32_t sla; short prefix_len; + int8_t sla_set; }; struct if_iaid {