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;
#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
#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
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;
}
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) &&
/* 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;
}
break;
}
- return 0;
+
+ return flags ? 0 : ipv4ll_handlert(ctx, cmd, rt);
}
#define n_route(a) nc_route(NULL, a)
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);
+ }
}
}
}
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 *,
}
}
}
+
+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;
+}
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);