summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2018-10-11 14:51:08 +0200
committerThomas Haller <thaller@redhat.com>2018-10-11 14:51:08 +0200
commit6e41d7906737ee79b10cf7c94036e1e080e8cab3 (patch)
tree7ee371a5316a663bef39b4156fc4f45a7282edff
parent8de09bb11993ecce403d71e7bd0c444011dd555b (diff)
parent98ec56c6704aa45b438e7c70ad8860a3c0dc5b70 (diff)
downloadNetworkManager-6e41d7906737ee79b10cf7c94036e1e080e8cab3.tar.gz
ndisc: merge branch 'th/ndisc-fixes'
https://github.com/NetworkManager/NetworkManager/pull/219
-rw-r--r--src/ndisc/nm-lndp-ndisc.c8
-rw-r--r--src/ndisc/nm-ndisc.c170
2 files changed, 99 insertions, 79 deletions
diff --git a/src/ndisc/nm-lndp-ndisc.c b/src/ndisc/nm-lndp-ndisc.c
index c0a0cd4096..8bb1812764 100644
--- a/src/ndisc/nm-lndp-ndisc.c
+++ b/src/ndisc/nm-lndp-ndisc.c
@@ -491,13 +491,17 @@ receive_rs (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
static gboolean
event_ready (GIOChannel *source, GIOCondition condition, NMNDisc *ndisc)
{
+ gs_unref_object NMNDisc *ndisc_keep_alive = g_object_ref (ndisc);
nm_auto_pop_netns NMPNetns *netns = NULL;
NMLndpNDiscPrivate *priv = NM_LNDP_NDISC_GET_PRIVATE ((NMLndpNDisc *) ndisc);
_LOGD ("processing libndp events");
- if (!nm_ndisc_netns_push (ndisc, &netns))
- return G_SOURCE_CONTINUE;
+ if (!nm_ndisc_netns_push (ndisc, &netns)) {
+ /* something is very wrong. Stop handling events. */
+ priv->event_id = 0;
+ return G_SOURCE_REMOVE;
+ }
ndp_callall_eventfd_handler (priv->ndp);
return G_SOURCE_CONTINUE;
diff --git a/src/ndisc/nm-ndisc.c b/src/ndisc/nm-ndisc.c
index 879eec67fe..a6b4453891 100644
--- a/src/ndisc/nm-ndisc.c
+++ b/src/ndisc/nm-ndisc.c
@@ -124,6 +124,66 @@ _preference_to_priority (NMIcmpv6RouterPref pref)
/*****************************************************************************/
+static gint32
+get_expiry_time (guint32 timestamp, guint32 lifetime)
+{
+ gint64 t;
+
+ /* timestamp is supposed to come from nm_utils_get_monotonic_timestamp_s().
+ * It is expected to be within a certain range. */
+ nm_assert (timestamp > 0);
+ nm_assert (timestamp <= G_MAXINT32);
+
+ if (lifetime == NM_NDISC_INFINITY)
+ return G_MAXINT32;
+
+ t = (gint64) timestamp + (gint64) lifetime;
+ return CLAMP (t, 0, G_MAXINT32 - 1);
+}
+
+#define get_expiry(item) \
+ ({ \
+ typeof (item) _item = (item); \
+ nm_assert (_item); \
+ get_expiry_time ((_item->timestamp), (_item->lifetime)); \
+ })
+
+#define get_expiry_half(item) \
+ ({ \
+ typeof (item) _item = (item); \
+ nm_assert (_item); \
+ get_expiry_time ((_item->timestamp),\
+ (_item->lifetime) == NM_NDISC_INFINITY \
+ ? NM_NDISC_INFINITY \
+ : (_item->lifetime) / 2); \
+ })
+
+#define get_expiry_preferred(item) \
+ ({ \
+ typeof (item) _item = (item); \
+ nm_assert (_item); \
+ get_expiry_time ((_item->timestamp), (_item->preferred)); \
+ })
+
+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)))
+
+/*****************************************************************************/
+
NMPNetns *
nm_ndisc_netns_get (NMNDisc *self)
{
@@ -264,9 +324,12 @@ nm_ndisc_add_gateway (NMNDisc *ndisc, const NMNDiscGateway *new)
continue;
}
+ if (get_expiry (item) == get_expiry (new))
+ return FALSE;
+
*item = *new;
_ASSERT_data_gateways (rdata);
- return FALSE;
+ return TRUE;
}
/* Put before less preferable gateways. */
@@ -358,17 +421,18 @@ nm_ndisc_add_address (NMNDisc *ndisc, const NMNDiscAddress *new)
NMNDiscAddress *item = &g_array_index (rdata->addresses, NMNDiscAddress, i);
if (IN6_ARE_ADDR_EQUAL (&item->address, &new->address)) {
- gboolean changed;
-
if (new->lifetime == 0) {
g_array_remove_index (rdata->addresses, i);
return TRUE;
}
- changed = item->timestamp + item->lifetime != new->timestamp + new->lifetime ||
- item->timestamp + item->preferred != new->timestamp + new->preferred;
+ if ( item->dad_counter == new->dad_counter
+ && get_expiry (item) == get_expiry (new)
+ && get_expiry_preferred (item) == get_expiry_preferred (new))
+ return FALSE;
+
*item = *new;
- return changed;
+ return TRUE;
}
}
@@ -419,7 +483,8 @@ nm_ndisc_add_route (NMNDisc *ndisc, const NMNDiscRoute *new)
for (i = 0; i < rdata->routes->len; ) {
NMNDiscRoute *item = &g_array_index (rdata->routes, NMNDiscRoute, i);
- if (IN6_ARE_ADDR_EQUAL (&item->network, &new->network) && item->plen == new->plen) {
+ if ( IN6_ARE_ADDR_EQUAL (&item->network, &new->network)
+ && item->plen == new->plen) {
if (new->lifetime == 0) {
g_array_remove_index (rdata->routes, i);
return TRUE;
@@ -430,8 +495,12 @@ nm_ndisc_add_route (NMNDisc *ndisc, const NMNDiscRoute *new)
continue;
}
- memcpy (item, new, sizeof (*new));
- return FALSE;
+ if ( get_expiry (item) == get_expiry (new)
+ && IN6_ARE_ADDR_EQUAL (&item->gateway, &new->gateway))
+ return FALSE;
+
+ *item = *new;
+ return TRUE;
}
/* Put before less preferable routes. */
@@ -470,11 +539,12 @@ nm_ndisc_add_dns_server (NMNDisc *ndisc, const NMNDiscDNSServer *new)
g_array_remove_index (rdata->dns_servers, i);
return TRUE;
}
- if (item->timestamp != new->timestamp || item->lifetime != new->lifetime) {
- *item = *new;
- return TRUE;
- }
- return FALSE;
+
+ if (get_expiry (item) == get_expiry (new))
+ return FALSE;
+
+ *item = *new;
+ return TRUE;
}
}
@@ -499,20 +569,17 @@ nm_ndisc_add_dns_domain (NMNDisc *ndisc, const NMNDiscDNSDomain *new)
item = &g_array_index (rdata->dns_domains, NMNDiscDNSDomain, i);
if (!g_strcmp0 (item->domain, new->domain)) {
- gboolean changed;
-
if (new->lifetime == 0) {
g_array_remove_index (rdata->dns_domains, i);
return TRUE;
}
- changed = (item->timestamp != new->timestamp ||
- item->lifetime != new->lifetime);
- if (changed) {
- item->timestamp = new->timestamp;
- item->lifetime = new->lifetime;
- }
- return changed;
+ if (get_expiry (item) == get_expiry (new))
+ return FALSE;
+
+ item->timestamp = new->timestamp;
+ item->lifetime = new->lifetime;
+ return TRUE;
}
}
@@ -860,57 +927,6 @@ dhcp_level_to_string (NMNDiscDHCPLevel dhcp_level)
}
}
-static gint32
-get_expiry_time (guint32 timestamp, guint32 lifetime)
-{
- gint64 t;
-
- /* timestamp is supposed to come from nm_utils_get_monotonic_timestamp_s().
- * It is expected to be within a certain range. */
- nm_assert (timestamp > 0);
- nm_assert (timestamp <= G_MAXINT32);
-
- if (lifetime == NM_NDISC_INFINITY)
- return G_MAXINT32;
-
- t = (gint64) timestamp + (gint64) lifetime;
- return CLAMP (t, 0, G_MAXINT32 - 1);
-}
-
-#define get_expiry(item) \
- ({ \
- typeof (item) _item = (item); \
- nm_assert (_item); \
- get_expiry_time ((_item->timestamp), (_item->lifetime)); \
- })
-
-#define get_expiry_half(item) \
- ({ \
- typeof (item) _item = (item); \
- nm_assert (_item); \
- get_expiry_time ((_item->timestamp),\
- (_item->lifetime) == NM_NDISC_INFINITY \
- ? NM_NDISC_INFINITY \
- : (_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)
{
@@ -1132,9 +1148,6 @@ check_timestamps (NMNDisc *ndisc, gint32 now, NMNDiscConfigMap changed)
clean_dns_servers (ndisc, now, &changed, &nextevent);
clean_dns_domains (ndisc, now, &changed, &nextevent);
- if (changed)
- nm_ndisc_emit_config_change (ndisc, changed);
-
if (nextevent != G_MAXINT32) {
if (nextevent <= now)
g_return_if_reached ();
@@ -1142,6 +1155,9 @@ check_timestamps (NMNDisc *ndisc, gint32 now, NMNDiscConfigMap changed)
(int) (nextevent - now));
priv->timeout_id = g_timeout_add_seconds (nextevent - now, timeout_cb, ndisc);
}
+
+ if (changed)
+ nm_ndisc_emit_config_change (ndisc, changed);
}
static gboolean