From ad6a36d4f3baba8b30976b1c2f04d1060dc725ff Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Thu, 6 Mar 2014 14:41:58 +0000 Subject: [PATCH] Initial support for OpenBSD interface and routing priority. --- README | 5 ++--- dhcpcd.c | 12 +++++++----- if-bsd.c | 6 ++++++ net.c | 33 ++++++++++++++++++++++++--------- net.h | 2 +- 5 files changed, 40 insertions(+), 18 deletions(-) diff --git a/README b/README index 6ee3f042..bce2455b 100644 --- a/README +++ b/README @@ -47,9 +47,8 @@ BSD systems where this is known to be a problem Occured in NetBSD-5.0, fixed in NetBSD-6.99.29 Occured in OpenBSD-4.2, fixed in OpenBSD-5.0 -On FreeBSD-10 dhcpcd cannot delete IPv4 subnet routes -On OpenBSD-5.4 dhcpcd cannot delete IPv4 subnet routes and the kernel allows -the addition of duplicate routes. +On FreeBSD-10 dhcpcd cannot delete IPv4 subnet routes. +On OpenBSD-5.5 dhcpcd cannot delete IPv4 subnet routes or IPv6 prefixes. We try and detect how dhcpcd should interact with system services at runtime. If we cannot auto-detect how do to this, or it is wrong then diff --git a/dhcpcd.c b/dhcpcd.c index 5ac26c74..88c895a9 100644 --- a/dhcpcd.c +++ b/dhcpcd.c @@ -297,9 +297,11 @@ find_interface(struct dhcpcd_ctx *ctx, const char *ifname) { struct interface *ifp; - TAILQ_FOREACH(ifp, ctx->ifaces, next) { - if (strcmp(ifp->name, ifname) == 0) - return ifp; + if (ctx != NULL && ctx->ifaces != NULL) { + TAILQ_FOREACH(ifp, ctx->ifaces, next) { + if (strcmp(ifp->name, ifname) == 0) + return ifp; + } } return NULL; } @@ -1410,8 +1412,8 @@ main(int argc, char **argv) #ifdef __OpenBSD__ syslog(LOG_WARNING, "OpenBSD errors that need to be fixed:"); syslog(LOG_WARNING, - "IPv4 subnet routes and IPv6 prefixes cannot be deleted"); - syslog(LOG_WARNING, "duplicate IPv4 subnet routes will be created"); + "IPv4 subnet routes cannot be deleted"); + syslog(LOG_WARNING, "IPv6 prefixes cannot be deleted"); #endif ctx.ifc = argc - optind; diff --git a/if-bsd.c b/if-bsd.c index 8d33cb50..de25b28d 100644 --- a/if-bsd.c +++ b/if-bsd.c @@ -290,6 +290,9 @@ if_route(const struct rt *rt, int action) else rtm.hdr.rtm_type = RTM_DELETE; rtm.hdr.rtm_flags = RTF_UP; +#ifdef SIOCGIFPRIORITY + rtm.hdr.rtm_priority = rt->metric; +#endif /* None interface subnet routes are static. */ if (rt->gate.s_addr != INADDR_ANY || rt->net.s_addr != state->net.s_addr || @@ -456,6 +459,9 @@ if_route6(const struct rt6 *rt, int action) rtm.hdr.rtm_type = RTM_DELETE; rtm.hdr.rtm_flags = RTF_UP; +#ifdef SIOCGIFPRIORITY + rtm.hdr.rtm_priority = rt->metric; +#endif /* None interface subnet routes are static. */ if (IN6_IS_ADDR_UNSPECIFIED(&rt->dest) && IN6_IS_ADDR_UNSPECIFIED(&rt->net)) diff --git a/net.c b/net.c index fba09ec8..2fa19e54 100644 --- a/net.c +++ b/net.c @@ -250,13 +250,19 @@ discover_interfaces(struct dhcpcd_ctx *ctx, int argc, char * const *argv) #endif #ifdef AF_LINK const struct sockaddr_dl *sdl; +#ifdef SIOCGIFPRIORITY + struct ifreq ifr; +#endif #ifdef IFLR_ACTIVE struct if_laddrreq iflr; - int socket_aflink; +#endif +#if defined(IFLR_ACTIVE) || defined(SIOCGIFPRIORITY) + int s; - socket_aflink = socket(AF_LINK, SOCK_DGRAM, 0); - if (socket_aflink == -1) + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) return NULL; +#endif +#ifdef IFLR_ACTIVE memset(&iflr, 0, sizeof(iflr)); #endif #elif AF_PACKET @@ -265,7 +271,6 @@ discover_interfaces(struct dhcpcd_ctx *ctx, int argc, char * const *argv) if (getifaddrs(&ifaddrs) == -1) return NULL; - ifs = malloc(sizeof(*ifs)); if (ifs == NULL) return NULL; @@ -339,8 +344,10 @@ discover_interfaces(struct dhcpcd_ctx *ctx, int argc, char * const *argv) } ifp = calloc(1, sizeof(*ifp)); - if (ifp == NULL) - return NULL; + if (ifp == NULL) { + syslog(LOG_ERR, "%s: %m", __func__); + break; + } ifp->ctx = ctx; strlcpy(ifp->name, p, sizeof(ifp->name)); ifp->flags = ifa->ifa_flags; @@ -378,7 +385,7 @@ discover_interfaces(struct dhcpcd_ctx *ctx, int argc, char * const *argv) MIN(ifa->ifa_addr->sa_len, sizeof(iflr.addr))); iflr.flags = IFLR_PREFIX; iflr.prefixlen = sdl->sdl_alen * NBBY; - if (ioctl(socket_aflink, SIOCGLIFADDR, &iflr) == -1 || + if (ioctl(s, SIOCGLIFADDR, &iflr) == -1 || !(iflr.flags & IFLR_ACTIVE)) { free_interface(ifp); @@ -463,6 +470,13 @@ discover_interfaces(struct dhcpcd_ctx *ctx, int argc, char * const *argv) continue; } +#ifdef SIOCGIFPRIORITY + /* Respect the interface priority */ + memset(&ifr, 0, sizeof(ifr)); + strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); + if (ioctl(s, SIOCGIFPRIORITY, &ifr) == 0) + ifp->metric = ifr.ifr_metric; +#else /* We reserve the 100 range for virtual interfaces, if and when * we can work them out. */ ifp->metric = 200 + ifp->index; @@ -470,6 +484,7 @@ discover_interfaces(struct dhcpcd_ctx *ctx, int argc, char * const *argv) ifp->wireless = 1; ifp->metric += 100; } +#endif TAILQ_INSERT_TAIL(ifs, ifp, next); } @@ -512,8 +527,8 @@ discover_interfaces(struct dhcpcd_ctx *ctx, int argc, char * const *argv) freeifaddrs(ifaddrs); -#ifdef IFLR_ACTIVE - close(socket_aflink); +#if defined(IFLR_ACTIVE) || defined(SIOCGIFPRIORITY) + close(s); #endif return ifs; diff --git a/net.h b/net.h index 2057f59c..087e28d7 100644 --- a/net.h +++ b/net.h @@ -41,7 +41,7 @@ /* Some systems have route metrics */ #ifndef HAVE_ROUTE_METRIC -# ifdef __linux__ +# if defined(__linux__) || defined(SIOCGIFPRIORITY) # define HAVE_ROUTE_METRIC 1 # endif # ifndef HAVE_ROUTE_METRIC -- 2.47.3