Merge ~alfonsosanchezbeato/snappy-hwe-snaps/+git/network-manager:fix-duplicated-conns into ~snappy-hwe-team/snappy-hwe-snaps/+git/network-manager:network-manager/xenial/1.2.2

Proposed by Alfonso Sanchez-Beato
Status: Merged
Approved by: Konrad Zapałowicz
Approved revision: c13396f08566e69e785ae24b5f63bde0f534d4eb
Merged at revision: 37cdd7f22c17dcc5be259c89e5ef59222a4854a6
Proposed branch: ~alfonsosanchezbeato/snappy-hwe-snaps/+git/network-manager:fix-duplicated-conns
Merge into: ~snappy-hwe-team/snappy-hwe-snaps/+git/network-manager:network-manager/xenial/1.2.2
Diff against target: 239 lines (+103/-42)
4 files modified
src/NetworkManagerUtils.c (+80/-24)
src/nm-core-utils.c (+21/-0)
src/nm-core-utils.h (+1/-0)
src/platform/nm-linux-platform.c (+1/-18)
Reviewer Review Type Date Requested Status
Konrad Zapałowicz (community) code Approve
System Enablement Bot continuous-integration Approve
Review via email: mp+361687@code.launchpad.net

Commit message

Set of patches to prevent duplicated addresses when NM re-starts. Fixes LP: #1811347

Description of the change

Set of patches to prevent duplicated addresses when NM re-starts. Fixes LP: #1811347

To post a comment you must log in.
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Konrad Zapałowicz (kzapalowicz) :
review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c
index 09ed25c..d0e2a5c 100644
--- a/src/NetworkManagerUtils.c
+++ b/src/NetworkManagerUtils.c
@@ -341,18 +341,19 @@ static int
341route_compare (NMIPRoute *route1, NMIPRoute *route2, gint64 default_metric)341route_compare (NMIPRoute *route1, NMIPRoute *route2, gint64 default_metric)
342{342{
343 gint64 r, metric1, metric2;343 gint64 r, metric1, metric2;
344 int family;
345 guint plen;
346 NMIPAddr a1 = { 0 }, a2 = { 0 };
344347
345 r = g_strcmp0 (nm_ip_route_get_dest (route1), nm_ip_route_get_dest (route2));348 family = nm_ip_route_get_family (route1);
346 if (r)349 r = family - nm_ip_route_get_family (route2);
347 return r;
348
349 r = nm_ip_route_get_prefix (route1) - nm_ip_route_get_prefix (route2);
350 if (r)350 if (r)
351 return r > 0 ? 1 : -1;351 return r > 0 ? 1 : -1;
352352
353 r = g_strcmp0 (nm_ip_route_get_next_hop (route1), nm_ip_route_get_next_hop (route2));353 plen = nm_ip_route_get_prefix (route1);
354 r = plen - nm_ip_route_get_prefix (route2);
354 if (r)355 if (r)
355 return r;356 return r > 0 ? 1 : -1;
356357
357 metric1 = nm_ip_route_get_metric (route1) == -1 ? default_metric : nm_ip_route_get_metric (route1);358 metric1 = nm_ip_route_get_metric (route1) == -1 ? default_metric : nm_ip_route_get_metric (route1);
358 metric2 = nm_ip_route_get_metric (route2) == -1 ? default_metric : nm_ip_route_get_metric (route2);359 metric2 = nm_ip_route_get_metric (route2) == -1 ? default_metric : nm_ip_route_get_metric (route2);
@@ -361,17 +362,36 @@ route_compare (NMIPRoute *route1, NMIPRoute *route2, gint64 default_metric)
361 if (r)362 if (r)
362 return r > 0 ? 1 : -1;363 return r > 0 ? 1 : -1;
363364
364 r = nm_ip_route_get_family (route1) - nm_ip_route_get_family (route2);365 r = g_strcmp0 (nm_ip_route_get_next_hop (route1), nm_ip_route_get_next_hop (route2));
365 if (r)366 if (r)
366 return r > 0 ? 1 : -1;367 return r;
368
369 /* NMIPRoute validates family and dest. inet_pton() is not expected to fail. */
370 inet_pton (family, nm_ip_route_get_dest (route1), &a1);
371 inet_pton (family, nm_ip_route_get_dest (route2), &a2);
372 nm_utils_ipx_address_clear_host_address (family, &a1, &a1, plen);
373 nm_utils_ipx_address_clear_host_address (family, &a2, &a2, plen);
374 r = memcmp (&a1, &a2, sizeof (a1));
375 if (r)
376 return r;
367377
368 return 0;378 return 0;
369}379}
370380
371static int381static int
372route_ptr_compare (const void *a, const void *b)382route_ptr_compare (const void *a, const void *b, gpointer metric)
373{383{
374 return route_compare (*(NMIPRoute **) a, *(NMIPRoute **) b, -1);384 return route_compare (*(NMIPRoute **) a, *(NMIPRoute **) b, *((gint64 *) metric));
385}
386
387static gboolean
388route_is_v6_multicast (NMIPRoute *route)
389{
390 if (nm_ip_route_get_prefix (route) == 8 &&
391 g_strcmp0 (nm_ip_route_get_dest (route), "ff00::") == 0)
392 return TRUE;
393
394 return FALSE;
375}395}
376396
377static gboolean397static gboolean
@@ -381,11 +401,14 @@ check_ip_routes (NMConnection *orig,
381 gint64 default_metric,401 gint64 default_metric,
382 gboolean v4)402 gboolean v4)
383{403{
384 gs_free NMIPRoute **routes1 = NULL, **routes2 = NULL;404 gs_free NMIPRoute **routes1 = NULL;
405 NMIPRoute **routes2;
385 NMSettingIPConfig *s_ip1, *s_ip2;406 NMSettingIPConfig *s_ip1, *s_ip2;
407 gint64 m;
386 const char *s_name;408 const char *s_name;
387 GHashTable *props;409 GHashTable *props;
388 guint i, num;410 guint i, i1, i2, num1, num2;
411 const guint8 PLEN = v4 ? 32 : 128;
389412
390 s_name = v4 ? NM_SETTING_IP4_CONFIG_SETTING_NAME :413 s_name = v4 ? NM_SETTING_IP4_CONFIG_SETTING_NAME :
391 NM_SETTING_IP6_CONFIG_SETTING_NAME;414 NM_SETTING_IP6_CONFIG_SETTING_NAME;
@@ -402,24 +425,57 @@ check_ip_routes (NMConnection *orig,
402 if (!s_ip1 || !s_ip2)425 if (!s_ip1 || !s_ip2)
403 return FALSE;426 return FALSE;
404427
405 num = nm_setting_ip_config_get_num_routes (s_ip1);428 num1 = nm_setting_ip_config_get_num_routes (s_ip1);
406 if (num != nm_setting_ip_config_get_num_routes (s_ip2))429 num2 = nm_setting_ip_config_get_num_routes (s_ip2);
407 return FALSE;
408430
409 routes1 = g_new (NMIPRoute *, num);431 routes1 = g_new (NMIPRoute *, (gsize) num1 + num2);
410 routes2 = g_new (NMIPRoute *, num);432 routes2 = &routes1[num1];
411433
412 for (i = 0; i < num; i++) {434 for (i = 0; i < num1; i++)
413 routes1[i] = nm_setting_ip_config_get_route (s_ip1, i);435 routes1[i] = nm_setting_ip_config_get_route (s_ip1, i);
436 for (i = 0; i < num2; i++)
414 routes2[i] = nm_setting_ip_config_get_route (s_ip2, i);437 routes2[i] = nm_setting_ip_config_get_route (s_ip2, i);
415 }
416438
417 qsort (routes1, num, sizeof (NMIPRoute *), route_ptr_compare);439 m = nm_setting_ip_config_get_route_metric (s_ip2);
418 qsort (routes2, num, sizeof (NMIPRoute *), route_ptr_compare);440 if (m != -1)
441 default_metric = m;
419442
420 for (i = 0; i < num; i++) {443 g_qsort_with_data (routes1, num1, sizeof (NMIPRoute *), route_ptr_compare, &default_metric);
421 if (route_compare (routes1[i], routes2[i], default_metric))444 g_qsort_with_data (routes2, num2, sizeof (NMIPRoute *), route_ptr_compare, &default_metric);
445
446 for (i1 = 0, i2 = 0; i2 < num2; i1++) {
447 if (i1 >= num1)
422 return FALSE;448 return FALSE;
449 if (route_compare (routes1[i1], routes2[i2], default_metric) == 0) {
450 i2++;
451 continue;
452 }
453
454 /* if @orig (@routes1) contains /32 routes that are missing in @candidate,
455 * we accept that.
456 *
457 * A /32 may have been added automatically, as a direct-route to the gateway.
458 * The generated connection (@orig) would contain that route, so we shall ignore
459 * it.
460 *
461 * Likeweise for /128 for IPv6. */
462 if (nm_ip_route_get_prefix (routes1[i1]) == PLEN)
463 continue;
464 /* We also ignore IPv6 default multicast route, that sometimes happen to be there */
465 if (!v4 && route_is_v6_multicast (routes1[i1]))
466 continue;
467
468 return FALSE;
469 }
470
471 /* check that @orig has no left-over (except host routes that we ignore). */
472 for (; i1 < num1; i1++) {
473 if (nm_ip_route_get_prefix (routes1[i1]) == PLEN)
474 continue;
475 if (!v4 && route_is_v6_multicast (routes1[i1]))
476 continue;
477
478 return FALSE;
423 }479 }
424480
425 remove_from_hash (settings, props, s_name, NM_SETTING_IP_CONFIG_ROUTES);481 remove_from_hash (settings, props, s_name, NM_SETTING_IP_CONFIG_ROUTES);
diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c
index aea80da..9701e48 100644
--- a/src/nm-core-utils.c
+++ b/src/nm-core-utils.c
@@ -200,6 +200,27 @@ nm_ethernet_address_is_valid (gconstpointer addr, gssize len)
200 return TRUE;200 return TRUE;
201}201}
202202
203gconstpointer
204nm_utils_ipx_address_clear_host_address (int family, gpointer dst, gconstpointer src, guint8 plen)
205{
206 g_return_val_if_fail (src, NULL);
207 g_return_val_if_fail (dst, NULL);
208
209 switch (family) {
210 case AF_INET:
211 g_return_val_if_fail (plen <= 32, NULL);
212 *((guint32 *) dst) = nm_utils_ip4_address_clear_host_address (*((guint32 *) src), plen);
213 break;
214 case AF_INET6:
215 g_return_val_if_fail (plen <= 128, NULL);
216 nm_utils_ip6_address_clear_host_address (dst, src, plen);
217 break;
218 default:
219 g_return_val_if_reached (NULL);
220 }
221 return dst;
222}
223
203/* nm_utils_ip4_address_clear_host_address:224/* nm_utils_ip4_address_clear_host_address:
204 * @addr: source ip6 address225 * @addr: source ip6 address
205 * @plen: prefix length of network226 * @plen: prefix length of network
diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h
index a55fb66..180b9df 100644
--- a/src/nm-core-utils.h
+++ b/src/nm-core-utils.h
@@ -93,6 +93,7 @@ GETTER (void) \
9393
94gboolean nm_ethernet_address_is_valid (gconstpointer addr, gssize len);94gboolean nm_ethernet_address_is_valid (gconstpointer addr, gssize len);
9595
96gconstpointer nm_utils_ipx_address_clear_host_address (int family, gpointer dst, gconstpointer src, guint8 plen);
96in_addr_t nm_utils_ip4_address_clear_host_address (in_addr_t addr, guint8 plen);97in_addr_t nm_utils_ip4_address_clear_host_address (in_addr_t addr, guint8 plen);
97const struct in6_addr *nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_addr *src, guint8 plen);98const struct in6_addr *nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_addr *src, guint8 plen);
98gboolean nm_utils_ip6_address_same_prefix (const struct in6_addr *addr_a, const struct in6_addr *addr_b, guint8 plen);99gboolean nm_utils_ip6_address_same_prefix (const struct in6_addr *addr_a, const struct in6_addr *addr_b, guint8 plen);
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index bbc3659..eade769 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -303,23 +303,6 @@ _support_user_ipv6ll_detect (struct nlattr **tb)
303 * Various utilities303 * Various utilities
304 ******************************************************************/304 ******************************************************************/
305305
306static void
307clear_host_address (int family, const void *network, guint8 plen, void *dst)
308{
309 g_return_if_fail (network);
310
311 switch (family) {
312 case AF_INET:
313 *((in_addr_t *) dst) = nm_utils_ip4_address_clear_host_address (*((in_addr_t *) network), plen);
314 break;
315 case AF_INET6:
316 nm_utils_ip6_address_clear_host_address ((struct in6_addr *) dst, (const struct in6_addr *) network, plen);
317 break;
318 default:
319 g_assert_not_reached ();
320 }
321}
322
323static int306static int
324_vlan_qos_mapping_cmp_from (gconstpointer a, gconstpointer b, gpointer user_data)307_vlan_qos_mapping_cmp_from (gconstpointer a, gconstpointer b, gpointer user_data)
325{308{
@@ -2273,7 +2256,7 @@ _nl_msg_new_route (int nlmsg_type,
22732256
2274 addr_len = family == AF_INET ? sizeof (in_addr_t) : sizeof (struct in6_addr);2257 addr_len = family == AF_INET ? sizeof (in_addr_t) : sizeof (struct in6_addr);
22752258
2276 clear_host_address (family, network, plen, &network_clean);2259 nm_utils_ipx_address_clear_host_address (family, &network_clean, network, plen);
2277 NLA_PUT (msg, RTA_DST, addr_len, &network_clean);2260 NLA_PUT (msg, RTA_DST, addr_len, &network_clean);
22782261
2279 NLA_PUT_U32 (msg, RTA_PRIORITY, metric);2262 NLA_PUT_U32 (msg, RTA_PRIORITY, metric);

Subscribers

People subscribed via source and target branches