summary refs log tree commit diff
path: root/src/ndisc
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2020-05-08 21:40:53 +0200
committerMichael Biebl <biebl@debian.org>2020-05-08 21:40:53 +0200
commitd460892bbfece74fb6d3cd846bf6ef548290be41 (patch)
tree0474e5be0b5e5fac0d2f3a1e554382e8d1aa6397 /src/ndisc
parent1e5977b62f896e844b548c3007ace9e1dfa7f9ed (diff)
New upstream version 1.24.0 upstream/1.24.0
Diffstat (limited to 'src/ndisc')
-rw-r--r--src/ndisc/nm-lndp-ndisc.c27
-rw-r--r--src/ndisc/nm-ndisc.c39
-rw-r--r--src/ndisc/tests/test-ndisc-fake.c5
3 files changed, 31 insertions, 40 deletions
diff --git a/src/ndisc/nm-lndp-ndisc.c b/src/ndisc/nm-lndp-ndisc.c
index b698489c..b10adc91 100644
--- a/src/ndisc/nm-lndp-ndisc.c
+++ b/src/ndisc/nm-lndp-ndisc.c
@@ -101,8 +101,6 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
 	int offset;
 	int hop_limit;
 	guint32 val;
-	guint32 clamp_pltime;
-	guint32 clamp_vltime;
 
 	/* Router discovery is subject to the following RFC documents:
 	 *
@@ -167,22 +165,7 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
 			changed |= NM_NDISC_CONFIG_GATEWAYS;
 	}
 
-	/* Addresses & Routes
-	 *
-	 * The Preferred Lifetime and Valid Lifetime of PIOs are capped to Router Lifetime
-	 * and NM_NDISC_VLTIME_MULT * Preferred Lifetime, respectively.
-	 *
-	 * The Lifetime of RIOs is capped to the Router Lifetime (there is no point in
-	 * maintaining a route if it employs a dead router).
-	 *
-	 * See draft-gont-6man-slaac-renum
-	 */
-	#define NM_NDISC_VLTIME_MULT ((guint32) 48)
-	clamp_pltime = ndp_msgra_router_lifetime (msgra);
-	clamp_vltime =   (clamp_pltime < G_MAXUINT32 / NM_NDISC_VLTIME_MULT)
-	               ? clamp_pltime * NM_NDISC_VLTIME_MULT
-	               : G_MAXUINT32;
-
+	/* Addresses & Routes */
 	ndp_msg_opt_for_each_offset (offset, msg, NDP_MSG_OPT_PREFIX) {
 		guint8 r_plen;
 		struct in6_addr r_network;
@@ -203,7 +186,7 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
 				.network = r_network,
 				.plen = r_plen,
 				.timestamp = now,
-				.lifetime = NM_MIN (ndp_msg_opt_prefix_valid_time (msg, offset), clamp_vltime),
+				.lifetime = ndp_msg_opt_prefix_valid_time (msg, offset),
 			};
 
 			if (nm_ndisc_add_route (ndisc, &route))
@@ -216,8 +199,8 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
 			NMNDiscAddress address = {
 				.address = r_network,
 				.timestamp = now,
-				.lifetime = NM_MIN (ndp_msg_opt_prefix_valid_time (msg, offset), clamp_vltime),
-				.preferred = NM_MIN (ndp_msg_opt_prefix_preferred_time (msg, offset), clamp_pltime),
+				.lifetime = ndp_msg_opt_prefix_valid_time (msg, offset),
+				.preferred = ndp_msg_opt_prefix_preferred_time (msg, offset),
 			};
 
 			if (address.preferred <= address.lifetime) {
@@ -231,7 +214,7 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
 			.gateway = gateway_addr,
 			.plen = ndp_msg_opt_route_prefix_len (msg, offset),
 			.timestamp = now,
-			.lifetime = NM_MIN (ndp_msg_opt_route_lifetime (msg, offset), clamp_pltime),
+			.lifetime = ndp_msg_opt_route_lifetime (msg, offset),
 			.preference = _route_preference_coerce (ndp_msg_opt_route_preference (msg, offset)),
 		};
 
diff --git a/src/ndisc/nm-ndisc.c b/src/ndisc/nm-ndisc.c
index bb3a92b0..5e556084 100644
--- a/src/ndisc/nm-ndisc.c
+++ b/src/ndisc/nm-ndisc.c
@@ -442,15 +442,8 @@ nm_ndisc_add_address (NMNDisc *ndisc,
 	}
 
 	if (existing) {
-		/* A Valid Lifetime of 0 eliminates the corresponding address(es). This deviates
-		 * from RFC4862 Section 5.5.3, item e), as recommended in IETF draft draft-gont-6man-slaac-renum.
-		 */
-		if (new->lifetime == 0) {
-			g_array_remove_index (rdata->addresses, i);
-			return TRUE;
-		}
-
 		if (from_ra) {
+			const gint32 NM_NDISC_PREFIX_LFT_MIN = 7200; /* seconds, RFC4862 5.5.3.e */
 			gint64 old_expiry_lifetime, old_expiry_preferred;
 
 			old_expiry_lifetime = get_expiry (existing);
@@ -459,16 +452,25 @@ nm_ndisc_add_address (NMNDisc *ndisc,
 			if (new->lifetime == NM_NDISC_INFINITY)
 				existing->lifetime = NM_NDISC_INFINITY;
 			else {
-				gint64 new_lifetime;
+				gint64 new_lifetime, remaining_lifetime;
 
-				/* Honor small valid lifetimes, as discussed in
-				 * draft-gont-6man-slaac-renum, to allow for more timelier
-				 * reaction to renumbering events. This deviates from
-				 * RFC4862 Section 5.5.3, item e).
-				 */
+				/* see RFC4862 5.5.3.e */
+				if (existing->lifetime == NM_NDISC_INFINITY)
+					remaining_lifetime = G_MAXINT64;
+				else
+					remaining_lifetime = ((gint64) existing->timestamp) + ((gint64) existing->lifetime) - ((gint64) now_s);
 				new_lifetime = ((gint64) new->timestamp) + ((gint64) new->lifetime) - ((gint64) now_s);
-				existing->timestamp = now_s;
-				existing->lifetime = CLAMP (new_lifetime, (gint64) 0, (gint64) (G_MAXUINT32 - 1));
+
+				if (   new_lifetime > (gint64) NM_NDISC_PREFIX_LFT_MIN
+				    || new_lifetime > remaining_lifetime) {
+					existing->timestamp = now_s;
+					existing->lifetime = CLAMP (new_lifetime, (gint64) 0, (gint64) (G_MAXUINT32 - 1));
+				} else if (remaining_lifetime <= (gint64) NM_NDISC_PREFIX_LFT_MIN) {
+					/* keep the current lifetime. */
+				} else {
+					existing->timestamp = now_s;
+					existing->lifetime = NM_NDISC_PREFIX_LFT_MIN;
+				}
 			}
 
 			if (new->preferred == NM_NDISC_INFINITY) {
@@ -485,6 +487,11 @@ nm_ndisc_add_address (NMNDisc *ndisc,
 			       || old_expiry_preferred != get_expiry_preferred (existing);
 		}
 
+		if (new->lifetime == 0) {
+			g_array_remove_index (rdata->addresses, i);
+			return TRUE;
+		}
+
 		if (   get_expiry (existing) == get_expiry (new)
 		    && get_expiry_preferred (existing) == get_expiry_preferred (new))
 			return FALSE;
diff --git a/src/ndisc/tests/test-ndisc-fake.c b/src/ndisc/tests/test-ndisc-fake.c
index 7a5eea01..91fe9802 100644
--- a/src/ndisc/tests/test-ndisc-fake.c
+++ b/src/ndisc/tests/test-ndisc-fake.c
@@ -217,8 +217,9 @@ test_everything_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed
 
 		g_assert_cmpint (rdata->gateways_n, ==, 1);
 		match_gateway (rdata, 0, "fe80::2", data->timestamp1, 10, NM_ICMPV6_ROUTER_PREF_MEDIUM);
-		g_assert_cmpint (rdata->addresses_n, ==, 1);
-		match_address (rdata, 0, "2001:db8:a:b::1", data->timestamp1, 10, 10);
+		g_assert_cmpint (rdata->addresses_n, ==, 2);
+		match_address (rdata, 0, "2001:db8:a:a::1", data->timestamp1, 10, 0);
+		match_address (rdata, 1, "2001:db8:a:b::1", data->timestamp1, 10, 10);
 		g_assert_cmpint (rdata->routes_n, ==, 1);
 		match_route (rdata, 0, "2001:db8:a:b::", 64, "fe80::2", data->timestamp1, 10, 10);
 		g_assert_cmpint (rdata->dns_servers_n, ==, 1);