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)
{
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);
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: