A libc in the future will include address flags in ifaddrs.
Although this does make the code a bit more #ifdef messy, the end result
is a smaller binary, and less ioctls to make.
echo "no"
fi
rm -f _ifam_pid.c _ifam_pid
+
+ printf "Testing for ifam_addrflags ... "
+ cat <<EOF >_ifam_addrflags.c
+#include <net/if.h>
+int main(void) {
+ struct ifa_msghdr ifam = { };
+ return (int)ifam.ifam_addrflags;
+}
+EOF
+ if $XCC _ifam_addrflags.c -o _ifam_addrflags 2>&3; then
+ echo "yes"
+ echo "#define HAVE_IFAM_ADDRFLAGS" >>$CONFIG_H
+ else
+ echo "no"
+ fi
+ rm -f _ifam_addrflags.c _ifam_addrflags
fi
abort=false
return getifaddrs(&ifap);
}
EOF
+LIBSOCKET=
if $XCC _getifaddrs.c -o _getifaddrs 2>&3; then
echo "yes"
elif $XCC _getifaddrs.c -o _getifaddrs -lsocket 2>&3; then
+ LIBSOCKET=-lsocket
echo "yes (-lsocket)"
echo "LDADD+= -lsocket" >>$CONFIG_MK
else
rm -f _getifaddrs.c _getifaddrs
$abort && exit 1
+printf "Testing for ifaddrs.ifa_addrflags ... "
+cat <<EOF >_getifaddrs_addrflags.c
+#include <sys/types.h>
+#include <ifaddrs.h>
+int main(void) {
+ struct ifaddrs *ifap;
+ getifaddrs(&ifap);
+ return (int)ifap->ifa_addrflags;
+}
+EOF
+if $XCC _getifaddrs_addrflags.c -o _getifaddrs_addrflags $LIBSOCKET 2>&3; then
+ echo "yes"
+ echo "#define HAVE_IFADDRS_ADDRFLAGS" >>$CONFIG_H
+else
+ echo "no"
+fi
+rm -f _getifaddrs_addrflags.c _getifaddrs_addrflags
+
printf "Testing for clock_gettime ... "
cat <<EOF >_clock_gettime.c
#include <time.h>
return 0;
}
+#if !(defined(HAVE_IFADDRS_ADDRFLAGS) && defined(HAVE_IFAM_ADDRFLAGS))
int
-if_addrflags(const struct ipv4_addr *ia)
+if_addrflags(const struct interface *ifp, const struct in_addr *addr,
+ __unused const char *alias)
{
#ifdef SIOCGIFAFLAG_IN
struct ifreq ifr;
struct sockaddr_in *sin;
memset(&ifr, 0, sizeof(ifr));
- strlcpy(ifr.ifr_name, ia->iface->name, sizeof(ifr.ifr_name));
+ strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
sin = (void *)&ifr.ifr_addr;
sin->sin_family = AF_INET;
- sin->sin_addr = ia->addr;
- if (ioctl(ia->iface->ctx->pf_inet_fd, SIOCGIFAFLAG_IN, &ifr) == -1)
+ sin->sin_addr = *addr;
+ if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFAFLAG_IN, &ifr) == -1)
return -1;
return ifr.ifr_addrflags;
#else
- UNUSED(ia);
+ UNUSED(ifp);
+ UNUSED(addr);
return 0;
#endif
}
+#endif
#endif /* INET */
#ifdef INET6
return 0;
}
+#if !(defined(HAVE_IFADDRS_ADDRFLAGS) && defined(HAVE_IFAM_ADDRFLAGS))
int
-if_addrflags6(const struct ipv6_addr *ia)
+if_addrflags6(const struct interface *ifp, const struct in6_addr *addr,
+ __unused const char *alias)
{
int flags;
struct in6_ifreq ifr6;
struct priv *priv;
memset(&ifr6, 0, sizeof(ifr6));
- strlcpy(ifr6.ifr_name, ia->iface->name, sizeof(ifr6.ifr_name));
+ strlcpy(ifr6.ifr_name, ifp->name, sizeof(ifr6.ifr_name));
ifr6.ifr_addr.sin6_family = AF_INET6;
- ifr6.ifr_addr.sin6_addr = ia->addr;
- ifa_scope(&ifr6.ifr_addr, ia->iface->index);
- priv = (struct priv *)ia->iface->ctx->priv;
+ ifr6.ifr_addr.sin6_addr = *addr;
+ ifa_scope(&ifr6.ifr_addr, ifp->index);
+ priv = (struct priv *)ifp->ctx->priv;
if (ioctl(priv->pf_inet6_fd, SIOCGIFAFLAG_IN6, &ifr6) != -1)
flags = ifr6.ifr_ifru.ifru_flags6;
else
flags = -1;
return flags;
}
+#endif
int
if_getlifetime6(struct ipv6_addr *ia)
{
struct interface *ifp;
const struct sockaddr *rti_info[RTAX_MAX];
+ int addrflags;
#ifdef HAVE_IFAM_PID
if (if_ownmsgpid(ctx, ifam->ifam_pid, 0))
get_addrs(ifam->ifam_addrs, ifam + 1, rti_info);
if (rti_info[RTAX_IFA] == NULL)
return;
+#ifdef HAVE_IFAM_ADDRFLAGS
+ addrflags = ifam->ifam_addrflags;
+#endif
switch (rti_info[RTAX_IFA]->sa_family) {
case AF_LINK:
{
}
#endif
+#ifndef HAVE_IFAM_ADDRFLAGS
+ if (ifam->ifam_type == RTM_DELADDR ||
+ (addrflags = if_addrflags(ifp, &addr, NULL)) == -1)
+ {
+ if (ifam->ifam_type != RTM_DELADDR || errno != EEXIST)
+ logger(ctx, LOG_ERR,
+ "%s: if_addrflags1: %s: %m",
+ ifp->name, inet_ntoa(addr));
+ addrflags = 0;
+ }
+#endif
+
ipv4_handleifa(ctx, ifam->ifam_type, NULL, ifp->name,
- &addr, &mask, &bcast);
+ &addr, &mask, &bcast, addrflags);
break;
}
#endif
sin6 = (const void *)rti_info[RTAX_NETMASK];
mask6 = sin6->sin6_addr;
DESCOPE(&mask6);
+
+#ifndef HAVE_IFAM_ADDRFLAGS
+ if (ifam->ifam_type == RTM_DELADDR ||
+ (addrflags = if_addrflags6(ifp, &addr6, NULL)) == -1)
+ {
+ if (ifam->ifam_type != RTM_DELADDR || errno != EEXIST)
+ logger(ctx, LOG_ERR,
+ "%s: if_addrflags1: %s: %m",
+ ifp->name, inet_ntoa(addr));
+ addrflags = 0;
+ }
+#endif
+
ipv6_handleifa(ctx, ifam->ifam_type, NULL,
- ifp->name, &addr6, ipv6_prefixlen(&mask6));
+ ifp->name, &addr6, ipv6_prefixlen(&mask6), addrflags);
break;
}
#endif
}
int
-if_addrflags(__unused const struct ipv4_addr *addr)
+if_addrflags(__unused const struct interface *ifp,
+__unused const struct in_addr *addr, __unused const char *alias)
{
/* Linux has no support for IPv4 address flags */
}
int
-if_addrflags6(const struct ipv6_addr *ia)
+if_addrflags6(const struct interface *ifp, const struct in6_addr *addr,
+ _unused const char *alias)
{
FILE *fp;
char *p, ifaddress[33], address[33], name[IF_NAMESIZE + 1];
return -1;
p = ifaddress;
- for (i = 0; i < (int)sizeof(ia->addr.s6_addr); i++) {
- p += snprintf(p, 3, "%.2x", ia->addr.s6_addr[i]);
+ for (i = 0; i < (int)sizeof(addr->s6_addr); i++) {
+ p += snprintf(p, 3, "%.2x", addr->s6_addr[i]);
}
*p = '\0';
errno = EINVAL;
return -1;
}
- if (strcmp(name, ia->iface->name) == 0 &&
+ if (strcmp(name, ifp->name) == 0 &&
strcmp(ifaddress, address) == 0)
{
fclose(fp);
}
int
-if_addrflags(const struct ipv4_addr *ia)
+if_addrflags(const struct interface *ifp, __unused const struct in_addr *addr,
+ const char *alias)
{
int flags, aflags;
- aflags = if_addrflags0(ia->iface->ctx->pf_inet_fd, ia->alias);
+ aflags = if_addrflags0(ifp->ctx->pf_inet_fd, alias);
if (aflags == -1)
return -1;
flags = 0;
}
int
-if_addrflags6(const struct ipv6_addr *ia)
+if_addrflags6(const struct interface *ifp, __unused const struct in6_addr *addr,
+ const char *alias)
{
struct priv *priv;
int aflags, flags;
- priv = (struct priv *)ia->iface->ctx->priv;
- aflags = if_addrflags0(priv->pf_inet6_fd, ia->alias);
+ priv = (struct priv *)ifp->ctx->priv;
+ aflags = if_addrflags0(priv->pf_inet6_fd, alias);
flags = 0;
if (aflags & IFF_DUPLICATE)
flags |= IN6_IFF_DUPLICATED;
#ifdef INET6
struct sockaddr_in6 *sin6, *net6;
#endif
+ int addrflags;
for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == NULL)
continue;
if ((ifp = if_find(ifs, ifa->ifa_name)) == NULL)
continue;
+#ifdef HAVE_IFADDRS_ADDRFLAGS
+ addrflags = (int)ifa->ifa_addrflags;
+#endif
switch(ifa->ifa_addr->sa_family) {
#ifdef INET
case AF_INET:
brd = (void *)ifa->ifa_dstaddr;
else
brd = (void *)ifa->ifa_broadaddr;
+#ifndef HAVE_IFADDRS_ADDRFLAGS
+ addrflags = if_addrflags(ifp, &addr->sin_addr,
+ ifa->ifa_name);
+ if (addrflags == -1) {
+ if (errno != EEXIST)
+ logger(ctx, LOG_ERR,
+ "%s: if_addrflags: %s: %m",
+ __func__,
+ inet_ntoa(addr->sin_addr));
+ continue;
+ }
+#endif
ipv4_handleifa(ctx, RTM_NEWADDR, ifs, ifa->ifa_name,
&addr->sin_addr, &net->sin_addr,
- brd ? &brd->sin_addr : NULL);
+ brd ? &brd->sin_addr : NULL, addrflags);
break;
#endif
#ifdef INET6
/* Remove the scope from the address */
sin6->sin6_addr.s6_addr[2] =
sin6->sin6_addr.s6_addr[3] = '\0';
+#endif
+#ifndef HAVE_IFADDRS_ADDRFLAGS
+ addrflags = if_addrflags6(ifp, &sin6->sin6_addr,
+ ifa->ifa_name);
+ if (addrflags == -1) {
+ if (errno != EEXIST)
+ logger(ctx, LOG_ERR,
+ "%s: if_addrflags6: %m", __func__);
+ continue;
+ }
#endif
ipv6_handleifa(ctx, RTM_NEWADDR, ifs,
ifa->ifa_name, &sin6->sin6_addr,
- ipv6_prefixlen(&net6->sin6_addr));
+ ipv6_prefixlen(&net6->sin6_addr), addrflags);
break;
#endif
}
void if_closeraw(struct interface *, int);
int if_address(unsigned char, const struct ipv4_addr *);
-int if_addrflags(const struct ipv4_addr *);
+int if_addrflags(const struct interface *, const struct in_addr *,
+ const char *);
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 ipv6_addr *);
+int if_addrflags6(const struct interface *, const struct in6_addr *,
+ const char *);
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)
+ const struct in_addr *brd, const int addrflags)
{
struct interface *ifp;
struct ipv4_state *state;
struct ipv4_addr *ia;
- int flags;
bool ia_is_new;
if (ifs == NULL)
ia->brd = *brd;
else
ia->brd.s_addr = INADDR_ANY;
-
- flags = if_addrflags(ia);
- if (flags == -1) {
- if (errno != EADDRNOTAVAIL)
- logger(ia->iface->ctx, LOG_ERR,
- "%s: %s: if_addrflags: %m",
- ia->iface->name, ia->saddr);
- return;
- }
- ia->addr_flags = flags;
+ ia->addr_flags = addrflags;
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 *);
+ const struct in_addr *, const struct in_addr *, const struct in_addr *,
+ int);
void ipv4_freeroutes(struct rt_head *);
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)
+ const struct in6_addr *addr, uint8_t prefix_len, int addrflags)
{
struct interface *ifp;
struct ipv6_state *state;
struct ipv6_addr *ia;
struct ll_callback *cb;
- int flags;
#if 0
char dbuf[INET6_ADDRSTRLEN];
ia->acquired = ia->created;
TAILQ_INSERT_TAIL(&state->addrs, ia, next);
}
- flags = if_addrflags6(ia);
- if (flags == -1) {
- if (errno != EADDRNOTAVAIL)
- logger(ia->iface->ctx, LOG_ERR,
- "%s: %s: if_addrflags6: %m",
- ia->iface->name, ia->saddr);
- return;
- }
- ia->addr_flags = flags;
+ ia->addr_flags = addrflags;
#ifdef IPV6_MANAGETEMPADDR
if (ia->addr_flags & IN6_IFF_TEMPORARY)
ia->flags |= IPV6_AF_TEMPORARY;
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);
+ const char *, const struct in6_addr *, uint8_t, int);
int ipv6_handleifa_addrs(int, struct ipv6_addrhead *, const struct ipv6_addr *);
struct ipv6_addr *ipv6_iffindaddr(struct interface *,
const struct in6_addr *, int);