ip6: turn RA acceptance off when RAs shouldn't be used (rh #588163)
Make sure we don't inadvertenly let the kernel assign an RA address when connections that don't allow RA are used.
This commit is contained in:
@@ -594,3 +594,32 @@ nm_utils_do_sysctl (const char *path, const char *value)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nm_utils_get_proc_sys_net_value (const char *path,
|
||||||
|
const char *iface,
|
||||||
|
guint32 *out_value)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
char *contents = NULL;
|
||||||
|
gboolean success = FALSE;
|
||||||
|
long int tmp;
|
||||||
|
|
||||||
|
if (!g_file_get_contents (path, &contents, NULL, &error)) {
|
||||||
|
nm_log_warn (LOGD_DEVICE, "(%s): error reading %s: (%d) %s",
|
||||||
|
iface, path,
|
||||||
|
error ? error->code : -1,
|
||||||
|
error && error->message ? error->message : "(unknown)");
|
||||||
|
g_clear_error (&error);
|
||||||
|
} else {
|
||||||
|
errno = 0;
|
||||||
|
tmp = strtol (contents, NULL, 10);
|
||||||
|
if ((errno == 0) && (tmp == 0 || tmp == 1)) {
|
||||||
|
*out_value = (guint32) tmp;
|
||||||
|
success = TRUE;
|
||||||
|
}
|
||||||
|
g_free (contents);
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -73,4 +73,8 @@ void value_hash_add_bool (GHashTable *hash,
|
|||||||
|
|
||||||
gboolean nm_utils_do_sysctl (const char *path, const char *value);
|
gboolean nm_utils_do_sysctl (const char *path, const char *value);
|
||||||
|
|
||||||
|
gboolean nm_utils_get_proc_sys_net_value (const char *path,
|
||||||
|
const char *iface,
|
||||||
|
guint32 *out_value);
|
||||||
|
|
||||||
#endif /* NETWORK_MANAGER_UTILS_H */
|
#endif /* NETWORK_MANAGER_UTILS_H */
|
||||||
|
@@ -83,10 +83,6 @@ typedef struct {
|
|||||||
char *iface;
|
char *iface;
|
||||||
int ifindex;
|
int ifindex;
|
||||||
|
|
||||||
char *accept_ra_path;
|
|
||||||
gboolean accept_ra_save_valid;
|
|
||||||
guint32 accept_ra_save;
|
|
||||||
|
|
||||||
char *disable_ip6_path;
|
char *disable_ip6_path;
|
||||||
gboolean disable_ip6_save_valid;
|
gboolean disable_ip6_save_valid;
|
||||||
guint32 disable_ip6_save;
|
guint32 disable_ip6_save;
|
||||||
@@ -111,12 +107,6 @@ nm_ip6_device_destroy (NMIP6Device *device)
|
|||||||
{
|
{
|
||||||
g_return_if_fail (device != NULL);
|
g_return_if_fail (device != NULL);
|
||||||
|
|
||||||
/* reset the saved RA value */
|
|
||||||
if (device->accept_ra_save_valid) {
|
|
||||||
nm_utils_do_sysctl (device->accept_ra_path,
|
|
||||||
device->accept_ra_save ? "1\n" : "0\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* reset the saved IPv6 value */
|
/* reset the saved IPv6 value */
|
||||||
if (device->disable_ip6_save_valid) {
|
if (device->disable_ip6_save_valid) {
|
||||||
nm_utils_do_sysctl (device->disable_ip6_path,
|
nm_utils_do_sysctl (device->disable_ip6_path,
|
||||||
@@ -135,37 +125,9 @@ nm_ip6_device_destroy (NMIP6Device *device)
|
|||||||
if (device->ip6flags_poll_id)
|
if (device->ip6flags_poll_id)
|
||||||
g_source_remove (device->ip6flags_poll_id);
|
g_source_remove (device->ip6flags_poll_id);
|
||||||
|
|
||||||
g_free (device->accept_ra_path);
|
|
||||||
g_slice_free (NMIP6Device, device);
|
g_slice_free (NMIP6Device, device);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
get_proc_sys_net_value (const char *path, const char *iface, guint32 *out_value)
|
|
||||||
{
|
|
||||||
GError *error = NULL;
|
|
||||||
char *contents = NULL;
|
|
||||||
gboolean success = FALSE;
|
|
||||||
long int tmp;
|
|
||||||
|
|
||||||
if (!g_file_get_contents (path, &contents, NULL, &error)) {
|
|
||||||
nm_log_warn (LOGD_IP6, "(%s): error reading %s: (%d) %s",
|
|
||||||
iface, path,
|
|
||||||
error ? error->code : -1,
|
|
||||||
error && error->message ? error->message : "(unknown)");
|
|
||||||
g_clear_error (&error);
|
|
||||||
} else {
|
|
||||||
errno = 0;
|
|
||||||
tmp = strtol (contents, NULL, 10);
|
|
||||||
if ((errno == 0) && (tmp == 0 || tmp == 1)) {
|
|
||||||
*out_value = (guint32) tmp;
|
|
||||||
success = TRUE;
|
|
||||||
}
|
|
||||||
g_free (contents);
|
|
||||||
}
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NMIP6Device *
|
static NMIP6Device *
|
||||||
nm_ip6_device_new (NMIP6Manager *manager, int ifindex)
|
nm_ip6_device_new (NMIP6Manager *manager, int ifindex)
|
||||||
{
|
{
|
||||||
@@ -195,23 +157,13 @@ nm_ip6_device_new (NMIP6Manager *manager, int ifindex)
|
|||||||
|
|
||||||
g_hash_table_replace (priv->devices, GINT_TO_POINTER (device->ifindex), device);
|
g_hash_table_replace (priv->devices, GINT_TO_POINTER (device->ifindex), device);
|
||||||
|
|
||||||
/* Grab the original value of "accept_ra" so we can restore it when the
|
|
||||||
* device is taken down.
|
|
||||||
*/
|
|
||||||
device->accept_ra_path = g_strdup_printf ("/proc/sys/net/ipv6/conf/%s/accept_ra",
|
|
||||||
device->iface);
|
|
||||||
g_assert (device->accept_ra_path);
|
|
||||||
device->accept_ra_save_valid = get_proc_sys_net_value (device->accept_ra_path,
|
|
||||||
device->iface,
|
|
||||||
&device->accept_ra_save);
|
|
||||||
|
|
||||||
/* and the original value of IPv6 enable/disable */
|
/* and the original value of IPv6 enable/disable */
|
||||||
device->disable_ip6_path = g_strdup_printf ("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
|
device->disable_ip6_path = g_strdup_printf ("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
|
||||||
device->iface);
|
device->iface);
|
||||||
g_assert (device->disable_ip6_path);
|
g_assert (device->disable_ip6_path);
|
||||||
device->disable_ip6_save_valid = get_proc_sys_net_value (device->disable_ip6_path,
|
device->disable_ip6_save_valid = nm_utils_get_proc_sys_net_value (device->disable_ip6_path,
|
||||||
device->iface,
|
device->iface,
|
||||||
&device->disable_ip6_save);
|
&device->disable_ip6_save);
|
||||||
|
|
||||||
return device;
|
return device;
|
||||||
|
|
||||||
@@ -835,8 +787,9 @@ netlink_notification (NMNetlinkMonitor *monitor, struct nl_msg *msg, gpointer us
|
|||||||
|
|
||||||
void
|
void
|
||||||
nm_ip6_manager_prepare_interface (NMIP6Manager *manager,
|
nm_ip6_manager_prepare_interface (NMIP6Manager *manager,
|
||||||
int ifindex,
|
int ifindex,
|
||||||
NMSettingIP6Config *s_ip6)
|
NMSettingIP6Config *s_ip6,
|
||||||
|
const char *accept_ra_path)
|
||||||
{
|
{
|
||||||
NMIP6ManagerPrivate *priv;
|
NMIP6ManagerPrivate *priv;
|
||||||
NMIP6Device *device;
|
NMIP6Device *device;
|
||||||
@@ -861,10 +814,10 @@ nm_ip6_manager_prepare_interface (NMIP6Manager *manager,
|
|||||||
/* Establish target state and turn router advertisement acceptance on or off */
|
/* Establish target state and turn router advertisement acceptance on or off */
|
||||||
if (!strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)) {
|
if (!strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)) {
|
||||||
device->target_state = NM_IP6_DEVICE_GOT_LINK_LOCAL;
|
device->target_state = NM_IP6_DEVICE_GOT_LINK_LOCAL;
|
||||||
nm_utils_do_sysctl (device->accept_ra_path, "0\n");
|
nm_utils_do_sysctl (accept_ra_path, "0\n");
|
||||||
} else {
|
} else {
|
||||||
device->target_state = NM_IP6_DEVICE_GOT_ADDRESS;
|
device->target_state = NM_IP6_DEVICE_GOT_ADDRESS;
|
||||||
nm_utils_do_sysctl (device->accept_ra_path, "1\n");
|
nm_utils_do_sysctl (accept_ra_path, "1\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -73,7 +73,8 @@ GType nm_ip6_manager_get_type (void);
|
|||||||
NMIP6Manager *nm_ip6_manager_get (void);
|
NMIP6Manager *nm_ip6_manager_get (void);
|
||||||
void nm_ip6_manager_prepare_interface (NMIP6Manager *manager,
|
void nm_ip6_manager_prepare_interface (NMIP6Manager *manager,
|
||||||
int ifindex,
|
int ifindex,
|
||||||
NMSettingIP6Config *s_ip6);
|
NMSettingIP6Config *s_ip6,
|
||||||
|
const char *accept_ra_path);
|
||||||
void nm_ip6_manager_begin_addrconf (NMIP6Manager *manager,
|
void nm_ip6_manager_begin_addrconf (NMIP6Manager *manager,
|
||||||
int ifindex);
|
int ifindex);
|
||||||
void nm_ip6_manager_cancel_addrconf (NMIP6Manager *manager,
|
void nm_ip6_manager_cancel_addrconf (NMIP6Manager *manager,
|
||||||
|
@@ -135,6 +135,9 @@ typedef struct {
|
|||||||
gulong ip6_config_changed_sigid;
|
gulong ip6_config_changed_sigid;
|
||||||
gboolean ip6_waiting_for_config;
|
gboolean ip6_waiting_for_config;
|
||||||
|
|
||||||
|
char * ip6_accept_ra_path;
|
||||||
|
guint32 ip6_accept_ra_save;
|
||||||
|
|
||||||
NMDHCPClient * dhcp6_client;
|
NMDHCPClient * dhcp6_client;
|
||||||
guint32 dhcp6_mode;
|
guint32 dhcp6_mode;
|
||||||
gulong dhcp6_state_sigid;
|
gulong dhcp6_state_sigid;
|
||||||
@@ -207,6 +210,41 @@ nm_device_init (NMDevice *self)
|
|||||||
priv->rfkill_type = RFKILL_TYPE_UNKNOWN;
|
priv->rfkill_type = RFKILL_TYPE_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_accept_ra_save (NMDevice *self)
|
||||||
|
{
|
||||||
|
NMDevicePrivate *priv;
|
||||||
|
const char *ip_iface;
|
||||||
|
char *new_path;
|
||||||
|
|
||||||
|
g_return_if_fail (self != NULL);
|
||||||
|
g_return_if_fail (NM_IS_DEVICE (self));
|
||||||
|
|
||||||
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||||
|
ip_iface = nm_device_get_ip_iface (self);
|
||||||
|
|
||||||
|
new_path = g_strdup_printf ("/proc/sys/net/ipv6/conf/%s/accept_ra", ip_iface);
|
||||||
|
g_assert (new_path);
|
||||||
|
|
||||||
|
if (priv->ip6_accept_ra_path) {
|
||||||
|
/* If the IP iface is different from before, use the new value */
|
||||||
|
if (!strcmp (new_path, priv->ip6_accept_ra_path)) {
|
||||||
|
g_free (new_path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_free (priv->ip6_accept_ra_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Grab the original value of "accept_ra" so we can restore it when NM exits */
|
||||||
|
priv->ip6_accept_ra_path = new_path;
|
||||||
|
if (!nm_utils_get_proc_sys_net_value (priv->ip6_accept_ra_path,
|
||||||
|
ip_iface,
|
||||||
|
&priv->ip6_accept_ra_save)) {
|
||||||
|
g_free (priv->ip6_accept_ra_path);
|
||||||
|
priv->ip6_accept_ra_path = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static GObject*
|
static GObject*
|
||||||
constructor (GType type,
|
constructor (GType type,
|
||||||
guint n_construct_params,
|
guint n_construct_params,
|
||||||
@@ -246,6 +284,8 @@ constructor (GType type,
|
|||||||
|
|
||||||
priv->dhcp_manager = nm_dhcp_manager_get ();
|
priv->dhcp_manager = nm_dhcp_manager_get ();
|
||||||
|
|
||||||
|
update_accept_ra_save (dev);
|
||||||
|
|
||||||
priv->initialized = TRUE;
|
priv->initialized = TRUE;
|
||||||
return object;
|
return object;
|
||||||
|
|
||||||
@@ -744,7 +784,8 @@ addrconf6_setup (NMDevice *self)
|
|||||||
s_ip6 = (NMSettingIP6Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG);
|
s_ip6 = (NMSettingIP6Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG);
|
||||||
nm_ip6_manager_prepare_interface (priv->ip6_manager,
|
nm_ip6_manager_prepare_interface (priv->ip6_manager,
|
||||||
nm_device_get_ip_ifindex (self),
|
nm_device_get_ip_ifindex (self),
|
||||||
s_ip6);
|
s_ip6,
|
||||||
|
priv->ip6_accept_ra_path);
|
||||||
priv->ip6_waiting_for_config = TRUE;
|
priv->ip6_waiting_for_config = TRUE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@@ -1589,6 +1630,8 @@ real_act_stage3_ip6_config_start (NMDevice *self, NMDeviceStateReason *reason)
|
|||||||
|
|
||||||
ip_iface = nm_device_get_ip_iface (self);
|
ip_iface = nm_device_get_ip_iface (self);
|
||||||
|
|
||||||
|
update_accept_ra_save (self);
|
||||||
|
|
||||||
priv->dhcp6_mode = IP6_DHCP_OPT_NONE;
|
priv->dhcp6_mode = IP6_DHCP_OPT_NONE;
|
||||||
|
|
||||||
if ( ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_AUTO)
|
if ( ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_AUTO)
|
||||||
@@ -1600,13 +1643,21 @@ real_act_stage3_ip6_config_start (NMDevice *self, NMDeviceStateReason *reason)
|
|||||||
nm_ip6_manager_begin_addrconf (priv->ip6_manager, nm_device_get_ip_ifindex (self));
|
nm_ip6_manager_begin_addrconf (priv->ip6_manager, nm_device_get_ip_ifindex (self));
|
||||||
ret = NM_ACT_STAGE_RETURN_POSTPONE;
|
ret = NM_ACT_STAGE_RETURN_POSTPONE;
|
||||||
} else if (ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) {
|
} else if (ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) {
|
||||||
|
/* Router advertisements shouldn't be used in pure DHCP mode */
|
||||||
|
if (priv->ip6_accept_ra_path)
|
||||||
|
nm_utils_do_sysctl (priv->ip6_accept_ra_path, "0\n");
|
||||||
|
|
||||||
priv->dhcp6_mode = IP6_DHCP_OPT_MANAGED;
|
priv->dhcp6_mode = IP6_DHCP_OPT_MANAGED;
|
||||||
ret = dhcp6_start (self, connection, priv->dhcp6_mode, reason);
|
ret = dhcp6_start (self, connection, priv->dhcp6_mode, reason);
|
||||||
} else if (ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) {
|
} else if (ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) {
|
||||||
priv->ip6_ready = TRUE;
|
priv->ip6_ready = TRUE;
|
||||||
ret = NM_ACT_STAGE_RETURN_STOP;
|
ret = NM_ACT_STAGE_RETURN_STOP;
|
||||||
} else if (ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_MANUAL))
|
} else if (ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
|
||||||
|
/* Router advertisements shouldn't be used in manual mode */
|
||||||
|
if (priv->ip6_accept_ra_path)
|
||||||
|
nm_utils_do_sysctl (priv->ip6_accept_ra_path, "0\n");
|
||||||
ret = NM_ACT_STAGE_RETURN_SUCCESS;
|
ret = NM_ACT_STAGE_RETURN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/* Other methods (shared) aren't implemented yet */
|
/* Other methods (shared) aren't implemented yet */
|
||||||
|
|
||||||
@@ -2676,6 +2727,10 @@ nm_device_deactivate_quickly (NMDevice *self)
|
|||||||
dnsmasq_cleanup (self);
|
dnsmasq_cleanup (self);
|
||||||
aipd_cleanup (self);
|
aipd_cleanup (self);
|
||||||
|
|
||||||
|
/* Turn off router advertisements until they are needed */
|
||||||
|
if (priv->ip6_accept_ra_path)
|
||||||
|
nm_utils_do_sysctl (priv->ip6_accept_ra_path, "0\n");
|
||||||
|
|
||||||
/* Call device type-specific deactivation */
|
/* Call device type-specific deactivation */
|
||||||
if (NM_DEVICE_GET_CLASS (self)->deactivate_quickly)
|
if (NM_DEVICE_GET_CLASS (self)->deactivate_quickly)
|
||||||
NM_DEVICE_GET_CLASS (self)->deactivate_quickly (self);
|
NM_DEVICE_GET_CLASS (self)->deactivate_quickly (self);
|
||||||
@@ -3247,6 +3302,13 @@ dispose (GObject *object)
|
|||||||
addrconf6_cleanup (self);
|
addrconf6_cleanup (self);
|
||||||
dnsmasq_cleanup (self);
|
dnsmasq_cleanup (self);
|
||||||
|
|
||||||
|
/* reset the saved RA value */
|
||||||
|
if (priv->ip6_accept_ra_path) {
|
||||||
|
nm_utils_do_sysctl (priv->ip6_accept_ra_path,
|
||||||
|
priv->ip6_accept_ra_save ? "1\n" : "0\n");
|
||||||
|
}
|
||||||
|
g_free (priv->ip6_accept_ra_path);
|
||||||
|
|
||||||
/* Take the device itself down and clear its IPv4 configuration */
|
/* Take the device itself down and clear its IPv4 configuration */
|
||||||
if (priv->managed && take_down) {
|
if (priv->managed && take_down) {
|
||||||
NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE;
|
NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE;
|
||||||
|
Reference in New Issue
Block a user