From: Roy Marples Date: Mon, 1 Feb 2016 22:16:26 +0000 (+0000) Subject: Fix a crash where existing routes dhcpcd wants to parse have an ip address X-Git-Tag: v6.10.2~85 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7ce7c86d7ecf006d4b71c215d2bea2e91f6d9271;p=thirdparty%2Fdhcpcd.git Fix a crash where existing routes dhcpcd wants to parse have an ip address as a gateway. Thanks to Christos Zoulas. --- diff --git a/if-bsd.c b/if-bsd.c index 9f63a345..91006376 100644 --- a/if-bsd.c +++ b/if-bsd.c @@ -463,6 +463,8 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, struct rt_msghdr *rtm) char *cp; struct sockaddr *sa, *rti_info[RTAX_MAX]; struct sockaddr_dl *sdl; + struct sockaddr_in *sin; + struct ipv4_addr *ia; cp = (char *)(void *)(rtm + 1); sa = (struct sockaddr *)(void *)cp; @@ -501,9 +503,22 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, struct rt_msghdr *rtm) sdl = (struct sockaddr_dl *)(void *)rti_info[RTAX_IFP]; rt->iface = if_findsdl(ctx, sdl); } else if (rtm->rtm_addrs & RTA_GATEWAY) { - sdl = (struct sockaddr_dl *)(void *)rti_info[RTAX_GATEWAY]; - if (sdl->sdl_family == AF_LINK) + sa = rti_info[RTAX_GATEWAY]; + switch (sa->sa_family) { + case AF_LINK: + sdl = (void *)sa; rt->iface = if_findsdl(ctx, sdl); + break; + case AF_INET: + sin = (void *)sa; + if ((ia = ipv4_findmaskaddr(ctx, &sin->sin_addr))) + rt->iface = ia->iface; + break; + default: + errno = EAFNOSUPPORT; + logger(ctx, LOG_ERR, "%s: %m", __func__); + return -1; + } } /* If we don't have an interface and it's a host route, it maybe @@ -511,8 +526,6 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, struct rt_msghdr *rtm) if (rt->iface == NULL && !(~rtm->rtm_flags & (RTF_HOST | RTF_GATEWAY))) { - struct ipv4_addr *ia; - if ((ia = ipv4_findaddr(ctx, &rt->dest))) rt->iface = ia->iface; } diff --git a/ipv4.c b/ipv4.c index 50de28f0..35572230 100644 --- a/ipv4.c +++ b/ipv4.c @@ -145,6 +145,23 @@ ipv4_iffindlladdr(struct interface *ifp) return NULL; } +static struct ipv4_addr * +ipv4_iffindmaskaddr(struct interface *ifp, const struct in_addr *addr) +{ + struct ipv4_state *state; + struct ipv4_addr *ap; + + state = IPV4_STATE(ifp); + if (state) { + TAILQ_FOREACH (ap, &state->addrs, next) { + if ((ap->addr.s_addr & ap->net.s_addr) == + (addr->s_addr & ap->net.s_addr)) + return ap; + } + } + return NULL; +} + struct ipv4_addr * ipv4_findaddr(struct dhcpcd_ctx *ctx, const struct in_addr *addr) { @@ -159,6 +176,20 @@ ipv4_findaddr(struct dhcpcd_ctx *ctx, const struct in_addr *addr) return NULL; } +struct ipv4_addr * +ipv4_findmaskaddr(struct dhcpcd_ctx *ctx, const struct in_addr *addr) +{ + struct interface *ifp; + struct ipv4_addr *ap; + + TAILQ_FOREACH(ifp, ctx->ifaces, next) { + ap = ipv4_iffindmaskaddr(ifp, addr); + if (ap) + return ap; + } + return NULL; +} + int ipv4_srcaddr(const struct rt *rt, struct in_addr *addr) { diff --git a/ipv4.h b/ipv4.h index 0d3f838d..138c43f9 100644 --- a/ipv4.h +++ b/ipv4.h @@ -121,6 +121,8 @@ struct ipv4_addr *ipv4_iffindaddr(struct interface *, const struct in_addr *, const struct in_addr *); struct ipv4_addr *ipv4_iffindlladdr(struct interface *); struct ipv4_addr *ipv4_findaddr(struct dhcpcd_ctx *, const struct in_addr *); +struct ipv4_addr *ipv4_findmaskaddr(struct dhcpcd_ctx *, + const struct in_addr *); int ipv4_srcaddr(const struct rt *, 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 *,