From: Roy Marples Date: Sat, 24 Nov 2012 20:17:33 +0000 (+0000) Subject: Set %interface for exported IPv6 link local addresses. X-Git-Tag: v5.6.4~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=586e542cb3231d44d2924fd8de695d82c3236b62;p=thirdparty%2Fdhcpcd.git Set %interface for exported IPv6 link local addresses. --- diff --git a/ipv6.c b/ipv6.c index 125b3872..793cf6b8 100644 --- 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 8f6ef27f..ef3b2352 100644 --- 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); diff --git a/ipv6rs.c b/ipv6rs.c index 4a0af375..0ca5b179 100644 --- 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: