creating ipv6_addr structures.
size_t i;
struct if_ia *ia;
struct ipv6_addr *a;
- char iabuf[INET6_ADDRSTRLEN];
- const char *iap;
state = D6_STATE(ifp);
/* Add any requested prefixes / addresses */
if (!((ia->ia_type == D6_OPTION_IA_PD && ia->prefix_len) ||
!IN6_IS_ADDR_UNSPECIFIED(&ia->addr)))
continue;
- a = calloc(1, sizeof(*a));
- if (a == NULL) {
- logerr(__func__);
- return;
- }
- a->flags = IPV6_AF_REQUEST;
- a->iface = ifp;
- a->dadcallback = dhcp6_dadcallback;
- memcpy(&a->iaid, &ia->iaid, sizeof(a->iaid));
- a->ia_type = ia->ia_type;
- //a->prefix_pltime = 0;
- //a->prefix_vltime = 0;
-
- if (ia->ia_type == D6_OPTION_IA_PD) {
- memcpy(&a->prefix, &ia->addr, sizeof(a->addr));
- a->prefix_len = ia->prefix_len;
- iap = inet_ntop(AF_INET6, &a->prefix,
- iabuf, sizeof(iabuf));
- } else {
- memcpy(&a->addr, &ia->addr, sizeof(a->addr));
+ a = ipv6_newaddr(ifp, &ia->addr,
/*
* RFC 5942 Section 5
* We cannot assume any prefix length, nor tie the
* before the address.
* As such we just give it a 128 prefix.
*/
- a->prefix_len = 128;
- ipv6_makeprefix(&a->prefix, &a->addr, a->prefix_len);
- iap = inet_ntop(AF_INET6, &a->addr,
- iabuf, sizeof(iabuf));
- }
- snprintf(a->saddr, sizeof(a->saddr),
- "%s/%d", iap, a->prefix_len);
+ ia->ia_type == D6_OPTION_IA_PD ? ia->prefix_len : 128,
+ IPV6_AF_REQUEST);
+ if (a == NULL)
+ continue;
+ a->dadcallback = dhcp6_dadcallback;
+ memcpy(&a->iaid, &ia->iaid, sizeof(a->iaid));
+ a->ia_type = ia->ia_type;
TAILQ_INSERT_TAIL(&state->addrs, a, next);
}
}
uint8_t *o, *nd;
uint16_t ol;
struct ipv6_addr *a;
- char iabuf[INET6_ADDRSTRLEN];
- const char *ias;
int i;
struct dhcp6_ia_addr ia;
break;
}
if (a == NULL) {
- a = calloc(1, sizeof(*a));
- if (a == NULL) {
- logerr(__func__);
- break;
- }
- a->iface = ifp;
- a->flags = IPV6_AF_NEW | IPV6_AF_ONLINK;
- a->dadcallback = dhcp6_dadcallback;
- a->ia_type = ot;
- memcpy(a->iaid, iaid, sizeof(a->iaid));
- a->addr = ia.addr;
- a->created = *acquired;
-
/*
* RFC 5942 Section 5
* We cannot assume any prefix length, nor tie the
* before the address.
* As such we just give it a 128 prefix.
*/
- a->prefix_len = 128;
- ipv6_makeprefix(&a->prefix, &a->addr, a->prefix_len);
- ias = inet_ntop(AF_INET6, &a->addr,
- iabuf, sizeof(iabuf));
- snprintf(a->saddr, sizeof(a->saddr),
- "%s/%d", ias, a->prefix_len);
+ a = ipv6_newaddr(ifp, &ia.addr, 128, IPV6_AF_ONLINK);
+ a->dadcallback = dhcp6_dadcallback;
+ a->ia_type = ot;
+ memcpy(a->iaid, iaid, sizeof(a->iaid));
+ a->created = *acquired;
TAILQ_INSERT_TAIL(&state->addrs, a, next);
} else {
struct dhcp6_state *state;
uint8_t *o, *nd;
struct ipv6_addr *a;
- char iabuf[INET6_ADDRSTRLEN];
- const char *ia;
int i;
uint8_t nb, *pw;
uint16_t ol;
}
if (a == NULL) {
- a = calloc(1, sizeof(*a));
- if (a == NULL) {
- logerr(__func__);
+ a = ipv6_newaddr(ifp, &pdp_prefix, pdp.prefix_len,
+ IPV6_AF_DELEGATEDPFX);
+ if (a == NULL)
break;
- }
- a->iface = ifp;
- a->flags = IPV6_AF_NEW | IPV6_AF_DELEGATEDPFX;
a->created = *acquired;
a->dadcallback = dhcp6_dadcallback;
a->ia_type = D6_OPTION_IA_PD;
memcpy(a->iaid, iaid, sizeof(a->iaid));
- /* pdp.prefix is not aligned so use copy. */
- a->prefix = pdp_prefix;
- a->prefix_len = pdp.prefix_len;
- ia = inet_ntop(AF_INET6, &a->prefix,
- iabuf, sizeof(iabuf));
- snprintf(a->saddr, sizeof(a->saddr),
- "%s/%d", ia, a->prefix_len);
TAILQ_INIT(&a->pd_pfxs);
TAILQ_INSERT_TAIL(&state->addrs, a, next);
} else {
struct dhcp6_state *state;
struct in6_addr addr, daddr;
struct ipv6_addr *ia;
- char sabuf[INET6_ADDRSTRLEN];
- const char *sa;
int pfxlen, dadcounter;
uint64_t vl;
break;
}
if (ia == NULL) {
- ia = calloc(1, sizeof(*ia));
- if (ia == NULL) {
- logerr(__func__);
+ ia = ipv6_newaddr(ifp, &daddr, (uint8_t)pfxlen, IPV6_AF_ONLINK);
+ if (ia == NULL)
return NULL;
- }
- ia->iface = ifp;
- ia->flags = IPV6_AF_NEW | IPV6_AF_ONLINK;
ia->dadcallback = dhcp6_dadcallback;
memcpy(&ia->iaid, &prefix->iaid, sizeof(ia->iaid));
ia->created = prefix->acquired;
- ia->addr = daddr;
TAILQ_INSERT_TAIL(&state->addrs, ia, next);
TAILQ_INSERT_TAIL(&prefix->pd_pfxs, ia, pd_next);
ia->prefix_pltime = prefix->prefix_pltime;
ia->prefix_vltime = prefix->prefix_vltime;
- sa = inet_ntop(AF_INET6, &ia->addr, sabuf, sizeof(sabuf));
- snprintf(ia->saddr, sizeof(ia->saddr), "%s/%d", sa, ia->prefix_len);
-
/* If the prefix length hasn't changed,
* don't install a reject route. */
if (prefix->prefix_len == pfxlen)
return 0;
}
-int
+static int
ipv6_makeprefix(struct in6_addr *prefix, const struct in6_addr *addr, int len)
{
int bytes, bits;
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 };
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
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);
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);
}
}
- 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 */
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;
}
char saddr[INET6_ADDRSTRLEN];
uint8_t iaid[4];
uint16_t ia_type;
+ int fd;
#ifndef SMALL
struct ipv6_addr *delegating_prefix;
#define IPV6_AF_REQUEST 0x0400
#define IPV6_AF_STATIC 0x0800
#define IPV6_AF_DELEGATEDLOG 0x1000
+#define IPV6_AF_RAPFX 0x2000
#ifdef IPV6_MANAGETEMPADDR
-#define IPV6_AF_TEMPORARY 0X2000
+#define IPV6_AF_TEMPORARY 0X4000
#endif
struct ll_callback {
const struct interface *ifp, int *dad_counter);
int ipv6_makeaddr(struct in6_addr *, struct interface *,
const struct in6_addr *, int);
-int ipv6_makeprefix(struct in6_addr *, const struct in6_addr *, int);
int ipv6_mask(struct in6_addr *, int);
uint8_t ipv6_prefixlen(const struct in6_addr *);
int ipv6_userprefix( const struct in6_addr *, short prefix_len,
const struct in6_addr *);
#define ipv6_linklocal(ifp) ipv6_iffindaddr((ifp), NULL, IN6_IFF_NOTUSEABLE)
int ipv6_addlinklocalcallback(struct interface *, void (*)(void *), void *);
+struct ipv6_addr *ipv6_newaddr(struct interface *, struct in6_addr *, uint8_t,
+ short);
void ipv6_freeaddr(struct ipv6_addr *);
void ipv6_freedrop(struct interface *, int);
#define ipv6_free(ifp) ipv6_freedrop((ifp), 0)
struct nd_opt_mtu mtu;
struct nd_opt_rdnss rdnss;
uint8_t *p;
- char buf[INET6_ADDRSTRLEN];
- const char *cbp;
struct ra *rap;
struct in6_addr pi_prefix;
struct ipv6_addr *ap;
IN6_ARE_ADDR_EQUAL(&ap->prefix, &pi_prefix))
break;
if (ap == NULL) {
+ short flags;
+
if (!(pi.nd_opt_pi_flags_reserved &
ND_OPT_PI_FLAG_AUTO) &&
!(pi.nd_opt_pi_flags_reserved &
ND_OPT_PI_FLAG_ONLINK))
continue;
- ap = calloc(1, sizeof(*ap));
- if (ap == NULL) {
- logerr(__func__);
- break;
- }
- ap->iface = rap->iface;
- ap->flags = IPV6_AF_NEW;
- ap->prefix_len = pi.nd_opt_pi_prefix_len;
- ap->prefix = pi_prefix;
+
+ flags = IPV6_AF_RAPFX;
if (pi.nd_opt_pi_flags_reserved &
ND_OPT_PI_FLAG_AUTO &&
- ap->iface->options->options &
+ rap->iface->options->options &
DHCPCD_IPV6RA_AUTOCONF)
- {
- ap->flags |= IPV6_AF_AUTOCONF;
- ap->dadcounter =
- ipv6_makeaddr(&ap->addr, ifp,
- &ap->prefix,
- pi.nd_opt_pi_prefix_len);
- if (ap->dadcounter == -1) {
- free(ap);
- break;
- }
- cbp = inet_ntop(AF_INET6,
- &ap->addr,
- buf, sizeof(buf));
- if (cbp)
- snprintf(ap->saddr,
- sizeof(ap->saddr),
- "%s/%d",
- cbp, ap->prefix_len);
- else
- ap->saddr[0] = '\0';
- } else {
- memset(&ap->addr, 0, sizeof(ap->addr));
- ap->saddr[0] = '\0';
- }
+ flags |= IPV6_AF_AUTOCONF;
+
+ ap = ipv6_newaddr(rap->iface,
+ &pi_prefix, pi.nd_opt_pi_prefix_len, flags);
+ if (ap == NULL)
+ break;
+ ap->prefix = pi_prefix;
ap->dadcallback = ipv6nd_dadcallback;
ap->created = ap->acquired = rap->acquired;
TAILQ_INSERT_TAIL(&rap->addrs, ap, next);