]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Allow the suffix of PD addresses to be configurable.
authorRoy Marples <roy@marples.name>
Fri, 29 Jan 2016 11:36:05 +0000 (11:36 +0000)
committerRoy Marples <roy@marples.name>
Fri, 29 Jan 2016 11:36:05 +0000 (11:36 +0000)
Fixes [0666660018].

dhcp6.c
dhcpcd.conf.5.in
if-options.c
if-options.h

diff --git a/dhcp6.c b/dhcp6.c
index 667815160bf4b77dd64a72d23f50ce080d09d3e4..88fe4f6f1c43596604c80621a68192808b5125d1 100644 (file)
--- a/dhcp6.c
+++ b/dhcp6.c
@@ -2336,6 +2336,7 @@ dhcp6_ifdelegateaddr(struct interface *ifp, struct ipv6_addr *prefix,
        char sabuf[INET6_ADDRSTRLEN];
        const char *sa;
        int pfxlen;
+       uint64_t vl;
 
        /* RFC6603 Section 4.2 */
        if (strcmp(ifp->name, ifs->name) == 0) {
@@ -2354,6 +2355,12 @@ dhcp6_ifdelegateaddr(struct interface *ifp, struct ipv6_addr *prefix,
            sla, ia)) == -1)
                return NULL;
 
+       if (ffs64(sla->suffix) > 128 - pfxlen) {
+               logger(ifp->ctx, LOG_ERR,
+                   "%s: suffix %" PRIu64 " + prefix_len %d > 128",
+                   ifp->name, sla->suffix, pfxlen);
+               return NULL;
+       }
 
        a = calloc(1, sizeof(*a));
        if (a == NULL) {
@@ -2371,11 +2378,11 @@ dhcp6_ifdelegateaddr(struct interface *ifp, struct ipv6_addr *prefix,
        a->prefix = addr;
        a->prefix_len = (uint8_t)pfxlen;
 
-       /* Wang a 1 at the end as the prefix could be >64
-        * making SLAAC impossible. */
-       a->addr = a->prefix;
-       a->addr.s6_addr[sizeof(a->addr.s6_addr) - 1] =
-           (uint8_t)(a->addr.s6_addr[sizeof(a->addr.s6_addr) - 1] + 1);
+       /* Add our suffix */
+       a->addr = addr;
+       vl = be64dec(addr.s6_addr + 8);
+       vl |= sla->suffix;
+       be64enc(a->addr.s6_addr + 8, vl);
 
        state = D6_STATE(ifp);
        /* Remove any exiting address */
index a7f0acd58e53ae75eb6a191be6d8ebb48adcceb3..35dd8069eeea46caa333b5af2569af6b91282c5a 100644 (file)
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd October 19, 2015
+.Dd January 29, 2016
 .Dt DHCPCD.CONF 5
 .Os
 .Sh NAME
@@ -252,7 +252,7 @@ Request a DHCPv6 Temporary Address for
 You can request more than one ia_ta by specifying a unique
 .Ar iaid
 for each one.
-.It Ic ia_pd Op Ar iaid Oo / Ar prefix / Ar prefix_len Oc Op Ar interface Op / Ar sla_id Op / Ar prefix_len
+.It Ic ia_pd Op Ar iaid Oo / Ar prefix / Ar prefix_len Oc Op Ar interface Op / Ar sla_id Op / Ar prefix_len Op / Ar suffix
 Request a DHCPv6 Delegated Prefix for
 .Ar iaid .
 This option must be used in an
@@ -273,7 +273,9 @@ Otherwise addresses are only assigned for each
 .Ar interface
 and
 .Ar sla_id .
-Each assigned address will have a suffix of 1.
+Each assigned address will have a
+.Ar suffix ,
+defaulting to 1.
 You cannot assign a prefix to the requesting interface unless the
 DHCPv6 server supports
 .Li RFC6603
index 9e4ce06dd344c40cbf21776316bae3ceab2a535c..0ca9f9373908cf2ea7c4199706f29996a336a09d 100644 (file)
@@ -1408,18 +1408,19 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
                        if (strlcpy(sla->ifname, p,
                            sizeof(sla->ifname)) >= sizeof(sla->ifname))
                        {
-                               logger(ctx, LOG_ERR, "%s: interface name too long",
-                                   arg);
+                               logger(ctx, LOG_ERR,
+                                   "%s: interface name too long", arg);
                                goto err_sla;
                        }
+                       sla->sla_set = 0;
+                       sla->prefix_len = 0;
+                       sla->suffix = 1;
                        p = np;
                        if (p) {
                                np = strchr(p, '/');
                                if (np)
                                        *np++ = '\0';
-                               if (*p == '\0')
-                                       sla->sla_set = 0;
-                               else {
+                               if (*p != '\0') {
                                        sla->sla = (uint32_t)strtou(p, NULL,
                                            0, 0, UINT32_MAX, &e);
                                        sla->sla_set = 1;
@@ -1430,20 +1431,40 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
                                                goto err_sla;
                                        }
                                }
-                               if (np) {
+                               p = np;
+                       }
+                       if (p) {
+                               np = strchr(p, '/');
+                               if (np)
+                                       *np++ = '\0';
+                               if (*p != '\0') {
                                        sla->prefix_len = (uint8_t)strtou(np,
-                                           NULL, 0, 0, 120, &e);
+                                   NULL, 0, 0, 120, &e);
                                        if (e) {
-                                               logger(ctx, LOG_ERR, "%s: failed to "
+                                               logger(ctx, LOG_ERR,
+                                                   "%s: failed to "
                                                    "convert prefix len",
                                                    ifname);
                                                goto err_sla;
                                        }
-                               } else
-                                       sla->prefix_len = 0;
-                       } else {
-                               sla->sla_set = 0;
-                               sla->prefix_len = 0;
+                               }
+                               p = np;
+                       }
+                       if (p) {
+                               np = strchr(p, '/');
+                               if (np)
+                                       *np = '\0';
+                               if (*p != '\0') {
+                                       sla->suffix = (uint64_t)strtou(p, NULL,
+                                           0, 0, UINT64_MAX, &e);
+                                       if (e) {
+                                               logger(ctx, LOG_ERR,
+                                                   "%s: failed to "
+                                                   "convert suffix",
+                                                   ifname);
+                                               goto err_sla;
+                                       }
+                               }
                        }
                        /* Sanity check */
                        for (sl = 0; sl < ia->sla_len - 1; sl++) {
index 66b87d8de3324a2f9e31d607f79d5689f0d0fc06..6c7ab153b26d93884419b733b888173840c4e21b 100644 (file)
@@ -129,6 +129,7 @@ struct if_sla {
        char ifname[IF_NAMESIZE];
        uint32_t sla;
        uint8_t prefix_len;
+       uint64_t suffix;
        int8_t sla_set;
 };