From: Roy Marples Date: Mon, 4 Mar 2019 14:34:59 +0000 (+0000) Subject: route: Free route when failing to insert. X-Git-Tag: v8.0.0~73 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d033f540341083078b2c583fff819590d75e613f;p=thirdparty%2Fdhcpcd.git route: Free route when failing to insert. This means the collection already has the route, so we avoid leaking memory. --- diff --git a/src/dhcp.c b/src/dhcp.c index b77eda16..73ca69f8 100644 --- a/src/dhcp.c +++ b/src/dhcp.c @@ -465,8 +465,10 @@ decode_rfc3442_rt(rb_tree_t *routes, struct interface *ifp, sa_in_init(&rt->rt_dest, &dest); sa_in_init(&rt->rt_netmask, &netmask); sa_in_init(&rt->rt_gateway, &gateway); - rb_tree_insert_node(routes, rt); - n++; + if (rb_tree_insert_node(routes, rt) != rt) + rt_free(rt); + else + n++; } return n; } @@ -653,8 +655,10 @@ get_option_routes(rb_tree_t *routes, struct interface *ifp, sa_in_init(&rt->rt_dest, &dest); sa_in_init(&rt->rt_netmask, &netmask); sa_in_init(&rt->rt_gateway, &gateway); - rb_tree_insert_node(routes, rt); - n++; + if (rb_tree_insert_node(routes, rt) != rt) + rt_free(rt); + else + n++; } } @@ -675,8 +679,10 @@ get_option_routes(rb_tree_t *routes, struct interface *ifp, sa_in_init(&rt->rt_dest, &dest); sa_in_init(&rt->rt_netmask, &netmask); sa_in_init(&rt->rt_gateway, &gateway); - rb_tree_insert_node(routes, rt); - n++; + if (rb_tree_insert_node(routes, rt) != rt) + rt_free(rt); + else + n++; } } diff --git a/src/if-options.c b/src/if-options.c index 074912d4..27354629 100644 --- a/src/if-options.c +++ b/src/if-options.c @@ -1110,7 +1110,8 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo, sa_in_init(&rt->rt_dest, &addr); sa_in_init(&rt->rt_netmask, &addr2); sa_in_init(&rt->rt_gateway, &addr3); - rb_tree_insert_node(&ifo->routes, rt); + if (rb_tree_insert_node(&ifo->routes, rt) != rt) + rt_free(rt); *fp = ' '; } else if (strncmp(arg, "routers=", strlen("routers=")) == 0) { if (parse_addr(&addr, NULL, p) == -1) @@ -1121,7 +1122,8 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo, sa_in_init(&rt->rt_dest, &addr2); sa_in_init(&rt->rt_netmask, &addr2); sa_in_init(&rt->rt_gateway, &addr); - rb_tree_insert_node(&ifo->routes, rt); + if (rb_tree_insert_node(&ifo->routes, rt) != rt) + rt_free(rt); } else if (strncmp(arg, "interface_mtu=", strlen("interface_mtu=")) == 0 || strncmp(arg, "mtu=", strlen("mtu=")) == 0) diff --git a/src/ipv4.c b/src/ipv4.c index 1bdfc4c5..cdccf6ce 100644 --- a/src/ipv4.c +++ b/src/ipv4.c @@ -283,7 +283,8 @@ inet_dhcproutes(rb_tree_t *routes, struct interface *ifp) //in.s_addr = INADDR_ANY; //sa_in_init(&rt->rt_gateway, &in); rt->rt_gateway.sa_family = AF_UNSPEC; - rb_tree_insert_node(&nroutes, rt); + if (rb_tree_insert_node(&nroutes, rt) != rt) + rt_free(rt); } /* If any set routes, grab them, otherwise DHCP routes. */ @@ -296,7 +297,8 @@ inet_dhcproutes(rb_tree_t *routes, struct interface *ifp) memcpy(rt, r, sizeof(*rt)); rt_setif(rt, ifp); rt->rt_dflags = RTDF_STATIC; - rb_tree_insert_node(&nroutes, rt); + if (rb_tree_insert_node(&nroutes, rt) != rt) + rt_free(rt); } } else { if (dhcp_get_routes(&nroutes, ifp) == -1) @@ -315,7 +317,8 @@ inet_dhcproutes(rb_tree_t *routes, struct interface *ifp) sa_in_init(&rt->rt_netmask, &in); sa_in_init(&rt->rt_gateway, &state->addr->brd); sa_in_init(&rt->rt_ifa, &state->addr->addr); - rb_tree_insert_node(&nroutes, rt); + if (rb_tree_insert_node(&nroutes, rt) != rt) + rt_free(rt); } /* Copy our address as the source address and set mtu */ @@ -327,8 +330,10 @@ inet_dhcproutes(rb_tree_t *routes, struct interface *ifp) if (!(rt->rt_dflags & RTDF_STATIC)) rt->rt_dflags |= RTDF_DHCP; sa_in_init(&rt->rt_ifa, &state->addr->addr); - rb_tree_insert_node(routes, rt); - n++; + if (rb_tree_insert_node(routes, rt) != rt) + rt_free(rt); + else + n++; } return n; @@ -420,7 +425,8 @@ inet_routerhostroute(rb_tree_t *routes, struct interface *ifp) sa_in_init(&rth->rt_gateway, &in); rth->rt_mtu = dhcp_get_mtu(ifp); sa_in_init(&rth->rt_ifa, &state->addr->addr); - rb_tree_insert_node(routes, rth); + if (rb_tree_insert_node(routes, rth) != rth) + rt_free(rth); } return 0; } diff --git a/src/ipv4ll.c b/src/ipv4ll.c index 673f583d..5ae3d485 100644 --- a/src/ipv4ll.c +++ b/src/ipv4ll.c @@ -108,7 +108,10 @@ ipv4ll_subnetroute(rb_tree_t *routes, struct interface *ifp) in.s_addr = INADDR_ANY; sa_in_init(&rt->rt_gateway, &in); sa_in_init(&rt->rt_ifa, &state->addr->addr); - rb_tree_insert_node(routes, rt); + if (rb_tree_insert_node(routes, rt) != rt) { + rt_free(rt); + return 0; + } return 1; } @@ -132,7 +135,10 @@ ipv4ll_defaultroute(rb_tree_t *routes, struct interface *ifp) sa_in_init(&rt->rt_netmask, &in); sa_in_init(&rt->rt_gateway, &in); sa_in_init(&rt->rt_ifa, &state->addr->addr); - rb_tree_insert_node(routes, rt); + if (rb_tree_insert_node(routes, rt) != rt) { + rt_free(rt); + return 0; + } return 1; } diff --git a/src/ipv6.c b/src/ipv6.c index f078972c..ee626330 100644 --- a/src/ipv6.c +++ b/src/ipv6.c @@ -2223,8 +2223,8 @@ inet6_staticroutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx) (IPV6_AF_ADDED | IPV6_AF_STATIC)) { rt = inet6_makeprefix(ifp, NULL, ia); - if (rt) - rb_tree_insert_node(routes, rt); + if (rt && rb_tree_insert_node(routes, rt) != rt) + rt_free(rt); } } } @@ -2248,15 +2248,17 @@ inet6_raroutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx, int expired, rt = inet6_makeprefix(rap->iface, rap, addr); if (rt) { rt->rt_dflags |= RTDF_RA; - rb_tree_insert_node(routes, rt); + if (rb_tree_insert_node(routes, rt) != rt) + rt_free(rt); } } if (rap->lifetime) { rt = inet6_makerouter(rap); if (rt) { rt->rt_dflags |= RTDF_RA; - rb_tree_insert_node(routes, rt); - if (have_default) + if (rb_tree_insert_node(routes, rt) != rt) + rt_free(rt); + else if (have_default) *have_default = true; } } @@ -2282,7 +2284,8 @@ inet6_dhcproutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx, if (rt == NULL) continue; rt->rt_dflags |= RTDF_DHCP; - rb_tree_insert_node(routes, rt); + if (rb_tree_insert_node(routes, rt) != rt) + rt_free(rt); } } } diff --git a/src/route.c b/src/route.c index 0015ff36..d7cfe7ba 100644 --- a/src/route.c +++ b/src/route.c @@ -354,10 +354,10 @@ rt_recvrt(int cmd, const struct rt *rt) assert(rt->rt_ifp->ctx != NULL); ctx = rt->rt_ifp->ctx; - f = rb_tree_find_node(&ctx->kroutes, rt); switch(cmd) { case RTM_DELETE: + f = rb_tree_find_node(&ctx->kroutes, rt); if (f != NULL) { rb_tree_remove_node(&ctx->kroutes, f); rt_free(f); @@ -370,12 +370,11 @@ rt_recvrt(int cmd, const struct rt *rt) } break; case RTM_ADD: - if (f != NULL) - break; if ((f = rt_new(rt->rt_ifp)) == NULL) break; memcpy(f, rt, sizeof(*f)); - rb_tree_insert_node(&ctx->kroutes, f); + if (rb_tree_insert_node(&ctx->kroutes, f) != f) + rt_free(f); break; } @@ -607,7 +606,11 @@ rt_build(struct dhcpcd_ctx *ctx, int af) continue; if (rt_doroute(rt)) { rb_tree_remove_node(&routes, rt); - rb_tree_insert_node(&added, rt); + if (rb_tree_insert_node(&added, rt) != rt) { + errno = EEXIST; + logerr(__func__); + rt_free(rt); + } } } @@ -632,7 +635,11 @@ rt_build(struct dhcpcd_ctx *ctx, int af) /* XXX This needs to be optimised. */ while ((rt = RB_TREE_MIN(&added)) != NULL) { rb_tree_remove_node(&added, rt); - rb_tree_insert_node(&ctx->routes, rt); + if (rb_tree_insert_node(&ctx->routes, rt) != rt) { + errno = EEXIST; + logerr(__func__); + rt_free(rt); + } } getfail: