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;
|
||||
}
|
||||
|
||||
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_get_proc_sys_net_value (const char *path,
|
||||
const char *iface,
|
||||
guint32 *out_value);
|
||||
|
||||
#endif /* NETWORK_MANAGER_UTILS_H */
|
||||
|
@@ -83,10 +83,6 @@ typedef struct {
|
||||
char *iface;
|
||||
int ifindex;
|
||||
|
||||
char *accept_ra_path;
|
||||
gboolean accept_ra_save_valid;
|
||||
guint32 accept_ra_save;
|
||||
|
||||
char *disable_ip6_path;
|
||||
gboolean disable_ip6_save_valid;
|
||||
guint32 disable_ip6_save;
|
||||
@@ -111,12 +107,6 @@ nm_ip6_device_destroy (NMIP6Device *device)
|
||||
{
|
||||
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 */
|
||||
if (device->disable_ip6_save_valid) {
|
||||
nm_utils_do_sysctl (device->disable_ip6_path,
|
||||
@@ -135,37 +125,9 @@ nm_ip6_device_destroy (NMIP6Device *device)
|
||||
if (device->ip6flags_poll_id)
|
||||
g_source_remove (device->ip6flags_poll_id);
|
||||
|
||||
g_free (device->accept_ra_path);
|
||||
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 *
|
||||
nm_ip6_device_new (NMIP6Manager *manager, int ifindex)
|
||||
{
|
||||
@@ -195,21 +157,11 @@ nm_ip6_device_new (NMIP6Manager *manager, int ifindex)
|
||||
|
||||
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 */
|
||||
device->disable_ip6_path = g_strdup_printf ("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
|
||||
device->iface);
|
||||
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->disable_ip6_save);
|
||||
|
||||
@@ -836,7 +788,8 @@ netlink_notification (NMNetlinkMonitor *monitor, struct nl_msg *msg, gpointer us
|
||||
void
|
||||
nm_ip6_manager_prepare_interface (NMIP6Manager *manager,
|
||||
int ifindex,
|
||||
NMSettingIP6Config *s_ip6)
|
||||
NMSettingIP6Config *s_ip6,
|
||||
const char *accept_ra_path)
|
||||
{
|
||||
NMIP6ManagerPrivate *priv;
|
||||
NMIP6Device *device;
|
||||
@@ -861,10 +814,10 @@ nm_ip6_manager_prepare_interface (NMIP6Manager *manager,
|
||||
/* Establish target state and turn router advertisement acceptance on or off */
|
||||
if (!strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_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 {
|
||||
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);
|
||||
void nm_ip6_manager_prepare_interface (NMIP6Manager *manager,
|
||||
int ifindex,
|
||||
NMSettingIP6Config *s_ip6);
|
||||
NMSettingIP6Config *s_ip6,
|
||||
const char *accept_ra_path);
|
||||
void nm_ip6_manager_begin_addrconf (NMIP6Manager *manager,
|
||||
int ifindex);
|
||||
void nm_ip6_manager_cancel_addrconf (NMIP6Manager *manager,
|
||||
|
@@ -135,6 +135,9 @@ typedef struct {
|
||||
gulong ip6_config_changed_sigid;
|
||||
gboolean ip6_waiting_for_config;
|
||||
|
||||
char * ip6_accept_ra_path;
|
||||
guint32 ip6_accept_ra_save;
|
||||
|
||||
NMDHCPClient * dhcp6_client;
|
||||
guint32 dhcp6_mode;
|
||||
gulong dhcp6_state_sigid;
|
||||
@@ -207,6 +210,41 @@ nm_device_init (NMDevice *self)
|
||||
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*
|
||||
constructor (GType type,
|
||||
guint n_construct_params,
|
||||
@@ -246,6 +284,8 @@ constructor (GType type,
|
||||
|
||||
priv->dhcp_manager = nm_dhcp_manager_get ();
|
||||
|
||||
update_accept_ra_save (dev);
|
||||
|
||||
priv->initialized = TRUE;
|
||||
return object;
|
||||
|
||||
@@ -744,7 +784,8 @@ addrconf6_setup (NMDevice *self)
|
||||
s_ip6 = (NMSettingIP6Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG);
|
||||
nm_ip6_manager_prepare_interface (priv->ip6_manager,
|
||||
nm_device_get_ip_ifindex (self),
|
||||
s_ip6);
|
||||
s_ip6,
|
||||
priv->ip6_accept_ra_path);
|
||||
priv->ip6_waiting_for_config = 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);
|
||||
|
||||
update_accept_ra_save (self);
|
||||
|
||||
priv->dhcp6_mode = IP6_DHCP_OPT_NONE;
|
||||
|
||||
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));
|
||||
ret = NM_ACT_STAGE_RETURN_POSTPONE;
|
||||
} 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;
|
||||
ret = dhcp6_start (self, connection, priv->dhcp6_mode, reason);
|
||||
} else if (ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) {
|
||||
priv->ip6_ready = TRUE;
|
||||
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;
|
||||
}
|
||||
|
||||
/* Other methods (shared) aren't implemented yet */
|
||||
|
||||
@@ -2676,6 +2727,10 @@ nm_device_deactivate_quickly (NMDevice *self)
|
||||
dnsmasq_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 */
|
||||
if (NM_DEVICE_GET_CLASS (self)->deactivate_quickly)
|
||||
NM_DEVICE_GET_CLASS (self)->deactivate_quickly (self);
|
||||
@@ -3247,6 +3302,13 @@ dispose (GObject *object)
|
||||
addrconf6_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 */
|
||||
if (priv->managed && take_down) {
|
||||
NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE;
|
||||
|
Reference in New Issue
Block a user