]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Allow ia_pd interfaces to be specified without a SLA.
authorRoy Marples <roy@marples.name>
Mon, 3 Jun 2013 22:02:51 +0000 (22:02 +0000)
committerRoy Marples <roy@marples.name>
Mon, 3 Jun 2013 22:02:51 +0000 (22:02 +0000)
dhcp6.c
dhcpcd.conf.5.in
if-options.c
if-options.h

diff --git a/dhcp6.c b/dhcp6.c
index af98fd64223377e4373a887d5e9d3b8dfb325aae..7c307da9c5ef9df15a2950e092f289304f710c23 100644 (file)
--- 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++) {
index 6db7c5b5b1ae739b0defdaf22dde5410c56b82f3..414c20545733f1e681937e6cf85a62931283c249 100644 (file)
@@ -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
index 11b5e80bbb244a5928dc285afca256eb587ce025..69a5a45c0619b6393833ef3853d875ee5211e654 100644 (file)
@@ -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;
index 7b2a74bb09bb100c6a3d5ac34616021bab583217..1efb6e4787f37cc20c8faa2555d5289a808862e5 100644 (file)
@@ -97,6 +97,7 @@ struct if_sla {
        char ifname[IF_NAMESIZE];
        uint32_t sla;
        short prefix_len;
+       int8_t sla_set;
 };
 
 struct if_iaid {