mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-11 01:40:19 +01:00
rdisc: add RA wait timeout
Add an advisory timeout when waiting for router advertisements so we can fail IPv6 addressing attempts when no router advertisement has been received.
This commit is contained in:
parent
bc18992dd8
commit
7c9d4e8f5a
4 changed files with 113 additions and 32 deletions
|
|
@ -270,7 +270,8 @@ typedef struct {
|
|||
NMIP6Config * ext_ip6_config; /* Stuff added outside NM */
|
||||
|
||||
NMRDisc * rdisc;
|
||||
gulong rdisc_config_changed_sigid;
|
||||
gulong rdisc_changed_id;
|
||||
gulong rdisc_timeout_id;
|
||||
NMSettingIP6ConfigPrivacy rdisc_use_tempaddr;
|
||||
/* IP6 config from autoconf */
|
||||
NMIP6Config * ac_ip6_config;
|
||||
|
|
@ -3591,6 +3592,21 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *self)
|
|||
nm_device_activate_schedule_ip6_config_result (self);
|
||||
}
|
||||
|
||||
static void
|
||||
rdisc_ra_timeout (NMRDisc *rdisc, NMDevice *self)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
/* We don't want to stop listening for router advertisements completely,
|
||||
* but instead let device activation continue activating. If an RA
|
||||
* shows up later, we'll use it as long as the device is not disconnected.
|
||||
*/
|
||||
|
||||
_LOGD (LOGD_IP6, "timed out waiting for IPv6 router advertisement");
|
||||
if (priv->ip6_state == IP_CONF)
|
||||
nm_device_activate_schedule_ip6_config_timeout (self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
addrconf6_start_with_link_ready (NMDevice *self)
|
||||
{
|
||||
|
|
@ -3610,8 +3626,14 @@ addrconf6_start_with_link_ready (NMDevice *self)
|
|||
nm_device_ipv6_sysctl_set (self, "accept_ra_pinfo", "0");
|
||||
nm_device_ipv6_sysctl_set (self, "accept_ra_rtr_pref", "0");
|
||||
|
||||
priv->rdisc_config_changed_sigid = g_signal_connect (priv->rdisc, NM_RDISC_CONFIG_CHANGED,
|
||||
G_CALLBACK (rdisc_config_changed), self);
|
||||
priv->rdisc_changed_id = g_signal_connect (priv->rdisc,
|
||||
NM_RDISC_CONFIG_CHANGED,
|
||||
G_CALLBACK (rdisc_config_changed),
|
||||
self);
|
||||
priv->rdisc_timeout_id = g_signal_connect (priv->rdisc,
|
||||
NM_RDISC_RA_TIMEOUT,
|
||||
G_CALLBACK (rdisc_ra_timeout),
|
||||
self);
|
||||
nm_rdisc_start (priv->rdisc);
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -3662,10 +3684,14 @@ addrconf6_cleanup (NMDevice *self)
|
|||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
if (priv->rdisc_config_changed_sigid) {
|
||||
g_signal_handler_disconnect (priv->rdisc,
|
||||
priv->rdisc_config_changed_sigid);
|
||||
priv->rdisc_config_changed_sigid = 0;
|
||||
if (priv->rdisc_changed_id) {
|
||||
g_signal_handler_disconnect (priv->rdisc, priv->rdisc_changed_id);
|
||||
priv->rdisc_changed_id = 0;
|
||||
}
|
||||
|
||||
if (priv->rdisc_timeout_id) {
|
||||
g_signal_handler_disconnect (priv->rdisc, priv->rdisc_timeout_id);
|
||||
priv->rdisc_timeout_id = 0;
|
||||
}
|
||||
|
||||
nm_device_remove_pending_action (self, PENDING_ACTION_AUTOCONF6, FALSE);
|
||||
|
|
@ -4647,6 +4673,12 @@ nm_device_activate_schedule_ip6_config_result (NMDevice *self)
|
|||
|
||||
g_return_if_fail (NM_IS_DEVICE (self));
|
||||
|
||||
/* If IP had previously failed, move it back to IP_CONF since we
|
||||
* clearly now have configuration.
|
||||
*/
|
||||
if (priv->ip6_state == IP_FAIL)
|
||||
priv->ip6_state = IP_CONF;
|
||||
|
||||
activation_source_schedule (self, nm_device_activate_ip6_config_commit, AF_INET6);
|
||||
|
||||
_LOG (level, LOGD_DEVICE | LOGD_IP6,
|
||||
|
|
|
|||
|
|
@ -40,7 +40,8 @@ typedef struct {
|
|||
guint send_rs_id;
|
||||
GIOChannel *event_channel;
|
||||
guint event_id;
|
||||
guint timeout_id;
|
||||
guint timeout_id; /* prefix/dns/etc lifetime timeout */
|
||||
guint ra_timeout_id; /* first RA timeout */
|
||||
|
||||
int solicitations_left;
|
||||
} NMLNDPRDiscPrivate;
|
||||
|
|
@ -433,11 +434,32 @@ translate_preference (enum ndp_route_preference preference)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clear_rs_timeout (NMLNDPRDisc *rdisc)
|
||||
{
|
||||
NMLNDPRDiscPrivate *priv = NM_LNDP_RDISC_GET_PRIVATE (rdisc);
|
||||
|
||||
if (priv->send_rs_id) {
|
||||
g_source_remove (priv->send_rs_id);
|
||||
priv->send_rs_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clear_ra_timeout (NMLNDPRDisc *rdisc)
|
||||
{
|
||||
NMLNDPRDiscPrivate *priv = NM_LNDP_RDISC_GET_PRIVATE (rdisc);
|
||||
|
||||
if (priv->ra_timeout_id) {
|
||||
g_source_remove (priv->ra_timeout_id);
|
||||
priv->ra_timeout_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
||||
{
|
||||
NMRDisc *rdisc = (NMRDisc *) user_data;
|
||||
NMLNDPRDiscPrivate *priv = NM_LNDP_RDISC_GET_PRIVATE (rdisc);
|
||||
NMRDiscConfigMap changed = 0;
|
||||
struct ndp_msgra *msgra = ndp_msgra (msg);
|
||||
NMRDiscGateway gateway;
|
||||
|
|
@ -458,10 +480,8 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
|||
*/
|
||||
debug ("(%s): received router advertisement at %u", rdisc->ifname, now);
|
||||
|
||||
if (priv->send_rs_id) {
|
||||
g_source_remove (priv->send_rs_id);
|
||||
priv->send_rs_id = 0;
|
||||
}
|
||||
clear_ra_timeout (NM_LNDP_RDISC (rdisc));
|
||||
clear_rs_timeout (NM_LNDP_RDISC (rdisc));
|
||||
|
||||
/* DHCP level:
|
||||
*
|
||||
|
|
@ -606,21 +626,25 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
process_events (NMRDisc *rdisc)
|
||||
static gboolean
|
||||
event_ready (GIOChannel *source, GIOCondition condition, NMRDisc *rdisc)
|
||||
{
|
||||
NMLNDPRDiscPrivate *priv = NM_LNDP_RDISC_GET_PRIVATE (rdisc);
|
||||
|
||||
debug ("(%s): processing libndp events.", rdisc->ifname);
|
||||
ndp_callall_eventfd_handler (priv->ndp);
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
event_ready (GIOChannel *source, GIOCondition condition, NMRDisc *rdisc)
|
||||
rdisc_ra_timeout_cb (gpointer user_data)
|
||||
{
|
||||
process_events (rdisc);
|
||||
NMLNDPRDisc *rdisc = NM_LNDP_RDISC (user_data);
|
||||
NMLNDPRDiscPrivate *priv = NM_LNDP_RDISC_GET_PRIVATE (rdisc);
|
||||
|
||||
return TRUE;
|
||||
priv->ra_timeout_id = 0;
|
||||
g_signal_emit_by_name (rdisc, NM_RDISC_RA_TIMEOUT);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -628,14 +652,20 @@ start (NMRDisc *rdisc)
|
|||
{
|
||||
NMLNDPRDiscPrivate *priv = NM_LNDP_RDISC_GET_PRIVATE (rdisc);
|
||||
int fd = ndp_get_eventfd (priv->ndp);
|
||||
guint ra_wait_secs;
|
||||
|
||||
priv->event_channel = g_io_channel_unix_new (fd);
|
||||
priv->event_id = g_io_add_watch (priv->event_channel, G_IO_IN, (GIOFunc) event_ready, rdisc);
|
||||
|
||||
/* Flush any pending messages to avoid using obsolete information */
|
||||
process_events (rdisc);
|
||||
clear_ra_timeout (NM_LNDP_RDISC (rdisc));
|
||||
ra_wait_secs = CLAMP (rdisc->rtr_solicitations * rdisc->rtr_solicitation_interval, 30, 120);
|
||||
priv->ra_timeout_id = g_timeout_add_seconds (ra_wait_secs, rdisc_ra_timeout_cb, rdisc);
|
||||
debug ("(%s): scheduling RA timeout in %d seconds", rdisc->ifname, ra_wait_secs);
|
||||
|
||||
ndp_msgrcv_handler_register (priv->ndp, &receive_ra, NDP_MSG_RA, rdisc->ifindex, rdisc);
|
||||
/* Flush any pending messages to avoid using obsolete information */
|
||||
event_ready (priv->event_channel, 0, rdisc);
|
||||
|
||||
ndp_msgrcv_handler_register (priv->ndp, receive_ra, NDP_MSG_RA, rdisc->ifindex, rdisc);
|
||||
solicit (rdisc);
|
||||
}
|
||||
|
||||
|
|
@ -647,21 +677,29 @@ nm_lndp_rdisc_init (NMLNDPRDisc *lndp_rdisc)
|
|||
}
|
||||
|
||||
static void
|
||||
nm_lndp_rdisc_finalize (GObject *object)
|
||||
dispose (GObject *object)
|
||||
{
|
||||
NMLNDPRDiscPrivate *priv = NM_LNDP_RDISC_GET_PRIVATE (object);
|
||||
NMLNDPRDisc *rdisc = NM_LNDP_RDISC (object);
|
||||
NMLNDPRDiscPrivate *priv = NM_LNDP_RDISC_GET_PRIVATE (rdisc);
|
||||
|
||||
if (priv->send_rs_id)
|
||||
g_source_remove (priv->send_rs_id);
|
||||
if (priv->timeout_id)
|
||||
clear_rs_timeout (rdisc);
|
||||
clear_ra_timeout (rdisc);
|
||||
|
||||
if (priv->timeout_id) {
|
||||
g_source_remove (priv->timeout_id);
|
||||
if (priv->event_channel)
|
||||
g_io_channel_unref (priv->event_channel);
|
||||
if (priv->event_id)
|
||||
g_source_remove (priv->event_id);
|
||||
priv->timeout_id = 0;
|
||||
}
|
||||
|
||||
if (priv->ndp)
|
||||
if (priv->event_id) {
|
||||
g_source_remove (priv->event_id);
|
||||
priv->event_id = 0;
|
||||
}
|
||||
g_clear_pointer (&priv->event_channel, g_io_channel_unref);
|
||||
|
||||
if (priv->ndp) {
|
||||
ndp_close (priv->ndp);
|
||||
priv->ndp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -672,6 +710,6 @@ nm_lndp_rdisc_class_init (NMLNDPRDiscClass *klass)
|
|||
|
||||
g_type_class_add_private (klass, sizeof (NMLNDPRDiscPrivate));
|
||||
|
||||
object_class->finalize = nm_lndp_rdisc_finalize;
|
||||
object_class->dispose = dispose;
|
||||
rdisc_class->start = start;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ G_DEFINE_TYPE (NMRDisc, nm_rdisc, G_TYPE_OBJECT)
|
|||
|
||||
enum {
|
||||
CONFIG_CHANGED,
|
||||
RA_TIMEOUT,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
|
|
@ -184,4 +185,12 @@ nm_rdisc_class_init (NMRDiscClass *klass)
|
|||
G_STRUCT_OFFSET (NMRDiscClass, config_changed),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 1, G_TYPE_INT);
|
||||
|
||||
signals[RA_TIMEOUT] = g_signal_new (
|
||||
NM_RDISC_RA_TIMEOUT,
|
||||
G_OBJECT_CLASS_TYPE (klass),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (NMRDiscClass, ra_timeout),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#define NM_RDISC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_RDISC, NMRDiscClass))
|
||||
|
||||
#define NM_RDISC_CONFIG_CHANGED "config-changed"
|
||||
#define NM_RDISC_RA_TIMEOUT "ra-timeout"
|
||||
|
||||
typedef enum {
|
||||
NM_RDISC_DHCP_LEVEL_UNKNOWN,
|
||||
|
|
@ -131,6 +132,7 @@ typedef struct {
|
|||
|
||||
void (*start) (NMRDisc *rdisc);
|
||||
void (*config_changed) (NMRDisc *rdisc, NMRDiscConfigMap changed);
|
||||
void (*ra_timeout) (NMRDisc *rdisc);
|
||||
} NMRDiscClass;
|
||||
|
||||
GType nm_rdisc_get_type (void);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue