While here, drop the flags argument from the ifa routines.
Instead, grab it in the main ifa handler - it was only for IPv6 addresses
in Linux anyway.
}
void
-dhcp6_handleifa(struct dhcpcd_ctx *ctx, int cmd, const char *ifname,
- const struct in6_addr *addr, int flags)
+dhcp6_handleifa(int cmd, struct ipv6_addr *ia)
{
- struct interface *ifp;
struct dhcp6_state *state;
- if (ctx->ifaces == NULL)
- return;
-
- TAILQ_FOREACH(ifp, ctx->ifaces, next) {
- state = D6_STATE(ifp);
- if (state == NULL || strcmp(ifp->name, ifname))
- continue;
- ipv6_handleifa_addrs(cmd, &state->addrs, addr, flags);
- }
-
+ if ((state = D6_STATE(ia->iface)) != NULL)
+ ipv6_handleifa_addrs(cmd, &state->addrs, ia);
}
ssize_t
ssize_t dhcp6_env(char **, const char *, const struct interface *,
const struct dhcp6_message *, size_t);
void dhcp6_free(struct interface *);
-void dhcp6_handleifa(struct dhcpcd_ctx *, int, const char *,
- const struct in6_addr *addr, int);
+void dhcp6_handleifa(int, struct ipv6_addr *);
int dhcp6_dadcompleted(const struct interface *);
void dhcp6_drop(struct interface *, const char *);
void dhcp6_dropnondelegates(struct interface *ifp);
}
int
-if_addrflags(const struct in_addr *addr, const struct interface *ifp)
+if_addrflags(const struct ipv4_addr *ia)
{
#ifdef SIOCGIFAFLAG_IN
struct ifreq ifr;
struct sockaddr_in *sin;
memset(&ifr, 0, sizeof(ifr));
- strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
+ strlcpy(ifr.ifr_name, ia->iface->name, sizeof(ifr.ifr_name));
sin = (void *)&ifr.ifr_addr;
sin->sin_family = AF_INET;
- sin->sin_addr = *addr;
+ sin->sin_addr = ia->addr;
if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFAFLAG_IN, &ifr) == -1)
return -1;
return ifr.ifr_addrflags;
}
int
-if_addrflags6(const struct in6_addr *addr, const struct interface *ifp)
+if_addrflags6(const struct ipv6_addr *ia)
{
int flags;
struct in6_ifreq ifr6;
struct priv *priv;
memset(&ifr6, 0, sizeof(ifr6));
- strlcpy(ifr6.ifr_name, ifp->name, sizeof(ifr6.ifr_name));
+ strlcpy(ifr6.ifr_name, ia->iface->name, sizeof(ifr6.ifr_name));
ifr6.ifr_addr.sin6_family = AF_INET6;
- ifr6.ifr_addr.sin6_addr = *addr;
+ ifr6.ifr_addr.sin6_addr = ia->addr;
ifa_scope(&ifr6.ifr_addr, ifp->index);
priv = (struct priv *)ifp->ctx->priv;
if (ioctl(priv->pf_inet6_fd, SIOCGIFAFLAG_IN6, &ifr6) != -1)
{
const struct sockaddr_in *sin;
struct in_addr addr, mask, bcast;
- int flags;
sin = (const void *)rti_info[RTAX_IFA];
addr.s_addr = sin != NULL && sin->sin_family == AF_INET ?
sin = (const void *)rti_info[RTAX_BRD];
bcast.s_addr = sin != NULL && sin->sin_family == AF_INET ?
sin->sin_addr.s_addr : INADDR_ANY;
- if (ifam->ifam_type == RTM_NEWADDR) {
- if ((flags = if_addrflags(&addr, ifp)) == -1)
- break;
- } else
- flags = 0;
ipv4_handleifa(ctx, ifam->ifam_type, NULL, ifp->name,
- &addr, &mask, &bcast, flags);
+ &addr, &mask, &bcast);
break;
}
#endif
{
struct in6_addr addr6, mask6;
const struct sockaddr_in6 *sin6;
- int flags;
sin6 = (const void *)rti_info[RTAX_IFA];
addr6 = sin6->sin6_addr;
sin6 = (const void *)rti_info[RTAX_NETMASK];
mask6 = sin6->sin6_addr;
DESCOPE(&mask6);
- if (ifam->ifam_type == RTM_NEWADDR) {
- if ((flags = if_addrflags6(&addr6, ifp)) == -1)
- break;
- } else
- flags = 0;
ipv6_handleifa(ctx, ifam->ifam_type, NULL,
- ifp->name, &addr6, ipv6_prefixlen(&mask6), flags);
+ ifp->name, &addr6, ipv6_prefixlen(&mask6));
break;
}
#endif
rta = RTA_NEXT(rta, len);
}
ipv4_handleifa(ctx, nlm->nlmsg_type, NULL, ifp->name,
- &addr, &net, &brd, ifa->ifa_flags);
+ &addr, &net, &brd);
break;
#endif
#ifdef INET6
rta = RTA_NEXT(rta, len);
}
ipv6_handleifa(ctx, nlm->nlmsg_type, NULL, ifp->name,
- &addr6, ifa->ifa_prefixlen, ifa->ifa_flags);
+ &addr6, ifa->ifa_prefixlen);
break;
#endif
}
}
int
-if_addrflags(__unused const struct in_addr *addr,
- __unused const struct interface *ifp)
+if_addrflags(__unused const struct ipv4_addr *addr)
{
/* Linux has no support for IPv4 address flags */
}
int
-if_addrflags6(const struct in6_addr *addr, const struct interface *ifp)
+if_addrflags6(const struct ipv6_addr *ia)
{
FILE *fp;
char *p, ifaddress[33], address[33], name[IF_NAMESIZE + 1];
return -1;
p = ifaddress;
- for (i = 0; i < (int)sizeof(addr->s6_addr); i++) {
- p += snprintf(p, 3, "%.2x", addr->s6_addr[i]);
+ for (i = 0; i < (int)sizeof(ia->addr.s6_addr); i++) {
+ p += snprintf(p, 3, "%.2x", ia->addr.s6_addr[i]);
}
*p = '\0';
{
if (strlen(address) != 32) {
fclose(fp);
- errno = ENOTSUP;
+ errno = EINVAL;
return -1;
}
- if (strcmp(name, ifp->name) == 0 &&
+ if (strcmp(name, ia->iface->name) == 0 &&
strcmp(ifaddress, address) == 0)
{
fclose(fp);
#ifdef INET6
struct sockaddr_in6 *sin6, *net6;
#endif
- int ifa_flags;
-
for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == NULL)
brd = (void *)ifa->ifa_dstaddr;
else
brd = (void *)ifa->ifa_broadaddr;
- ifa_flags = if_addrflags(&addr->sin_addr, ifp);
ipv4_handleifa(ctx, RTM_NEWADDR, ifs, ifa->ifa_name,
&addr->sin_addr, &net->sin_addr,
- brd ? &brd->sin_addr : NULL, ifa_flags);
+ brd ? &brd->sin_addr : NULL);
break;
#endif
#ifdef INET6
sin6->sin6_addr.s6_addr[2] =
sin6->sin6_addr.s6_addr[3] = '\0';
#endif
- ifa_flags = if_addrflags6(&sin6->sin6_addr, ifp);
- if (ifa_flags != -1)
- ipv6_handleifa(ctx, RTM_NEWADDR, ifs,
- ifa->ifa_name,
- &sin6->sin6_addr,
- ipv6_prefixlen(&net6->sin6_addr),
- ifa_flags);
+ ipv6_handleifa(ctx, RTM_NEWADDR, ifs,
+ ifa->ifa_name, &sin6->sin6_addr,
+ ipv6_prefixlen(&net6->sin6_addr));
break;
#endif
}
void if_closeraw(struct interface *, int);
int if_address(unsigned char, const struct ipv4_addr *);
-int if_addrflags(const struct in_addr *, const struct interface *);
+int if_addrflags(const struct ipv4_addr *);
int if_route(unsigned char, const struct rt *rt);
int if_initrt(struct dhcpcd_ctx *);
#endif
int if_address6(unsigned char, const struct ipv6_addr *);
-int if_addrflags6(const struct in6_addr *, const struct interface *);
+int if_addrflags6(const struct ipv6_addr *);
int if_getlifetime6(struct ipv6_addr *);
int if_route6(unsigned char, const struct rt6 *rt);
ipv4_handleifa(struct dhcpcd_ctx *ctx,
int cmd, struct if_head *ifs, const char *ifname,
const struct in_addr *addr, const struct in_addr *mask,
- const struct in_addr *brd, int flags)
+ const struct in_addr *brd)
{
struct interface *ifp;
struct ipv4_state *state;
ia->brd = *brd;
else
ia->brd.s_addr = INADDR_ANY;
- ia->addr_flags = flags;
+ ia->addr_flags = if_addrflags(ia);
break;
case RTM_DELADDR:
if (ia == NULL)
struct ipv4_addr *ipv4_findmaskaddr(struct dhcpcd_ctx *,
const struct in_addr *);
void ipv4_handleifa(struct dhcpcd_ctx *, int, struct if_head *, const char *,
- const struct in_addr *, const struct in_addr *, const struct in_addr *,
- int);
+ const struct in_addr *, const struct in_addr *, const struct in_addr *);
void ipv4_freeroutes(struct rt_head *);
ipv6_checkaddrflags(void *arg)
{
struct ipv6_addr *ap;
- int ifa_flags;
ap = arg;
- ifa_flags = if_addrflags6(&ap->addr, ap->iface);
if (ifa_flags == -1)
logger(ap->iface->ctx, LOG_ERR,
"%s: if_addrflags6: %m", ap->iface->name);
else if (!(ifa_flags & IN6_IFF_TENTATIVE)) {
ipv6_handleifa(ap->iface->ctx, RTM_NEWADDR,
ap->iface->ctx->ifaces, ap->iface->name,
- &ap->addr, ap->prefix_len, ifa_flags);
+ &ap->addr, ap->prefix_len);
} else {
struct timespec tv;
void
ipv6_handleifa(struct dhcpcd_ctx *ctx,
int cmd, struct if_head *ifs, const char *ifname,
- const struct in6_addr *addr, uint8_t prefix_len, int flags)
+ const struct in6_addr *addr, uint8_t prefix_len)
{
struct interface *ifp;
struct ipv6_state *state;
- struct ipv6_addr *ap;
+ struct ipv6_addr *ia;
struct ll_callback *cb;
#if 0
dbp = inet_ntop(AF_INET6, &addr->s6_addr,
dbuf, INET6_ADDRSTRLEN);
- logger(ctx, LOG_INFO, "%s: cmd %d addr %s flags %d",
- ifname, cmd, dbp, flags);
+ logger(ctx, LOG_INFO, "%s: cmd %d addr %s",
+ ifname, cmd, dbp);
#endif
if (ifs == NULL)
ifs = ctx->ifaces;
- if (ifs == NULL) {
- errno = ESRCH;
+ if (ifs == NULL)
return;
- }
if ((ifp = if_find(ifs, ifname)) == NULL)
return;
if ((state = ipv6_getstate(ifp)) == NULL)
return;
- if (!IN6_IS_ADDR_LINKLOCAL(addr)) {
- ipv6nd_handleifa(ctx, cmd, ifname, addr, flags);
- dhcp6_handleifa(ctx, cmd, ifname, addr, flags);
- }
-
- TAILQ_FOREACH(ap, &state->addrs, next) {
- if (IN6_ARE_ADDR_EQUAL(&ap->addr, addr))
+ TAILQ_FOREACH(ia, &state->addrs, next) {
+ if (IN6_ARE_ADDR_EQUAL(&ia->addr, addr))
break;
}
switch (cmd) {
case RTM_DELADDR:
- if (ap) {
- TAILQ_REMOVE(&state->addrs, ap, next);
- ipv6_freeaddr(ap);
+ if (ia != NULL) {
+ TAILQ_REMOVE(&state->addrs, ia, next);
+ /* We'll free it at the end of the function. */
}
break;
case RTM_NEWADDR:
- if (ap == NULL) {
+ if (ia == NULL) {
char buf[INET6_ADDRSTRLEN];
const char *cbp;
- ap = calloc(1, sizeof(*ap));
- if (ap == NULL) {
+ if ((ia = calloc(1, sizeof(*ia))) == NULL) {
logger(ctx, LOG_ERR,
"%s: calloc: %m", __func__);
break;
}
#ifdef ALIAS_ADDR
- strlcpy(ap->alias, ifname, sizeof(ap->alias));
+ strlcpy(ia->alias, ifname, sizeof(ia->alias));
#endif
- ap->iface = ifp;
- ap->addr = *addr;
- ap->prefix_len = prefix_len;
- ipv6_makeprefix(&ap->prefix, &ap->addr,
- ap->prefix_len);
+ ia->iface = ifp;
+ ia->addr = *addr;
+ ia->prefix_len = prefix_len;
+ ipv6_makeprefix(&ia->prefix, &ia->addr,
+ ia->prefix_len);
cbp = inet_ntop(AF_INET6, &addr->s6_addr,
buf, sizeof(buf));
if (cbp)
- snprintf(ap->saddr, sizeof(ap->saddr),
+ snprintf(ia->saddr, sizeof(ia->saddr),
"%s/%d", cbp, prefix_len);
- if (if_getlifetime6(ap) == -1) {
+ if (if_getlifetime6(ia) == -1) {
/* No support or address vanished.
* Either way, just set a deprecated
* infinite time lifetime and continue.
* temporary addresses.
* As we can't extend infinite, we'll
* create a new temporary address. */
- ap->prefix_pltime = 0;
- ap->prefix_vltime =
+ ia->prefix_pltime = 0;
+ ia->prefix_vltime =
ND6_INFINITE_LIFETIME;
}
/* This is a minor regression against RFC 4941
* pretend lifetimes are infinite and always
* generate a new temporary address on
* restart. */
- ap->acquired = ap->created;
- TAILQ_INSERT_TAIL(&state->addrs,
- ap, next);
+ ia->acquired = ia->created;
+ TAILQ_INSERT_TAIL(&state->addrs, ia, next);
}
- ap->addr_flags = flags;
+ ia->addr_flags = if_addrflags6(ia);
#ifdef IPV6_MANAGETEMPADDR
- if (ap->addr_flags & IN6_IFF_TEMPORARY)
- ap->flags |= IPV6_AF_TEMPORARY;
+ if (ia->addr_flags & IN6_IFF_TEMPORARY)
+ ia->flags |= IPV6_AF_TEMPORARY;
#endif
- if (IN6_IS_ADDR_LINKLOCAL(&ap->addr) || ap->dadcallback) {
+ if (IN6_IS_ADDR_LINKLOCAL(&ia->addr) || ia->dadcallback) {
#ifdef IPV6_POLLADDRFLAG
- if (ap->addr_flags & IN6_IFF_TENTATIVE) {
+ if (ia->addr_flags & IN6_IFF_TENTATIVE) {
struct timespec tv;
ms_to_ts(&tv, RETRANS_TIMER / 2);
eloop_timeout_add_tv(
- ap->iface->ctx->eloop,
- &tv, ipv6_checkaddrflags, ap);
+ ia->iface->ctx->eloop,
+ &tv, ipv6_checkaddrflags, ia);
break;
}
#endif
- if (ap->dadcallback)
- ap->dadcallback(ap);
+ if (ia->dadcallback)
+ ia->dadcallback(ia);
- if (IN6_IS_ADDR_LINKLOCAL(&ap->addr) &&
- !(ap->addr_flags & IN6_IFF_NOTUSEABLE))
+ if (IN6_IS_ADDR_LINKLOCAL(&ia->addr) &&
+ !(ia->addr_flags & IN6_IFF_NOTUSEABLE))
{
/* Now run any callbacks.
* Typically IPv6RS or DHCPv6 */
}
break;
}
+
+ if (ia != NULL) {
+ if (!IN6_IS_ADDR_LINKLOCAL(&ia->addr)) {
+ ipv6nd_handleifa(cmd, ia);
+ dhcp6_handleifa(cmd, ia);
+ }
+
+ /* Done with the ia now, so free it. */
+ if (cmd == RTM_DELADDR)
+ ipv6_freeaddr(ia);
+ }
}
int
int
ipv6_handleifa_addrs(int cmd,
- struct ipv6_addrhead *addrs, const struct in6_addr *addr, int flags)
+ struct ipv6_addrhead *addrs, const struct ipv6_addr *addr)
{
- struct ipv6_addr *ap, *apn;
+ struct ipv6_addr *ia, *ian;
uint8_t found, alldadcompleted;
alldadcompleted = 1;
found = 0;
- TAILQ_FOREACH_SAFE(ap, addrs, next, apn) {
- if (!IN6_ARE_ADDR_EQUAL(addr, &ap->addr)) {
- if (ap->flags & IPV6_AF_ADDED &&
- !(ap->flags & IPV6_AF_DADCOMPLETED))
+ TAILQ_FOREACH_SAFE(ia, addrs, next, ian) {
+ if (!IN6_ARE_ADDR_EQUAL(&addr->addr, &ia->addr)) {
+ if (ia->flags & IPV6_AF_ADDED &&
+ !(ia->flags & IPV6_AF_DADCOMPLETED))
alldadcompleted = 0;
continue;
}
switch (cmd) {
case RTM_DELADDR:
- if (ap->flags & IPV6_AF_ADDED) {
- logger(ap->iface->ctx, LOG_INFO,
+ if (ia->flags & IPV6_AF_ADDED) {
+ logger(ia->iface->ctx, LOG_INFO,
"%s: deleted address %s",
- ap->iface->name, ap->saddr);
- ap->flags &= ~IPV6_AF_ADDED;
+ ia->iface->name, ia->saddr);
+ ia->flags &= ~IPV6_AF_ADDED;
}
break;
case RTM_NEWADDR:
/* Safety - ignore tentative announcements */
- if (flags & (IN6_IFF_DETACHED |IN6_IFF_TENTATIVE))
+ if (addr->addr_flags &
+ (IN6_IFF_DETACHED | IN6_IFF_TENTATIVE))
break;
- if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0) {
+ if ((ia->flags & IPV6_AF_DADCOMPLETED) == 0) {
found++;
- if (flags & IN6_IFF_DUPLICATED)
- ap->flags |= IPV6_AF_DUPLICATED;
+ if (addr->addr_flags & IN6_IFF_DUPLICATED)
+ ia->flags |= IPV6_AF_DUPLICATED;
else
- ap->flags &= ~IPV6_AF_DUPLICATED;
- if (ap->dadcallback)
- ap->dadcallback(ap);
+ ia->flags &= ~IPV6_AF_DUPLICATED;
+ if (ia->dadcallback)
+ ia->dadcallback(ia);
/* We need to set this here in-case the
* dadcallback function checks it */
- ap->flags |= IPV6_AF_DADCOMPLETED;
+ ia->flags |= IPV6_AF_DADCOMPLETED;
}
break;
}
void ipv6_freedrop_addrs(struct ipv6_addrhead *, int,
const struct interface *);
void ipv6_handleifa(struct dhcpcd_ctx *ctx, int, struct if_head *,
- const char *, const struct in6_addr *, uint8_t, int);
-int ipv6_handleifa_addrs(int, struct ipv6_addrhead *,
- const struct in6_addr *, int);
+ const char *, const struct in6_addr *, uint8_t);
+int ipv6_handleifa_addrs(int, struct ipv6_addrhead *, const struct ipv6_addr *);
struct ipv6_addr *ipv6_iffindaddr(struct interface *,
const struct in6_addr *, int);
int ipv6_hasaddr(const struct interface *);
}
void
-ipv6nd_handleifa(struct dhcpcd_ctx *ctx, int cmd, const char *ifname,
- const struct in6_addr *addr, int flags)
+ipv6nd_handleifa(int cmd, struct ipv6_addr *addr)
{
struct ra *rap;
- if (ctx->ipv6 == NULL)
- return;
- TAILQ_FOREACH(rap, ctx->ipv6->ra_routers, next) {
- if (strcmp(rap->iface->name, ifname))
+ TAILQ_FOREACH(rap, addr->iface->ctx->ipv6->ra_routers, next) {
+ if (rap->iface != addr->iface)
continue;
- ipv6_handleifa_addrs(cmd, &rap->addrs, addr, flags);
+ ipv6_handleifa_addrs(cmd, &rap->addrs, addr);
}
}
void ipv6nd_expirera(void *arg);
int ipv6nd_hasra(const struct interface *);
int ipv6nd_hasradhcp(const struct interface *);
-void ipv6nd_handleifa(struct dhcpcd_ctx *, int,
- const char *, const struct in6_addr *, int);
+void ipv6nd_handleifa(int, struct ipv6_addr *);
int ipv6nd_dadcompleted(const struct interface *);
void ipv6nd_expire(struct interface *, uint32_t);
void ipv6nd_drop(struct interface *);