]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Set %interface for exported IPv6 link local addresses.
authorRoy Marples <roy@marples.name>
Sat, 24 Nov 2012 20:11:49 +0000 (20:11 +0000)
committerRoy Marples <roy@marples.name>
Sat, 24 Nov 2012 20:11:49 +0000 (20:11 +0000)
configure.c
dhcp.c
dhcp.h
dhcp6.c
ipv6.c
ipv6.h
ipv6rs.c

index 334e375c667b96f49ca2a88cbba301ee103eabbd..7d8475d245caaaecb0031d592dc558d28d5d145b 100644 (file)
@@ -282,11 +282,11 @@ make_env(const struct interface *iface, const char *reason, char ***argv)
                }
        }
        if (dhcp && iface->state->old) {
-               e = configure_env(NULL, NULL, iface->state->old, ifo);
+               e = configure_env(NULL, NULL, iface->state->old, iface);
                if (e > 0) {
                        env = xrealloc(env, sizeof(char *) * (elen + e + 1));
                        elen += configure_env(env + elen, "old",
-                           iface->state->old, ifo);
+                           iface->state->old, iface);
                }
                append_config(&env, &elen, "old",
                    (const char *const *)ifo->config);
@@ -303,11 +303,11 @@ make_env(const struct interface *iface, const char *reason, char ***argv)
 
 dumplease:
        if (dhcp && iface->state->new) {
-               e = configure_env(NULL, NULL, iface->state->new, ifo);
+               e = configure_env(NULL, NULL, iface->state->new, iface);
                if (e > 0) {
                        env = xrealloc(env, sizeof(char *) * (elen + e + 1));
                        elen += configure_env(env + elen, "new",
-                           iface->state->new, ifo);
+                           iface->state->new, iface);
                }
                append_config(&env, &elen, "new",
                    (const char *const *)ifo->config);
diff --git a/dhcp.c b/dhcp.c
index 673875221cb97e507876f34f8723a86a8cf07f17..3a157350cddcd04358029a012747f35edcca0b32 100644 (file)
--- a/dhcp.c
+++ b/dhcp.c
@@ -1222,7 +1222,8 @@ print_string(char *s, ssize_t len, int dl, const uint8_t *data)
 }
 
 ssize_t
-print_option(char *s, ssize_t len, int type, int dl, const uint8_t *data)
+print_option(char *s, ssize_t len, int type, int dl, const uint8_t *data,
+    const char *ifname)
 {
        const uint8_t *e, *t;
        uint16_t u16;
@@ -1232,8 +1233,7 @@ print_option(char *s, ssize_t len, int type, int dl, const uint8_t *data)
        struct in_addr addr;
        ssize_t bytes = 0;
        ssize_t l;
-       char *tmp, ntopbuf[INET6_ADDRSTRLEN];
-       const char *addr6;
+       char *tmp;
 
        if (type & RFC3397) {
                l = decode_rfc3397(NULL, 0, dl, data);
@@ -1280,10 +1280,13 @@ print_option(char *s, ssize_t len, int type, int dl, const uint8_t *data)
                data += sizeof(u16);
                dl -= sizeof(u16);
                if (dl)
-                       l += print_option(s, len, STRING, dl, data);
+                       l += print_option(s, len, STRING, dl, data, ifname);
                return l;
        }
 
+       if (type & IPV6) {
+       }
+
        if (!s) {
                if (type & UINT8)
                        l = 3;
@@ -1303,8 +1306,15 @@ print_option(char *s, ssize_t len, int type, int dl, const uint8_t *data)
                        l = 16;
                        dl /= 4;
                } else if (type & IPV6) {
-                       l = INET6_ADDRSTRLEN;
-                       dl /= 16;
+                       e = data + dl;
+                       l = 0;
+                       while (data < e) {
+                               if (l)
+                                       l++; /* space */
+                               l += ipv6_printaddr(NULL, 0, data, ifname);
+                               data += 16;
+                       }
+                       return l + 1;
                } else if (type & BINHEX) {
                        l = 2;
                } else {
@@ -1350,9 +1360,7 @@ print_option(char *s, ssize_t len, int type, int dl, const uint8_t *data)
                        l = snprintf(s, len, "%s", inet_ntoa(addr));
                        data += sizeof(addr.s_addr);
                } else if (type & IPV6) {
-                       addr6 = inet_ntop(AF_INET6, data,
-                           ntopbuf, sizeof(ntopbuf));
-                       l = snprintf(s, len, "%s", addr6);
+                       l = ipv6_printaddr(s, len, data, ifname);
                        data += 16;
                } else if (type & BINHEX) {
                        l = snprintf(s, len, "%.2x", data[0]);
@@ -1369,8 +1377,9 @@ print_option(char *s, ssize_t len, int type, int dl, const uint8_t *data)
 
 ssize_t
 configure_env(char **env, const char *prefix, const struct dhcp_message *dhcp,
-    const struct if_options *ifo)
+    const struct interface *ifp)
 {
+       const struct if_options *ifo;
        const uint8_t *p;
        int pl;
        struct in_addr addr;
@@ -1383,6 +1392,7 @@ configure_env(char **env, const char *prefix, const struct dhcp_message *dhcp,
        char cidr[4];
        uint8_t overl = 0;
 
+       ifo = ifp->state->options;
        get_option_uint8(&overl, dhcp, DHO_OPTIONSOVERLOADED);
 
        if (!env) {
@@ -1442,14 +1452,14 @@ configure_env(char **env, const char *prefix, const struct dhcp_message *dhcp,
                        p += 3;
                        pl -= 3;
                }
-               len = print_option(NULL, 0, opt->type, pl, p);
+               len = print_option(NULL, 0, opt->type, pl, p, ifp->name);
                if (len < 0)
                        return -1;
                e = strlen(prefix) + strlen(opt->var) + len + 4;
                v = val = *ep++ = xmalloc(e);
                v += snprintf(val, e, "%s_%s=", prefix, opt->var);
                if (len != 0)
-                       print_option(v, len, opt->type, pl, p);
+                       print_option(v, len, opt->type, pl, p, ifp->name);
        }
 
        return ep - env;
diff --git a/dhcp.h b/dhcp.h
index e6190c89300091a90b623cc35bdd6223456e19b3..64a5ff82d0e6a581e3430b6929268ac3e82963b3 100644 (file)
--- a/dhcp.h
+++ b/dhcp.h
@@ -217,11 +217,10 @@ int get_option_uint8(uint8_t *, const struct dhcp_message *, uint8_t);
 struct rt *get_option_routes(const struct dhcp_message *, const char *,
     unsigned long long *);
 ssize_t decode_rfc3397(char *, ssize_t, int, const uint8_t *);
-ssize_t print_string(char *s, ssize_t len, int dl, const uint8_t *data);
-ssize_t print_option(char *s, ssize_t len, int type, int dl,
-    const uint8_t *data);
+ssize_t print_string(char *, ssize_t, int, const uint8_t *);
+ssize_t print_option(char *, ssize_t, int, int, const uint8_t *, const char *);
 ssize_t configure_env(char **, const char *, const struct dhcp_message *,
-    const struct if_options *);
+    const struct interface *);
 
 int dhcp_message_add_addr(struct dhcp_message *, uint8_t, struct in_addr);
 ssize_t make_message(struct dhcp_message **, const struct interface *,
diff --git a/dhcp6.c b/dhcp6.c
index 12d0312cfcc3865fb80176ae3f57340ed4ed9fef..9026d3e8545a0268f22c97bee1c0ccc6e09e3997 100644 (file)
--- a/dhcp6.c
+++ b/dhcp6.c
@@ -767,6 +767,9 @@ dhcp6_startdiscover(void *arg)
        state->new = NULL;
        state->new_len = 0;
 
+       /* XXX remove this line when we fix discover stamping on assigned */
+       dhcp6_freedrop_addrs(ifp, 0);
+
        if (dhcp6_makemessage(ifp) == -1)
                syslog(LOG_ERR, "%s: dhcp6_makemessage: %m", ifp->name);
        else
@@ -1591,14 +1594,14 @@ dhcp6_env(char **env, const char *prefix, const struct interface *ifp,
                }
                ol = ntohs(o->len);
                od = D6_COPTION_DATA(o);
-               len = print_option(NULL, 0, opt->type, ol, od);
+               len = print_option(NULL, 0, opt->type, ol, od, ifp->name);
                if (len < 0)
                        return -1;
                e = strlen(prefix) + 6 + strlen(opt->var) + len + 4;
                v = val = *ep++ = xmalloc(e);
                v += snprintf(val, e, "%s_dhcp6_%s=", prefix, opt->var);
                if (len != 0)
-                       print_option(v, len, opt->type, ol, od);
+                       print_option(v, len, opt->type, ol, od, ifp->name);
 
        }
 
diff --git a/ipv6.c b/ipv6.c
index 7a4a166db98626c774e23f7b9f3aa85c9981b4bc..198cb2d0fccfeff592c6c91dc1fc1c1b89990541 100644 (file)
--- a/ipv6.c
+++ b/ipv6.c
@@ -78,6 +78,38 @@ int ipv6_init(void)
        return 0;
 }
 
+ssize_t
+ipv6_printaddr(char *s, ssize_t sl, const uint8_t *d, const char *ifname)
+{
+       char buf[INET6_ADDRSTRLEN];
+       const char *p;
+       ssize_t l;
+
+       p = inet_ntop(AF_INET6, d, buf, sizeof(buf));
+       if (p == NULL)
+               return -1;
+
+       l = strlen(p);
+       if (d[0] == 0xfe && (d[1] & 0xc0) == 0x80)
+               l += 1 + strlen(ifname);
+
+       if (s == NULL)
+               return l;
+
+       if (sl < l) {
+               errno = ENOMEM;
+               return -1;
+       }
+               
+       s += strlcpy(s, p, sl);
+       if (d[0] == 0xfe && (d[1] & 0xc0) == 0x80) {
+               *s++ = '%';
+               s += strlcpy(s, ifname, sl);
+       }
+       *s = '\0';
+       return l;
+}
+
 struct in6_addr *
 ipv6_linklocal(const char *ifname)
 {
diff --git a/ipv6.h b/ipv6.h
index 55be21681f52055ce333cc6959ed3a6ff77468bf..92a913535df16560761b8f5f29c08699b36b85c7 100644 (file)
--- a/ipv6.h
+++ b/ipv6.h
@@ -62,6 +62,7 @@ struct rt6 {
 TAILQ_HEAD(rt6head, rt6);
 
 int ipv6_init(void);
+ssize_t ipv6_printaddr(char *, ssize_t, const uint8_t *, const char *);
 struct in6_addr *ipv6_linklocal(const char *);
 int ipv6_makeaddr(struct in6_addr *, const char *, const struct in6_addr *, int);
 int ipv6_makeprefix(struct in6_addr *, const struct in6_addr *, int);
index ff76432eaeaa84fea9344480571466b3847f1c7a..fc2c3a4c80ceaf728bb1d48736e704f54104d652 100644 (file)
--- a/ipv6rs.c
+++ b/ipv6rs.c
@@ -651,28 +651,25 @@ ipv6rs_handledata(_unused void *arg)
                            nd_opt_rdnss_lifetime);
                        op += sizeof(rdnss->nd_opt_rdnss_lifetime);
                        l = 0;
-                       for (n = ndo->nd_opt_len - 1; n > 1; n -= 2) {
-                               memcpy(&addr.s6_addr, op, sizeof(addr.s6_addr));
-                               cbp = inet_ntop(AF_INET6, &addr,
-                                   ntopbuf, INET6_ADDRSTRLEN);
-                               if (cbp == NULL) {
-                                       syslog(LOG_ERR,
-                                           "%s: invalid RDNSS address",
-                                           ifp->name);
-                               } else {
-                                       if (opt) {
-                                               l = strlen(opt);
-                                               opt = xrealloc(opt,
-                                                       l + strlen(cbp) + 2);
-                                               opt[l] = ' ';
-                                               strcpy(opt + l + 1, cbp);
-                                       } else
-                                               opt = xstrdup(cbp);
-                                       if (lifetime > 0)
-                                               has_dns = 1;
-                               }
-                               op += sizeof(addr.s6_addr);
+                       for (n = ndo->nd_opt_len - 1; n > 1; n -= 2,
+                           op += sizeof(addr.s6_addr))
+                       {
+                               l += ipv6_printaddr(NULL, 0, op, ifp->name) + 1;
+                       }
+                       op = (uint8_t *)ndo;
+                       op += offsetof(struct nd_opt_rdnss,
+                           nd_opt_rdnss_lifetime);
+                       op += sizeof(rdnss->nd_opt_rdnss_lifetime);
+                       tmp = opt = malloc(l);
+                       for (n = ndo->nd_opt_len - 1; n > 1; n -= 2,
+                           op += sizeof(addr.s6_addr))
+                       {
+                               tmp += ipv6_printaddr(tmp, l, op, ifp->name);
+                               *tmp++ = ' ';
+                               if (lifetime > 0)
+                                       has_dns = 1;
                        }
+                       (*--tmp) = '\0';
                        break;
                        
                case ND_OPT_DNSSL: