changeset 4515:768ba28719eb draft

route: Fix stamping on existing kernel routes
author Roy Marples <roy@marples.name>
date Sat, 04 May 2019 19:38:44 +0100
parents 011f49d4e4b8
children a519e4e62efd
files src/route.c
diffstat 1 files changed, 22 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/src/route.c	Sat May 04 11:07:18 2019 +0100
+++ b/src/route.c	Sat May 04 19:38:44 2019 +0100
@@ -401,7 +401,7 @@
 rt_add(rb_tree_t *kroutes, struct rt *nrt, struct rt *ort)
 {
 	struct dhcpcd_ctx *ctx;
-	bool change;
+	bool change, kroute, result;
 
 	assert(nrt != NULL);
 	ctx = nrt->rt_ifp->ctx;
@@ -423,7 +423,7 @@
 
 	rt_desc(ort == NULL ? "adding" : "changing", nrt);
 
-	change = false;
+	change = kroute = result = false;
 	if (ort == NULL) {
 		ort = rb_tree_find_node(kroutes, nrt);
 		if (ort != NULL &&
@@ -438,6 +438,7 @@
 			if (ort->rt_mtu == nrt->rt_mtu)
 				return true;
 			change = true;
+			kroute = true;
 		}
 	} else if (ort->rt_dflags & RTDF_FAKE &&
 	    !(nrt->rt_dflags & RTDF_FAKE) &&
@@ -464,8 +465,10 @@
 #endif
 
 	if (change) {
-		if (if_route(RTM_CHANGE, nrt) != -1)
-			return true;
+		if (if_route(RTM_CHANGE, nrt) != -1) {
+			result = true;
+			goto out;
+		}
 		if (errno != ESRCH)
 			logerr("if_route (CHG)");
 	}
@@ -477,9 +480,9 @@
 		if (ort != NULL) {
 			if (if_route(RTM_DELETE, ort) == -1 && errno != ESRCH)
 				logerr("if_route (DEL)");
-			memcpy(ort, nrt, sizeof(*ort));
 		}
-		return true;
+		result = true;
+		goto out;
 	}
 
 	/* If the kernel claims the route exists we need to rip out the
@@ -496,6 +499,8 @@
 	if (ort != NULL) {
 		if (if_route(RTM_DELETE, ort) == -1 && errno != ESRCH)
 			logerr("if_route (DEL)");
+		else
+			kroute = false;
 	}
 #ifdef ROUTE_PER_GATEWAY
 	/* The OS allows many routes to the same dest with different gateways.
@@ -508,16 +513,23 @@
 		}
 	}
 #endif
+
 	if (if_route(RTM_ADD, nrt) != -1) {
-		if (ort != NULL)
-			memcpy(ort, nrt, sizeof(*ort));
-		return true;
+		result = true;
+		goto out;
 	}
+
 #ifdef HAVE_ROUTE_METRIC
 logerr:
 #endif
 	logerr("if_route (ADD)");
-	return false;
+
+out:
+	if (kroute) {
+		rb_tree_remove_node(kroutes, ort);
+		rt_free(ort);
+	}
+	return result;
 }
 
 static bool