]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Ensure routes are initialised correctly, fixes #265.
authorRoy Marples <roy@marples.name>
Sun, 17 Mar 2013 13:00:03 +0000 (13:00 +0000)
committerRoy Marples <roy@marples.name>
Sun, 17 Mar 2013 13:00:03 +0000 (13:00 +0000)
If we fail to malloc any part of a route, clear all the routes.

dhcp.c
ipv4.c

diff --git a/dhcp.c b/dhcp.c
index 1b1fcd915cf4657f36e7f7a2d729ffe8fb174390..e757cbb1c4c59f8dcc7ae03ac923130379690b30 100644 (file)
--- a/dhcp.c
+++ b/dhcp.c
@@ -497,7 +497,6 @@ decode_rfc3442_rt(int dl, const uint8_t *data)
                cidr = *p++;
                if (cidr > 32) {
                        ipv4_freeroutes(routes);
-                       free(routes);
                        errno = EINVAL;
                        return NULL;
                }
@@ -506,7 +505,6 @@ decode_rfc3442_rt(int dl, const uint8_t *data)
                if (rt == NULL) {
                        syslog(LOG_ERR, "%s: %m", __func__);
                        ipv4_freeroutes(routes);
-                       free(routes);
                        return NULL;
                }
                TAILQ_INSERT_TAIL(routes, rt, next);
@@ -749,6 +747,7 @@ get_option_routes(struct interface *ifp, const struct dhcp_message *dhcp)
                syslog(LOG_ERR, "%s: %m", __func__);
                return NULL;
        }
+       TAILQ_INIT(routes);
        if (!has_option_mask(ifo->nomask, DHO_STATICROUTE))
                p = get_option(dhcp, DHO_STATICROUTE, &len, NULL);
        else
@@ -759,7 +758,8 @@ get_option_routes(struct interface *ifp, const struct dhcp_message *dhcp)
                        route = calloc(1, sizeof(*route));
                        if (route == NULL) {
                                syslog(LOG_ERR, "%s: %m", __func__);
-                               break;
+                               ipv4_freeroutes(routes);
+                               return NULL;
                        }
                        memcpy(&route->dest.s_addr, p, 4);
                        p += 4;
@@ -781,7 +781,8 @@ get_option_routes(struct interface *ifp, const struct dhcp_message *dhcp)
                        route = calloc(1, sizeof(*route));
                        if (route == NULL) {
                                syslog(LOG_ERR, "%s: %m", __func__);
-                               break;
+                               ipv4_freeroutes(routes);
+                               return NULL;
                        }
                        memcpy(&route->gate.s_addr, p, 4);
                        p += 4;
diff --git a/ipv4.c b/ipv4.c
index a7f0f9133d940e4d914659cf90598c0c5407847a..02979ca933a714f8d0214f3a0f15ddd53618f9b4 100644 (file)
--- a/ipv4.c
+++ b/ipv4.c
@@ -341,6 +341,9 @@ add_subnet_route(struct rt_head *rt, const struct interface *ifp)
        struct rt *r;
        const struct dhcp_state *s;
 
+       if (rt == NULL) /* earlier malloc failed */
+               return NULL;
+
        s = D_CSTATE(ifp);
        if (s->net.s_addr == INADDR_BROADCAST ||
            s->net.s_addr == INADDR_ANY ||
@@ -350,8 +353,11 @@ add_subnet_route(struct rt_head *rt, const struct interface *ifp)
                return rt;
 
        r = malloc(sizeof(*r));
-       if (r == NULL)
+       if (r == NULL) {
+               syslog(LOG_ERR, "%s: %m", __func__);
+               ipv4_freeroutes(rt);
                return NULL;
+       }
        r->dest.s_addr = s->addr.s_addr & s->net.s_addr;
        r->net.s_addr = s->net.s_addr;
        r->gate.s_addr = 0;
@@ -394,10 +400,12 @@ massage_host_routes(struct rt_head *rt, const struct interface *ifp)
 {
        struct rt *r;
 
-       TAILQ_FOREACH(r, rt, next) {
-               if (r->gate.s_addr == D_CSTATE(ifp)->addr.s_addr &&
-                   r->net.s_addr == INADDR_BROADCAST)
-                       r->gate.s_addr = r->dest.s_addr;
+       if (rt) {
+               TAILQ_FOREACH(r, rt, next) {
+                       if (r->gate.s_addr == D_CSTATE(ifp)->addr.s_addr &&
+                           r->net.s_addr == INADDR_BROADCAST)
+                               r->gate.s_addr = r->dest.s_addr;
+               }
        }
        return rt;
 }
@@ -407,12 +415,15 @@ add_destination_route(struct rt_head *rt, const struct interface *iface)
 {
        struct rt *r;
 
-       if (!(iface->flags & IFF_POINTOPOINT) ||
+       if (rt == NULL || /* failed a malloc earlier probably */
+           !(iface->flags & IFF_POINTOPOINT) ||
            !has_option_mask(iface->options->dstmask, DHO_ROUTER))
                return rt;
+
        r = malloc(sizeof(*r));
        if (r == NULL) {
                syslog(LOG_ERR, "%s: %m", __func__);
+               ipv4_freeroutes(rt);
                return NULL;
        }
        r->dest.s_addr = INADDR_ANY;
@@ -430,6 +441,9 @@ add_router_host_route(struct rt_head *rt, const struct interface *ifp)
        struct rt *rtp, *rtn;
        const char *cp, *cp2, *cp3, *cplim;
 
+       if (rt == NULL) /* earlier malloc failed */
+               return NULL;
+
        TAILQ_FOREACH(rtp, rt, next) {
                if (rtp->dest.s_addr != INADDR_ANY)
                        continue;
@@ -466,7 +480,8 @@ add_router_host_route(struct rt_head *rt, const struct interface *ifp)
                rtn = malloc(sizeof(*rtn));
                if (rtn == NULL) {
                        syslog(LOG_ERR, "%s: %m", __func__);
-                       continue;
+                       ipv4_freeroutes(rt);
+                       return NULL;
                }
                rtn->dest.s_addr = rtp->gate.s_addr;
                rtn->net.s_addr = INADDR_BROADCAST;
@@ -501,6 +516,8 @@ ipv4_buildroutes(void)
                        dnr = add_router_host_route(dnr, ifp);
                        dnr = add_destination_route(dnr, ifp);
                }
+               if (dnr == NULL) /* failed to malloc all new routes */
+                       continue;
                TAILQ_FOREACH_SAFE(rt, dnr, next, rtn) {
                        rt->iface = ifp;
                        rt->metric = ifp->metric;