summaryrefslogtreecommitdiffstats
path: root/src/ipv6.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2017-06-13 20:47:49 +0100
committerRoy Marples <roy@marples.name>2017-06-13 20:47:49 +0100
commit6b068a4357a1f6644b4748cdf72edd280f73f135 (patch)
treeb6a9055cd59f6a9afacccfa26af7f72a1d90eec2 /src/ipv6.c
parentb059aeb66e9105af734d2c6bfc3ce85872aee446 (diff)
downloaddhcpcd-6b068a4357a1f6644b4748cdf72edd280f73f135.tar.xz
Make ipv6_newaddr() more flexable so it's the sole source of
creating ipv6_addr structures.
Diffstat (limited to 'src/ipv6.c')
-rw-r--r--src/ipv6.c99
1 files changed, 54 insertions, 45 deletions
diff --git a/src/ipv6.c b/src/ipv6.c
index bd385694..b37610ae 100644
--- a/src/ipv6.c
+++ b/src/ipv6.c
@@ -379,7 +379,7 @@ ipv6_makeaddr(struct in6_addr *addr, struct interface *ifp,
return 0;
}
-int
+static int
ipv6_makeprefix(struct in6_addr *prefix, const struct in6_addr *addr, int len)
{
int bytes, bits;
@@ -1286,21 +1286,18 @@ ipv6_addlinklocalcallback(struct interface *ifp,
static struct ipv6_addr *
ipv6_newlinklocal(struct interface *ifp)
{
- struct ipv6_addr *ap;
+ struct ipv6_addr *ia;
+ struct in6_addr in6;
- ap = calloc(1, sizeof(*ap));
- if (ap != NULL) {
- ap->iface = ifp;
- ap->prefix.s6_addr32[0] = htonl(0xfe800000);
- ap->prefix.s6_addr32[1] = 0;
- ap->prefix_len = 64;
- ap->dadcounter = 0;
- ap->prefix_pltime = ND6_INFINITE_LIFETIME;
- ap->prefix_vltime = ND6_INFINITE_LIFETIME;
- ap->flags = IPV6_AF_NEW;
- ap->addr_flags = IN6_IFF_TENTATIVE;
- }
- return ap;
+ in6.s6_addr32[0] = htonl(0xfe800000);
+ in6.s6_addr32[1] = 0;
+ ia = ipv6_newaddr(ifp, &in6, 64, 0);
+ if (ia != NULL) {
+ ia->prefix_pltime = ND6_INFINITE_LIFETIME;
+ ia->prefix_vltime = ND6_INFINITE_LIFETIME;
+ ia->addr_flags = IN6_IFF_TENTATIVE;
+ }
+ return ia;
}
static const uint8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
@@ -1445,31 +1442,56 @@ ipv6_tryaddlinklocal(struct interface *ifp)
return ipv6_addlinklocal(ifp);
}
-static struct ipv6_addr *
-ipv6_newaddr(struct interface *ifp, struct in6_addr *addr, uint8_t prefix_len)
+struct ipv6_addr *
+ipv6_newaddr(struct interface *ifp, struct in6_addr *addr, uint8_t prefix_len,
+ short flags)
{
struct ipv6_addr *ia;
char buf[INET6_ADDRSTRLEN];
const char *cbp;
- if ((ia = calloc(1, sizeof(*ia))) == NULL)
- return NULL;
+ ia = calloc(1, sizeof(*ia));
+ if (ia == NULL)
+ goto err;
+
ia->iface = ifp;
- ia->flags = IPV6_AF_NEW;
+ ia->flags = IPV6_AF_NEW | flags;
ia->addr_flags = IN6_IFF_TENTATIVE;
- ia->addr = *addr;
ia->prefix_len = prefix_len;
- if (ipv6_makeprefix(&ia->prefix, &ia->addr, ia->prefix_len) == -1) {
- free(ia);
- return NULL;
+
+ if (ia->flags & IPV6_AF_AUTOCONF) {
+ ia->prefix = *addr;
+ ia->dadcounter = ipv6_makeaddr(&ia->addr, ifp,
+ &ia->prefix,
+ ia->prefix_len);
+ if (ia->dadcounter == -1)
+ goto err;
+ } else if (ia->flags & IPV6_AF_RAPFX) {
+ ia->prefix = *addr;
+ return ia;
+ } else if (ia->flags & IPV6_AF_REQUEST && prefix_len != 128) {
+ ia->prefix = *addr;
+ cbp = inet_ntop(AF_INET6, &ia->prefix, buf, sizeof(buf));
+ goto paddr;
+ } else {
+ ia->addr = *addr;
+ if (ipv6_makeprefix(&ia->prefix,
+ &ia->addr, ia->prefix_len) == -1)
+ goto err;
}
+
cbp = inet_ntop(AF_INET6, &ia->addr, buf, sizeof(buf));
- if (cbp)
- snprintf(ia->saddr, sizeof(ia->saddr), "%s/%d",
- cbp, ia->prefix_len);
- else
- ia->saddr[0] = '\0';
+paddr:
+ if (cbp == NULL)
+ goto err;
+ snprintf(ia->saddr, sizeof(ia->saddr), "%s/%d", cbp, ia->prefix_len);
+
return ia;
+
+err:
+ logerr(__func__);
+ free(ia);
+ return NULL;
}
static void
@@ -1569,7 +1591,7 @@ ipv6_startstatic(struct interface *ifp)
struct ipv6_state *state;
ia = ipv6_newaddr(ifp, &ifp->options->req_addr6,
- ifp->options->req_prefix_len);
+ ifp->options->req_prefix_len, 0);
if (ia == NULL)
return -1;
state = IPV6_STATE(ifp);
@@ -1865,8 +1887,6 @@ ipv6_createtempaddr(struct ipv6_addr *ia0, const struct timespec *now)
const struct ipv6_addr *ap;
struct ipv6_addr *ia;
uint32_t i, trylimit;
- char buf[INET6_ADDRSTRLEN];
- const char *cbp;
trylimit = TEMP_IDGEN_RETRIES;
state = IPV6_STATE(ia0->iface);
@@ -1913,17 +1933,11 @@ again:
}
}
- if ((ia = calloc(1, sizeof(*ia))) == NULL)
- return NULL;
-
- ia->iface = ia0->iface;
- ia->addr = addr;
+ ia = ipv6_newaddr(ia0->iface, &addr, ia0->prefix_len,
+ IPV6_AF_AUTOCONF | IPV6_AF_TEMPORARY);
/* Must be made tentative, for our DaD to work */
ia->addr_flags = IN6_IFF_TENTATIVE;
ia->dadcallback = ipv6_tempdadcallback;
- ia->flags = IPV6_AF_NEW | IPV6_AF_AUTOCONF | IPV6_AF_TEMPORARY;
- ia->prefix = ia0->prefix;
- ia->prefix_len = ia0->prefix_len;
ia->created = ia->acquired = now ? *now : ia0->acquired;
/* Ensure desync is still valid */
@@ -1943,11 +1957,6 @@ again:
return NULL;
}
- cbp = inet_ntop(AF_INET6, &ia->addr, buf, sizeof(buf));
- if (cbp)
- snprintf(ia->saddr, sizeof(ia->saddr), "%s/%d",
- cbp, ia->prefix_len); else ia->saddr[0] = '\0';
-
TAILQ_INSERT_TAIL(&state->addrs, ia, next);
return ia;
}