diff options
author | Thomas Haller <thaller@redhat.com> | 2020-09-15 15:36:19 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2020-09-15 15:36:19 +0200 |
commit | 6ce482c526e0550c9bafdee8fcb5e6fa3c4e39e5 (patch) | |
tree | 58bfaa556620eec8f951e00bbfa1f12cc2515ed8 | |
parent | e8eaaa78d1dc777bcaf11e20cc93d3509d9aa0b7 (diff) | |
download | NetworkManager-6ce482c526e0550c9bafdee8fcb5e6fa3c4e39e5.tar.gz |
device/ndisc: add nm_ndisc_stop() method
It is bad style to rely on the last unref of an object for stopping
the operation. With a ref-counted object you should never rely on
anybody else still having (or not having) a reference. Hence, you
should not rely on stopping the ND during the last unref.
Add an explicit nm_ndisc_stop() function.
-rw-r--r-- | src/ndisc/nm-fake-ndisc.c | 11 | ||||
-rw-r--r-- | src/ndisc/nm-lndp-ndisc.c | 55 | ||||
-rw-r--r-- | src/ndisc/nm-ndisc.c | 47 | ||||
-rw-r--r-- | src/ndisc/nm-ndisc.h | 2 |
4 files changed, 94 insertions, 21 deletions
diff --git a/src/ndisc/nm-fake-ndisc.c b/src/ndisc/nm-fake-ndisc.c index 5e5adfb844..14ef18d58b 100644 --- a/src/ndisc/nm-fake-ndisc.c +++ b/src/ndisc/nm-fake-ndisc.c @@ -337,6 +337,14 @@ start (NMNDisc *ndisc) priv->receive_ra_id = g_timeout_add_seconds (ra->when, receive_ra, ndisc); } +static void +stop (NMNDisc *ndisc) +{ + NMFakeNDiscPrivate *priv = NM_FAKE_NDISC_GET_PRIVATE (ndisc); + + nm_clear_g_source (&priv->receive_ra_id); +} + void nm_fake_ndisc_emit_new_ras (NMFakeNDisc *self) { @@ -388,7 +396,8 @@ nm_fake_ndisc_class_init (NMFakeNDiscClass *klass) object_class->dispose = dispose; - ndisc_class->start = start; + ndisc_class->start = start; + ndisc_class->stop = stop; ndisc_class->send_rs = send_rs; signals[RS_SENT] = diff --git a/src/ndisc/nm-lndp-ndisc.c b/src/ndisc/nm-lndp-ndisc.c index 0d78a5356b..654d9693ae 100644 --- a/src/ndisc/nm-lndp-ndisc.c +++ b/src/ndisc/nm-lndp-ndisc.c @@ -535,6 +535,36 @@ start (NMNDisc *ndisc) } } +static void +_cleanup (NMNDisc *ndisc) +{ + NMLndpNDiscPrivate *priv = NM_LNDP_NDISC_GET_PRIVATE (ndisc); + + nm_clear_g_source_inst (&priv->event_source); + + if (priv->ndp) { + switch (nm_ndisc_get_node_type (ndisc)) { + case NM_NDISC_NODE_TYPE_HOST: + ndp_msgrcv_handler_unregister (priv->ndp, receive_ra, NDP_MSG_RA, nm_ndisc_get_ifindex (ndisc), ndisc); + break; + case NM_NDISC_NODE_TYPE_ROUTER: + ndp_msgrcv_handler_unregister (priv->ndp, receive_rs, NDP_MSG_RS, nm_ndisc_get_ifindex (ndisc), ndisc); + break; + default: + nm_assert_not_reached (); + break; + } + ndp_close (priv->ndp); + priv->ndp = NULL; + } +} + +static void +stop (NMNDisc *ndisc) +{ + _cleanup (ndisc); +} + /*****************************************************************************/ static int @@ -659,24 +689,8 @@ static void dispose (GObject *object) { NMNDisc *ndisc = NM_NDISC (object); - NMLndpNDiscPrivate *priv = NM_LNDP_NDISC_GET_PRIVATE (ndisc); - nm_clear_g_source_inst (&priv->event_source); - - if (priv->ndp) { - switch (nm_ndisc_get_node_type (ndisc)) { - case NM_NDISC_NODE_TYPE_HOST: - ndp_msgrcv_handler_unregister (priv->ndp, receive_ra, NDP_MSG_RA, nm_ndisc_get_ifindex (ndisc), ndisc); - break; - case NM_NDISC_NODE_TYPE_ROUTER: - ndp_msgrcv_handler_unregister (priv->ndp, receive_rs, NDP_MSG_RS, nm_ndisc_get_ifindex (ndisc), ndisc); - break; - default: - g_assert_not_reached (); - } - ndp_close (priv->ndp); - priv->ndp = NULL; - } + _cleanup (ndisc); G_OBJECT_CLASS (nm_lndp_ndisc_parent_class)->dispose (object); } @@ -688,7 +702,8 @@ nm_lndp_ndisc_class_init (NMLndpNDiscClass *klass) NMNDiscClass *ndisc_class = NM_NDISC_CLASS (klass); object_class->dispose = dispose; - ndisc_class->start = start; - ndisc_class->send_rs = send_rs; - ndisc_class->send_ra = send_ra; + ndisc_class->start = start; + ndisc_class->stop = stop; + ndisc_class->send_rs = send_rs; + ndisc_class->send_ra = send_ra; } diff --git a/src/ndisc/nm-ndisc.c b/src/ndisc/nm-ndisc.c index 9b2002905c..e01bd42e3d 100644 --- a/src/ndisc/nm-ndisc.c +++ b/src/ndisc/nm-ndisc.c @@ -960,6 +960,53 @@ nm_ndisc_start (NMNDisc *ndisc) announce_router_initial (ndisc); } +void +nm_ndisc_stop (NMNDisc *ndisc) +{ + nm_auto_pop_netns NMPNetns *netns = NULL; + NMNDiscDataInternal *rdata; + NMNDiscPrivate *priv; + + g_return_if_fail (NM_IS_NDISC (ndisc)); + + priv = NM_NDISC_GET_PRIVATE (ndisc); + + nm_assert (NM_NDISC_GET_CLASS (ndisc)->stop); + + _LOGD ("stopping neighbor discovery for ifindex %d", + priv->ifindex); + + if (!nm_ndisc_netns_push (ndisc, &netns)) + return; + + NM_NDISC_GET_CLASS (ndisc)->stop (ndisc); + + rdata = &priv->rdata; + + g_array_set_size (rdata->gateways, 0); + g_array_set_size (rdata->addresses, 0); + g_array_set_size (rdata->routes, 0); + g_array_set_size (rdata->dns_servers, 0); + g_array_set_size (rdata->dns_domains, 0); + priv->rdata.public.hop_limit = 64; + + /* Start at very low number so that last_rs - router_solicitation_interval + * is much lower than nm_utils_get_monotonic_timestamp_sec() at startup. + */ + priv->last_rs = G_MININT32; + nm_clear_g_source_inst (&priv->ra_timeout_source); + nm_clear_g_source (&priv->send_rs_id); + nm_clear_g_source (&priv->send_ra_id); + nm_clear_g_free (&priv->last_error); + nm_clear_g_source (&priv->timeout_id); + + priv->solicitations_left = 0; + priv->announcements_left = 0; + + priv->last_rs = G_MININT32; + priv->last_ra = G_MININT32; +} + NMNDiscConfigMap nm_ndisc_dad_failed (NMNDisc *ndisc, const struct in6_addr *address, gboolean emit_changed_signal) { diff --git a/src/ndisc/nm-ndisc.h b/src/ndisc/nm-ndisc.h index 4130fd9f77..5190478cd2 100644 --- a/src/ndisc/nm-ndisc.h +++ b/src/ndisc/nm-ndisc.h @@ -163,6 +163,7 @@ typedef struct { GObjectClass parent; void (*start) (NMNDisc *ndisc); + void (*stop) (NMNDisc *ndisc); gboolean (*send_rs) (NMNDisc *ndisc, GError **error); gboolean (*send_ra) (NMNDisc *ndisc, GError **error); } NMNDiscClass; @@ -177,6 +178,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_stop (NMNDisc *ndisc); NMNDiscConfigMap nm_ndisc_dad_failed (NMNDisc *ndisc, const struct in6_addr *address, gboolean emit_changed_signal); |