]> 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:17:33 +0000 (20:17 +0000)
committerRoy Marples <roy@marples.name>
Sat, 24 Nov 2012 20:17:33 +0000 (20:17 +0000)
ipv6.c
ipv6.h
ipv6rs.c

diff --git a/ipv6.c b/ipv6.c
index 125b3872291bf9551b6df39d87bb451799661edb..793cf6b84712ac6e57a70a19ed8fcf7bb2e9e4d3 100644 (file)
--- a/ipv6.c
+++ b/ipv6.c
@@ -79,6 +79,38 @@ ipv6_open(void)
        return socket_afnet6;
 }
 
+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 8f6ef27f8da6584d933e0bd1412132c17221f363..ef3b2352c3c48663e5600bad5be9fe570f30e9fc 100644 (file)
--- a/ipv6.h
+++ b/ipv6.h
@@ -65,6 +65,7 @@ TAILQ_HEAD(rt6head, rt6);
 extern int socket_afnet6;
 
 int ipv6_open(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_mask(struct in6_addr *, int);
index 4a0af3750a6d2f3fd143bdba13ead104e870d03d..0ca5b179f423a5d44d04b44cf0657406d25eea9d 100644 (file)
--- a/ipv6rs.c
+++ b/ipv6rs.c
@@ -629,28 +629,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: