From: Roy Marples Date: Fri, 8 Apr 2016 20:02:41 +0000 (+0000) Subject: If a normal default route is added, delete our IPv4LL default route. X-Git-Tag: v6.10.2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=baa179d3388db253fd56cf79a56ab83bdadf4817;p=thirdparty%2Fdhcpcd.git If a normal default route is added, delete our IPv4LL default route. If a normal defaulr route is deleted, and no other exists, add our IPv4LL default route. Fixes [bd6daf1d59]. --- diff --git a/if-bsd.c b/if-bsd.c index 82fb73b0..0930b955 100644 --- a/if-bsd.c +++ b/if-bsd.c @@ -768,7 +768,7 @@ if_initrt(struct interface *ifp) for (p = buf; p < end; p += rtm->rtm_msglen) { rtm = (void *)p; if (if_copyrt(ifp->ctx, &rt, rtm) == 0) - ipv4_handlert(ifp->ctx, RTM_ADD, &rt); + ipv4_handlert(ifp->ctx, RTM_ADD, &rt, 1); } free(buf); return 0; @@ -1316,7 +1316,7 @@ if_managelink(struct dhcpcd_ctx *ctx) #ifdef INET case AF_INET: if (if_copyrt(ctx, &rt, rtm) == 0) - ipv4_handlert(ctx, rtm->rtm_type, &rt); + ipv4_handlert(ctx, rtm->rtm_type,&rt,0); break; #endif #ifdef INET6 diff --git a/if-linux.c b/if-linux.c index 3d260399..08be0955 100644 --- a/if-linux.c +++ b/if-linux.c @@ -608,7 +608,7 @@ link_route(struct dhcpcd_ctx *ctx, __unused struct interface *ifp, #ifdef INET case AF_INET: if (if_copyrt(ctx, &rt, nlm) == 0) - ipv4_handlert(ctx, cmd, &rt); + ipv4_handlert(ctx, cmd, &rt, 0); break; #endif #ifdef INET6 @@ -1463,7 +1463,7 @@ _if_initrt(struct dhcpcd_ctx *ctx, __unused struct interface *ifp, struct rt rt; if (if_copyrt(ctx, &rt, nlm) == 0) - ipv4_handlert(ctx, RTM_ADD, &rt); + ipv4_handlert(ctx, RTM_ADD, &rt, 1); return 0; } diff --git a/ipv4.c b/ipv4.c index 33768dc0..a00f705b 100644 --- a/ipv4.c +++ b/ipv4.c @@ -397,7 +397,7 @@ ipv4_findrt(struct dhcpcd_ctx *ctx, const struct rt *rt, int flags) TAILQ_FOREACH(r, ctx->ipv4_kroutes, next) { if (rt->dest.s_addr == r->dest.s_addr && #ifdef HAVE_ROUTE_METRIC - rt->iface == r->iface && + (rt->iface == NULL || rt->iface == r->iface) && (!flags || rt->metric == r->metric) && #else (!flags || rt->iface == r->iface) && @@ -422,7 +422,7 @@ ipv4_freerts(struct rt_head *routes) /* If something other than dhcpcd removes a route, * we need to remove it from our internal table. */ int -ipv4_handlert(struct dhcpcd_ctx *ctx, int cmd, const struct rt *rt) +ipv4_handlert(struct dhcpcd_ctx *ctx, int cmd, const struct rt *rt, int flags) { struct rt *f; @@ -453,7 +453,8 @@ ipv4_handlert(struct dhcpcd_ctx *ctx, int cmd, const struct rt *rt) } break; } - return 0; + + return flags ? 0 : ipv4ll_handlert(ctx, cmd, rt); } #define n_route(a) nc_route(NULL, a) @@ -869,15 +870,21 @@ ipv4_buildroutes(struct dhcpcd_ctx *ctx) ipv4_freeroutes(dnr); } - /* If we don't manage a default route, grab one without a + /* If there is no default route, grab one without a * gateway for any IPv4LL enabled interfaces. */ if (!has_default) { - TAILQ_FOREACH(ifp, ctx->ifaces, next) { - if ((rt = ipv4ll_default_route(ifp)) != NULL) { - if (ipv4_doroute(rt, nrs) == 1) - TAILQ_INSERT_TAIL(nrs, rt, next); - else - free(rt); + struct rt def; + + memset(&def, 0, sizeof(def)); + if (ipv4_findrt(ctx, &def, 0) == NULL) { + TAILQ_FOREACH(ifp, ctx->ifaces, next) { + if ((rt = ipv4ll_default_route(ifp)) != NULL) { + if (ipv4_doroute(rt, nrs) == 1) { + TAILQ_INSERT_TAIL(nrs, rt, next); + break; + } else + free(rt); + } } } } diff --git a/ipv4.h b/ipv4.h index ec6489b0..f38d0ce1 100644 --- a/ipv4.h +++ b/ipv4.h @@ -114,7 +114,7 @@ int ipv4_preferanother(struct interface *); struct ipv4_addr *ipv4_addaddr(struct interface *, const struct in_addr *, const struct in_addr *, const struct in_addr *); void ipv4_applyaddr(void *); -int ipv4_handlert(struct dhcpcd_ctx *, int, const struct rt *); +int ipv4_handlert(struct dhcpcd_ctx *, int, const struct rt *, int); void ipv4_freerts(struct rt_head *); struct ipv4_addr *ipv4_iffindaddr(struct interface *, diff --git a/ipv4ll.c b/ipv4ll.c index a1f10303..07d4a5dc 100644 --- a/ipv4ll.c +++ b/ipv4ll.c @@ -444,3 +444,25 @@ ipv4ll_freedrop(struct interface *ifp, int drop) } } } + +int +ipv4ll_handlert(struct dhcpcd_ctx *ctx, __unused int cmd, const struct rt *rt) +{ + struct interface *ifp; + + /* Only interested in default route changes. */ + if (rt->dest.s_addr != INADDR_ANY) + return 0; + + /* If any interface is running IPv4LL, rebuild our routing table. */ + TAILQ_FOREACH(ifp, ctx->ifaces, next) { + if (IPV4LL_STATE_RUNNING(ifp)) + break; + } + if (ifp != NULL) { + if_initrt(ifp); + ipv4_buildroutes(ctx); + } + + return 0; +} diff --git a/ipv4ll.h b/ipv4ll.h index fe5e70d7..37093f38 100644 --- a/ipv4ll.h +++ b/ipv4ll.h @@ -65,7 +65,7 @@ ssize_t ipv4ll_env(char **, const char *, const struct interface *); void ipv4ll_start(void *); void ipv4ll_claimed(void *); void ipv4ll_handle_failure(void *); -int ipv4ll_handlert(struct dhcpcd_ctx *, int, struct rt *); +int ipv4ll_handlert(struct dhcpcd_ctx *, int, const struct rt *); #define ipv4ll_free(ifp) ipv4ll_freedrop((ifp), 0); #define ipv4ll_drop(ifp) ipv4ll_freedrop((ifp), 1);