Initial IPv6 support (only handles "manual" and "ignore" currently)

This commit is contained in:
Dan Winship
2009-07-29 12:12:41 -04:00
parent db2748b545
commit fc8e609784
13 changed files with 896 additions and 166 deletions

View File

@@ -198,15 +198,20 @@ check_one_address (struct nl_object *object, void *user_data)
struct rtnl_addr *addr = (struct rtnl_addr *) object;
int err;
if (rtnl_addr_get_ifindex (addr) == data->ifindex) {
if (rtnl_addr_get_family (addr) == data->family) {
if (rtnl_addr_get_ifindex (addr) != data->ifindex)
return;
if (data->family && rtnl_addr_get_family (addr) != data->family)
return;
if (data->family == AF_INET6 &&
rtnl_addr_get_scope (addr) == rtnl_str2scope ("link"))
return;
err = rtnl_addr_delete (data->nlh, addr, 0);
if (err < 0) {
nm_warning ("(%s) error %d returned from rtnl_addr_delete(): %s",
data->iface, err, nl_geterror());
}
}
}
}
static gboolean
@@ -386,6 +391,194 @@ nm_system_apply_ip4_config (const char *iface,
return TRUE;
}
static struct rtnl_route *
nm_system_device_set_ip6_route (const char *iface,
const struct in6_addr *ip6_dest,
guint32 ip6_prefix,
const struct in6_addr *ip6_gateway,
guint32 metric,
int mss)
{
struct nl_handle *nlh;
struct rtnl_route *route;
struct nl_addr *dest_addr;
struct nl_addr *gw_addr = NULL;
int err, iface_idx;
nlh = nm_netlink_get_default_handle ();
g_return_val_if_fail (nlh != NULL, NULL);
iface_idx = nm_netlink_iface_to_index (iface);
g_return_val_if_fail (iface_idx >= 0, NULL);
route = create_route (iface_idx, mss);
g_return_val_if_fail (route != NULL, NULL);
/* Destination */
dest_addr = nl_addr_build (AF_INET6, (struct in6_addr *)ip6_dest, sizeof (*ip6_dest));
g_return_val_if_fail (dest_addr != NULL, NULL);
nl_addr_set_prefixlen (dest_addr, (int) ip6_prefix);
rtnl_route_set_dst (route, dest_addr);
nl_addr_put (dest_addr);
/* Gateway */
if (ip6_gateway && !IN6_IS_ADDR_UNSPECIFIED (ip6_gateway)) {
gw_addr = nl_addr_build (AF_INET6, (struct in6_addr *)ip6_gateway, sizeof (*ip6_gateway));
if (gw_addr) {
rtnl_route_set_gateway (route, gw_addr);
rtnl_route_set_scope (route, RT_SCOPE_UNIVERSE);
} else {
nm_warning ("Invalid gateway");
rtnl_route_put (route);
return NULL;
}
}
/* Metric */
if (metric)
rtnl_route_set_prio (route, metric);
/* Add the route */
err = rtnl_route_add (nlh, route, 0);
if (err == -ESRCH && ip6_gateway) {
/* Gateway might be over a bridge; try adding a route to gateway first */
struct rtnl_route *route2;
route2 = create_route (iface_idx, mss);
if (route2) {
/* Add route to gateway over bridge */
rtnl_route_set_dst (route2, gw_addr);
err = rtnl_route_add (nlh, route2, 0);
if (!err) {
/* Try adding the route again */
err = rtnl_route_add (nlh, route, 0);
if (err)
rtnl_route_del (nlh, route2, 0);
}
rtnl_route_put (route2);
}
}
if (gw_addr)
nl_addr_put (gw_addr);
if (err) {
nm_warning ("Failed to set IPv6 route on '%s': %s", iface, nl_geterror ());
rtnl_route_put (route);
route = NULL;
}
return route;
}
static gboolean
add_ip6_addresses (NMIP6Config *config, const char *iface)
{
struct nl_handle *nlh = NULL;
struct nl_cache *addr_cache = NULL;
int i, iface_idx, err;
AddrCheckData check_data;
guint32 flags = 0;
nlh = nm_netlink_get_default_handle ();
if (!nlh)
return FALSE;
addr_cache = rtnl_addr_alloc_cache (nlh);
if (!addr_cache)
return FALSE;
nl_cache_mngt_provide (addr_cache);
iface_idx = nm_netlink_iface_to_index (iface);
memset (&check_data, 0, sizeof (check_data));
check_data.iface = iface;
check_data.nlh = nlh;
check_data.ifindex = iface_idx;
check_data.family = AF_INET6;
/* Remove all existing IPv6 addresses */
nl_cache_foreach (addr_cache, check_one_address, &check_data);
for (i = 0; i < nm_ip6_config_get_num_addresses (config); i++) {
NMIP6Address *addr;
struct rtnl_addr *nl_addr = NULL;
addr = nm_ip6_config_get_address (config, i);
g_assert (addr);
flags = NM_RTNL_ADDR_DEFAULT;
nl_addr = nm_ip6_config_to_rtnl_addr (config, i, flags);
if (!nl_addr) {
nm_warning ("couldn't create rtnl address!\n");
continue;
}
rtnl_addr_set_ifindex (nl_addr, iface_idx);
if ((err = rtnl_addr_add (nlh, nl_addr, 0)) < 0)
nm_warning ("(%s) error %d returned from rtnl_addr_add():\n%s", iface, err, nl_geterror());
rtnl_addr_put (nl_addr);
}
nl_cache_free (addr_cache);
return TRUE;
}
/*
* nm_system_apply_ip6_config
*
* Set IPv6 configuration of the device from an NMIP6Config object.
*
*/
gboolean
nm_system_apply_ip6_config (const char *iface,
NMIP6Config *config,
int priority,
NMIP6ConfigCompareFlags flags)
{
int i;
g_return_val_if_fail (iface != NULL, FALSE);
g_return_val_if_fail (config != NULL, FALSE);
if (flags & NM_IP6_COMPARE_FLAG_ADDRESSES) {
if (!add_ip6_addresses (config, iface))
return FALSE;
sleep (1); // FIXME?
}
if (flags & NM_IP6_COMPARE_FLAG_ROUTES) {
for (i = 0; i < nm_ip6_config_get_num_routes (config); i++) {
NMIP6Route *route = nm_ip6_config_get_route (config, i);
struct rtnl_route *tmp;
/* Don't add the route if it doesn't have a gateway and the connection
* is never supposed to be the default connection.
*/
if ( nm_ip6_config_get_never_default (config)
&& IN6_IS_ADDR_UNSPECIFIED(nm_ip6_route_get_dest (route)))
continue;
tmp = nm_system_device_set_ip6_route (iface,
nm_ip6_route_get_dest (route),
nm_ip6_route_get_prefix (route),
nm_ip6_route_get_next_hop (route),
nm_ip6_route_get_metric (route),
nm_ip6_config_get_mss (config));
rtnl_route_put (tmp);
}
}
// FIXME
// if (priority > 0)
// nm_system_device_set_priority (iface, config, priority);
return TRUE;
}
/*
* nm_system_device_set_up_down
*
@@ -719,27 +912,7 @@ nm_system_replace_default_ip4_route (const char *iface, guint32 gw, guint32 mss)
return success;
}
/*
* nm_system_device_flush_ip4_addresses
*
* Flush all network addresses associated with a network device
*
*/
void nm_system_device_flush_ip4_addresses (NMDevice *dev)
{
g_return_if_fail (dev != NULL);
nm_system_device_flush_ip4_addresses_with_iface (nm_device_get_ip_iface (dev));
}
/*
* nm_system_device_flush_ip4_addresses_with_iface
*
* Flush all network addresses associated with a network device
*
*/
void nm_system_device_flush_ip4_addresses_with_iface (const char *iface)
static void flush_addresses (const char *iface, gboolean ipv4_only)
{
struct nl_handle *nlh = NULL;
struct nl_cache *addr_cache = NULL;
@@ -756,7 +929,7 @@ void nm_system_device_flush_ip4_addresses_with_iface (const char *iface)
memset (&check_data, 0, sizeof (check_data));
check_data.iface = iface;
check_data.nlh = nlh;
check_data.family = AF_INET;
check_data.family = ipv4_only ? AF_INET : 0;
check_data.ifindex = nm_netlink_iface_to_index (iface);
addr_cache = rtnl_addr_alloc_cache (nlh);
@@ -771,16 +944,29 @@ void nm_system_device_flush_ip4_addresses_with_iface (const char *iface)
}
/*
* nm_system_device_flush_ip4_routes
* nm_system_device_flush_addresses
*
* Flush all network addresses associated with a network device
*
*/
void nm_system_device_flush_ip4_routes (NMDevice *dev)
void nm_system_device_flush_addresses (NMDevice *dev)
{
g_return_if_fail (dev != NULL);
nm_system_device_flush_ip4_routes_with_iface (nm_device_get_ip_iface (dev));
flush_addresses (nm_device_get_ip_iface (dev),
nm_device_get_ip6_config (dev) == NULL);
}
/*
* nm_system_device_flush_addresses_with_iface
*
* Flush all network addresses associated with a network device
*
*/
void nm_system_device_flush_addresses_with_iface (const char *iface)
{
flush_addresses (iface, FALSE);
}
@@ -802,6 +988,7 @@ foreach_route (void (*callback)(struct nl_object *, gpointer),
typedef struct {
const char *iface;
int iface_idx;
int family;
} RouteCheckData;
static void
@@ -811,10 +998,10 @@ check_one_route (struct nl_object *object, void *user_data)
struct rtnl_route *route = (struct rtnl_route *) object;
int err;
/* Delete all IPv4 routes from this interface */
/* Delete all routes from this interface */
if (rtnl_route_get_oif (route) != data->iface_idx)
return;
if (rtnl_route_get_family (route) != AF_INET)
if (data->family && rtnl_route_get_family (route) != data->family)
return;
err = rtnl_route_del (nm_netlink_get_default_handle (), route, 0);
@@ -824,13 +1011,7 @@ check_one_route (struct nl_object *object, void *user_data)
}
}
/*
* nm_system_device_flush_ip4_routes_with_iface
*
* Flush all routes associated with a network device
*
*/
void nm_system_device_flush_ip4_routes_with_iface (const char *iface)
static void flush_routes (const char *iface, gboolean ipv4_only)
{
int iface_idx;
RouteCheckData check_data;
@@ -842,10 +1023,36 @@ void nm_system_device_flush_ip4_routes_with_iface (const char *iface)
memset (&check_data, 0, sizeof (check_data));
check_data.iface = iface;
check_data.iface_idx = iface_idx;
check_data.family = ipv4_only ? AF_INET : 0;
foreach_route (check_one_route, &check_data);
}
/*
* nm_system_device_flush_routes
*
* Flush all network addresses associated with a network device
*
*/
void nm_system_device_flush_routes (NMDevice *dev)
{
g_return_if_fail (dev != NULL);
flush_routes (nm_device_get_ip_iface (dev),
nm_device_get_ip6_config (dev) == NULL);
}
/*
* nm_system_device_flush_routes_with_iface
*
* Flush all routes associated with a network device
*
*/
void nm_system_device_flush_routes_with_iface (const char *iface)
{
flush_routes (iface, FALSE);
}
typedef struct {
struct rtnl_route *route;
NMIP4Config *config;

View File

@@ -33,8 +33,8 @@
* implemented in the backend files in backends/ directory
*/
void nm_system_device_flush_ip4_routes (NMDevice *dev);
void nm_system_device_flush_ip4_routes_with_iface (const char *iface);
void nm_system_device_flush_routes (NMDevice *dev);
void nm_system_device_flush_routes_with_iface (const char *iface);
gboolean nm_system_replace_default_ip4_route (const char *iface,
guint32 gw,
@@ -50,8 +50,8 @@ gboolean nm_system_replace_default_ip4_route_vpn (const char *iface,
struct rtnl_route *nm_system_add_ip4_vpn_gateway_route (NMDevice *parent_device, NMIP4Config *vpn_config);
void nm_system_device_flush_ip4_addresses (NMDevice *dev);
void nm_system_device_flush_ip4_addresses_with_iface (const char *iface);
void nm_system_device_flush_addresses (NMDevice *dev);
void nm_system_device_flush_addresses_with_iface (const char *iface);
void nm_system_enable_loopback (void);
void nm_system_update_dns (void);
@@ -61,6 +61,11 @@ gboolean nm_system_apply_ip4_config (const char *iface,
int priority,
NMIP4ConfigCompareFlags flags);
gboolean nm_system_apply_ip6_config (const char *iface,
NMIP6Config *config,
int priority,
NMIP6ConfigCompareFlags flags);
gboolean nm_system_device_set_up_down (NMDevice *dev,
gboolean up,
gboolean *no_firmware);

View File

@@ -20,8 +20,11 @@
*/
#include <glib.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "NetworkManagerUtils.h"
#include "nm-utils.h"
@@ -259,6 +262,112 @@ nm_utils_merge_ip4_config (NMIP4Config *ip4_config, NMSettingIP4Config *setting)
nm_ip4_config_set_never_default (ip4_config, TRUE);
}
static inline gboolean
ip6_addresses_equal (const struct in6_addr *a, const struct in6_addr *b)
{
return memcmp (a, b, sizeof (struct in6_addr)) == 0;
}
/* This is exactly identical to nm_utils_merge_ip4_config, with s/4/6/,
* except that we can't compare addresses with ==.
*/
void
nm_utils_merge_ip6_config (NMIP6Config *ip6_config, NMSettingIP6Config *setting)
{
int i, j;
if (!setting)
return; /* Defaults are just fine */
if (nm_setting_ip6_config_get_ignore_auto_dns (setting)) {
nm_ip6_config_reset_nameservers (ip6_config);
nm_ip6_config_reset_domains (ip6_config);
nm_ip6_config_reset_searches (ip6_config);
}
if (nm_setting_ip6_config_get_ignore_auto_routes (setting))
nm_ip6_config_reset_routes (ip6_config);
for (i = 0; i < nm_setting_ip6_config_get_num_dns (setting); i++) {
const struct in6_addr *ns;
gboolean found = FALSE;
/* Avoid dupes */
ns = nm_setting_ip6_config_get_dns (setting, i);
for (j = 0; j < nm_ip6_config_get_num_nameservers (ip6_config); j++) {
if (ip6_addresses_equal (nm_ip6_config_get_nameserver (ip6_config, j), ns)) {
found = TRUE;
break;
}
}
if (!found)
nm_ip6_config_add_nameserver (ip6_config, ns);
}
/* DNS search domains */
for (i = 0; i < nm_setting_ip6_config_get_num_dns_searches (setting); i++) {
const char *search = nm_setting_ip6_config_get_dns_search (setting, i);
gboolean found = FALSE;
/* Avoid dupes */
for (j = 0; j < nm_ip6_config_get_num_searches (ip6_config); j++) {
if (!strcmp (search, nm_ip6_config_get_search (ip6_config, j))) {
found = TRUE;
break;
}
}
if (!found)
nm_ip6_config_add_search (ip6_config, search);
}
/* IPv6 addresses */
for (i = 0; i < nm_setting_ip6_config_get_num_addresses (setting); i++) {
NMIP6Address *setting_addr = nm_setting_ip6_config_get_address (setting, i);
guint32 num;
num = nm_ip6_config_get_num_addresses (ip6_config);
for (j = 0; j < num; j++) {
NMIP6Address *cfg_addr = nm_ip6_config_get_address (ip6_config, j);
/* Dupe, override with user-specified address */
if (ip6_addresses_equal (nm_ip6_address_get_address (cfg_addr), nm_ip6_address_get_address (setting_addr))) {
nm_ip6_config_replace_address (ip6_config, j, setting_addr);
break;
}
}
if (j == num)
nm_ip6_config_add_address (ip6_config, setting_addr);
}
/* IPv6 routes */
for (i = 0; i < nm_setting_ip6_config_get_num_routes (setting); i++) {
NMIP6Route *setting_route = nm_setting_ip6_config_get_route (setting, i);
guint32 num;
num = nm_ip6_config_get_num_routes (ip6_config);
for (j = 0; j < num; j++) {
NMIP6Route *cfg_route = nm_ip6_config_get_route (ip6_config, j);
/* Dupe, override with user-specified route */
if ( ip6_addresses_equal (nm_ip6_route_get_dest (cfg_route), nm_ip6_route_get_dest (setting_route))
&& (nm_ip6_route_get_prefix (cfg_route) == nm_ip6_route_get_prefix (setting_route))
&& ip6_addresses_equal (nm_ip6_route_get_next_hop (cfg_route), nm_ip6_route_get_next_hop (setting_route))) {
nm_ip6_config_replace_route (ip6_config, j, setting_route);
break;
}
}
if (j == num)
nm_ip6_config_add_route (ip6_config, setting_route);
}
if (nm_setting_ip6_config_get_never_default (setting))
nm_ip6_config_set_never_default (ip6_config, TRUE);
}
void
nm_utils_call_dispatcher (const char *action,
NMConnection *connection,
@@ -444,3 +553,29 @@ value_hash_add_uint (GHashTable *hash,
value_hash_add (hash, key, value);
}
gboolean
nm_utils_do_sysctl (const char *path, const char *value)
{
int fd, len, nwrote, total;
fd = open (path, O_WRONLY | O_TRUNC);
if (fd == -1)
return FALSE;
len = strlen (value);
total = 0;
do {
nwrote = write (fd, value + total, len - total);
if (nwrote == -1) {
if (errno == EINTR)
continue;
close (fd);
return FALSE;
}
total += nwrote;
} while (total < len);
close (fd);
return TRUE;
}

View File

@@ -29,6 +29,8 @@
#include "nm-device.h"
#include "nm-ip4-config.h"
#include "nm-setting-ip4-config.h"
#include "nm-ip6-config.h"
#include "nm-setting-ip6-config.h"
#include "nm-connection.h"
gboolean nm_ethernet_address_is_valid (const struct ether_addr *test_addr);
@@ -38,6 +40,7 @@ int nm_spawn_process (const char *args);
char *nm_ether_ntop (const struct ether_addr *mac);
void nm_utils_merge_ip4_config (NMIP4Config *ip4_config, NMSettingIP4Config *setting);
void nm_utils_merge_ip6_config (NMIP6Config *ip6_config, NMSettingIP6Config *setting);
void nm_utils_call_dispatcher (const char *action,
NMConnection *connection,
@@ -64,5 +67,6 @@ void value_hash_add_uint (GHashTable *hash,
const char *key,
guint32 val);
gboolean nm_utils_do_sysctl (const char *path, const char *value);
#endif /* NETWORK_MANAGER_UTILS_H */

View File

@@ -131,7 +131,7 @@ ppp_ip4_config (NMPPPManager *ppp_manager,
nm_device_set_ip_iface (device, iface);
NM_MODEM_GET_PRIVATE (device)->pending_ip4_config = g_object_ref (config);
nm_device_activate_schedule_stage4_ip_config_get (device);
nm_device_activate_schedule_stage4_ip4_config_get (device);
}
static void
@@ -235,7 +235,7 @@ static_stage3_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_da
g_value_get_uint (g_value_array_get_nth (ret_array, i)));
g_value_array_free (ret_array);
nm_device_activate_schedule_stage4_ip_config_get (device);
nm_device_activate_schedule_stage4_ip4_config_get (device);
} else {
nm_warning ("Retrieving IP4 configuration failed: %s", error->message);
g_error_free (error);
@@ -303,7 +303,7 @@ real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
}
static NMActStageReturn
real_act_stage3_ip_config_start (NMDevice *device, NMDeviceStateReason *reason)
real_act_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason)
{
NMActStageReturn ret;
@@ -315,7 +315,7 @@ real_act_stage3_ip_config_start (NMDevice *device, NMDeviceStateReason *reason)
ret = static_stage3_config (device, reason);
break;
case MM_MODEM_IP_METHOD_DHCP:
ret = NM_DEVICE_CLASS (nm_modem_parent_class)->act_stage3_ip_config_start (device, reason);
ret = NM_DEVICE_CLASS (nm_modem_parent_class)->act_stage3_ip4_config_start (device, reason);
break;
default:
g_warning ("Invalid IP method");
@@ -376,8 +376,8 @@ real_deactivate_quickly (NMDevice *device)
case MM_MODEM_IP_METHOD_DHCP:
iface = nm_device_get_iface (device);
nm_system_device_flush_ip4_routes_with_iface (iface);
nm_system_device_flush_ip4_addresses_with_iface (iface);
nm_system_device_flush_routes_with_iface (iface);
nm_system_device_flush_addresses_with_iface (iface);
nm_system_device_set_up_down_with_iface (iface, FALSE, NULL);
break;
default:
@@ -611,7 +611,7 @@ nm_modem_class_init (NMModemClass *klass)
device_class->get_generic_capabilities = real_get_generic_capabilities;
device_class->act_stage2_config = real_act_stage2_config;
device_class->act_stage3_ip_config_start = real_act_stage3_ip_config_start;
device_class->act_stage3_ip4_config_start = real_act_stage3_ip4_config_start;
device_class->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config;
device_class->deactivate_quickly = real_deactivate_quickly;
device_class->hw_is_up = real_hw_is_up;

View File

@@ -313,7 +313,7 @@ ppp_ip4_config (NMPPPManager *ppp_manager,
nm_device_set_ip_iface (device, iface);
NM_DEVICE_BT_GET_PRIVATE (device)->pending_ip4_config = g_object_ref (config);
nm_device_activate_schedule_stage4_ip_config_get (device);
nm_device_activate_schedule_stage4_ip4_config_get (device);
}
static void
@@ -626,7 +626,7 @@ real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
}
static NMActStageReturn
real_act_stage3_ip_config_start (NMDevice *device, NMDeviceStateReason *reason)
real_act_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason)
{
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device);
NMActStageReturn ret;
@@ -634,7 +634,7 @@ real_act_stage3_ip_config_start (NMDevice *device, NMDeviceStateReason *reason)
if (priv->bt_type == NM_BT_CAPABILITY_DUN)
ret = ppp_stage3_start (device, reason);
else
ret = NM_DEVICE_CLASS (nm_device_bt_parent_class)->act_stage3_ip_config_start (device, reason);
ret = NM_DEVICE_CLASS (nm_device_bt_parent_class)->act_stage3_ip4_config_start (device, reason);
return ret;
}
@@ -841,7 +841,7 @@ nm_device_bt_class_init (NMDeviceBtClass *klass)
device_class->connection_secrets_updated = real_connection_secrets_updated;
device_class->deactivate_quickly = real_deactivate_quickly;
device_class->act_stage2_config = real_act_stage2_config;
device_class->act_stage3_ip_config_start = real_act_stage3_ip_config_start;
device_class->act_stage3_ip4_config_start = real_act_stage3_ip4_config_start;
device_class->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config;
device_class->check_connection_compatible = real_check_connection_compatible;

View File

@@ -1255,7 +1255,7 @@ ppp_ip4_config (NMPPPManager *ppp_manager,
nm_device_set_ip_iface (device, iface);
NM_DEVICE_ETHERNET_GET_PRIVATE (device)->pending_ip4_config = g_object_ref (config);
nm_device_activate_schedule_stage4_ip_config_get (device);
nm_device_activate_schedule_stage4_ip4_config_get (device);
}
static NMActStageReturn

View File

@@ -123,6 +123,14 @@ nm_device_interface_init (gpointer g_iface)
DBUS_TYPE_G_OBJECT_PATH,
G_PARAM_READWRITE));
g_object_interface_install_property
(g_iface,
g_param_spec_boxed (NM_DEVICE_INTERFACE_IP6_CONFIG,
"IP6 Config",
"IP6 Config",
DBUS_TYPE_G_OBJECT_PATH,
G_PARAM_READWRITE));
g_object_interface_install_property
(g_iface,
g_param_spec_uint (NM_DEVICE_INTERFACE_STATE,

View File

@@ -48,6 +48,7 @@ typedef enum
#define NM_DEVICE_INTERFACE_IP4_ADDRESS "ip4-address"
#define NM_DEVICE_INTERFACE_IP4_CONFIG "ip4-config"
#define NM_DEVICE_INTERFACE_DHCP4_CONFIG "dhcp4-config"
#define NM_DEVICE_INTERFACE_IP6_CONFIG "ip6-config"
#define NM_DEVICE_INTERFACE_STATE "state"
#define NM_DEVICE_INTERFACE_DEVICE_TYPE "device-type" /* ugh */
#define NM_DEVICE_INTERFACE_MANAGED "managed"
@@ -63,6 +64,7 @@ typedef enum {
NM_DEVICE_INTERFACE_PROP_IP4_ADDRESS,
NM_DEVICE_INTERFACE_PROP_IP4_CONFIG,
NM_DEVICE_INTERFACE_PROP_DHCP4_CONFIG,
NM_DEVICE_INTERFACE_PROP_IP6_CONFIG,
NM_DEVICE_INTERFACE_PROP_STATE,
NM_DEVICE_INTERFACE_PROP_DEVICE_TYPE,
NM_DEVICE_INTERFACE_PROP_MANAGED,

View File

@@ -3022,7 +3022,7 @@ real_act_stage4_get_ip4_config (NMDevice *dev,
static NMActStageReturn
real_act_stage4_ip_config_timeout (NMDevice *dev,
real_act_stage4_ip4_config_timeout (NMDevice *dev,
NMIP4Config **config,
NMDeviceStateReason *reason)
{
@@ -3070,7 +3070,7 @@ real_act_stage4_ip_config_timeout (NMDevice *dev,
/* For Ad-Hoc networks, chain up to parent to get a Zeroconf IP */
klass = NM_DEVICE_WIFI_GET_CLASS (self);
parent_class = NM_DEVICE_CLASS (g_type_class_peek_parent (klass));
ret = parent_class->act_stage4_ip_config_timeout (dev, &real_config, reason);
ret = parent_class->act_stage4_ip4_config_timeout (dev, &real_config, reason);
} else {
/* Non-encrypted network or authentication is enforced by some
* entity (AP, RADIUS server, etc), but IP configure failed. Alert
@@ -3555,7 +3555,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
parent_class->act_stage1_prepare = real_act_stage1_prepare;
parent_class->act_stage2_config = real_act_stage2_config;
parent_class->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config;
parent_class->act_stage4_ip_config_timeout = real_act_stage4_ip_config_timeout;
parent_class->act_stage4_ip4_config_timeout = real_act_stage4_ip4_config_timeout;
parent_class->deactivate = real_deactivate;
parent_class->deactivate_quickly = real_deactivate_quickly;
parent_class->can_interrupt_activation = real_can_interrupt_activation;

View File

@@ -47,12 +47,14 @@
#include "nm-utils.h"
#include "nm-netlink.h"
#include "nm-setting-ip4-config.h"
#include "nm-setting-ip6-config.h"
#include "nm-setting-connection.h"
#include "nm-dnsmasq-manager.h"
#include "nm-dhcp4-config.h"
#include "nm-marshal.h"
#define NM_ACT_REQUEST_IP4_CONFIG "nm-act-request-ip4-config"
#define NM_ACT_REQUEST_IP6_CONFIG "nm-act-request-ip6-config"
static void device_interface_init (NMDeviceInterface *device_interface_class);
@@ -86,15 +88,19 @@ typedef struct {
gboolean managed; /* whether managed by NM or not */
guint32 ip4_address;
struct in6_addr ip6_address;
NMActRequest * act_request;
guint act_source_id;
gpointer act_source_func;
guint act_source6_id;
gpointer act_source6_func;
gulong secrets_updated_id;
gulong secrets_failed_id;
/* IP configuration info */
gboolean ip4_ready;
gboolean ip6_ready;
/* IP4 configuration info */
NMIP4Config * ip4_config; /* Config from DHCP, PPP, or system config files */
NMDHCPManager * dhcp_manager;
guint32 dhcp_timeout;
@@ -112,6 +118,9 @@ typedef struct {
guint aipd_watch;
guint aipd_timeout;
guint32 aipd_addr;
/* IP6 configuration info */
NMIP6Config *ip6_config;
} NMDevicePrivate;
static gboolean check_connection_compatible (NMDeviceInterface *device,
@@ -123,7 +132,7 @@ static gboolean nm_device_activate (NMDeviceInterface *device,
static void nm_device_deactivate (NMDeviceInterface *device, NMDeviceStateReason reason);
static gboolean nm_device_spec_match_list (NMDeviceInterface *device, const GSList *specs);
static void nm_device_activate_schedule_stage5_ip_config_commit (NMDevice *self);
static void nm_device_activate_schedule_stage5_ip_config_commit (NMDevice *self, int family);
static void nm_device_take_down (NMDevice *dev, gboolean wait, NMDeviceStateReason reason);
@@ -131,6 +140,7 @@ static gboolean nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no
static gboolean nm_device_is_up (NMDevice *self);
static gboolean nm_device_set_ip4_config (NMDevice *dev, NMIP4Config *config, NMDeviceStateReason *reason);
static gboolean nm_device_set_ip6_config (NMDevice *dev, NMIP6Config *config, NMDeviceStateReason *reason);
static void
device_interface_init (NMDeviceInterface *device_interface_class)
@@ -150,7 +160,6 @@ nm_device_init (NMDevice *self)
priv->type = NM_DEVICE_TYPE_UNKNOWN;
priv->capabilities = NM_DEVICE_CAP_NONE;
memset (&priv->ip6_address, 0, sizeof (struct in6_addr));
priv->state = NM_DEVICE_STATE_UNMANAGED;
priv->dhcp_timeout = 0;
}
@@ -439,24 +448,44 @@ dnsmasq_state_changed_cb (NMDnsMasqManager *manager, guint32 status, gpointer us
}
static void
activation_source_clear (NMDevice *self, gboolean remove_source)
activation_source_clear (NMDevice *self, gboolean remove_source, int family)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
guint *act_source_id;
gpointer *act_source_func;
if (priv->act_source_id) {
if (family == AF_INET6) {
act_source_id = &priv->act_source6_id;
act_source_func = &priv->act_source6_func;
} else {
act_source_id = &priv->act_source_id;
act_source_func = &priv->act_source_func;
}
if (*act_source_id) {
if (remove_source)
g_source_remove (priv->act_source_id);
priv->act_source_id = 0;
priv->act_source_func = NULL;
g_source_remove (*act_source_id);
*act_source_id = 0;
*act_source_func = NULL;
}
}
static void
activation_source_schedule (NMDevice *self, GSourceFunc func)
activation_source_schedule (NMDevice *self, GSourceFunc func, int family)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
guint *act_source_id;
gpointer *act_source_func;
if (priv->act_source_id)
if (family == AF_INET6) {
act_source_id = &priv->act_source6_id;
act_source_func = &priv->act_source6_func;
} else {
act_source_id = &priv->act_source_id;
act_source_func = &priv->act_source_func;
}
if (*act_source_id)
nm_warning ("activation stage already scheduled");
/* Don't bother rescheduling the same function that's about to
@@ -464,13 +493,51 @@ activation_source_schedule (NMDevice *self, GSourceFunc func)
* streams of associate events before NM has had a chance to process
* the first one.
*/
if (!priv->act_source_id || (priv->act_source_func != func)) {
activation_source_clear (self, TRUE);
priv->act_source_id = g_idle_add (func, self);
priv->act_source_func = func;
if (!*act_source_id || (*act_source_func != func)) {
activation_source_clear (self, TRUE, family);
*act_source_id = g_idle_add (func, self);
*act_source_func = func;
}
}
static void
configure_ip6_router_advertisements (NMDevice *dev)
{
NMActRequest *req;
NMConnection *connection;
const char *iface, *method = NULL;
NMSettingIP6Config *s_ip6;
gboolean accept_ra = TRUE;
char *sysctl_path;
req = nm_device_get_act_request (dev);
if (!req)
return;
connection = nm_act_request_get_connection (req);
if (!connection)
return;
s_ip6 = (NMSettingIP6Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG);
if (s_ip6)
method = nm_setting_ip6_config_get_method (s_ip6);
if (!method || !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE))
return;
if ( !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)
|| !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL))
accept_ra = FALSE;
iface = nm_device_get_iface (dev);
g_return_if_fail (strchr (iface, '/') == NULL &&
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, accept_ra ? "1\n" : "0\n");
g_free (sysctl_path);
}
/*
* nm_device_activate_stage1_device_prepare
*
@@ -481,17 +548,22 @@ static gboolean
nm_device_activate_stage1_device_prepare (gpointer user_data)
{
NMDevice *self = NM_DEVICE (user_data);
const char * iface;
const char *iface;
NMActStageReturn ret;
NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
/* Clear the activation source ID now that this stage has run */
activation_source_clear (self, FALSE);
activation_source_clear (self, FALSE, 0);
iface = nm_device_get_iface (self);
nm_info ("Activation (%s) Stage 1 of 5 (Device Prepare) started...", iface);
nm_device_state_changed (self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE);
/* Ensure that IPv6 Router Advertisement handling is properly
* enabled/disabled before bringing up the interface.
*/
configure_ip6_router_advertisements (self);
ret = NM_DEVICE_GET_CLASS (self)->act_stage1_prepare (self, &reason);
if (ret == NM_ACT_STAGE_RETURN_POSTPONE) {
goto out;
@@ -525,7 +597,7 @@ nm_device_activate_schedule_stage1_device_prepare (NMDevice *self)
priv = NM_DEVICE_GET_PRIVATE (self);
g_return_if_fail (priv->act_request);
activation_source_schedule (self, nm_device_activate_stage1_device_prepare);
activation_source_schedule (self, nm_device_activate_stage1_device_prepare, 0);
nm_info ("Activation (%s) Stage 1 of 5 (Device Prepare) scheduled...",
nm_device_get_iface (self));
@@ -562,7 +634,7 @@ nm_device_activate_stage2_device_config (gpointer user_data)
gboolean no_firmware = FALSE;
/* Clear the activation source ID now that this stage has run */
activation_source_clear (self, FALSE);
activation_source_clear (self, FALSE, 0);
iface = nm_device_get_iface (self);
nm_info ("Activation (%s) Stage 2 of 5 (Device Configure) starting...", iface);
@@ -612,7 +684,7 @@ nm_device_activate_schedule_stage2_device_config (NMDevice *self)
priv = NM_DEVICE_GET_PRIVATE (self);
g_return_if_fail (priv->act_request);
activation_source_schedule (self, nm_device_activate_stage2_device_config);
activation_source_schedule (self, nm_device_activate_stage2_device_config, 0);
nm_info ("Activation (%s) Stage 2 of 5 (Device Configure) scheduled...",
nm_device_get_iface (self));
@@ -772,7 +844,7 @@ nm_device_handle_autoip4_event (NMDevice *self,
priv->aipd_addr = ip.s_addr;
aipd_timeout_remove (self);
nm_device_activate_schedule_stage4_ip_config_get (self);
nm_device_activate_schedule_stage4_ip4_config_get (self);
break;
case NM_DEVICE_STATE_ACTIVATED:
priv->aipd_addr = ip.s_addr;
@@ -837,7 +909,7 @@ aipd_timeout_cb (gpointer user_data)
aipd_cleanup (self);
if (nm_device_get_state (self) == NM_DEVICE_STATE_IP_CONFIG)
nm_device_activate_schedule_stage4_ip_config_timeout (self);
nm_device_activate_schedule_stage4_ip4_config_timeout (self);
return FALSE;
}
@@ -902,7 +974,7 @@ aipd_exec (NMDevice *self, GError **error)
}
static NMActStageReturn
real_act_stage3_ip_config_start (NMDevice *self, NMDeviceStateReason *reason)
real_act_stage3_ip4_config_start (NMDevice *self, NMDeviceStateReason *reason)
{
NMConnection *connection;
NMSettingConnection *s_con;
@@ -976,39 +1048,54 @@ real_act_stage3_ip_config_start (NMDevice *self, NMDeviceStateReason *reason)
return ret;
}
static NMActStageReturn
real_act_stage3_ip6_config_start (NMDevice *self, NMDeviceStateReason *reason)
{
return NM_ACT_STAGE_RETURN_SUCCESS;
}
/*
* nm_device_activate_stage3_ip_config_start
*
* Begin IP configuration with either DHCP or static IP.
* Begin automatic/manual IP configuration
*
*/
static gboolean
nm_device_activate_stage3_ip_config_start (gpointer user_data)
{
NMDevice *self = NM_DEVICE (user_data);
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
const char *iface;
NMActStageReturn ret;
NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
/* Clear the activation source ID now that this stage has run */
activation_source_clear (self, FALSE);
activation_source_clear (self, FALSE, 0);
priv->ip4_ready = priv->ip6_ready = FALSE;
iface = nm_device_get_iface (self);
nm_info ("Activation (%s) Stage 3 of 5 (IP Configure Start) started...", iface);
nm_device_state_changed (self, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_NONE);
ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip_config_start (self, &reason);
if (ret == NM_ACT_STAGE_RETURN_POSTPONE)
goto out;
else if (ret == NM_ACT_STAGE_RETURN_FAILURE)
{
ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip4_config_start (self, &reason);
if (ret == NM_ACT_STAGE_RETURN_SUCCESS)
nm_device_activate_schedule_stage4_ip4_config_get (self);
else if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
goto out;
}
g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS);
} else
g_assert (ret == NM_ACT_STAGE_RETURN_POSTPONE);
nm_device_activate_schedule_stage4_ip_config_get (self);
ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip6_config_start (self, &reason);
if (ret == NM_ACT_STAGE_RETURN_SUCCESS)
nm_device_activate_schedule_stage4_ip6_config_get (self);
else if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
goto out;
} else
g_assert (ret == NM_ACT_STAGE_RETURN_POSTPONE);
out:
nm_info ("Activation (%s) Stage 3 of 5 (IP Configure Start) complete.", iface);
@@ -1031,7 +1118,7 @@ nm_device_activate_schedule_stage3_ip_config_start (NMDevice *self)
priv = NM_DEVICE_GET_PRIVATE (self);
g_return_if_fail (priv->act_request);
activation_source_schedule (self, nm_device_activate_stage3_ip_config_start);
activation_source_schedule (self, nm_device_activate_stage3_ip_config_start, 0);
nm_info ("Activation (%s) Stage 3 of 5 (IP Configure Start) scheduled.",
nm_device_get_iface (self));
@@ -1172,15 +1259,14 @@ real_act_stage4_get_ip4_config (NMDevice *self,
return ret;
}
/*
* nm_device_activate_stage4_ip_config_get
* nm_device_activate_stage4_ip4_config_get
*
* Retrieve the correct IP config.
* Retrieve the correct IPv4 config.
*
*/
static gboolean
nm_device_activate_stage4_ip_config_get (gpointer user_data)
nm_device_activate_stage4_ip4_config_get (gpointer user_data)
{
NMDevice *self = NM_DEVICE (user_data);
NMIP4Config *ip4_config = NULL;
@@ -1189,10 +1275,10 @@ nm_device_activate_stage4_ip_config_get (gpointer user_data)
NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
/* Clear the activation source ID now that this stage has run */
activation_source_clear (self, FALSE);
activation_source_clear (self, FALSE, AF_INET);
iface = nm_device_get_iface (self);
nm_info ("Activation (%s) Stage 4 of 5 (IP Configure Get) started...", iface);
nm_info ("Activation (%s) Stage 4 of 5 (IP4 Configure Get) started...", iface);
ret = NM_DEVICE_GET_CLASS (self)->act_stage4_get_ip4_config (self, &ip4_config, &reason);
if (ret == NM_ACT_STAGE_RETURN_POSTPONE)
@@ -1207,22 +1293,22 @@ nm_device_activate_stage4_ip_config_get (gpointer user_data)
g_object_set_data (G_OBJECT (nm_device_get_act_request (self)),
NM_ACT_REQUEST_IP4_CONFIG, ip4_config);
nm_device_activate_schedule_stage5_ip_config_commit (self);
nm_device_activate_schedule_stage5_ip_config_commit (self, AF_INET);
out:
nm_info ("Activation (%s) Stage 4 of 5 (IP Configure Get) complete.", iface);
nm_info ("Activation (%s) Stage 4 of 5 (IP4 Configure Get) complete.", iface);
return FALSE;
}
/*
* nm_device_activate_schedule_stage4_ip_config_get
* nm_device_activate_schedule_stage4_ip4_config_get
*
* Schedule creation of the IP config
* Schedule creation of the IPv4 config
*
*/
void
nm_device_activate_schedule_stage4_ip_config_get (NMDevice *self)
nm_device_activate_schedule_stage4_ip4_config_get (NMDevice *self)
{
NMDevicePrivate *priv;
@@ -1231,15 +1317,15 @@ nm_device_activate_schedule_stage4_ip_config_get (NMDevice *self)
priv = NM_DEVICE_GET_PRIVATE (self);
g_return_if_fail (priv->act_request);
activation_source_schedule (self, nm_device_activate_stage4_ip_config_get);
activation_source_schedule (self, nm_device_activate_stage4_ip4_config_get, AF_INET);
nm_info ("Activation (%s) Stage 4 of 5 (IP Configure Get) scheduled...",
nm_info ("Activation (%s) Stage 4 of 5 (IP4 Configure Get) scheduled...",
nm_device_get_iface (self));
}
static NMActStageReturn
real_act_stage4_ip_config_timeout (NMDevice *self,
real_act_stage4_ip4_config_timeout (NMDevice *self,
NMIP4Config **config,
NMDeviceStateReason *reason)
{
@@ -1256,13 +1342,13 @@ real_act_stage4_ip_config_timeout (NMDevice *self,
/*
* nm_device_activate_stage4_ip_config_timeout
* nm_device_activate_stage4_ip4_config_timeout
*
* Retrieve the correct IP config.
* Time out on retrieving the IPv4 config.
*
*/
static gboolean
nm_device_activate_stage4_ip_config_timeout (gpointer user_data)
nm_device_activate_stage4_ip4_config_timeout (gpointer user_data)
{
NMDevice *self = NM_DEVICE (user_data);
NMIP4Config *ip4_config = NULL;
@@ -1271,12 +1357,12 @@ nm_device_activate_stage4_ip_config_timeout (gpointer user_data)
NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
/* Clear the activation source ID now that this stage has run */
activation_source_clear (self, FALSE);
activation_source_clear (self, FALSE, AF_INET);
iface = nm_device_get_iface (self);
nm_info ("Activation (%s) Stage 4 of 5 (IP Configure Timeout) started...", iface);
nm_info ("Activation (%s) Stage 4 of 5 (IP4 Configure Timeout) started...", iface);
ret = NM_DEVICE_GET_CLASS (self)->act_stage4_ip_config_timeout (self, &ip4_config, &reason);
ret = NM_DEVICE_GET_CLASS (self)->act_stage4_ip4_config_timeout (self, &ip4_config, &reason);
if (ret == NM_ACT_STAGE_RETURN_POSTPONE) {
goto out;
} else if (!ip4_config || (ret == NM_ACT_STAGE_RETURN_FAILURE)) {
@@ -1289,22 +1375,22 @@ nm_device_activate_stage4_ip_config_timeout (gpointer user_data)
g_object_set_data (G_OBJECT (nm_device_get_act_request (self)),
NM_ACT_REQUEST_IP4_CONFIG, ip4_config);
nm_device_activate_schedule_stage5_ip_config_commit (self);
nm_device_activate_schedule_stage5_ip_config_commit (self, AF_INET);
out:
nm_info ("Activation (%s) Stage 4 of 5 (IP Configure Timeout) complete.", iface);
nm_info ("Activation (%s) Stage 4 of 5 (IP4 Configure Timeout) complete.", iface);
return FALSE;
}
/*
* nm_device_activate_schedule_stage4_ip_config_timeout
* nm_device_activate_schedule_stage4_ip4_config_timeout
*
* Deal with a timeout of the IP configuration
* Deal with a timeout of the IPv4 configuration
*
*/
void
nm_device_activate_schedule_stage4_ip_config_timeout (NMDevice *self)
nm_device_activate_schedule_stage4_ip4_config_timeout (NMDevice *self)
{
NMDevicePrivate *priv;
@@ -1313,9 +1399,192 @@ nm_device_activate_schedule_stage4_ip_config_timeout (NMDevice *self)
priv = NM_DEVICE_GET_PRIVATE (self);
g_return_if_fail (priv->act_request);
activation_source_schedule (self, nm_device_activate_stage4_ip_config_timeout);
activation_source_schedule (self, nm_device_activate_stage4_ip4_config_timeout, AF_INET);
nm_info ("Activation (%s) Stage 4 of 5 (IP Configure Timeout) scheduled...",
nm_info ("Activation (%s) Stage 4 of 5 (IP4 Configure Timeout) scheduled...",
nm_device_get_iface (self));
}
static NMActStageReturn
real_act_stage4_get_ip6_config (NMDevice *self,
NMIP6Config **config,
NMDeviceStateReason *reason)
{
NMConnection *connection;
NMSettingIP6Config *s_ip6;
const char *ip_iface;
const char *method = NULL;
g_return_val_if_fail (config != NULL, NM_ACT_STAGE_RETURN_FAILURE);
g_return_val_if_fail (*config == NULL, NM_ACT_STAGE_RETURN_FAILURE);
g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
/* Use the IP interface (not the control interface) for IP stuff */
ip_iface = nm_device_get_ip_iface (self);
connection = nm_act_request_get_connection (nm_device_get_act_request (self));
g_assert (connection);
s_ip6 = (NMSettingIP6Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG);
if (s_ip6)
method = nm_setting_ip6_config_get_method (s_ip6);
if (!method || !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) {
*config = NULL;
return NM_ACT_STAGE_RETURN_SUCCESS;
}
*config = nm_ip6_config_new ();
if (!*config) {
*reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE;
return NM_ACT_STAGE_RETURN_FAILURE;
}
if (!strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL))
nm_utils_merge_ip6_config (*config, s_ip6);
return NM_ACT_STAGE_RETURN_SUCCESS;
}
/*
* nm_device_activate_stage4_ip6_config_get
*
* Retrieve the correct IPv6 config.
*
*/
static gboolean
nm_device_activate_stage4_ip6_config_get (gpointer user_data)
{
NMDevice *self = NM_DEVICE (user_data);
NMIP6Config *ip6_config = NULL;
NMActStageReturn ret;
const char *iface = NULL;
NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
/* Clear the activation source ID now that this stage has run */
activation_source_clear (self, FALSE, AF_INET6);
iface = nm_device_get_iface (self);
nm_info ("Activation (%s) Stage 4 of 5 (IP6 Configure Get) started...", iface);
ret = NM_DEVICE_GET_CLASS (self)->act_stage4_get_ip6_config (self, &ip6_config, &reason);
if (ret == NM_ACT_STAGE_RETURN_POSTPONE)
goto out;
else if (ret == NM_ACT_STAGE_RETURN_FAILURE)
{
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
goto out;
}
g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS);
g_object_set_data (G_OBJECT (nm_device_get_act_request (self)),
NM_ACT_REQUEST_IP6_CONFIG, ip6_config);
nm_device_activate_schedule_stage5_ip_config_commit (self, AF_INET6);
out:
nm_info ("Activation (%s) Stage 4 of 5 (IP6 Configure Get) complete.", iface);
return FALSE;
}
/*
* nm_device_activate_schedule_stage4_ip6_config_get
*
* Schedule creation of the IPv6 config
*
*/
void
nm_device_activate_schedule_stage4_ip6_config_get (NMDevice *self)
{
NMDevicePrivate *priv;
g_return_if_fail (NM_IS_DEVICE (self));
priv = NM_DEVICE_GET_PRIVATE (self);
g_return_if_fail (priv->act_request);
activation_source_schedule (self, nm_device_activate_stage4_ip6_config_get, AF_INET6);
nm_info ("Activation (%s) Stage 4 of 5 (IP6 Configure Get) scheduled...",
nm_device_get_iface (self));
}
static NMActStageReturn
real_act_stage4_ip6_config_timeout (NMDevice *self,
NMIP6Config **config,
NMDeviceStateReason *reason)
{
g_return_val_if_fail (config != NULL, NM_ACT_STAGE_RETURN_FAILURE);
g_return_val_if_fail (*config == NULL, NM_ACT_STAGE_RETURN_FAILURE);
*reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE;
return NM_ACT_STAGE_RETURN_FAILURE;
}
/*
* nm_device_activate_stage4_ip6_config_timeout
*
* Time out on retrieving the IPv6 config.
*
*/
static gboolean
nm_device_activate_stage4_ip6_config_timeout (gpointer user_data)
{
NMDevice *self = NM_DEVICE (user_data);
NMIP6Config *ip6_config = NULL;
const char *iface;
NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
/* Clear the activation source ID now that this stage has run */
activation_source_clear (self, FALSE, AF_INET6);
iface = nm_device_get_iface (self);
nm_info ("Activation (%s) Stage 4 of 5 (IP6 Configure Timeout) started...", iface);
ret = NM_DEVICE_GET_CLASS (self)->act_stage4_ip6_config_timeout (self, &ip6_config, &reason);
if (ret == NM_ACT_STAGE_RETURN_POSTPONE) {
goto out;
} else if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
goto out;
}
g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS);
/* FIXME g_assert (ip6_config); */
g_object_set_data (G_OBJECT (nm_device_get_act_request (self)),
NM_ACT_REQUEST_IP6_CONFIG, ip6_config);
nm_device_activate_schedule_stage5_ip_config_commit (self, AF_INET6);
out:
nm_info ("Activation (%s) Stage 4 of 5 (IP6 Configure Timeout) complete.", iface);
return FALSE;
}
/*
* nm_device_activate_schedule_stage4_ip6_config_timeout
*
* Deal with a timeout of the IPv6 configuration
*
*/
void
nm_device_activate_schedule_stage4_ip6_config_timeout (NMDevice *self)
{
NMDevicePrivate *priv;
g_return_if_fail (NM_IS_DEVICE (self));
priv = NM_DEVICE_GET_PRIVATE (self);
g_return_if_fail (priv->act_request);
activation_source_schedule (self, nm_device_activate_stage4_ip6_config_timeout, AF_INET6);
nm_info ("Activation (%s) Stage 4 of 5 (IP6 Configure Timeout) scheduled...",
nm_device_get_iface (self));
}
@@ -1330,32 +1599,22 @@ share_child_setup (gpointer user_data G_GNUC_UNUSED)
static gboolean
share_init (void)
{
int fd, count, status;
int status;
char *modules[] = { "ip_tables", "iptable_nat", "nf_nat_ftp", "nf_nat_irc",
"nf_nat_sip", "nf_nat_tftp", "nf_nat_pptp", "nf_nat_h323",
NULL };
char **iter;
fd = open ("/proc/sys/net/ipv4/ip_forward", O_WRONLY | O_TRUNC);
if (fd) {
count = write (fd, "1\n", 2);
if (count != 2) {
if (!nm_utils_do_sysctl ("/proc/sys/net/ipv4/ip_forward", "1\n")) {
nm_warning ("%s: Error starting IP forwarding: (%d) %s",
__func__, errno, strerror (errno));
return FALSE;
}
close (fd);
}
fd = open ("/proc/sys/net/ipv4/ip_dynaddr", O_WRONLY | O_TRUNC);
if (fd) {
count = write (fd, "1\n", 2);
if (count != 2) {
if (!nm_utils_do_sysctl ("/proc/sys/net/ipv4/ip_dynaddr", "1\n")) {
nm_warning ("%s: Error starting IP forwarding: (%d) %s",
__func__, errno, strerror (errno));
}
close (fd);
}
for (iter = modules; *iter; iter++) {
char *argv[3] = { "/sbin/modprobe", *iter, NULL };
@@ -1464,6 +1723,7 @@ nm_device_activate_stage5_ip_config_commit (gpointer user_data)
{
NMDevice *self = NM_DEVICE (user_data);
NMIP4Config *ip4_config = NULL;
NMIP6Config *ip6_config = NULL;
const char *iface, *method = NULL;
NMConnection *connection;
NMSettingIP4Config *s_ip4;
@@ -1472,9 +1732,12 @@ nm_device_activate_stage5_ip_config_commit (gpointer user_data)
ip4_config = g_object_get_data (G_OBJECT (nm_device_get_act_request (self)),
NM_ACT_REQUEST_IP4_CONFIG);
g_assert (ip4_config);
ip6_config = g_object_get_data (G_OBJECT (nm_device_get_act_request (self)),
NM_ACT_REQUEST_IP6_CONFIG);
/* FIXME g_assert (ip6_config); */
/* Clear the activation source ID now that this stage has run */
activation_source_clear (self, FALSE);
activation_source_clear (self, FALSE, 0);
iface = nm_device_get_iface (self);
nm_info ("Activation (%s) Stage 5 of 5 (IP Configure Commit) started...",
@@ -1485,6 +1748,11 @@ nm_device_activate_stage5_ip_config_commit (gpointer user_data)
goto out;
}
if (!nm_device_set_ip6_config (self, ip6_config, &reason)) {
nm_info ("Activation (%s) Stage 5 of 5 (IP Configure Commit) IPv6 failed",
iface);
}
connection = nm_act_request_get_connection (nm_device_get_act_request (self));
s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
if (s_ip4)
@@ -1504,8 +1772,9 @@ out:
nm_info ("Activation (%s) Stage 5 of 5 (IP Configure Commit) complete.",
iface);
/* Balance IP4Config creation; device takes ownership in set_ip4_config() */
/* Balance IP config creation; device takes ownership in set_ip*_config() */
g_object_unref (ip4_config);
g_object_unref (ip6_config);
return FALSE;
}
@@ -1517,7 +1786,7 @@ out:
* Schedule commit of the IP config
*/
static void
nm_device_activate_schedule_stage5_ip_config_commit (NMDevice *self)
nm_device_activate_schedule_stage5_ip_config_commit (NMDevice *self, int family)
{
NMDevicePrivate *priv;
@@ -1526,7 +1795,15 @@ nm_device_activate_schedule_stage5_ip_config_commit (NMDevice *self)
priv = NM_DEVICE_GET_PRIVATE (self);
g_return_if_fail (priv->act_request);
activation_source_schedule (self, nm_device_activate_stage5_ip_config_commit);
if (family == AF_INET)
priv->ip4_ready = TRUE;
else if (family == AF_INET6)
priv->ip6_ready = TRUE;
if (!priv->ip4_ready || !priv->ip6_ready)
return;
activation_source_schedule (self, nm_device_activate_stage5_ip_config_commit, 0);
nm_info ("Activation (%s) Stage 5 of 5 (IP Configure Commit) scheduled...",
nm_device_get_iface (self));
@@ -1581,7 +1858,8 @@ nm_device_deactivate_quickly (NMDevice *self)
priv = NM_DEVICE_GET_PRIVATE (self);
/* Break the activation chain */
activation_source_clear (self, TRUE);
activation_source_clear (self, TRUE, AF_INET);
activation_source_clear (self, TRUE, AF_INET6);
if (priv->failed_to_disconnected_id) {
g_source_remove (priv->failed_to_disconnected_id);
@@ -1641,10 +1919,11 @@ nm_device_deactivate (NMDeviceInterface *device, NMDeviceStateReason reason)
/* Clean up nameservers and addresses */
nm_device_set_ip4_config (self, NULL, &ignored);
nm_device_set_ip6_config (self, NULL, &ignored);
/* Take out any entries in the routing table and any IP address the device had. */
nm_system_device_flush_ip4_routes (self);
nm_system_device_flush_ip4_addresses (self);
nm_system_device_flush_routes (self);
nm_system_device_flush_addresses (self);
nm_device_update_ip4_address (self);
/* Call device type-specific deactivation */
@@ -1873,7 +2152,7 @@ dhcp_state_changed (NMDHCPManager *dhcp_manager,
case DHC_REBOOT: /* have valid lease, but now obtained a different one */
case DHC_REBIND: /* new, different lease */
if (dev_state == NM_DEVICE_STATE_IP_CONFIG)
nm_device_activate_schedule_stage4_ip_config_get (device);
nm_device_activate_schedule_stage4_ip4_config_get (device);
else if (dev_state == NM_DEVICE_STATE_ACTIVATED)
handle_dhcp_lease_change (device);
break;
@@ -1881,7 +2160,7 @@ dhcp_state_changed (NMDHCPManager *dhcp_manager,
nm_dhcp4_config_reset (priv->dhcp4_config);
if (nm_device_get_state (device) == NM_DEVICE_STATE_IP_CONFIG)
nm_device_activate_schedule_stage4_ip_config_timeout (device);
nm_device_activate_schedule_stage4_ip4_config_timeout (device);
break;
case DHC_FAIL: /* all attempts to contact server timed out, sleeping */
case DHC_ABEND: /* dhclient exited abnormally */
@@ -1913,7 +2192,7 @@ dhcp_timeout (NMDHCPManager *dhcp_manager,
return;
if (nm_device_get_state (device) == NM_DEVICE_STATE_IP_CONFIG)
nm_device_activate_schedule_stage4_ip_config_timeout (device);
nm_device_activate_schedule_stage4_ip4_config_timeout (device);
}
gboolean
@@ -2049,7 +2328,6 @@ nm_device_set_ip4_config (NMDevice *self,
return success;
}
/*
* nm_device_get_ip4_address
*
@@ -2090,6 +2368,69 @@ nm_device_update_ip4_address (NMDevice *self)
close (fd);
}
static gboolean
nm_device_set_ip6_config (NMDevice *self,
NMIP6Config *new_config,
NMDeviceStateReason *reason)
{
NMDevicePrivate *priv;
const char *ip_iface;
NMIP6Config *old_config = NULL;
gboolean success = TRUE;
NMIP6ConfigCompareFlags diff = NM_IP6_COMPARE_FLAG_ALL;
NMNamedManager *named_mgr;
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
g_return_val_if_fail (reason != NULL, FALSE);
priv = NM_DEVICE_GET_PRIVATE (self);
ip_iface = nm_device_get_ip_iface (self);
old_config = priv->ip6_config;
if (new_config && old_config)
diff = nm_ip6_config_diff (new_config, old_config);
/* No actual change, do nothing */
if (diff == NM_IP6_COMPARE_FLAG_NONE)
return TRUE;
named_mgr = nm_named_manager_get ();
if (old_config) {
/* Remove any previous IP6 Config from the named manager */
nm_named_manager_remove_ip6_config (named_mgr, ip_iface, old_config);
g_object_unref (old_config);
priv->ip6_config = NULL;
}
if (new_config) {
priv->ip6_config = g_object_ref (new_config);
success = nm_system_apply_ip6_config (ip_iface, new_config, nm_device_get_priority (self), diff);
if (success) {
/* Export over D-Bus */
if (!nm_ip6_config_get_dbus_path (new_config))
nm_ip6_config_export (new_config);
/* Add the DNS information to the named manager */
nm_named_manager_add_ip6_config (named_mgr, ip_iface, new_config, NM_NAMED_IP_CONFIG_TYPE_DEFAULT);
}
}
g_object_unref (named_mgr);
g_object_notify (G_OBJECT (self), NM_DEVICE_INTERFACE_IP6_CONFIG);
return success;
}
NMIP6Config *
nm_device_get_ip6_config (NMDevice *self)
{
g_return_val_if_fail (self != NULL, NULL);
return NM_DEVICE_GET_PRIVATE (self)->ip6_config;
}
static gboolean
nm_device_is_up (NMDevice *self)
{
@@ -2229,7 +2570,8 @@ dispose (GObject *object)
clear_act_request (self);
activation_source_clear (self, TRUE);
activation_source_clear (self, TRUE, AF_INET);
activation_source_clear (self, TRUE, AF_INET6);
nm_device_set_use_dhcp (self, FALSE);
@@ -2349,6 +2691,15 @@ get_property (GObject *object, guint prop_id,
else
g_value_set_boxed (value, "/");
break;
case NM_DEVICE_INTERFACE_PROP_IP6_CONFIG:
if ((state == NM_DEVICE_STATE_ACTIVATED) || (state == NM_DEVICE_STATE_IP_CONFIG)) {
if (priv->ip6_config) {
g_value_set_boxed (value, nm_ip6_config_get_dbus_path (priv->ip6_config));
break;
}
}
g_value_set_boxed (value, "/");
break;
case NM_DEVICE_INTERFACE_PROP_STATE:
g_value_set_uint (value, priv->state);
break;
@@ -2386,9 +2737,12 @@ nm_device_class_init (NMDeviceClass *klass)
klass->get_generic_capabilities = real_get_generic_capabilities;
klass->act_stage1_prepare = real_act_stage1_prepare;
klass->act_stage2_config = real_act_stage2_config;
klass->act_stage3_ip_config_start = real_act_stage3_ip_config_start;
klass->act_stage3_ip4_config_start = real_act_stage3_ip4_config_start;
klass->act_stage3_ip6_config_start = real_act_stage3_ip6_config_start;
klass->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config;
klass->act_stage4_ip_config_timeout = real_act_stage4_ip_config_timeout;
klass->act_stage4_get_ip6_config = real_act_stage4_get_ip6_config;
klass->act_stage4_ip4_config_timeout = real_act_stage4_ip4_config_timeout;
klass->act_stage4_ip6_config_timeout = real_act_stage4_ip6_config_timeout;
/* Properties */
@@ -2420,6 +2774,10 @@ nm_device_class_init (NMDeviceClass *klass)
NM_DEVICE_INTERFACE_PROP_DHCP4_CONFIG,
NM_DEVICE_INTERFACE_DHCP4_CONFIG);
g_object_class_override_property (object_class,
NM_DEVICE_INTERFACE_PROP_IP6_CONFIG,
NM_DEVICE_INTERFACE_IP6_CONFIG);
g_object_class_override_property (object_class,
NM_DEVICE_INTERFACE_PROP_STATE,
NM_DEVICE_INTERFACE_STATE);

View File

@@ -29,6 +29,7 @@
#include "NetworkManager.h"
#include "nm-activation-request.h"
#include "nm-ip4-config.h"
#include "nm-ip6-config.h"
#include "nm-dhcp4-config.h"
#include "nm-connection.h"
@@ -92,14 +93,22 @@ typedef struct {
NMDeviceStateReason *reason);
NMActStageReturn (* act_stage2_config) (NMDevice *self,
NMDeviceStateReason *reason);
NMActStageReturn (* act_stage3_ip_config_start) (NMDevice *self,
NMActStageReturn (* act_stage3_ip4_config_start) (NMDevice *self,
NMDeviceStateReason *reason);
NMActStageReturn (* act_stage3_ip6_config_start) (NMDevice *self,
NMDeviceStateReason *reason);
NMActStageReturn (* act_stage4_get_ip4_config) (NMDevice *self,
NMIP4Config **config,
NMDeviceStateReason *reason);
NMActStageReturn (* act_stage4_ip_config_timeout) (NMDevice *self,
NMActStageReturn (* act_stage4_get_ip6_config) (NMDevice *self,
NMIP6Config **config,
NMDeviceStateReason *reason);
NMActStageReturn (* act_stage4_ip4_config_timeout) (NMDevice *self,
NMIP4Config **config,
NMDeviceStateReason *reason);
NMActStageReturn (* act_stage4_ip6_config_timeout) (NMDevice *self,
NMIP6Config **config,
NMDeviceStateReason *reason);
void (* deactivate) (NMDevice *self);
void (* deactivate_quickly) (NMDevice *self);
@@ -128,7 +137,6 @@ int nm_device_get_priority (NMDevice *dev);
guint32 nm_device_get_ip4_address (NMDevice *dev);
void nm_device_update_ip4_address (NMDevice *dev);
struct in6_addr * nm_device_get_ip6_address (NMDevice *dev);
gboolean nm_device_get_use_dhcp (NMDevice *dev);
void nm_device_set_use_dhcp (NMDevice *dev,
@@ -136,6 +144,7 @@ void nm_device_set_use_dhcp (NMDevice *dev,
NMDHCP4Config * nm_device_get_dhcp4_config (NMDevice *dev);
NMIP4Config * nm_device_get_ip4_config (NMDevice *dev);
NMIP6Config * nm_device_get_ip6_config (NMDevice *dev);
void * nm_device_get_system_config_data (NMDevice *dev);
@@ -149,8 +158,10 @@ NMConnection * nm_device_get_best_auto_connection (NMDevice *dev,
void nm_device_activate_schedule_stage1_device_prepare (NMDevice *device);
void nm_device_activate_schedule_stage2_device_config (NMDevice *device);
void nm_device_activate_schedule_stage4_ip_config_get (NMDevice *device);
void nm_device_activate_schedule_stage4_ip_config_timeout (NMDevice *device);
void nm_device_activate_schedule_stage4_ip4_config_get (NMDevice *device);
void nm_device_activate_schedule_stage4_ip4_config_timeout (NMDevice *device);
void nm_device_activate_schedule_stage4_ip6_config_get (NMDevice *device);
void nm_device_activate_schedule_stage4_ip6_config_timeout (NMDevice *device);
gboolean nm_device_deactivate_quickly (NMDevice *dev);
gboolean nm_device_is_activating (NMDevice *dev);
gboolean nm_device_can_interrupt_activation (NMDevice *self);

View File

@@ -851,8 +851,8 @@ vpn_cleanup (NMVPNConnection *connection)
if (priv->tundev) {
nm_system_device_set_up_down_with_iface (priv->tundev, FALSE, NULL);
nm_system_device_flush_ip4_routes_with_iface (priv->tundev);
nm_system_device_flush_ip4_addresses_with_iface (priv->tundev);
nm_system_device_flush_routes_with_iface (priv->tundev);
nm_system_device_flush_addresses_with_iface (priv->tundev);
}
if (priv->ip4_config) {