From: Roy Marples Date: Sat, 24 Nov 2012 20:11:49 +0000 (+0000) Subject: Set %interface for exported IPv6 link local addresses. X-Git-Tag: v5.99.3~7 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c2e168a8c1e01d763c1cc6555b7fd276b6210297;p=thirdparty%2Fdhcpcd.git Set %interface for exported IPv6 link local addresses. --- diff --git a/configure.c b/configure.c index 334e375c..7d8475d2 100644 --- a/configure.c +++ b/configure.c @@ -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 67387522..3a157350 100644 --- 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 e6190c89..64a5ff82 100644 --- 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 12d0312c..9026d3e8 100644 --- 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 7a4a166d..198cb2d0 100644 --- 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 55be2168..92a91353 100644 --- 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); diff --git a/ipv6rs.c b/ipv6rs.c index ff76432e..fc2c3a4c 100644 --- 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: