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
{
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;
}
#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;
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 ||
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))
#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
if (getifaddrs(&ifaddrs) == -1)
return NULL;
-
ifs = malloc(sizeof(*ifs));
if (ifs == NULL)
return NULL;
}
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;
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);
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;
ifp->wireless = 1;
ifp->metric += 100;
}
+#endif
TAILQ_INSERT_TAIL(ifs, ifp, next);
}
freeifaddrs(ifaddrs);
-#ifdef IFLR_ACTIVE
- close(socket_aflink);
+#if defined(IFLR_ACTIVE) || defined(SIOCGIFPRIORITY)
+ close(s);
#endif
return ifs;
/* 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