diff --git a/src/ip6-manager/nm-ip6-manager.c b/src/ip6-manager/nm-ip6-manager.c index 7f280cec1..8908c8604 100644 --- a/src/ip6-manager/nm-ip6-manager.c +++ b/src/ip6-manager/nm-ip6-manager.c @@ -18,6 +18,7 @@ * Copyright (C) 2009 Red Hat, Inc. */ +#include #include #include @@ -68,6 +69,10 @@ typedef struct { char *iface; int index; + char *accept_ra_path; + gboolean accept_ra_save_valid; + guint32 accept_ra_save; + guint finish_addrconf_id; guint config_changed_id; @@ -179,6 +184,14 @@ nm_ip6_manager_class_init (NMIP6ManagerClass *manager_class) static void 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"); + } + if (device->finish_addrconf_id) g_source_remove (device->finish_addrconf_id); if (device->config_changed_id) @@ -189,6 +202,7 @@ nm_ip6_device_destroy (NMIP6Device *device) if (device->rdnss_timeout_id) g_source_remove (device->rdnss_timeout_id); + g_free (device->accept_ra_path); g_slice_free (NMIP6Device, device); } @@ -600,6 +614,8 @@ nm_ip6_device_new (NMIP6Manager *manager, const char *iface) { NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (manager); NMIP6Device *device; + GError *error = NULL; + char *contents = NULL; device = g_slice_new0 (NMIP6Device); if (!device) { @@ -616,6 +632,14 @@ nm_ip6_device_new (NMIP6Manager *manager, const char *iface) } device->index = nm_netlink_iface_to_index (iface); + device->accept_ra_path = g_strdup_printf ("/proc/sys/net/ipv6/conf/%s/accept_ra", iface); + if (!device->accept_ra_path) { + nm_warning ("%s: Out of memory creating IP6 addrconf object " + "property 'accept_ra_path'.", + iface); + goto error; + } + device->manager = manager; device->rdnss_servers = g_array_new (FALSE, FALSE, sizeof (NMIP6RDNSS)); @@ -623,6 +647,27 @@ nm_ip6_device_new (NMIP6Manager *manager, const char *iface) g_hash_table_replace (priv->devices_by_iface, device->iface, device); g_hash_table_replace (priv->devices_by_index, GINT_TO_POINTER (device->index), device); + /* Grab the original value of "accept_ra" so we can restore it when the + * device is taken down. + */ + if (!g_file_get_contents (device->accept_ra_path, &contents, NULL, &error)) { + nm_warning ("%s: error reading %s: (%d) %s", + iface, device->accept_ra_path, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + } else { + long int tmp; + + errno = 0; + tmp = strtol (contents, NULL, 10); + if ((errno == 0) && (tmp == 0 || tmp == 1)) { + device->accept_ra_save = (guint32) tmp; + device->accept_ra_save_valid = TRUE; + } + g_free (contents); + } + return device; error: @@ -638,7 +683,6 @@ nm_ip6_manager_prepare_interface (NMIP6Manager *manager, NMIP6ManagerPrivate *priv; NMIP6Device *device; const char *method = NULL; - char *sysctl_path; g_return_if_fail (NM_IS_IP6_MANAGER (manager)); g_return_if_fail (iface != NULL); @@ -662,10 +706,9 @@ nm_ip6_manager_prepare_interface (NMIP6Manager *manager, strcmp (iface, "all") != 0 && strcmp (iface, "default") != 0); - sysctl_path = g_strdup_printf ("/proc/sys/net/ipv6/conf/%s/accept_ra", iface); - nm_utils_do_sysctl (sysctl_path, - device->target_state >= NM_IP6_DEVICE_GOT_ADDRESS ? "1\n" : "0\n"); - g_free (sysctl_path); + /* Turn router advertisement acceptance on or off... */ + nm_utils_do_sysctl (device->accept_ra_path, + device->target_state >= NM_IP6_DEVICE_GOT_ADDRESS ? "1\n" : "0\n"); } void diff --git a/src/nm-device.c b/src/nm-device.c index 1a7b8f8ae..6c0f99ca4 100644 --- a/src/nm-device.c +++ b/src/nm-device.c @@ -607,21 +607,22 @@ nm_device_cleanup_ip6 (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - if (priv->ip6_manager) { - if (priv->ip6_addrconf_sigid) { - g_signal_handler_disconnect (priv->ip6_manager, - priv->ip6_addrconf_sigid); - priv->ip6_addrconf_sigid = 0; - } - if (priv->ip6_config_changed_sigid) { - g_signal_handler_disconnect (priv->ip6_manager, - priv->ip6_config_changed_sigid); - priv->ip6_config_changed_sigid = 0; - } + if (!priv->ip6_manager) + return; - g_object_unref (priv->ip6_manager); - priv->ip6_manager = NULL; + if (priv->ip6_addrconf_sigid) { + g_signal_handler_disconnect (priv->ip6_manager, + priv->ip6_addrconf_sigid); + priv->ip6_addrconf_sigid = 0; } + if (priv->ip6_config_changed_sigid) { + g_signal_handler_disconnect (priv->ip6_manager, + priv->ip6_config_changed_sigid); + priv->ip6_config_changed_sigid = 0; + } + + g_object_unref (priv->ip6_manager); + priv->ip6_manager = NULL; } /*