summary refs log tree commit diff
path: root/src/ndisc
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2018-04-23 18:00:21 +0200
committerMichael Biebl <biebl@debian.org>2018-04-23 18:00:21 +0200
commitf60117b41d5433be1b4a96d82cd11d0c3dce9b63 (patch)
tree2dd55c4ab0fdcbe9cddb26adb4a554b1a45c73c8 /src/ndisc
parent7e9ff09fcb2366b383b7ebbec80d2f6fff117290 (diff)
New upstream version 1.11.3 upstream/1.11.3
Diffstat (limited to 'src/ndisc')
-rw-r--r--src/ndisc/nm-lndp-ndisc.c52
-rw-r--r--src/ndisc/nm-ndisc.c55
-rw-r--r--src/ndisc/nm-ndisc.h33
-rw-r--r--src/ndisc/tests/meson.build23
4 files changed, 125 insertions, 38 deletions
diff --git a/src/ndisc/nm-lndp-ndisc.c b/src/ndisc/nm-lndp-ndisc.c
index 70200ed3..c0a0cd40 100644
--- a/src/ndisc/nm-lndp-ndisc.c
+++ b/src/ndisc/nm-lndp-ndisc.c
@@ -173,10 +173,10 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
 	 */
 	{
 		const NMNDiscGateway gateway = {
-		    .address = gateway_addr,
-		    .timestamp = now,
-		    .lifetime = ndp_msgra_router_lifetime (msgra),
-		    .preference = _route_preference_coerce (ndp_msgra_route_preference (msgra)),
+			.address = gateway_addr,
+			.timestamp = now,
+			.lifetime = ndp_msgra_router_lifetime (msgra),
+			.preference = _route_preference_coerce (ndp_msgra_route_preference (msgra)),
 		};
 
 		if (nm_ndisc_add_gateway (ndisc, &gateway))
@@ -195,12 +195,16 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
 			continue;
 		nm_utils_ip6_address_clear_host_address (&r_network, ndp_msg_opt_prefix (msg, offset), r_plen);
 
+		if (   IN6_IS_ADDR_UNSPECIFIED (&r_network)
+		    || IN6_IS_ADDR_LINKLOCAL (&r_network))
+			continue;
+
 		if (ndp_msg_opt_prefix_flag_on_link (msg, offset)) {
-			NMNDiscRoute route = {
-			    .network = r_network,
-			    .plen = r_plen,
-			    .timestamp = now,
-			    .lifetime = ndp_msg_opt_prefix_valid_time (msg, offset),
+			const NMNDiscRoute route = {
+				.network = r_network,
+				.plen = r_plen,
+				.timestamp = now,
+				.lifetime = ndp_msg_opt_prefix_valid_time (msg, offset),
 			};
 
 			if (nm_ndisc_add_route (ndisc, &route))
@@ -211,10 +215,10 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
 		if (   r_plen == 64
 		    && ndp_msg_opt_prefix_flag_auto_addr_conf (msg, offset)) {
 			NMNDiscAddress address = {
-			    .address = r_network,
-			    .timestamp = now,
-			    .lifetime = ndp_msg_opt_prefix_valid_time (msg, offset),
-			    .preferred = ndp_msg_opt_prefix_preferred_time (msg, offset),
+				.address = r_network,
+				.timestamp = now,
+				.lifetime = ndp_msg_opt_prefix_valid_time (msg, offset),
+				.preferred = ndp_msg_opt_prefix_preferred_time (msg, offset),
 			};
 
 			if (address.preferred > address.lifetime)
@@ -225,11 +229,11 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
 	}
 	ndp_msg_opt_for_each_offset(offset, msg, NDP_MSG_OPT_ROUTE) {
 		NMNDiscRoute route = {
-		    .gateway = gateway_addr,
-		    .plen = ndp_msg_opt_route_prefix_len (msg, offset),
-		    .timestamp = now,
-		    .lifetime = ndp_msg_opt_route_lifetime (msg, offset),
-		    .preference = _route_preference_coerce (ndp_msg_opt_route_preference (msg, offset)),
+			.gateway = gateway_addr,
+			.plen = ndp_msg_opt_route_prefix_len (msg, offset),
+			.timestamp = now,
+			.lifetime = ndp_msg_opt_route_lifetime (msg, offset),
+			.preference = _route_preference_coerce (ndp_msg_opt_route_preference (msg, offset)),
 		};
 
 		if (route.plen == 0 || route.plen > 128)
@@ -248,9 +252,9 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
 
 		ndp_msg_opt_rdnss_for_each_addr (addr, addr_index, msg, offset) {
 			NMNDiscDNSServer dns_server = {
-			    .address = *addr,
-			    .timestamp = now,
-			    .lifetime = ndp_msg_opt_rdnss_lifetime (msg, offset),
+				.address = *addr,
+				.timestamp = now,
+				.lifetime = ndp_msg_opt_rdnss_lifetime (msg, offset),
 			};
 
 			/* Pad the lifetime somewhat to give a bit of slack in cases
@@ -270,9 +274,9 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
 
 		ndp_msg_opt_dnssl_for_each_domain (domain, domain_index, msg, offset) {
 			NMNDiscDNSDomain dns_domain = {
-			    .domain = domain,
-			    .timestamp = now,
-			    .lifetime = ndp_msg_opt_rdnss_lifetime (msg, offset),
+				.domain = domain,
+				.timestamp = now,
+				.lifetime = ndp_msg_opt_rdnss_lifetime (msg, offset),
 			};
 
 			/* Pad the lifetime somewhat to give a bit of slack in cases
diff --git a/src/ndisc/nm-ndisc.c b/src/ndisc/nm-ndisc.c
index 6b44a96c..ba61cb11 100644
--- a/src/ndisc/nm-ndisc.c
+++ b/src/ndisc/nm-ndisc.c
@@ -89,7 +89,7 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE (
 );
 
 enum {
-	CONFIG_CHANGED,
+	CONFIG_RECEIVED,
 	RA_TIMEOUT,
 	LAST_SIGNAL
 };
@@ -235,7 +235,7 @@ static void
 _emit_config_change (NMNDisc *self, NMNDiscConfigMap changed)
 {
 	_config_changed_log (self, changed);
-	g_signal_emit (self, signals[CONFIG_CHANGED], 0,
+	g_signal_emit (self, signals[CONFIG_RECEIVED], 0,
 	               _data_complete (&NM_NDISC_GET_PRIVATE (self)->rdata),
 	               (guint) changed);
 }
@@ -349,6 +349,11 @@ nm_ndisc_add_address (NMNDisc *ndisc, const NMNDiscAddress *new)
 	NMNDiscDataInternal *rdata = &priv->rdata;
 	guint i;
 
+	nm_assert (new);
+	nm_assert (new->timestamp > 0 && new->timestamp < G_MAXINT32);
+	nm_assert (!IN6_IS_ADDR_UNSPECIFIED (&new->address));
+	nm_assert (!IN6_IS_ADDR_LINKLOCAL (&new->address));
+
 	for (i = 0; i < rdata->addresses->len; i++) {
 		NMNDiscAddress *item = &g_array_index (rdata->addresses, NMNDiscAddress, i);
 
@@ -792,7 +797,7 @@ nm_ndisc_start (NMNDisc *ndisc)
 }
 
 void
-nm_ndisc_dad_failed (NMNDisc *ndisc, struct in6_addr *address)
+nm_ndisc_dad_failed (NMNDisc *ndisc, const struct in6_addr *address)
 {
 	NMNDiscDataInternal *rdata;
 	guint i;
@@ -887,6 +892,23 @@ get_expiry_time (guint32 timestamp, guint32 lifetime)
 		                   : (_item->lifetime) / 2); \
 	})
 
+static const char *
+_get_exp (char *buf, gsize buf_size, gint64 now_ns, gint32 expiry_time)
+{
+	int l;
+
+	if (expiry_time == G_MAXINT32)
+		return "permanent";
+	l = g_snprintf (buf, buf_size,
+	                "%.4f",
+	                ((double) ((expiry_time * NM_UTILS_NS_PER_SECOND) - now_ns)) / ((double) NM_UTILS_NS_PER_SECOND));
+	nm_assert (l < buf_size);
+	return buf;
+}
+
+#define get_exp(buf, now_ns, item) \
+	_get_exp ((buf), G_N_ELEMENTS (buf), (now_ns), (get_expiry (item)))
+
 static void
 _config_changed_log (NMNDisc *ndisc, NMNDiscConfigMap changed)
 {
@@ -896,10 +918,14 @@ _config_changed_log (NMNDisc *ndisc, NMNDiscConfigMap changed)
 	char changedstr[CONFIG_MAP_MAX_STR];
 	char addrstr[INET6_ADDRSTRLEN];
 	char str_pref[35];
+	char str_exp[100];
+	gint64 now_ns;
 
 	if (!_LOGD_ENABLED ())
 		return;
 
+	now_ns = nm_utils_get_monotonic_timestamp_ns ();
+
 	priv = NM_NDISC_GET_PRIVATE (ndisc);
 	rdata = &priv->rdata;
 
@@ -910,35 +936,38 @@ _config_changed_log (NMNDisc *ndisc, NMNDiscConfigMap changed)
 		NMNDiscGateway *gateway = &g_array_index (rdata->gateways, NMNDiscGateway, i);
 
 		inet_ntop (AF_INET6, &gateway->address, addrstr, sizeof (addrstr));
-		_LOGD ("  gateway %s pref %s exp %d", addrstr,
+		_LOGD ("  gateway %s pref %s exp %s", addrstr,
 		       nm_icmpv6_router_pref_to_string (gateway->preference, str_pref, sizeof (str_pref)),
-		       get_expiry (gateway));
+		       get_exp (str_exp, now_ns, gateway));
 	}
 	for (i = 0; i < rdata->addresses->len; i++) {
-		NMNDiscAddress *address = &g_array_index (rdata->addresses, NMNDiscAddress, i);
+		const NMNDiscAddress *address = &g_array_index (rdata->addresses, NMNDiscAddress, i);
 
 		inet_ntop (AF_INET6, &address->address, addrstr, sizeof (addrstr));
-		_LOGD ("  address %s exp %d", addrstr, get_expiry (address));
+		_LOGD ("  address %s exp %s", addrstr,
+		       get_exp (str_exp, now_ns, address));
 	}
 	for (i = 0; i < rdata->routes->len; i++) {
 		NMNDiscRoute *route = &g_array_index (rdata->routes, NMNDiscRoute, i);
 
 		inet_ntop (AF_INET6, &route->network, addrstr, sizeof (addrstr));
-		_LOGD ("  route %s/%u via %s pref %s exp %d", addrstr, (guint) route->plen,
+		_LOGD ("  route %s/%u via %s pref %s exp %s", addrstr, (guint) route->plen,
 		       nm_utils_inet6_ntop (&route->gateway, NULL),
 		       nm_icmpv6_router_pref_to_string (route->preference, str_pref, sizeof (str_pref)),
-		       get_expiry (route));
+		       get_exp (str_exp, now_ns, route));
 	}
 	for (i = 0; i < rdata->dns_servers->len; i++) {
 		NMNDiscDNSServer *dns_server = &g_array_index (rdata->dns_servers, NMNDiscDNSServer, i);
 
 		inet_ntop (AF_INET6, &dns_server->address, addrstr, sizeof (addrstr));
-		_LOGD ("  dns_server %s exp %d", addrstr, get_expiry (dns_server));
+		_LOGD ("  dns_server %s exp %s", addrstr,
+		       get_exp (str_exp, now_ns, dns_server));
 	}
 	for (i = 0; i < rdata->dns_domains->len; i++) {
 		NMNDiscDNSDomain *dns_domain = &g_array_index (rdata->dns_domains, NMNDiscDNSDomain, i);
 
-		_LOGD ("  dns_domain %s exp %d", dns_domain->domain, get_expiry (dns_domain));
+		_LOGD ("  dns_domain %s exp %s", dns_domain->domain,
+		       get_exp (str_exp, now_ns, dns_domain));
 	}
 }
 
@@ -979,7 +1008,7 @@ clean_addresses (NMNDisc *ndisc, gint32 now, NMNDiscConfigMap *changed, gint32 *
 	rdata = &NM_NDISC_GET_PRIVATE (ndisc)->rdata;
 
 	for (i = 0; i < rdata->addresses->len; ) {
-		NMNDiscAddress *item = &g_array_index (rdata->addresses, NMNDiscAddress, i);
+		const NMNDiscAddress *item = &g_array_index (rdata->addresses, NMNDiscAddress, i);
 
 		if (item->lifetime != NM_NDISC_INFINITY) {
 			gint32 expiry = get_expiry (item);
@@ -1354,7 +1383,7 @@ nm_ndisc_class_init (NMNDiscClass *klass)
 	                      G_PARAM_STATIC_STRINGS);
 	g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
 
-	signals[CONFIG_CHANGED] =
+	signals[CONFIG_RECEIVED] =
 	    g_signal_new (NM_NDISC_CONFIG_RECEIVED,
 	                  G_OBJECT_CLASS_TYPE (klass),
 	                  G_SIGNAL_RUN_FIRST,
diff --git a/src/ndisc/nm-ndisc.h b/src/ndisc/nm-ndisc.h
index b66c2289..9a8a27d7 100644
--- a/src/ndisc/nm-ndisc.h
+++ b/src/ndisc/nm-ndisc.h
@@ -27,6 +27,9 @@
 #include "nm-setting-ip6-config.h"
 #include "NetworkManagerUtils.h"
 
+#include "platform/nm-platform.h"
+#include "platform/nmp-object.h"
+
 #define NM_TYPE_NDISC            (nm_ndisc_get_type ())
 #define NM_NDISC(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_NDISC, NMNDisc))
 #define NM_NDISC_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_NDISC, NMNDiscClass))
@@ -174,7 +177,7 @@ NMNDiscNodeType nm_ndisc_get_node_type (NMNDisc *self);
 
 gboolean nm_ndisc_set_iid (NMNDisc *ndisc, const NMUtilsIPv6IfaceId iid);
 void nm_ndisc_start (NMNDisc *ndisc);
-void nm_ndisc_dad_failed (NMNDisc *ndisc, struct in6_addr *address);
+void nm_ndisc_dad_failed (NMNDisc *ndisc, const struct in6_addr *address);
 void nm_ndisc_set_config (NMNDisc *ndisc,
                           const GArray *addresses,
                           const GArray *dns_servers,
@@ -184,4 +187,32 @@ NMPlatform *nm_ndisc_get_platform (NMNDisc *self);
 NMPNetns *nm_ndisc_netns_get (NMNDisc *self);
 gboolean nm_ndisc_netns_push (NMNDisc *self, NMPNetns **netns);
 
+static inline gboolean
+nm_ndisc_dad_addr_is_fail_candidate_event (NMPlatformSignalChangeType change_type,
+                                           const NMPlatformIP6Address *addr)
+{
+	return    !NM_FLAGS_HAS (addr->n_ifa_flags, IFA_F_TEMPORARY)
+	       && (   (change_type == NM_PLATFORM_SIGNAL_CHANGED && addr->n_ifa_flags & IFA_F_DADFAILED)
+	           || (change_type == NM_PLATFORM_SIGNAL_REMOVED && addr->n_ifa_flags & IFA_F_TENTATIVE));
+}
+
+static inline gboolean
+nm_ndisc_dad_addr_is_fail_candidate (NMPlatform *platform,
+                                     const NMPObject *obj)
+{
+	const NMPlatformIP6Address *addr;
+
+	addr = NMP_OBJECT_CAST_IP6_ADDRESS (nm_platform_lookup_obj (platform,
+	                                                            NMP_CACHE_ID_TYPE_OBJECT_TYPE,
+	                                                            obj));
+	if (   addr
+	    && (   NM_FLAGS_HAS (addr->n_ifa_flags, IFA_F_TEMPORARY)
+	        || !NM_FLAGS_HAS (addr->n_ifa_flags, IFA_F_DADFAILED))) {
+		/* the address still/again exists and is not in DADFAILED state. Skip it. */
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
 #endif /* __NETWORKMANAGER_NDISC_H__ */
diff --git a/src/ndisc/tests/meson.build b/src/ndisc/tests/meson.build
new file mode 100644
index 00000000..2f479c2d
--- /dev/null
+++ b/src/ndisc/tests/meson.build
@@ -0,0 +1,23 @@
+test_unit = 'test-ndisc-fake'
+
+exe = executable(
+  test_unit,
+  test_unit + '.c',
+  dependencies: test_nm_dep,
+  c_args: test_cflags_platform
+)
+
+test(
+  'ndisc/' + test_unit,
+  test_script,
+  args: test_args + [exe.full_path()]
+)
+
+test = 'test-ndisc-linux'
+
+exe = executable(
+  test,
+  test + '.c',
+  dependencies: test_nm_dep,
+  c_args: test_cflags_platform
+)