]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Fix a crash where existing routes dhcpcd wants to parse have an ip address
authorRoy Marples <roy@marples.name>
Mon, 1 Feb 2016 22:16:26 +0000 (22:16 +0000)
committerRoy Marples <roy@marples.name>
Mon, 1 Feb 2016 22:16:26 +0000 (22:16 +0000)
as a gateway.
Thanks to Christos Zoulas.

if-bsd.c
ipv4.c
ipv4.h

index 9f63a3454518723247ade785168ace817d56afee..910063765d1083efc48f88c24e1af657ad74fef2 100644 (file)
--- 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 50de28f04e2eec0c33547886c17ea76daf06419a..3557223014202414d9cd8aedd235f4fe1601a53e 100644 (file)
--- 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 0d3f838d051280c051ae5838d0421deb36028e95..138c43f924c6e3bab46a241fbdffa52bcbb3d1b8 100644 (file)
--- 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 *,