!ipv6rs_addrexists(ap))
{
syslog(LOG_INFO, "%s: deleting address %s",
- ifp->name, ap->saddr);
- if (del_address6(ifp, ap) == -1 &&
+ ap->iface->name, ap->saddr);
+ if (del_address6(ap) == -1 &&
errno != EADDRNOTAVAIL)
syslog(LOG_ERR, "del_address6 %m");
}
p += sizeof(u32);
memcpy(&u32, p, sizeof(u32));
a->prefix_vltime = ntohl(u32);
- if (a->prefix_pltime < state->lowpl)
+ if (a->prefix_pltime && a->prefix_pltime < state->lowpl)
state->lowpl = a->prefix_pltime;
- if (a->prefix_vltime > state->expire)
+ if (a->prefix_vltime && a->prefix_vltime > state->expire)
state->expire = a->prefix_vltime;
ia = inet_ntop(AF_INET6, &a->addr.s6_addr,
iabuf, sizeof(iabuf));
memcpy(&u32, p, sizeof(u32));
p += sizeof(u32);
a->prefix_vltime = ntohl(u32);
- if (a->prefix_pltime < state->lowpl)
+ if (a->prefix_pltime && a->prefix_pltime < state->lowpl)
state->lowpl = a->prefix_pltime;
- if (a->prefix_vltime > state->expire)
+ if (a->prefix_vltime && a->prefix_vltime > state->expire)
state->expire = a->prefix_vltime;
memcpy(&u8, p, sizeof(u8));
p += sizeof(u8);
TAILQ_FOREACH(ap, &state->addrs, next) {
if (IN6_ARE_ADDR_EQUAL(&ap->addr, &a->addr)) {
TAILQ_REMOVE(&state->addrs, ap, next);
+ /* Keep our flags */
+ a->flags |= ap->flags;
free(ap);
- break;
}
}
#ifdef INET6
int
-if_address6(const struct interface *ifp, const struct ipv6_addr *a, int action)
+if_address6(const struct ipv6_addr *a, int action)
{
int s, r;
struct in6_aliasreq ifa;
if (s == -1)
return -1;
memset(&ifa, 0, sizeof(ifa));
- strlcpy(ifa.ifra_name, ifp->name, sizeof(ifa.ifra_name));
+ strlcpy(ifa.ifra_name, a->iface->name, sizeof(ifa.ifra_name));
/*
* We should not set IN6_IFF_TENTATIVE as the kernel should be
* able to work out if it's a new address or not.
#ifdef INET6
int
-if_address6(const struct interface *ifp, const struct ipv6_addr *ap, int action)
+if_address6(const struct ipv6_addr *ap, int action)
{
struct nlma *nlm;
struct ifa_cacheinfo cinfo;
nlm->hdr.nlmsg_type = RTM_NEWADDR;
} else
nlm->hdr.nlmsg_type = RTM_DELADDR;
- nlm->ifa.ifa_index = ifp->index;
+ nlm->ifa.ifa_index = ap->iface->index;
nlm->ifa.ifa_family = AF_INET6;
nlm->ifa.ifa_prefixlen = ap->prefix_len;
/* This creates the aliased interface */
syslog(ap->flags & IPV6_AF_NEW ? LOG_INFO : LOG_DEBUG,
"%s: adding address %s", ap->iface->name, ap->saddr);
- if (add_address6(ap->iface, ap) == -1) {
+ if (add_address6(ap) == -1) {
syslog(LOG_ERR, "add_address6 %m");
return -1;
}
return 0;
}
-ssize_t
-ipv6_addaddrs(struct ipv6_addrhead *addrs)
-{
- struct ipv6_addr *ap;
- ssize_t i;
-
- i = 0;
- TAILQ_FOREACH(ap, addrs, next) {
- if (ap->prefix_vltime == 0 ||
- IN6_IS_ADDR_UNSPECIFIED(&ap->addr) ||
- ap->flags & IPV6_AF_DELEGATED)
- continue;
- if (ipv6_addaddr(ap) == 0)
- i++;
- }
-
- return i;
-}
-
static struct ipv6_state *
ipv6_getstate(struct interface *ifp)
{
ifname, cmd, buf, flags);
#endif
- /* Safety - ignore tentative announcements */
+ /* Safety, remove tentative addresses */
if (cmd == RTM_NEWADDR) {
- if (flags & (IN6_IFF_TENTATIVE | IN6_IFF_DUPLICATED))
+ if (flags & IN6_IFF_TENTATIVE)
cmd = RTM_DELADDR;
#ifdef IN6_IFF_DETACHED
if (flags & IN6_IFF_DETACHED)
return;
}
- if (IN6_IS_ADDR_LINKLOCAL(addr)) {
- state = ipv6_getstate(ifp);
- if (state == NULL)
- return;
- TAILQ_FOREACH(ap, &state->ll_addrs, next) {
- if (IN6_ARE_ADDR_EQUAL(&ap->addr, addr))
- break;
+ if (!IN6_IS_ADDR_LINKLOCAL(addr)) {
+ ipv6rs_handleifa(cmd, ifname, addr, flags);
+ dhcp6_handleifa(cmd, ifname, addr, flags);
+ return;
+ }
+
+ state = ipv6_getstate(ifp);
+ if (state == NULL)
+ return;
+
+ /* We don't care about duplicated LL addresses, so remove them */
+ if (flags & IN6_IFF_DUPLICATED)
+ cmd = RTM_DELADDR;
+
+ TAILQ_FOREACH(ap, &state->ll_addrs, next) {
+ if (IN6_ARE_ADDR_EQUAL(&ap->addr, addr))
+ break;
+ }
+
+ switch (cmd) {
+ case RTM_DELADDR:
+ if (ap) {
+ TAILQ_REMOVE(&state->ll_addrs, ap, next);
+ free(ap);
}
- switch (cmd) {
- case RTM_DELADDR:
- if (ap) {
- TAILQ_REMOVE(&state->ll_addrs, ap, next);
- free(ap);
- }
- return;
- case RTM_NEWADDR:
- if (ap == NULL) {
- ap = calloc(1, sizeof(*ap));
- memcpy(ap->addr.s6_addr, addr->s6_addr,
- sizeof(ap->addr.s6_addr));
- TAILQ_INSERT_TAIL(&state->ll_addrs,
- ap, next);
-
- /* Now run any callbacks.
- * Typically IPv6RS or DHCPv6 */
- while ((cb = TAILQ_FIRST(&state->ll_callbacks)))
- {
- TAILQ_REMOVE(&state->ll_callbacks,
- cb, next);
- cb->callback(cb->arg);
- free(cb);
- }
+ break;
+ case RTM_NEWADDR:
+ if (ap == NULL) {
+ ap = calloc(1, sizeof(*ap));
+ memcpy(ap->addr.s6_addr, addr->s6_addr,
+ sizeof(ap->addr.s6_addr));
+ TAILQ_INSERT_TAIL(&state->ll_addrs,
+ ap, next);
+
+ /* Now run any callbacks.
+ * Typically IPv6RS or DHCPv6 */
+ while ((cb = TAILQ_FIRST(&state->ll_callbacks)))
+ {
+ TAILQ_REMOVE(&state->ll_callbacks,
+ cb, next);
+ cb->callback(cb->arg);
+ free(cb);
}
- return;
- default:
- return;
}
+ break;
}
-
- ipv6rs_handleifa(cmd, ifname, addr, flags);
- dhcp6_handleifa(cmd, ifname, addr, flags);
}
const struct ll_addr *
found++;
if (flags & IN6_IFF_DUPLICATED)
ap->flags |= IPV6_AF_DUPLICATED;
+ else
+ ap->flags &= ~IPV6_AF_DUPLICATED;
if (ap->dadcallback)
ap->dadcallback(ap);
/* We need to set this here in-case the
int ipv6_userprefix( const struct in6_addr *, short prefix_len,
uint64_t user_number, struct in6_addr *result, short result_len);
int ipv6_addaddr(struct ipv6_addr *);
-ssize_t ipv6_addaddrs(struct ipv6_addrhead *);
void ipv6_handleifa(int, struct if_head *,
const char *, const struct in6_addr *, int);
int ipv6_handleifa_addrs(int, struct ipv6_addrhead *,
ssize_t
ipv6ns_probeaddrs(struct ipv6_addrhead *addrs)
{
- struct ipv6_addr *ap;
+ struct ipv6_addr *ap, *apn;
ssize_t i;
i = 0;
- TAILQ_FOREACH(ap, addrs, next) {
- if (ap->prefix_vltime == 0 ||
- IN6_IS_ADDR_UNSPECIFIED(&ap->addr) ||
- ap->flags & IPV6_AF_DELEGATED)
- continue;
- ipv6ns_probeaddr(ap);
- if (ap->flags & IPV6_AF_NEW)
- i++;
+ TAILQ_FOREACH_SAFE(ap, addrs, next, apn) {
+ if (ap->prefix_vltime == 0) {
+ TAILQ_REMOVE(addrs, ap, next);
+ if (ap->flags & IPV6_AF_ADDED)
+ syslog(LOG_INFO, "%s: deleting address %s",
+ ap->iface->name, ap->saddr);
+ if (del_address6(ap) == -1 &&
+ errno != EADDRNOTAVAIL)
+ syslog(LOG_ERR, "del_address6 %m");
+ if (ap->dadcallback)
+ eloop_q_timeout_delete(0, NULL,
+ ap->dadcallback);
+ free(ap);
+ } else if (!IN6_IS_ADDR_UNSPECIFIED(&ap->addr) &&
+ !(ap->flags & IPV6_AF_DELEGATED))
+ {
+ ipv6ns_probeaddr(ap);
+ if (ap->flags & IPV6_AF_NEW)
+ i++;
+ }
}
return i;
{
syslog(LOG_INFO, "%s: deleting address %s",
rap->iface->name, ap->saddr);
- if (del_address6(rap->iface, ap) == -1 &&
+ if (del_address6(ap) == -1 &&
errno != EADDRNOTAVAIL)
syslog(LOG_ERR, "del_address6 %m");
}
}
ap->dadcallback = ipv6rs_dadcallback;
TAILQ_INSERT_TAIL(&rap->addrs, ap, next);
- } else if (ap->prefix_vltime !=
- ntohl(pi->nd_opt_pi_valid_time) ||
- ap->prefix_pltime !=
- ntohl(pi->nd_opt_pi_preferred_time) ||
- ap->flags & IPV6_AF_DUPLICATED)
- {
- ap->flags |= IPV6_AF_NEW;
}
if (pi->nd_opt_pi_flags_reserved &
ND_OPT_PI_FLAG_ONLINK)
ap->prefix_pltime =
ntohl(pi->nd_opt_pi_preferred_time);
ap->nsprobes = 0;
- ap->flags &= ~IPV6_AF_DUPLICATED;
if (opt) {
l = strlen(opt);
tmp = realloc(opt,
int if_conf(struct interface *);
int if_init(struct interface *);
-int if_address6(const struct interface *, const struct ipv6_addr *, int);
-#define add_address6(ifp, a) if_address6(ifp, a, 1)
-#define del_address6(ifp, a) if_address6(ifp, a, -1)
+int if_address6(const struct ipv6_addr *, int);
+#define add_address6(a) if_address6(a, 1)
+#define del_address6(a) if_address6(a, -1)
int in6_addr_flags(const char *, const struct in6_addr *);
int if_route6(const struct rt6 *rt, int);