diff --git a/include/nm-dbus-glib-types.h b/include/nm-dbus-glib-types.h
index be52614cf..cfb08274c 100644
--- a/include/nm-dbus-glib-types.h
+++ b/include/nm-dbus-glib-types.h
@@ -34,8 +34,10 @@
#define DBUS_TYPE_G_MAP_OF_STRING (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING))
#define DBUS_TYPE_G_LIST_OF_STRING (dbus_g_type_get_collection ("GSList", G_TYPE_STRING))
-#define DBUS_TYPE_G_IP6_ADDRESS (dbus_g_type_get_struct ("GValueArray", DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT, DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_INVALID))
+#define DBUS_TYPE_G_IP6_ADDRESS (dbus_g_type_get_struct ("GValueArray", DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT, G_TYPE_INVALID))
#define DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_IP6_ADDRESS))
+#define DBUS_TYPE_G_IP6_ROUTE (dbus_g_type_get_struct ("GValueArray", DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT, DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT, G_TYPE_INVALID))
+#define DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_IP6_ROUTE))
#endif /* DBUS_GLIB_TYPES_H */
diff --git a/introspection/Makefile.am b/introspection/Makefile.am
index a77dba1a7..eee9eb189 100644
--- a/introspection/Makefile.am
+++ b/introspection/Makefile.am
@@ -4,6 +4,7 @@ EXTRA_DIST = \
errors.xml \
vpn-errors.xml \
nm-access-point.xml \
+ nm-device-bt.xml \
nm-device-wifi.xml \
nm-device-ethernet.xml \
nm-device-cdma.xml \
@@ -11,6 +12,7 @@ EXTRA_DIST = \
nm-device-serial.xml \
nm-device.xml \
nm-ip4-config.xml \
+ nm-ip6-config.xml \
nm-manager.xml \
nm-manager-client.xml \
nm-settings.xml \
diff --git a/introspection/nm-ip6-config.xml b/introspection/nm-ip6-config.xml
new file mode 100644
index 000000000..d1349b0c2
--- /dev/null
+++ b/introspection/nm-ip6-config.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+ Tuples of IPv6 address/prefix.
+
+
+ The nameservers in use.
+
+
+ A list of domains this address belongs to.
+
+
+ Tuples of IPv6 route/prefix/next-hop/metric.
+
+
+
+
diff --git a/libnm-util/Makefile.am b/libnm-util/Makefile.am
index bc7befb06..1a5a94eb3 100644
--- a/libnm-util/Makefile.am
+++ b/libnm-util/Makefile.am
@@ -17,6 +17,7 @@ libnm_util_include_HEADERS = \
nm-setting-bluetooth.h \
nm-setting-connection.h \
nm-setting-ip4-config.h \
+ nm-setting-ip6-config.h \
nm-setting-ppp.h \
nm-setting-pppoe.h \
nm-setting-serial.h \
@@ -106,5 +107,5 @@ pkgconfig_DATA = libnm-util.pc
DISTCLEANFILES = libnm-util.pc
-EXTRA_DIST = libnm-util.pc.in libnm-util.ver nm-setting-ip6-config.h
+EXTRA_DIST = libnm-util.pc.in libnm-util.ver
diff --git a/libnm-util/libnm-util.ver b/libnm-util/libnm-util.ver
index 4d372a743..92228f525 100644
--- a/libnm-util/libnm-util.ver
+++ b/libnm-util/libnm-util.ver
@@ -140,6 +140,56 @@ global:
nm_setting_ip4_config_get_dhcp_hostname;
nm_setting_ip4_config_get_dhcp_send_hostname;
nm_setting_ip4_config_get_never_default;
+ nm_setting_ip6_config_error_get_type;
+ nm_setting_ip6_config_error_quark;
+ nm_ip6_address_new;
+ nm_ip6_address_dup;
+ nm_ip6_address_ref;
+ nm_ip6_address_unref;
+ nm_ip6_address_compare;
+ nm_ip6_address_get_address;
+ nm_ip6_address_set_address;
+ nm_ip6_address_get_prefix;
+ nm_ip6_address_set_prefix;
+ nm_ip6_route_new;
+ nm_ip6_route_dup;
+ nm_ip6_route_ref;
+ nm_ip6_route_unref;
+ nm_ip6_route_compare;
+ nm_ip6_route_get_dest;
+ nm_ip6_route_set_dest;
+ nm_ip6_route_get_prefix;
+ nm_ip6_route_set_prefix;
+ nm_ip6_route_get_next_hop;
+ nm_ip6_route_set_next_hop;
+ nm_ip6_route_get_metric;
+ nm_ip6_route_set_metric;
+ nm_setting_ip6_config_get_type;
+ nm_setting_ip6_config_new;
+ nm_setting_ip6_config_get_method;
+ nm_setting_ip6_config_get_num_dns;
+ nm_setting_ip6_config_get_dns;
+ nm_setting_ip6_config_add_dns;
+ nm_setting_ip6_config_remove_dns;
+ nm_setting_ip6_config_clear_dns;
+ nm_setting_ip6_config_get_num_dns_searches;
+ nm_setting_ip6_config_get_dns_search;
+ nm_setting_ip6_config_add_dns_search;
+ nm_setting_ip6_config_remove_dns_search;
+ nm_setting_ip6_config_clear_dns_searches;
+ nm_setting_ip6_config_get_num_addresses;
+ nm_setting_ip6_config_get_address;
+ nm_setting_ip6_config_add_address;
+ nm_setting_ip6_config_remove_address;
+ nm_setting_ip6_config_clear_addresses;
+ nm_setting_ip6_config_get_num_routes;
+ nm_setting_ip6_config_get_route;
+ nm_setting_ip6_config_add_route;
+ nm_setting_ip6_config_remove_route;
+ nm_setting_ip6_config_clear_routes;
+ nm_setting_ip6_config_get_ignore_auto_routes;
+ nm_setting_ip6_config_get_ignore_auto_dns;
+ nm_setting_ip6_config_get_never_default;
nm_setting_need_secrets;
nm_setting_ppp_error_get_type;
nm_setting_ppp_error_quark;
@@ -263,6 +313,10 @@ global:
nm_utils_ip4_prefix_to_netmask;
nm_utils_ip4_routes_from_gvalue;
nm_utils_ip4_routes_to_gvalue;
+ nm_utils_ip6_addresses_from_gvalue;
+ nm_utils_ip6_addresses_to_gvalue;
+ nm_utils_ip6_routes_from_gvalue;
+ nm_utils_ip6_routes_to_gvalue;
nm_utils_is_empty_ssid;
nm_utils_same_ssid;
nm_utils_security_valid;
diff --git a/libnm-util/nm-connection.c b/libnm-util/nm-connection.c
index e0160232c..810032ae5 100644
--- a/libnm-util/nm-connection.c
+++ b/libnm-util/nm-connection.c
@@ -266,6 +266,11 @@ register_default_settings (void)
NM_SETTING_IP4_CONFIG_ERROR,
6);
+ register_one_setting (NM_SETTING_IP6_CONFIG_SETTING_NAME,
+ NM_TYPE_SETTING_IP6_CONFIG,
+ NM_SETTING_IP6_CONFIG_ERROR,
+ 6);
+
/* Be sure to update DEFAULT_MAP_SIZE if you add another setting!! */
}
diff --git a/libnm-util/nm-setting-8021x.c b/libnm-util/nm-setting-8021x.c
index 1c7a8bc70..68efff391 100644
--- a/libnm-util/nm-setting-8021x.c
+++ b/libnm-util/nm-setting-8021x.c
@@ -947,7 +947,7 @@ static EAPMethodsTable eap_methods_table[] = {
{ "peap", need_secrets_phase2, verify_ttls },
{ "ttls", need_secrets_phase2, verify_ttls },
{ "sim", need_secrets_sim, NULL },
- { "gtc", NULL, NULL }, // FIXME: implement
+ { "gtc", need_secrets_password, verify_identity },
{ "otp", NULL, NULL }, // FIXME: implement
{ NULL, NULL, NULL }
};
diff --git a/libnm-util/nm-setting-ip6-config.c b/libnm-util/nm-setting-ip6-config.c
index 66defb38c..d9da92fa8 100644
--- a/libnm-util/nm-setting-ip6-config.c
+++ b/libnm-util/nm-setting-ip6-config.c
@@ -30,13 +30,6 @@
#include "nm-utils.h"
#include "nm-dbus-glib-types.h"
-GSList *nm_utils_ip6_addresses_from_gvalue (const GValue *value);
-void nm_utils_ip6_addresses_to_gvalue (GSList *list, GValue *value);
-
-GSList *nm_utils_ip6_dns_from_gvalue (const GValue *value);
-void nm_utils_ip6_dns_to_gvalue (GSList *list, GValue *value);
-
-
GQuark
nm_setting_ip6_config_error_quark (void)
{
@@ -83,9 +76,9 @@ typedef struct {
GSList *dns_search; /* list of strings */
GSList *addresses; /* array of NMIP6Address */
GSList *routes; /* array of NMIP6Route */
+ gboolean ignore_auto_routes;
gboolean ignore_auto_dns;
- gboolean ignore_ra;
- char *dhcp_mode;
+ gboolean never_default;
} NMSettingIP6ConfigPrivate;
@@ -96,9 +89,9 @@ enum {
PROP_DNS_SEARCH,
PROP_ADDRESSES,
PROP_ROUTES,
+ PROP_IGNORE_AUTO_ROUTES,
PROP_IGNORE_AUTO_DNS,
- PROP_IGNORE_ROUTER_ADV,
- PROP_DHCP_MODE,
+ PROP_NEVER_DEFAULT,
LAST_PROP
};
@@ -397,6 +390,14 @@ nm_setting_ip6_config_clear_routes (NMSettingIP6Config *setting)
priv->routes = NULL;
}
+gboolean
+nm_setting_ip6_config_get_ignore_auto_routes (NMSettingIP6Config *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE);
+
+ return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->ignore_auto_routes;
+}
+
gboolean
nm_setting_ip6_config_get_ignore_auto_dns (NMSettingIP6Config *setting)
{
@@ -406,19 +407,11 @@ nm_setting_ip6_config_get_ignore_auto_dns (NMSettingIP6Config *setting)
}
gboolean
-nm_setting_ip6_config_get_ignore_router_adv (NMSettingIP6Config *setting)
+nm_setting_ip6_config_get_never_default (NMSettingIP6Config *setting)
{
g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE);
- return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->ignore_ra;
-}
-
-const char *
-nm_setting_ip6_config_get_dhcp_mode (NMSettingIP6Config *setting)
-{
- g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE);
-
- return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->dhcp_mode;
+ return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->never_default;
}
static gboolean
@@ -443,6 +436,7 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
return FALSE;
}
} else if ( !strcmp (priv->method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)
+ || !strcmp (priv->method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)
|| !strcmp (priv->method, NM_SETTING_IP6_CONFIG_METHOD_SHARED)) {
if (!priv->ignore_auto_dns) {
if (priv->dns && g_slist_length (priv->dns)) {
@@ -469,17 +463,6 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
NM_SETTING_IP6_CONFIG_ADDRESSES);
return FALSE;
}
-
- /* if router advertisement autoconf is disabled, dhcpv6 mode must
- * be SOMETHING as long as the user has selected the auto method
- */
- if (priv->ignore_ra && (priv->dhcp_mode == NULL)) {
- g_set_error (error,
- NM_SETTING_IP6_CONFIG_ERROR,
- NM_SETTING_IP6_CONFIG_ERROR_INVALID_PROPERTY,
- NM_SETTING_IP6_CONFIG_DHCP_MODE);
- return FALSE;
- }
} else {
g_set_error (error,
NM_SETTING_IP6_CONFIG_ERROR,
@@ -540,17 +523,16 @@ set_property (GObject *object, guint prop_id,
break;
case PROP_ROUTES:
nm_utils_slist_free (priv->routes, g_free);
- priv->routes = nm_utils_ip6_addresses_from_gvalue (value);
+ priv->routes = nm_utils_ip6_routes_from_gvalue (value);
+ break;
+ case PROP_IGNORE_AUTO_ROUTES:
+ priv->ignore_auto_routes = g_value_get_boolean (value);
break;
case PROP_IGNORE_AUTO_DNS:
priv->ignore_auto_dns = g_value_get_boolean (value);
break;
- case PROP_IGNORE_ROUTER_ADV:
- priv->ignore_ra = g_value_get_boolean (value);
- break;
- case PROP_DHCP_MODE:
- g_free (priv->dhcp_mode);
- priv->dhcp_mode = g_value_dup_string (value);
+ case PROP_NEVER_DEFAULT:
+ priv->never_default = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -578,16 +560,16 @@ get_property (GObject *object, guint prop_id,
nm_utils_ip6_addresses_to_gvalue (priv->addresses, value);
break;
case PROP_ROUTES:
- nm_utils_ip6_addresses_to_gvalue (priv->routes, value);
+ nm_utils_ip6_routes_to_gvalue (priv->routes, value);
+ break;
+ case PROP_IGNORE_AUTO_ROUTES:
+ g_value_set_boolean (value, priv->ignore_auto_routes);
break;
case PROP_IGNORE_AUTO_DNS:
g_value_set_boolean (value, priv->ignore_auto_dns);
break;
- case PROP_IGNORE_ROUTER_ADV:
- g_value_set_boolean (value, priv->ignore_ra);
- break;
- case PROP_DHCP_MODE:
- g_value_set_string (value, priv->dhcp_mode);
+ case PROP_NEVER_DEFAULT:
+ g_value_set_boolean (value, priv->never_default);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -601,6 +583,8 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *setting_class)
GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+ g_type_class_add_private (setting_class, sizeof (NMSettingIP6ConfigPrivate));
+
/* virtual methods */
object_class->set_property = set_property;
object_class->get_property = get_property;
@@ -645,39 +629,39 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *setting_class)
_nm_param_spec_specialized (NM_SETTING_IP6_CONFIG_ROUTES,
"Routes",
"List of NMSettingIP6Addresses",
- DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS,
+ DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+ g_object_class_install_property
+ (object_class, PROP_IGNORE_AUTO_ROUTES,
+ g_param_spec_boolean (NM_SETTING_IP6_CONFIG_IGNORE_AUTO_ROUTES,
+ "Ignore automatic routes",
+ "Ignore automatic routes",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+
g_object_class_install_property
(object_class, PROP_IGNORE_AUTO_DNS,
g_param_spec_boolean (NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS,
- "Ignore DHCPv6 DNS",
- "Ignore DHCPv6 DNS",
+ "Ignore DHCPv6/RDNSS DNS",
+ "Ignore DHCPv6/RDNSS DNS",
FALSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
g_object_class_install_property
- (object_class, PROP_IGNORE_ROUTER_ADV,
- g_param_spec_boolean (NM_SETTING_IP6_CONFIG_IGNORE_ROUTER_ADV,
- "Ignore Router Advertisements",
- "Ignore Router Advertisements",
+ (object_class, PROP_NEVER_DEFAULT,
+ g_param_spec_boolean (NM_SETTING_IP6_CONFIG_NEVER_DEFAULT,
+ "Never default",
+ "Never make this connection the default IPv6 connection",
FALSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
- g_object_class_install_property
- (object_class, PROP_DHCP_MODE,
- g_param_spec_string (NM_SETTING_IP6_CONFIG_DHCP_MODE,
- "DHCPv6 Client Mode",
- "DHCPv6 Client Mode",
- NULL,
- G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
}
struct NMIP6Address {
guint32 refcount;
- struct in6_addr *address; /* network byte order */
+ struct in6_addr address;
guint32 prefix;
- struct in6_addr *gateway; /* network byte order */
};
NMIP6Address *
@@ -700,16 +684,7 @@ nm_ip6_address_dup (NMIP6Address *source)
address = nm_ip6_address_new ();
address->prefix = source->prefix;
-
- if (source->address) {
- address->address = g_malloc0 (sizeof (struct in6_addr));
- memcpy (address->address, source->address, sizeof (struct in6_addr));
- }
-
- if (source->gateway) {
- address->gateway = g_malloc0 (sizeof (struct in6_addr));
- memcpy (address->gateway, source->gateway, sizeof (struct in6_addr));
- }
+ memcpy (&address->address, &source->address, sizeof (struct in6_addr));
return address;
}
@@ -731,8 +706,6 @@ nm_ip6_address_unref (NMIP6Address *address)
address->refcount--;
if (address->refcount == 0) {
- g_free (address->address);
- g_free (address->gateway);
memset (address, 0, sizeof (NMIP6Address));
g_free (address);
}
@@ -747,9 +720,8 @@ nm_ip6_address_compare (NMIP6Address *address, NMIP6Address *other)
g_return_val_if_fail (other != NULL, FALSE);
g_return_val_if_fail (other->refcount > 0, FALSE);
- if ( memcmp (address->address, other->address, sizeof (struct in6_addr))
- || address->prefix != other->prefix
- || memcmp (address->gateway, other->gateway, sizeof (struct in6_addr)))
+ if ( memcmp (&address->address, &other->address, sizeof (struct in6_addr))
+ || address->prefix != other->prefix)
return FALSE;
return TRUE;
}
@@ -760,7 +732,7 @@ nm_ip6_address_get_address (NMIP6Address *address)
g_return_val_if_fail (address != NULL, 0);
g_return_val_if_fail (address->refcount > 0, 0);
- return address->address;
+ return &address->address;
}
void
@@ -768,14 +740,9 @@ nm_ip6_address_set_address (NMIP6Address *address, const struct in6_addr *addr)
{
g_return_if_fail (address != NULL);
g_return_if_fail (address->refcount > 0);
+ g_return_if_fail (addr != NULL);
- g_free (address->address);
- address->address = NULL;
-
- if (addr) {
- address->address = g_malloc0 (sizeof (struct in6_addr));
- memcpy (address->address, addr, sizeof (struct in6_addr));
- }
+ memcpy (&address->address, addr, sizeof (struct in6_addr));
}
guint32
@@ -796,37 +763,12 @@ nm_ip6_address_set_prefix (NMIP6Address *address, guint32 prefix)
address->prefix = prefix;
}
-const struct in6_addr *
-nm_ip6_address_get_gateway (NMIP6Address *address)
-{
- g_return_val_if_fail (address != NULL, 0);
- g_return_val_if_fail (address->refcount > 0, 0);
-
- return address->gateway;
-}
-
-void
-nm_ip6_address_set_gateway (NMIP6Address *address, const struct in6_addr *gateway)
-{
- g_return_if_fail (address != NULL);
- g_return_if_fail (address->refcount > 0);
-
- g_free (address->gateway);
- address->gateway = NULL;
-
- if (gateway) {
- address->gateway = g_malloc0 (sizeof (struct in6_addr));
- memcpy (address->gateway, gateway, sizeof (struct in6_addr));
- }
-}
-
-
struct NMIP6Route {
guint32 refcount;
- struct in6_addr *dest; /* network byte order */
+ struct in6_addr dest;
guint32 prefix;
- struct in6_addr *next_hop; /* network byte order */
+ struct in6_addr next_hop;
guint32 metric; /* lower metric == more preferred */
};
@@ -851,16 +793,8 @@ nm_ip6_route_dup (NMIP6Route *source)
route = nm_ip6_route_new ();
route->prefix = source->prefix;
route->metric = source->metric;
-
- if (source->dest) {
- route->dest = g_malloc0 (sizeof (struct in6_addr));
- memcpy (route->dest, source->dest, sizeof (struct in6_addr));
- }
-
- if (source->next_hop) {
- route->next_hop = g_malloc0 (sizeof (struct in6_addr));
- memcpy (route->next_hop, source->next_hop, sizeof (struct in6_addr));
- }
+ memcpy (&route->dest, &source->dest, sizeof (struct in6_addr));
+ memcpy (&route->next_hop, &source->next_hop, sizeof (struct in6_addr));
return route;
}
@@ -882,8 +816,6 @@ nm_ip6_route_unref (NMIP6Route *route)
route->refcount--;
if (route->refcount == 0) {
- g_free (route->dest);
- g_free (route->next_hop);
memset (route, 0, sizeof (NMIP6Route));
g_free (route);
}
@@ -898,9 +830,9 @@ nm_ip6_route_compare (NMIP6Route *route, NMIP6Route *other)
g_return_val_if_fail (other != NULL, FALSE);
g_return_val_if_fail (other->refcount > 0, FALSE);
- if ( memcmp (route->dest, other->dest, sizeof (struct in6_addr))
+ if ( memcmp (&route->dest, &other->dest, sizeof (struct in6_addr))
|| route->prefix != other->prefix
- || memcmp (route->next_hop, other->next_hop, sizeof (struct in6_addr))
+ || memcmp (&route->next_hop, &other->next_hop, sizeof (struct in6_addr))
|| route->metric != other->metric)
return FALSE;
return TRUE;
@@ -912,7 +844,7 @@ nm_ip6_route_get_dest (NMIP6Route *route)
g_return_val_if_fail (route != NULL, 0);
g_return_val_if_fail (route->refcount > 0, 0);
- return route->dest;
+ return &route->dest;
}
void
@@ -920,14 +852,9 @@ nm_ip6_route_set_dest (NMIP6Route *route, const struct in6_addr *dest)
{
g_return_if_fail (route != NULL);
g_return_if_fail (route->refcount > 0);
+ g_return_if_fail (dest != NULL);
- g_free (route->dest);
- route->dest = NULL;
-
- if (dest) {
- route->dest = g_malloc0 (sizeof (struct in6_addr));
- memcpy (route->dest, dest, sizeof (struct in6_addr));
- }
+ memcpy (&route->dest, dest, sizeof (struct in6_addr));
}
guint32
@@ -954,7 +881,7 @@ nm_ip6_route_get_next_hop (NMIP6Route *route)
g_return_val_if_fail (route != NULL, 0);
g_return_val_if_fail (route->refcount > 0, 0);
- return route->next_hop;
+ return &route->next_hop;
}
void
@@ -962,14 +889,9 @@ nm_ip6_route_set_next_hop (NMIP6Route *route, const struct in6_addr *next_hop)
{
g_return_if_fail (route != NULL);
g_return_if_fail (route->refcount > 0);
+ g_return_if_fail (next_hop != NULL);
- g_free (route->next_hop);
- route->next_hop = NULL;
-
- if (next_hop) {
- route->next_hop = g_malloc0 (sizeof (struct in6_addr));
- memcpy (route->next_hop, next_hop, sizeof (struct in6_addr));
- }
+ memcpy (&route->next_hop, next_hop, sizeof (struct in6_addr));
}
guint32
@@ -989,4 +911,3 @@ nm_ip6_route_set_metric (NMIP6Route *route, guint32 metric)
route->metric = metric;
}
-
diff --git a/libnm-util/nm-setting-ip6-config.h b/libnm-util/nm-setting-ip6-config.h
index 879d82e0c..4e3994023 100644
--- a/libnm-util/nm-setting-ip6-config.h
+++ b/libnm-util/nm-setting-ip6-config.h
@@ -54,21 +54,20 @@ GType nm_setting_ip6_config_error_get_type (void);
#define NM_SETTING_IP6_CONFIG_ERROR nm_setting_ip6_config_error_quark ()
GQuark nm_setting_ip6_config_error_quark (void);
-#define NM_SETTING_IP6_CONFIG_METHOD "method"
-#define NM_SETTING_IP6_CONFIG_DNS "dns"
-#define NM_SETTING_IP6_CONFIG_DNS_SEARCH "dns-search"
-#define NM_SETTING_IP6_CONFIG_ADDRESSES "addresses"
-#define NM_SETTING_IP6_CONFIG_ROUTES "routes"
-#define NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS "ignore-auto-dns"
-#define NM_SETTING_IP6_CONFIG_IGNORE_ROUTER_ADV "ignore-router-adv"
-#define NM_SETTING_IP6_CONFIG_DHCP_MODE "dhcp-mode"
+#define NM_SETTING_IP6_CONFIG_METHOD "method"
+#define NM_SETTING_IP6_CONFIG_DNS "dns"
+#define NM_SETTING_IP6_CONFIG_DNS_SEARCH "dns-search"
+#define NM_SETTING_IP6_CONFIG_ADDRESSES "addresses"
+#define NM_SETTING_IP6_CONFIG_ROUTES "routes"
+#define NM_SETTING_IP6_CONFIG_IGNORE_AUTO_ROUTES "ignore-auto-routes"
+#define NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS "ignore-auto-dns"
+#define NM_SETTING_IP6_CONFIG_NEVER_DEFAULT "never-default"
-#define NM_SETTING_IP6_CONFIG_METHOD_AUTO "auto"
-#define NM_SETTING_IP6_CONFIG_METHOD_MANUAL "manual"
-#define NM_SETTING_IP6_CONFIG_METHOD_SHARED "shared"
-
-#define NM_SETTING_IP6_CONFIG_DHCPV6_MODE_INFO "info"
-#define NM_SETTING_IP6_CONFIG_DHCPV6_MODE_REQUEST "request"
+#define NM_SETTING_IP6_CONFIG_METHOD_IGNORE "ignore"
+#define NM_SETTING_IP6_CONFIG_METHOD_AUTO "auto"
+#define NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL "link-local"
+#define NM_SETTING_IP6_CONFIG_METHOD_MANUAL "manual"
+#define NM_SETTING_IP6_CONFIG_METHOD_SHARED "shared"
typedef struct NMIP6Address NMIP6Address;
@@ -82,16 +81,12 @@ gboolean nm_ip6_address_compare (NMIP6Address *address, NMIP6A
const struct in6_addr *nm_ip6_address_get_address (NMIP6Address *address);
void nm_ip6_address_set_address (NMIP6Address *address,
- const struct in6_addr *addr); /* network byte order */
+ const struct in6_addr *addr);
guint32 nm_ip6_address_get_prefix (NMIP6Address *address);
void nm_ip6_address_set_prefix (NMIP6Address *address,
guint32 prefix);
-const struct in6_addr *nm_ip6_address_get_gateway (NMIP6Address *address);
-void nm_ip6_address_set_gateway (NMIP6Address *address,
- const struct in6_addr *addr); /* network byte order */
-
typedef struct NMIP6Route NMIP6Route;
NMIP6Route * nm_ip6_route_new (void);
@@ -103,7 +98,7 @@ gboolean nm_ip6_route_compare (NMIP6Route *route, NMIP6Route
const struct in6_addr *nm_ip6_route_get_dest (NMIP6Route *route);
void nm_ip6_route_set_dest (NMIP6Route *route,
- const struct in6_addr *dest); /* network byte order */
+ const struct in6_addr *dest);
guint32 nm_ip6_route_get_prefix (NMIP6Route *route);
void nm_ip6_route_set_prefix (NMIP6Route *route,
@@ -111,7 +106,7 @@ void nm_ip6_route_set_prefix (NMIP6Route *route,
const struct in6_addr *nm_ip6_route_get_next_hop (NMIP6Route *route);
void nm_ip6_route_set_next_hop (NMIP6Route *route,
- const struct in6_addr *next_hop); /* network byte order */
+ const struct in6_addr *next_hop);
guint32 nm_ip6_route_get_metric (NMIP6Route *route);
void nm_ip6_route_set_metric (NMIP6Route *route,
@@ -125,40 +120,38 @@ typedef struct {
NMSettingClass parent;
} NMSettingIP6ConfigClass;
-/* IPv6 support is currently incomplete. Do not use. */
-
GType nm_setting_ip6_config_get_type (void);
-NMSetting * nm_setting_ip6_config_new (void);
-const char * nm_setting_ip6_config_get_method (NMSettingIP6Config *setting);
+NMSetting * nm_setting_ip6_config_new (void);
+const char * nm_setting_ip6_config_get_method (NMSettingIP6Config *setting);
-guint32 nm_setting_ip6_config_get_num_dns (NMSettingIP6Config *setting);
-const struct in6_addr *nm_setting_ip6_config_get_dns (NMSettingIP6Config *setting, guint32 i);
-gboolean nm_setting_ip6_config_add_dns (NMSettingIP6Config *setting, const struct in6_addr *dns);
-void nm_setting_ip6_config_remove_dns (NMSettingIP6Config *setting, guint32 i);
-void nm_setting_ip6_config_clear_dns (NMSettingIP6Config *setting);
+guint32 nm_setting_ip6_config_get_num_dns (NMSettingIP6Config *setting);
+const struct in6_addr *nm_setting_ip6_config_get_dns (NMSettingIP6Config *setting, guint32 i);
+gboolean nm_setting_ip6_config_add_dns (NMSettingIP6Config *setting, const struct in6_addr *dns);
+void nm_setting_ip6_config_remove_dns (NMSettingIP6Config *setting, guint32 i);
+void nm_setting_ip6_config_clear_dns (NMSettingIP6Config *setting);
-guint32 nm_setting_ip6_config_get_num_dns_searches (NMSettingIP6Config *setting);
-const char * nm_setting_ip6_config_get_dns_search (NMSettingIP6Config *setting, guint32 i);
-gboolean nm_setting_ip6_config_add_dns_search (NMSettingIP6Config *setting, const char *dns_search);
-void nm_setting_ip6_config_remove_dns_search (NMSettingIP6Config *setting, guint32 i);
-void nm_setting_ip6_config_clear_dns_searches (NMSettingIP6Config *setting);
+guint32 nm_setting_ip6_config_get_num_dns_searches (NMSettingIP6Config *setting);
+const char * nm_setting_ip6_config_get_dns_search (NMSettingIP6Config *setting, guint32 i);
+gboolean nm_setting_ip6_config_add_dns_search (NMSettingIP6Config *setting, const char *dns_search);
+void nm_setting_ip6_config_remove_dns_search (NMSettingIP6Config *setting, guint32 i);
+void nm_setting_ip6_config_clear_dns_searches (NMSettingIP6Config *setting);
-guint32 nm_setting_ip6_config_get_num_addresses (NMSettingIP6Config *setting);
-NMIP6Address * nm_setting_ip6_config_get_address (NMSettingIP6Config *setting, guint32 i);
-gboolean nm_setting_ip6_config_add_address (NMSettingIP6Config *setting, NMIP6Address *address);
-void nm_setting_ip6_config_remove_address (NMSettingIP6Config *setting, guint32 i);
-void nm_setting_ip6_config_clear_addresses (NMSettingIP6Config *setting);
+guint32 nm_setting_ip6_config_get_num_addresses (NMSettingIP6Config *setting);
+NMIP6Address * nm_setting_ip6_config_get_address (NMSettingIP6Config *setting, guint32 i);
+gboolean nm_setting_ip6_config_add_address (NMSettingIP6Config *setting, NMIP6Address *address);
+void nm_setting_ip6_config_remove_address (NMSettingIP6Config *setting, guint32 i);
+void nm_setting_ip6_config_clear_addresses (NMSettingIP6Config *setting);
-guint32 nm_setting_ip6_config_get_num_routes (NMSettingIP6Config *setting);
-NMIP6Route * nm_setting_ip6_config_get_route (NMSettingIP6Config *setting, guint32 i);
-gboolean nm_setting_ip6_config_add_route (NMSettingIP6Config *setting, NMIP6Route *route);
-void nm_setting_ip6_config_remove_route (NMSettingIP6Config *setting, guint32 i);
-void nm_setting_ip6_config_clear_routes (NMSettingIP6Config *setting);
+guint32 nm_setting_ip6_config_get_num_routes (NMSettingIP6Config *setting);
+NMIP6Route * nm_setting_ip6_config_get_route (NMSettingIP6Config *setting, guint32 i);
+gboolean nm_setting_ip6_config_add_route (NMSettingIP6Config *setting, NMIP6Route *route);
+void nm_setting_ip6_config_remove_route (NMSettingIP6Config *setting, guint32 i);
+void nm_setting_ip6_config_clear_routes (NMSettingIP6Config *setting);
+gboolean nm_setting_ip6_config_get_ignore_auto_routes (NMSettingIP6Config *setting);
-gboolean nm_setting_ip6_config_get_ignore_auto_dns (NMSettingIP6Config *setting);
-gboolean nm_setting_ip6_config_get_ignore_router_adv (NMSettingIP6Config *setting);
-const char * nm_setting_ip6_config_get_dhcp_mode (NMSettingIP6Config *setting);
+gboolean nm_setting_ip6_config_get_ignore_auto_dns (NMSettingIP6Config *setting);
+gboolean nm_setting_ip6_config_get_never_default (NMSettingIP6Config *setting);
G_END_DECLS
diff --git a/libnm-util/nm-utils.c b/libnm-util/nm-utils.c
index f9a56f470..a03412140 100644
--- a/libnm-util/nm-utils.c
+++ b/libnm-util/nm-utils.c
@@ -54,14 +54,6 @@
* access points and devices, among other things.
*/
-/* IP6 currently incomplete */
-GSList *nm_utils_ip6_addresses_from_gvalue (const GValue *value);
-void nm_utils_ip6_addresses_to_gvalue (GSList *list, GValue *value);
-
-GSList *nm_utils_ip6_dns_from_gvalue (const GValue *value);
-void nm_utils_ip6_dns_to_gvalue (GSList *list, GValue *value);
-
-
struct EncodingTriplet
{
const char *encoding1;
@@ -1228,14 +1220,13 @@ nm_utils_ip6_addresses_from_gvalue (const GValue *value)
for (i = 0; addresses && (i < addresses->len); i++) {
GValueArray *elements = (GValueArray *) g_ptr_array_index (addresses, i);
GValue *tmp;
- GByteArray *ba_addr, *ba_gw;
+ GByteArray *ba_addr;
NMIP6Address *addr;
guint32 prefix;
- if ( (elements->n_values != 3)
+ if ( (elements->n_values != 2)
|| (G_VALUE_TYPE (g_value_array_get_nth (elements, 0)) != DBUS_TYPE_G_UCHAR_ARRAY)
- || (G_VALUE_TYPE (g_value_array_get_nth (elements, 1)) != G_TYPE_UINT)
- || (G_VALUE_TYPE (g_value_array_get_nth (elements, 2)) != DBUS_TYPE_G_UCHAR_ARRAY)) {
+ || (G_VALUE_TYPE (g_value_array_get_nth (elements, 1)) != G_TYPE_UINT)) {
nm_warning ("%s: ignoring invalid IP6 address structure", __func__);
continue;
}
@@ -1256,18 +1247,9 @@ nm_utils_ip6_addresses_from_gvalue (const GValue *value)
continue;
}
- tmp = g_value_array_get_nth (elements, 2);
- ba_gw = g_value_get_boxed (tmp);
- if (ba_gw->len != 16) {
- nm_warning ("%s: ignoring invalid IP6 gateway of length %d",
- __func__, ba_gw->len);
- continue;
- }
-
addr = nm_ip6_address_new ();
nm_ip6_address_set_prefix (addr, prefix);
nm_ip6_address_set_address (addr, (const struct in6_addr *) ba_addr->data);
- nm_ip6_address_set_gateway (addr, (const struct in6_addr *) ba_gw->data);
list = g_slist_prepend (list, addr);
}
@@ -1284,31 +1266,131 @@ nm_utils_ip6_addresses_to_gvalue (GSList *list, GValue *value)
for (iter = list; iter; iter = iter->next) {
NMIP6Address *addr = (NMIP6Address *) iter->data;
- GValue element = { 0, };
- GByteArray *ba_addr, *ba_gw;
+ GValueArray *array;
+ GValue element = {0, };
+ GByteArray *ba;
- g_value_init (&element, DBUS_TYPE_G_IP6_ADDRESS);
- g_value_take_boxed (&element, dbus_g_type_specialized_construct (DBUS_TYPE_G_IP6_ADDRESS));
+ array = g_value_array_new (2);
- ba_addr = g_byte_array_sized_new (16);
- g_byte_array_append (ba_addr, (guint8 *) nm_ip6_address_get_address (addr), 16);
-
- ba_gw = g_byte_array_sized_new (16);
- g_byte_array_append (ba_gw, (guint8 *) nm_ip6_address_get_gateway (addr), 16);
-
- dbus_g_type_struct_set (&element,
- 0, ba_addr,
- 1, nm_ip6_address_get_prefix (addr),
- 2, ba_gw,
- G_MAXUINT);
-
- g_ptr_array_add (addresses, g_value_get_boxed (&element));
+ g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY);
+ ba = g_byte_array_new ();
+ g_byte_array_append (ba, (guint8 *) nm_ip6_address_get_address (addr), 16);
+ g_value_take_boxed (&element, ba);
+ g_value_array_append (array, &element);
g_value_unset (&element);
+
+ g_value_init (&element, G_TYPE_UINT);
+ g_value_set_uint (&element, nm_ip6_address_get_prefix (addr));
+ g_value_array_append (array, &element);
+ g_value_unset (&element);
+
+ g_ptr_array_add (addresses, array);
}
g_value_take_boxed (value, addresses);
}
+GSList *
+nm_utils_ip6_routes_from_gvalue (const GValue *value)
+{
+ GPtrArray *routes;
+ int i;
+ GSList *list = NULL;
+
+ routes = (GPtrArray *) g_value_get_boxed (value);
+ for (i = 0; routes && (i < routes->len); i++) {
+ GValueArray *route_values = (GValueArray *) g_ptr_array_index (routes, i);
+ GByteArray *dest, *next_hop;
+ guint prefix, metric;
+ NMIP6Route *route;
+
+ if ( (route_values->n_values != 4)
+ || (G_VALUE_TYPE (g_value_array_get_nth (route_values, 0)) != DBUS_TYPE_G_UCHAR_ARRAY)
+ || (G_VALUE_TYPE (g_value_array_get_nth (route_values, 1)) != G_TYPE_UINT)
+ || (G_VALUE_TYPE (g_value_array_get_nth (route_values, 2)) != DBUS_TYPE_G_UCHAR_ARRAY)
+ || (G_VALUE_TYPE (g_value_array_get_nth (route_values, 3)) != G_TYPE_UINT)) {
+ nm_warning ("Ignoring invalid IP6 route");
+ continue;
+ }
+
+ dest = g_value_get_boxed (g_value_array_get_nth (route_values, 0));
+ if (dest->len != 16) {
+ nm_warning ("%s: ignoring invalid IP6 dest address of length %d",
+ __func__, dest->len);
+ continue;
+ }
+
+ prefix = g_value_get_uint (g_value_array_get_nth (route_values, 1));
+
+ next_hop = g_value_get_boxed (g_value_array_get_nth (route_values, 2));
+ if (next_hop->len != 16) {
+ nm_warning ("%s: ignoring invalid IP6 next_hop address of length %d",
+ __func__, next_hop->len);
+ continue;
+ }
+
+ metric = g_value_get_uint (g_value_array_get_nth (route_values, 3));
+
+ route = nm_ip6_route_new ();
+ nm_ip6_route_set_dest (route, (struct in6_addr *)dest->data);
+ nm_ip6_route_set_prefix (route, prefix);
+ nm_ip6_route_set_next_hop (route, (struct in6_addr *)next_hop->data);
+ nm_ip6_route_set_metric (route, metric);
+ list = g_slist_prepend (list, route);
+ }
+
+ return g_slist_reverse (list);
+}
+
+void
+nm_utils_ip6_routes_to_gvalue (GSList *list, GValue *value)
+{
+ GPtrArray *routes;
+ GSList *iter;
+
+ routes = g_ptr_array_new ();
+
+ for (iter = list; iter; iter = iter->next) {
+ NMIP6Route *route = (NMIP6Route *) iter->data;
+ GValueArray *array;
+ const struct in6_addr *addr;
+ GByteArray *ba;
+ GValue element = {0, };
+
+ array = g_value_array_new (4);
+
+ g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY);
+ addr = nm_ip6_route_get_dest (route);
+ ba = g_byte_array_new ();
+ g_byte_array_append (ba, (guchar *)addr, sizeof (*addr));
+ g_value_take_boxed (&element, ba);
+ g_value_array_append (array, &element);
+ g_value_unset (&element);
+
+ g_value_init (&element, G_TYPE_UINT);
+ g_value_set_uint (&element, nm_ip6_route_get_prefix (route));
+ g_value_array_append (array, &element);
+ g_value_unset (&element);
+
+ g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY);
+ addr = nm_ip6_route_get_next_hop (route);
+ ba = g_byte_array_new ();
+ g_byte_array_append (ba, (guchar *)addr, sizeof (*addr));
+ g_value_take_boxed (&element, ba);
+ g_value_array_append (array, &element);
+ g_value_unset (&element);
+
+ g_value_init (&element, G_TYPE_UINT);
+ g_value_set_uint (&element, nm_ip6_route_get_metric (route));
+ g_value_array_append (array, &element);
+ g_value_unset (&element);
+
+ g_ptr_array_add (routes, array);
+ }
+
+ g_value_take_boxed (value, routes);
+}
+
GSList *
nm_utils_ip6_dns_from_gvalue (const GValue *value)
{
diff --git a/libnm-util/nm-utils.h b/libnm-util/nm-utils.h
index 629bc59fe..810c6e7e9 100644
--- a/libnm-util/nm-utils.h
+++ b/libnm-util/nm-utils.h
@@ -193,6 +193,15 @@ void nm_utils_ip4_routes_to_gvalue (GSList *list, GValue *value);
guint32 nm_utils_ip4_netmask_to_prefix (guint32 netmask);
guint32 nm_utils_ip4_prefix_to_netmask (guint32 prefix);
+GSList *nm_utils_ip6_addresses_from_gvalue (const GValue *value);
+void nm_utils_ip6_addresses_to_gvalue (GSList *list, GValue *value);
+
+GSList *nm_utils_ip6_routes_from_gvalue (const GValue *value);
+void nm_utils_ip6_routes_to_gvalue (GSList *list, GValue *value);
+
+GSList *nm_utils_ip6_dns_from_gvalue (const GValue *value);
+void nm_utils_ip6_dns_to_gvalue (GSList *list, GValue *value);
+
char *nm_utils_uuid_generate (void);
char *nm_utils_uuid_generate_from_string (const char *s);
diff --git a/policy/Makefile.am b/policy/Makefile.am
index 9ce677b18..c5d24764e 100644
--- a/policy/Makefile.am
+++ b/policy/Makefile.am
@@ -5,8 +5,6 @@ dist_polkit_policy_DATA = $(dist_polkit_policy_in_files:.policy.in=.policy)
@INTLTOOL_POLICY_RULE@
-EXTRA_DIST = $(dist_polkit_policy_in_files)
-
check:
@for f in $(dist_polkit_policy_DATA); do \
echo -n "Validate PolicyKit policy in $$f : "; \
diff --git a/src/Makefile.am b/src/Makefile.am
index 79c2a2e64..d8878e05d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -80,6 +80,8 @@ NetworkManager_SOURCES = \
nm-hostname-provider.h \
nm-ip4-config.c \
nm-ip4-config.h \
+ nm-ip6-config.c \
+ nm-ip6-config.h \
nm-secrets-provider-interface.c \
nm-secrets-provider-interface.h \
nm-active-connection.h \
@@ -129,6 +131,9 @@ nm-device-bt-glue.h: $(top_srcdir)/introspection/nm-device-bt.xml
nm-ip4-config-glue.h: $(top_srcdir)/introspection/nm-ip4-config.xml
dbus-binding-tool --prefix=nm_ip4_config --mode=glib-server --output=$@ $<
+nm-ip6-config-glue.h: $(top_srcdir)/introspection/nm-ip6-config.xml
+ dbus-binding-tool --prefix=nm_ip6_config --mode=glib-server --output=$@ $<
+
nm-active-connection-glue.h: $(top_srcdir)/introspection/nm-active-connection.xml
dbus-binding-tool --prefix=nm_active_connection --mode=glib-server --output=$@ $<
@@ -143,6 +148,7 @@ BUILT_SOURCES = \
nm-device-wifi-glue.h \
nm-device-bt-glue.h \
nm-ip4-config-glue.h \
+ nm-ip6-config-glue.h \
nm-active-connection-glue.h \
nm-dhcp4-config-glue.h
diff --git a/src/NetworkManager.conf b/src/NetworkManager.conf
index a5eee46e8..87814bec2 100644
--- a/src/NetworkManager.conf
+++ b/src/NetworkManager.conf
@@ -4,10 +4,10 @@
-
+
-
+
@@ -15,58 +15,58 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
512
diff --git a/src/NetworkManagerSystem.c b/src/NetworkManagerSystem.c
index 508e0fe93..9f62d7fb0 100644
--- a/src/NetworkManagerSystem.c
+++ b/src/NetworkManagerSystem.c
@@ -198,14 +198,19 @@ 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) {
- 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());
- }
- }
+ 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());
}
}
@@ -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;
diff --git a/src/NetworkManagerSystem.h b/src/NetworkManagerSystem.h
index b83a663d0..f2c2693ac 100644
--- a/src/NetworkManagerSystem.h
+++ b/src/NetworkManagerSystem.h
@@ -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);
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c
index a030a3867..4934d465c 100644
--- a/src/NetworkManagerUtils.c
+++ b/src/NetworkManagerUtils.c
@@ -20,8 +20,11 @@
*/
#include
+#include
+#include
#include
#include
+#include
#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;
+}
+
diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h
index a987d21b4..05f3b837a 100644
--- a/src/NetworkManagerUtils.h
+++ b/src/NetworkManagerUtils.h
@@ -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 */
diff --git a/src/modem-manager/nm-modem.c b/src/modem-manager/nm-modem.c
index 3826dce15..48f9296ed 100644
--- a/src/modem-manager/nm-modem.c
+++ b/src/modem-manager/nm-modem.c
@@ -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;
diff --git a/src/named-manager/nm-named-manager.c b/src/named-manager/nm-named-manager.c
index cab06abf4..b89c80118 100644
--- a/src/named-manager/nm-named-manager.c
+++ b/src/named-manager/nm-named-manager.c
@@ -63,8 +63,6 @@ struct NMNamedManagerPrivate {
NMIP4Config * vpn_config;
NMIP4Config * device_config;
GSList * configs;
-
- gboolean disposed;
};
@@ -94,29 +92,71 @@ nm_named_manager_error_quark (void)
return quark;
}
+typedef struct {
+ GPtrArray *nameservers;
+ const char *domain;
+ GPtrArray *searches;
+} NMResolvConfData;
+
static void
-merge_one_ip4_config (NMIP4Config *dst, NMIP4Config *src)
+merge_one_ip4_config (NMResolvConfData *rc, NMIP4Config *src)
{
- guint32 num, num_domains, i;
+ guint32 num, i;
num = nm_ip4_config_get_num_nameservers (src);
- for (i = 0; i < num; i++)
- nm_ip4_config_add_nameserver (dst, nm_ip4_config_get_nameserver (src, i));
+ for (i = 0; i < num; i++) {
+ struct in_addr addr;
+ char buf[INET_ADDRSTRLEN];
- num_domains = nm_ip4_config_get_num_domains (src);
- for (i = 0; i < num_domains; i++)
- nm_ip4_config_add_domain (dst, nm_ip4_config_get_domain (src, i));
+ addr.s_addr = nm_ip4_config_get_nameserver (src, i);
+ if (inet_ntop (AF_INET, &addr, buf, INET_ADDRSTRLEN) > 0)
+ g_ptr_array_add (rc->nameservers, g_strdup (buf));
+ }
+
+ num = nm_ip4_config_get_num_domains (src);
+ for (i = 0; i < num; i++) {
+ if (!rc->domain)
+ rc->domain = nm_ip4_config_get_domain (src, i);
+ g_ptr_array_add (rc->searches, g_strdup (nm_ip4_config_get_domain (src, i)));
+ }
num = nm_ip4_config_get_num_searches (src);
for (i = 0; i < num; i++)
- nm_ip4_config_add_search (dst, nm_ip4_config_get_search (src, i));
+ g_ptr_array_add (rc->searches, g_strdup (nm_ip4_config_get_search (src, i)));
+}
- /* Add the 'domain' list to searches as well since overloading the
- * 'domain_name' DHCP field used to be the way you got searches
- * into resolv.conf.
- */
- for (i = 0; i < num_domains; i++)
- nm_ip4_config_add_search (dst, nm_ip4_config_get_domain (src, i));
+static void
+merge_one_ip6_config (NMResolvConfData *rc, NMIP6Config *src)
+{
+ guint32 num, i;
+
+ num = nm_ip6_config_get_num_nameservers (src);
+ for (i = 0; i < num; i++) {
+ const struct in6_addr *addr;
+ char buf[INET6_ADDRSTRLEN];
+
+ addr = nm_ip6_config_get_nameserver (src, i);
+
+ /* inet_ntop is probably supposed to do this for us, but it doesn't */
+ if (IN6_IS_ADDR_V4MAPPED (addr)) {
+ if (inet_ntop (AF_INET, &(addr->s6_addr32[3]), buf, INET_ADDRSTRLEN) > 0)
+ g_ptr_array_add (rc->nameservers, g_strdup (buf));
+ } else {
+ if (inet_ntop (AF_INET6, addr, buf, INET6_ADDRSTRLEN) > 0)
+ g_ptr_array_add (rc->nameservers, g_strdup (buf));
+ }
+ }
+
+ num = nm_ip6_config_get_num_domains (src);
+ for (i = 0; i < num; i++) {
+ if (!rc->domain)
+ rc->domain = nm_ip6_config_get_domain (src, i);
+ g_ptr_array_add (rc->searches, g_strdup (nm_ip6_config_get_domain (src, i)));
+ }
+
+ num = nm_ip6_config_get_num_searches (src);
+ for (i = 0; i < num; i++)
+ g_ptr_array_add (rc->searches, g_strdup (nm_ip6_config_get_search (src, i)));
}
@@ -183,6 +223,15 @@ dispatch_netconfig (const char *domain,
if (pid < 0)
return FALSE;
+ // FIXME: this is wrong. We are not writing out the iface-specific
+ // resolv.conf data, we are writing out an already-fully-merged
+ // resolv.conf. Assuming netconfig works in the obvious way, then
+ // there are various failure modes, such as, eg, bringing up a VPN on
+ // eth0, then bringing up wlan0, then bringing down the VPN. Because
+ // NMNamedManager would have claimed that the VPN DNS server was also
+ // part of the wlan0 config, it will remain in resolv.conf after the
+ // VPN goes down, even though it is presumably no longer reachable
+ // at that point.
write_to_netconfig (fd, "INTERFACE", iface);
if (searches) {
@@ -391,50 +440,16 @@ update_resolv_conf (const char *domain,
return *error ? FALSE : TRUE;
}
-static char **
-compute_searches (guint32 num, NMIP4Config *config, gboolean searches)
-{
- GPtrArray *array;
- size_t len, elem_len;
- const char *elem;
- int i;
-
- /* Search list is limited to 6 domains total per 'man resolv.conf' */
- if (num > 6)
- num = 6;
-
- array = g_ptr_array_sized_new (num + 1);
- for (i = 0, len = 0; i < num; i++) {
- elem = searches ? nm_ip4_config_get_search (config, i)
- : nm_ip4_config_get_domain (config, i);
- elem_len = strlen (elem);
-
- /* The search list is limited to 256 characters per 'man resolv.conf' */
- if (len + elem_len > 255)
- break;
-
- g_ptr_array_add (array, g_strdup (elem));
- len += elem_len + 1; /* +1 for spaces */
- }
-
- g_ptr_array_add (array, NULL);
- return (char **) g_ptr_array_free (array, FALSE);
-}
-
static gboolean
rewrite_resolv_conf (NMNamedManager *mgr, const char *iface, GError **error)
{
NMNamedManagerPrivate *priv;
- NMIP4Config *composite;
+ NMResolvConfData rc;
GSList *iter;
- GPtrArray *array;
const char *domain = NULL;
char **searches = NULL;
char **nameservers = NULL;
- int num_domains;
- int num_searches;
- int num_nameservers;
- int i;
+ int num, i, len;
gboolean success = FALSE;
g_return_val_if_fail (error != NULL, FALSE);
@@ -442,66 +457,54 @@ rewrite_resolv_conf (NMNamedManager *mgr, const char *iface, GError **error)
priv = NM_NAMED_MANAGER_GET_PRIVATE (mgr);
- /* Construct the composite config from all the currently active IP4Configs */
- composite = nm_ip4_config_new ();
+ rc.nameservers = g_ptr_array_new ();
+ rc.domain = NULL;
+ rc.searches = g_ptr_array_new ();
if (priv->vpn_config)
- merge_one_ip4_config (composite, priv->vpn_config);
+ merge_one_ip4_config (&rc, priv->vpn_config);
if (priv->device_config)
- merge_one_ip4_config (composite, priv->device_config);
+ merge_one_ip4_config (&rc, priv->device_config);
for (iter = priv->configs; iter; iter = g_slist_next (iter)) {
- NMIP4Config *config = NM_IP4_CONFIG (iter->data);
+ if (NM_IS_IP4_CONFIG (iter->data)) {
+ NMIP4Config *config = NM_IP4_CONFIG (iter->data);
- if ((config == priv->vpn_config) || (config == priv->device_config))
- continue;
-
- merge_one_ip4_config (composite, config);
- }
-
- /* Some DHCP servers like to put multiple search paths into the domain
- * option as the domain-search option wasn't around in the first RFC.
- * We should try and support these old servers as best we can. */
-
- num_domains = nm_ip4_config_get_num_domains (composite);
- num_searches = nm_ip4_config_get_num_searches (composite);
-
- /* Domain */
- if (num_domains > 0)
- domain = nm_ip4_config_get_domain (composite, 0);
-
- /* Searches */
- if (num_searches > 0)
- searches = compute_searches (num_searches, composite, TRUE);
- else if (num_domains > 0)
- searches = compute_searches (num_searches, composite, FALSE);
-
- /* Name servers */
- num_nameservers = nm_ip4_config_get_num_nameservers (composite);
- if (num_nameservers > 0) {
- array = g_ptr_array_sized_new (num_nameservers + 1);
- for (i = 0; i < num_nameservers; i++) {
- struct in_addr addr;
- char *buf;
-
- addr.s_addr = nm_ip4_config_get_nameserver (composite, i);
- buf = g_malloc0 (ADDR_BUF_LEN);
- if (!buf)
+ if ((config == priv->vpn_config) || (config == priv->device_config))
continue;
- if (inet_ntop (AF_INET, &addr, buf, ADDR_BUF_LEN))
- g_ptr_array_add (array, buf);
- else
- nm_warning ("%s: error converting IP4 address 0x%X",
- __func__, ntohl (addr.s_addr));
- }
+ merge_one_ip4_config (&rc, config);
+ } else {
+ NMIP6Config *config = NM_IP6_CONFIG (iter->data);
- g_ptr_array_add (array, NULL);
- nameservers = (char **) g_ptr_array_free (array, FALSE);
+ merge_one_ip6_config (&rc, config);
+ }
}
- g_object_unref (composite);
+ domain = rc.domain;
+
+ /* Per 'man resolv.conf', the search list is limited to 6 domains
+ * totalling 256 characters.
+ */
+ num = MIN (rc.searches->len, 6);
+ for (i = 0, len = 0; i < num; i++) {
+ len += strlen (rc.searches->pdata[i]) + 1; /* +1 for spaces */
+ if (len > 256)
+ break;
+ }
+ g_ptr_array_set_size (rc.searches, i);
+ if (rc.searches->len) {
+ g_ptr_array_add (rc.searches, NULL);
+ searches = (char **) g_ptr_array_free (rc.searches, FALSE);
+ } else
+ g_ptr_array_free (rc.searches, TRUE);
+
+ if (rc.nameservers->len) {
+ g_ptr_array_add (rc.nameservers, NULL);
+ nameservers = (char **) g_ptr_array_free (rc.nameservers, FALSE);
+ } else
+ g_ptr_array_free (rc.nameservers, TRUE);
#ifdef RESOLVCONF_PATH
success = dispatch_resolvconf (domain, searches, nameservers, iface, error);
@@ -518,17 +521,19 @@ rewrite_resolv_conf (NMNamedManager *mgr, const char *iface, GError **error)
if (success)
nm_system_update_dns ();
- g_strfreev (searches);
- g_strfreev (nameservers);
+ if (searches)
+ g_strfreev (searches);
+ if (nameservers)
+ g_strfreev (nameservers);
return success;
}
gboolean
nm_named_manager_add_ip4_config (NMNamedManager *mgr,
- const char *iface,
- NMIP4Config *config,
- NMNamedIPConfigType cfg_type)
+ const char *iface,
+ NMIP4Config *config,
+ NMNamedIPConfigType cfg_type)
{
NMNamedManagerPrivate *priv;
GError *error = NULL;
@@ -564,8 +569,8 @@ nm_named_manager_add_ip4_config (NMNamedManager *mgr,
gboolean
nm_named_manager_remove_ip4_config (NMNamedManager *mgr,
- const char *iface,
- NMIP4Config *config)
+ const char *iface,
+ NMIP4Config *config)
{
NMNamedManagerPrivate *priv;
GError *error = NULL;
@@ -588,6 +593,66 @@ nm_named_manager_remove_ip4_config (NMNamedManager *mgr,
if (config == priv->device_config)
priv->device_config = NULL;
+ g_object_unref (config);
+
+ if (!rewrite_resolv_conf (mgr, iface, &error)) {
+ nm_warning ("Could not commit DNS changes. Error: '%s'", error ? error->message : "(none)");
+ if (error)
+ g_error_free (error);
+ }
+
+ return TRUE;
+}
+
+gboolean
+nm_named_manager_add_ip6_config (NMNamedManager *mgr,
+ const char *iface,
+ NMIP6Config *config,
+ NMNamedIPConfigType cfg_type)
+{
+ NMNamedManagerPrivate *priv;
+ GError *error = NULL;
+
+ g_return_val_if_fail (mgr != NULL, FALSE);
+ g_return_val_if_fail (iface != NULL, FALSE);
+ g_return_val_if_fail (config != NULL, FALSE);
+
+ g_return_val_if_fail (cfg_type == NM_NAMED_IP_CONFIG_TYPE_DEFAULT, FALSE);
+
+ priv = NM_NAMED_MANAGER_GET_PRIVATE (mgr);
+
+ /* Don't allow the same zone added twice */
+ if (!g_slist_find (priv->configs, config))
+ priv->configs = g_slist_append (priv->configs, g_object_ref (config));
+
+ if (!rewrite_resolv_conf (mgr, iface, &error)) {
+ nm_warning ("Could not commit DNS changes. Error: '%s'", error ? error->message : "(none)");
+ g_error_free (error);
+ }
+
+ return TRUE;
+}
+
+gboolean
+nm_named_manager_remove_ip6_config (NMNamedManager *mgr,
+ const char *iface,
+ NMIP6Config *config)
+{
+ NMNamedManagerPrivate *priv;
+ GError *error = NULL;
+
+ g_return_val_if_fail (mgr != NULL, FALSE);
+ g_return_val_if_fail (iface != NULL, FALSE);
+ g_return_val_if_fail (config != NULL, FALSE);
+
+ priv = NM_NAMED_MANAGER_GET_PRIVATE (mgr);
+
+ /* Can't remove it if it wasn't in the list to begin with */
+ if (!g_slist_find (priv->configs, config))
+ return FALSE;
+
+ priv->configs = g_slist_remove (priv->configs, config);
+
g_object_unref (config);
if (!rewrite_resolv_conf (mgr, iface, &error)) {
diff --git a/src/named-manager/nm-named-manager.h b/src/named-manager/nm-named-manager.h
index 2b5b64757..47c8e7115 100644
--- a/src/named-manager/nm-named-manager.h
+++ b/src/named-manager/nm-named-manager.h
@@ -28,6 +28,7 @@
#include
#include
#include "nm-ip4-config.h"
+#include "nm-ip6-config.h"
typedef enum {
NM_NAMED_MANAGER_ERROR_SYSTEM,
@@ -69,13 +70,22 @@ GType nm_named_manager_get_type (void);
NMNamedManager * nm_named_manager_get (void);
gboolean nm_named_manager_add_ip4_config (NMNamedManager *mgr,
- const char *iface,
+ const char *iface,
NMIP4Config *config,
NMNamedIPConfigType cfg_type);
gboolean nm_named_manager_remove_ip4_config (NMNamedManager *mgr,
- const char *iface,
- NMIP4Config *config);
+ const char *iface,
+ NMIP4Config *config);
+
+gboolean nm_named_manager_add_ip6_config (NMNamedManager *mgr,
+ const char *iface,
+ NMIP6Config *config,
+ NMNamedIPConfigType cfg_type);
+
+gboolean nm_named_manager_remove_ip6_config (NMNamedManager *mgr,
+ const char *iface,
+ NMIP6Config *config);
G_END_DECLS
diff --git a/src/nm-device-bt.c b/src/nm-device-bt.c
index 2517c797b..06a4d8d0f 100644
--- a/src/nm-device-bt.c
+++ b/src/nm-device-bt.c
@@ -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;
diff --git a/src/nm-device-ethernet.c b/src/nm-device-ethernet.c
index 2c68f790d..bdb740ed9 100644
--- a/src/nm-device-ethernet.c
+++ b/src/nm-device-ethernet.c
@@ -1256,7 +1256,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
diff --git a/src/nm-device-interface.c b/src/nm-device-interface.c
index 7f287a869..5e72afab9 100644
--- a/src/nm-device-interface.c
+++ b/src/nm-device-interface.c
@@ -23,6 +23,7 @@
#include "nm-setting-connection.h"
#include "nm-device-interface.h"
#include "nm-utils.h"
+#include "nm-properties-changed-signal.h"
#include "nm-device-interface-glue.h"
@@ -123,6 +124,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,
@@ -152,7 +161,7 @@ nm_device_interface_init (gpointer g_iface)
"Type Description",
"Device type description",
NULL,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT));
/* Signals */
g_signal_new ("state-changed",
diff --git a/src/nm-device-interface.h b/src/nm-device-interface.h
index 97a95da47..0273c750d 100644
--- a/src/nm-device-interface.h
+++ b/src/nm-device-interface.h
@@ -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,
diff --git a/src/nm-device-wifi.c b/src/nm-device-wifi.c
index 0fbff7424..eefb1366a 100644
--- a/src/nm-device-wifi.c
+++ b/src/nm-device-wifi.c
@@ -3022,9 +3022,9 @@ real_act_stage4_get_ip4_config (NMDevice *dev,
static NMActStageReturn
-real_act_stage4_ip_config_timeout (NMDevice *dev,
- NMIP4Config **config,
- NMDeviceStateReason *reason)
+real_act_stage4_ip4_config_timeout (NMDevice *dev,
+ NMIP4Config **config,
+ NMDeviceStateReason *reason)
{
NMDeviceWifi *self = NM_DEVICE_WIFI (dev);
NMAccessPoint *ap = nm_device_wifi_get_activation_ap (self);
@@ -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;
@@ -3610,7 +3610,8 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
g_param_spec_boolean (NM_DEVICE_WIFI_SCANNING,
"Scanning",
"Scanning",
- 0, G_PARAM_READABLE));
+ FALSE,
+ G_PARAM_READABLE | NM_PROPERTY_PARAM_NO_EXPORT));
/* Signals */
signals[ACCESS_POINT_ADDED] =
diff --git a/src/nm-device.c b/src/nm-device.c
index 56634ef8f..53e18f21c 100644
--- a/src/nm-device.c
+++ b/src/nm-device.c
@@ -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,
@@ -124,7 +133,7 @@ static void nm_device_deactivate (NMDeviceInterface *device, NMDeviceStateReason
static gboolean spec_match_list (NMDeviceInterface *device, const GSList *specs);
static NMConnection *connection_match_config (NMDeviceInterface *device, const GSList *connections);
-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);
@@ -132,6 +141,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)
@@ -152,7 +162,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;
}
@@ -441,24 +450,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
@@ -466,13 +495,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
*
@@ -483,17 +550,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;
@@ -527,7 +599,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));
@@ -564,7 +636,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);
@@ -614,7 +686,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));
@@ -774,7 +846,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;
@@ -839,7 +911,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;
}
@@ -904,7 +976,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;
@@ -978,39 +1050,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);
@@ -1033,7 +1120,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));
@@ -1174,15 +1261,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;
@@ -1191,10 +1277,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)
@@ -1209,22 +1295,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;
@@ -1233,17 +1319,17 @@ 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,
- NMIP4Config **config,
- NMDeviceStateReason *reason)
+real_act_stage4_ip4_config_timeout (NMDevice *self,
+ NMIP4Config **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);
@@ -1258,13 +1344,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;
@@ -1273,12 +1359,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)) {
@@ -1291,22 +1377,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;
@@ -1315,9 +1401,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));
}
@@ -1332,31 +1601,21 @@ 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) {
- nm_warning ("%s: Error starting IP forwarding: (%d) %s",
- __func__, errno, strerror (errno));
- return FALSE;
- }
- close (fd);
+ 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;
}
- fd = open ("/proc/sys/net/ipv4/ip_dynaddr", O_WRONLY | O_TRUNC);
- if (fd) {
- count = write (fd, "1\n", 2);
- if (count != 2) {
- nm_warning ("%s: Error starting IP forwarding: (%d) %s",
- __func__, errno, strerror (errno));
- }
- close (fd);
+ 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));
}
for (iter = modules; *iter; iter++) {
@@ -1466,6 +1725,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;
@@ -1474,9 +1734,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...",
@@ -1487,6 +1750,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)
@@ -1506,8 +1774,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;
}
@@ -1519,7 +1788,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;
@@ -1528,7 +1797,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));
@@ -1583,7 +1860,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);
@@ -1643,10 +1921,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 */
@@ -1875,7 +2154,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;
@@ -1883,7 +2162,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 */
@@ -1915,7 +2194,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
@@ -2051,7 +2330,6 @@ nm_device_set_ip4_config (NMDevice *self,
return success;
}
-
/*
* nm_device_get_ip4_address
*
@@ -2092,6 +2370,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)
{
@@ -2251,7 +2592,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);
if (!take_down)
nm_device_set_use_dhcp (self, FALSE);
@@ -2372,6 +2714,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;
@@ -2409,9 +2760,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 */
@@ -2443,6 +2797,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);
diff --git a/src/nm-device.h b/src/nm-device.h
index f3d63235e..d06375cc6 100644
--- a/src/nm-device.h
+++ b/src/nm-device.h
@@ -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,
- NMDeviceStateReason *reason);
+ 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);
@@ -130,7 +139,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,
@@ -138,6 +146,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);
@@ -151,8 +160,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);
diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c
new file mode 100644
index 000000000..990ba3df3
--- /dev/null
+++ b/src/nm-ip6-config.c
@@ -0,0 +1,726 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2005 - 2008 Red Hat, Inc.
+ * Copyright (C) 2006 - 2008 Novell, Inc.
+ */
+
+#include
+#include
+#include
+#include "nm-ip6-config.h"
+#include "nm-dbus-manager.h"
+#include "NetworkManager.h"
+#include "NetworkManagerUtils.h"
+#include "nm-setting-ip6-config.h"
+#include "nm-utils.h"
+
+#include
+#include
+#include
+
+#include "nm-ip6-config-glue.h"
+#include "nm-dbus-glib-types.h"
+
+
+G_DEFINE_TYPE (NMIP6Config, nm_ip6_config, G_TYPE_OBJECT)
+
+#define NM_IP6_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_IP6_CONFIG, NMIP6ConfigPrivate))
+
+typedef struct {
+ char *path;
+
+ GSList *addresses;
+ struct in6_addr ptp_address;
+
+ guint32 mss; /* Maximum Segment Size of the route */
+
+ GArray *nameservers;
+ GPtrArray *domains;
+ GPtrArray *searches;
+
+ GSList *routes;
+
+ gboolean never_default;
+} NMIP6ConfigPrivate;
+
+
+enum {
+ PROP_0,
+ PROP_ADDRESSES,
+ PROP_NAMESERVERS,
+ PROP_DOMAINS,
+ PROP_ROUTES,
+
+ LAST_PROP
+};
+
+
+static struct nl_addr *
+nm_utils_ip6_addr_to_nl_addr (const struct in6_addr *ip6_addr)
+{
+ struct nl_addr * nla = NULL;
+
+ if (!(nla = nl_addr_alloc (sizeof (struct in6_addr))))
+ return NULL;
+ nl_addr_set_family (nla, AF_INET6);
+ nl_addr_set_binary_addr (nla, (struct in6_addr *)ip6_addr, sizeof (struct in6_addr));
+
+ return nla;
+}
+
+
+NMIP6Config *
+nm_ip6_config_new (void)
+{
+ return (NMIP6Config *) g_object_new (NM_TYPE_IP6_CONFIG, NULL);
+}
+
+void
+nm_ip6_config_export (NMIP6Config *config)
+{
+ NMIP6ConfigPrivate *priv;
+ NMDBusManager *dbus_mgr;
+ DBusGConnection *connection;
+ static guint32 counter = 0;
+
+ g_return_if_fail (NM_IS_IP6_CONFIG (config));
+
+ priv = NM_IP6_CONFIG_GET_PRIVATE (config);
+ g_return_if_fail (priv->path == NULL);
+
+ dbus_mgr = nm_dbus_manager_get ();
+ connection = nm_dbus_manager_get_connection (dbus_mgr);
+ priv->path = g_strdup_printf (NM_DBUS_PATH "/IP6Config/%d", counter++);
+
+ dbus_g_connection_register_g_object (connection, priv->path, G_OBJECT (config));
+ g_object_unref (dbus_mgr);
+}
+
+const char *
+nm_ip6_config_get_dbus_path (NMIP6Config *config)
+{
+ g_return_val_if_fail (NM_IS_IP6_CONFIG (config), FALSE);
+
+ return NM_IP6_CONFIG_GET_PRIVATE (config)->path;
+}
+
+void
+nm_ip6_config_take_address (NMIP6Config *config, NMIP6Address *address)
+{
+ NMIP6ConfigPrivate *priv;
+
+ g_return_if_fail (NM_IS_IP6_CONFIG (config));
+ g_return_if_fail (address != NULL);
+
+ priv = NM_IP6_CONFIG_GET_PRIVATE (config);
+ priv->addresses = g_slist_append (priv->addresses, address);
+}
+
+void
+nm_ip6_config_add_address (NMIP6Config *config,
+ NMIP6Address *address)
+{
+ NMIP6ConfigPrivate *priv;
+
+ g_return_if_fail (NM_IS_IP6_CONFIG (config));
+ g_return_if_fail (address != NULL);
+
+ priv = NM_IP6_CONFIG_GET_PRIVATE (config);
+ priv->addresses = g_slist_append (priv->addresses, nm_ip6_address_dup (address));
+}
+
+void
+nm_ip6_config_replace_address (NMIP6Config *config,
+ guint i,
+ NMIP6Address *new_address)
+{
+ NMIP6ConfigPrivate *priv;
+ GSList *old;
+
+ g_return_if_fail (NM_IS_IP6_CONFIG (config));
+
+ priv = NM_IP6_CONFIG_GET_PRIVATE (config);
+ old = g_slist_nth (priv->addresses, i);
+ g_return_if_fail (old != NULL);
+ nm_ip6_address_unref ((NMIP6Address *) old->data);
+
+ old->data = nm_ip6_address_dup (new_address);
+}
+
+NMIP6Address *nm_ip6_config_get_address (NMIP6Config *config, guint i)
+{
+ g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL);
+
+ return (NMIP6Address *) g_slist_nth_data (NM_IP6_CONFIG_GET_PRIVATE (config)->addresses, i);
+}
+
+guint32 nm_ip6_config_get_num_addresses (NMIP6Config *config)
+{
+ g_return_val_if_fail (NM_IS_IP6_CONFIG (config), 0);
+
+ return g_slist_length (NM_IP6_CONFIG_GET_PRIVATE (config)->addresses);
+}
+
+const struct in6_addr *nm_ip6_config_get_ptp_address (NMIP6Config *config)
+{
+ g_return_val_if_fail (NM_IS_IP6_CONFIG (config), 0);
+
+ return &NM_IP6_CONFIG_GET_PRIVATE (config)->ptp_address;
+}
+
+void nm_ip6_config_set_ptp_address (NMIP6Config *config, struct in6_addr *ptp_addr)
+{
+ g_return_if_fail (NM_IS_IP6_CONFIG (config));
+
+ NM_IP6_CONFIG_GET_PRIVATE (config)->ptp_address = *ptp_addr;
+}
+
+void nm_ip6_config_add_nameserver (NMIP6Config *config, const struct in6_addr *nameserver)
+{
+ NMIP6ConfigPrivate *priv;
+ struct in6_addr *nameservers;
+ int i;
+
+ g_return_if_fail (NM_IS_IP6_CONFIG (config));
+ g_return_if_fail (nameserver > 0);
+
+ priv = NM_IP6_CONFIG_GET_PRIVATE (config);
+
+ /* No dupes */
+ nameservers = (struct in6_addr *)priv->nameservers->data;
+ for (i = 0; i < priv->nameservers->len; i++) {
+ g_return_if_fail (memcmp (nameserver, &nameservers[i], sizeof (struct in6_addr)) == 0);
+ }
+
+ g_array_append_val (priv->nameservers, *nameserver);
+}
+
+const struct in6_addr *nm_ip6_config_get_nameserver (NMIP6Config *config, guint i)
+{
+ g_return_val_if_fail (NM_IS_IP6_CONFIG (config), 0);
+
+ return &g_array_index (NM_IP6_CONFIG_GET_PRIVATE (config)->nameservers, struct in6_addr, i);
+}
+
+guint32 nm_ip6_config_get_num_nameservers (NMIP6Config *config)
+{
+ g_return_val_if_fail (NM_IS_IP6_CONFIG (config), 0);
+
+ return NM_IP6_CONFIG_GET_PRIVATE (config)->nameservers->len;
+}
+
+void nm_ip6_config_reset_nameservers (NMIP6Config *config)
+{
+ NMIP6ConfigPrivate *priv;
+
+ g_return_if_fail (NM_IS_IP6_CONFIG (config));
+
+ priv = NM_IP6_CONFIG_GET_PRIVATE (config);
+ if (priv->nameservers->len)
+ g_array_remove_range (priv->nameservers, 0, priv->nameservers->len);
+}
+
+void
+nm_ip6_config_take_route (NMIP6Config *config, NMIP6Route *route)
+{
+ NMIP6ConfigPrivate *priv;
+
+ g_return_if_fail (NM_IS_IP6_CONFIG (config));
+ g_return_if_fail (route != NULL);
+
+ priv = NM_IP6_CONFIG_GET_PRIVATE (config);
+ priv->routes = g_slist_append (priv->routes, route);
+}
+
+void
+nm_ip6_config_add_route (NMIP6Config *config, NMIP6Route *route)
+{
+ NMIP6ConfigPrivate *priv;
+
+ g_return_if_fail (NM_IS_IP6_CONFIG (config));
+ g_return_if_fail (route != NULL);
+
+ priv = NM_IP6_CONFIG_GET_PRIVATE (config);
+ priv->routes = g_slist_append (priv->routes, nm_ip6_route_dup (route));
+}
+
+void
+nm_ip6_config_replace_route (NMIP6Config *config,
+ guint i,
+ NMIP6Route *new_route)
+{
+ NMIP6ConfigPrivate *priv;
+ GSList *old;
+
+ g_return_if_fail (NM_IS_IP6_CONFIG (config));
+
+ priv = NM_IP6_CONFIG_GET_PRIVATE (config);
+ old = g_slist_nth (priv->routes, i);
+ g_return_if_fail (old != NULL);
+ nm_ip6_route_unref ((NMIP6Route *) old->data);
+
+ old->data = nm_ip6_route_dup (new_route);
+}
+
+NMIP6Route *
+nm_ip6_config_get_route (NMIP6Config *config, guint i)
+{
+ g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL);
+
+ return (NMIP6Route *) g_slist_nth_data (NM_IP6_CONFIG_GET_PRIVATE (config)->routes, i);
+}
+
+guint32 nm_ip6_config_get_num_routes (NMIP6Config *config)
+{
+ g_return_val_if_fail (NM_IS_IP6_CONFIG (config), 0);
+
+ return g_slist_length (NM_IP6_CONFIG_GET_PRIVATE (config)->routes);
+}
+
+void nm_ip6_config_reset_routes (NMIP6Config *config)
+{
+ NMIP6ConfigPrivate *priv;
+
+ g_return_if_fail (NM_IS_IP6_CONFIG (config));
+
+ priv = NM_IP6_CONFIG_GET_PRIVATE (config);
+ g_slist_foreach (priv->routes, (GFunc) g_free, NULL);
+ priv->routes = NULL;
+}
+
+void nm_ip6_config_add_domain (NMIP6Config *config, const char *domain)
+{
+ NMIP6ConfigPrivate *priv;
+ int i;
+
+ g_return_if_fail (NM_IS_IP6_CONFIG (config));
+ g_return_if_fail (domain != NULL);
+ g_return_if_fail (strlen (domain) > 0);
+
+ priv = NM_IP6_CONFIG_GET_PRIVATE (config);
+
+ for (i = 0; i < priv->domains->len; i++) {
+ if (!strcmp (g_ptr_array_index (priv->domains, i), domain))
+ return;
+ }
+
+ g_ptr_array_add (priv->domains, g_strdup (domain));
+}
+
+const char *nm_ip6_config_get_domain (NMIP6Config *config, guint i)
+{
+ g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL);
+
+ return (const char *) g_ptr_array_index (NM_IP6_CONFIG_GET_PRIVATE (config)->domains, i);
+}
+
+guint32 nm_ip6_config_get_num_domains (NMIP6Config *config)
+{
+ g_return_val_if_fail (NM_IS_IP6_CONFIG (config), 0);
+
+ return NM_IP6_CONFIG_GET_PRIVATE (config)->domains->len;
+}
+
+void nm_ip6_config_reset_domains (NMIP6Config *config)
+{
+ NMIP6ConfigPrivate *priv;
+ int i;
+
+ g_return_if_fail (NM_IS_IP6_CONFIG (config));
+
+ priv = NM_IP6_CONFIG_GET_PRIVATE (config);
+ for (i = 0; i < priv->domains->len; i++)
+ g_free (g_ptr_array_index (priv->domains, i));
+ g_ptr_array_free (priv->domains, TRUE);
+ priv->domains = g_ptr_array_sized_new (3);
+}
+
+void nm_ip6_config_add_search (NMIP6Config *config, const char *search)
+{
+ NMIP6ConfigPrivate *priv;
+ int i;
+
+ g_return_if_fail (config != NULL);
+ g_return_if_fail (search != NULL);
+ g_return_if_fail (strlen (search) > 0);
+
+ priv = NM_IP6_CONFIG_GET_PRIVATE (config);
+
+ for (i = 0; i < priv->searches->len; i++) {
+ if (!strcmp (g_ptr_array_index (priv->searches, i), search))
+ return;
+ }
+
+ g_ptr_array_add (priv->searches, g_strdup (search));
+}
+
+const char *nm_ip6_config_get_search (NMIP6Config *config, guint i)
+{
+ g_return_val_if_fail (config != NULL, NULL);
+
+ return (const char *) g_ptr_array_index (NM_IP6_CONFIG_GET_PRIVATE (config)->searches, i);
+}
+
+guint32 nm_ip6_config_get_num_searches (NMIP6Config *config)
+{
+ g_return_val_if_fail (config != NULL, 0);
+
+ return NM_IP6_CONFIG_GET_PRIVATE (config)->searches->len;
+}
+
+void nm_ip6_config_reset_searches (NMIP6Config *config)
+{
+ NMIP6ConfigPrivate *priv;
+ int i;
+
+ g_return_if_fail (NM_IS_IP6_CONFIG (config));
+
+ priv = NM_IP6_CONFIG_GET_PRIVATE (config);
+ for (i = 0; i < priv->searches->len; i++)
+ g_free (g_ptr_array_index (priv->searches, i));
+ g_ptr_array_free (priv->searches, TRUE);
+ priv->searches = g_ptr_array_sized_new (3);
+}
+
+guint32 nm_ip6_config_get_mss (NMIP6Config *config)
+{
+ g_return_val_if_fail (NM_IS_IP6_CONFIG (config), 0);
+
+ return NM_IP6_CONFIG_GET_PRIVATE (config)->mss;
+}
+
+void nm_ip6_config_set_mss (NMIP6Config *config, guint32 mss)
+{
+ g_return_if_fail (NM_IS_IP6_CONFIG (config));
+
+ NM_IP6_CONFIG_GET_PRIVATE (config)->mss = mss;
+}
+
+gboolean
+nm_ip6_config_get_never_default (NMIP6Config *config)
+{
+ g_return_val_if_fail (NM_IS_IP6_CONFIG (config), FALSE);
+
+ return NM_IP6_CONFIG_GET_PRIVATE (config)->never_default;
+}
+
+void
+nm_ip6_config_set_never_default (NMIP6Config *config, gboolean never_default)
+{
+ g_return_if_fail (NM_IS_IP6_CONFIG (config));
+
+ NM_IP6_CONFIG_GET_PRIVATE (config)->never_default = never_default;
+}
+
+/* libnl convenience/conversion functions */
+
+static int ip6_addr_to_rtnl_local (const struct in6_addr *ip6_address, struct rtnl_addr *addr)
+{
+ struct nl_addr * local = NULL;
+ int err = 0;
+
+ g_return_val_if_fail (addr != NULL, -1);
+
+ local = nm_utils_ip6_addr_to_nl_addr (ip6_address);
+ err = rtnl_addr_set_local (addr, local);
+ nl_addr_put (local);
+
+ return err;
+}
+
+static int ip6_addr_to_rtnl_peer (const struct in6_addr *ip6_address, struct rtnl_addr *addr)
+{
+ struct nl_addr * peer = NULL;
+ int err = 0;
+
+ g_return_val_if_fail (addr != NULL, -1);
+
+ peer = nm_utils_ip6_addr_to_nl_addr (ip6_address);
+ err = rtnl_addr_set_peer (addr, peer);
+ nl_addr_put (peer);
+
+ return err;
+}
+
+struct rtnl_addr *
+nm_ip6_config_to_rtnl_addr (NMIP6Config *config, guint32 i, guint32 flags)
+{
+ NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config);
+ NMIP6Address *config_addr;
+ struct rtnl_addr *addr;
+ gboolean success = TRUE;
+
+ g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL);
+
+ config_addr = nm_ip6_config_get_address (config, i);
+ g_return_val_if_fail (config_addr != NULL, NULL);
+
+ if (!(addr = rtnl_addr_alloc()))
+ return NULL;
+
+ if (flags & NM_RTNL_ADDR_ADDR)
+ success = (ip6_addr_to_rtnl_local (nm_ip6_address_get_address (config_addr), addr) >= 0);
+
+ if (flags & NM_RTNL_ADDR_PTP_ADDR)
+ success = (ip6_addr_to_rtnl_peer (&priv->ptp_address, addr) >= 0);
+
+ if (flags & NM_RTNL_ADDR_PREFIX)
+ rtnl_addr_set_prefixlen (addr, nm_ip6_address_get_prefix (config_addr));
+
+ if (!success) {
+ rtnl_addr_put (addr);
+ addr = NULL;
+ }
+
+ return addr;
+}
+
+static gboolean
+addr_slist_compare (GSList *a, GSList *b)
+{
+ GSList *iter_a, *iter_b;
+ gboolean found = FALSE;
+
+ for (iter_a = a; iter_a; iter_a = g_slist_next (iter_a)) {
+ NMIP6Address *addr_a = (NMIP6Address *) iter_a->data;
+
+ for (iter_b = b, found = FALSE; iter_b; iter_b = g_slist_next (iter_b)) {
+ NMIP6Address *addr_b = (NMIP6Address *) iter_b->data;
+
+ if (nm_ip6_address_compare (addr_a, addr_b)) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+route_slist_compare (GSList *a, GSList *b)
+{
+ GSList *iter_a, *iter_b;
+ gboolean found = FALSE;
+
+ for (iter_a = a; iter_a; iter_a = g_slist_next (iter_a)) {
+ NMIP6Route *route_a = (NMIP6Route *) iter_a->data;
+
+ for (iter_b = b, found = FALSE; iter_b; iter_b = g_slist_next (iter_b)) {
+ NMIP6Route *route_b = (NMIP6Route *) iter_b->data;
+
+ if (nm_ip6_route_compare (route_a, route_b)) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+string_array_compare (GPtrArray *a, GPtrArray *b)
+{
+ int i, j;
+ gboolean found = FALSE;
+
+ for (i = 0; i < a->len; i++) {
+ for (j = 0, found = FALSE; j < b->len; j++) {
+ const char *item_a = g_ptr_array_index (a, i);
+ const char *item_b = g_ptr_array_index (b, j);
+
+ if ((!item_a && !item_b) || (item_a && item_b && !strcmp (item_a, item_b))) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+addr_array_compare (GArray *a, GArray *b)
+{
+ struct in6_addr *addrs_a, *addrs_b;
+ int i, j;
+ gboolean found = FALSE;
+
+ addrs_a = (struct in6_addr *)a->data;
+ addrs_b = (struct in6_addr *)b->data;
+ for (i = 0; i < a->len; i++) {
+ for (j = 0, found = FALSE; j < b->len; j++) {
+ if (memcmp (&addrs_a[i], &addrs_b[j], sizeof (struct in6_addr)) == 0) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+NMIP6ConfigCompareFlags
+nm_ip6_config_diff (NMIP6Config *a, NMIP6Config *b)
+{
+ NMIP6ConfigPrivate *a_priv;
+ NMIP6ConfigPrivate *b_priv;
+ NMIP6ConfigCompareFlags flags = NM_IP6_COMPARE_FLAG_NONE;
+
+ if ((a && !b) || (b && !a))
+ return 0xFFFFFFFF;
+ if (!a && !b)
+ return NM_IP6_COMPARE_FLAG_NONE;
+
+ a_priv = NM_IP6_CONFIG_GET_PRIVATE (a);
+ b_priv = NM_IP6_CONFIG_GET_PRIVATE (b);
+
+ if ( !addr_slist_compare (a_priv->addresses, b_priv->addresses)
+ || !addr_slist_compare (b_priv->addresses, a_priv->addresses))
+ flags |= NM_IP6_COMPARE_FLAG_ADDRESSES;
+
+ if (memcmp (&a_priv->ptp_address, &b_priv->ptp_address, sizeof (struct in6_addr)) != 0)
+ flags |= NM_IP6_COMPARE_FLAG_PTP_ADDRESS;
+
+ if ( (a_priv->nameservers->len != b_priv->nameservers->len)
+ || !addr_array_compare (a_priv->nameservers, b_priv->nameservers)
+ || !addr_array_compare (b_priv->nameservers, a_priv->nameservers))
+ flags |= NM_IP6_COMPARE_FLAG_NAMESERVERS;
+
+ if ( !route_slist_compare (a_priv->routes, b_priv->routes)
+ || !route_slist_compare (b_priv->routes, a_priv->routes))
+ flags |= NM_IP6_COMPARE_FLAG_ROUTES;
+
+ if ( (a_priv->domains->len != b_priv->domains->len)
+ || !string_array_compare (a_priv->domains, b_priv->domains)
+ || !string_array_compare (b_priv->domains, a_priv->domains))
+ flags |= NM_IP6_COMPARE_FLAG_DOMAINS;
+
+ if ( (a_priv->searches->len != b_priv->searches->len)
+ || !string_array_compare (a_priv->searches, b_priv->searches)
+ || !string_array_compare (b_priv->searches, a_priv->searches))
+ flags |= NM_IP6_COMPARE_FLAG_SEARCHES;
+
+ if (a_priv->mss != b_priv->mss)
+ flags |= NM_IP6_COMPARE_FLAG_MSS;
+
+ return flags;
+}
+
+static void
+nm_ip6_config_init (NMIP6Config *config)
+{
+ NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config);
+
+ priv->nameservers = g_array_new (FALSE, TRUE, sizeof (struct in6_addr));
+ priv->domains = g_ptr_array_sized_new (3);
+ priv->searches = g_ptr_array_sized_new (3);
+}
+
+static void
+finalize (GObject *object)
+{
+ NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (object);
+
+ nm_utils_slist_free (priv->addresses, (GDestroyNotify) nm_ip6_address_unref);
+ nm_utils_slist_free (priv->routes, (GDestroyNotify) nm_ip6_route_unref);
+ g_array_free (priv->nameservers, TRUE);
+ g_ptr_array_free (priv->domains, TRUE);
+ g_ptr_array_free (priv->searches, TRUE);
+
+ G_OBJECT_CLASS (nm_ip6_config_parent_class)->finalize (object);
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_ADDRESSES:
+ nm_utils_ip6_addresses_to_gvalue (priv->addresses, value);
+ break;
+ case PROP_NAMESERVERS:
+ g_value_set_boxed (value, priv->nameservers);
+ break;
+ case PROP_DOMAINS:
+ g_value_set_boxed (value, priv->domains);
+ break;
+ case PROP_ROUTES:
+ nm_utils_ip6_routes_to_gvalue (priv->routes, value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_ip6_config_class_init (NMIP6ConfigClass *config_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (config_class);
+
+ g_type_class_add_private (config_class, sizeof (NMIP6ConfigPrivate));
+
+ /* virtual methods */
+ object_class->get_property = get_property;
+ object_class->finalize = finalize;
+
+ /* properties */
+ g_object_class_install_property
+ (object_class, PROP_ADDRESSES,
+ g_param_spec_boxed (NM_IP6_CONFIG_ADDRESSES,
+ "Addresses",
+ "IP6 addresses",
+ DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT,
+ G_PARAM_READABLE));
+ g_object_class_install_property
+ (object_class, PROP_NAMESERVERS,
+ g_param_spec_boxed (NM_IP6_CONFIG_NAMESERVERS,
+ "Nameservers",
+ "DNS list",
+ DBUS_TYPE_G_UINT_ARRAY,
+ G_PARAM_READABLE));
+ g_object_class_install_property
+ (object_class, PROP_DOMAINS,
+ g_param_spec_boxed (NM_IP6_CONFIG_DOMAINS,
+ "Domains",
+ "Domains",
+ DBUS_TYPE_G_ARRAY_OF_STRING,
+ G_PARAM_READABLE));
+ g_object_class_install_property
+ (object_class, PROP_ROUTES,
+ g_param_spec_boxed (NM_IP6_CONFIG_ROUTES,
+ "Routes",
+ "Routes",
+ DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT,
+ G_PARAM_READABLE));
+
+ dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (config_class),
+ &dbus_glib_nm_ip6_config_object_info);
+}
diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h
new file mode 100644
index 000000000..4fd959d53
--- /dev/null
+++ b/src/nm-ip6-config.h
@@ -0,0 +1,120 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ */
+
+#ifndef NM_IP6_CONFIG_H
+#define NM_IP6_CONFIG_H
+
+#include
+#include
+
+#include "nm-setting-ip6-config.h"
+
+#define NM_TYPE_IP6_CONFIG (nm_ip6_config_get_type ())
+#define NM_IP6_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IP6_CONFIG, NMIP6Config))
+#define NM_IP6_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_IP6_CONFIG, NMIP6ConfigClass))
+#define NM_IS_IP6_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_IP6_CONFIG))
+#define NM_IS_IP6_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_IP6_CONFIG))
+#define NM_IP6_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_IP6_CONFIG, NMIP6ConfigClass))
+
+typedef struct {
+ GObject parent;
+} NMIP6Config;
+
+typedef struct {
+ GObjectClass parent;
+} NMIP6ConfigClass;
+
+#define NM_IP6_CONFIG_ADDRESSES "addresses"
+#define NM_IP6_CONFIG_NAMESERVERS "nameservers"
+#define NM_IP6_CONFIG_DOMAINS "domains"
+#define NM_IP6_CONFIG_ROUTES "routes"
+
+GType nm_ip6_config_get_type (void);
+
+
+NMIP6Config * nm_ip6_config_new (void);
+void nm_ip6_config_export (NMIP6Config *config);
+const char * nm_ip6_config_get_dbus_path (NMIP6Config *config);
+
+void nm_ip6_config_take_address (NMIP6Config *config, NMIP6Address *address);
+void nm_ip6_config_add_address (NMIP6Config *config, NMIP6Address *address);
+void nm_ip6_config_replace_address (NMIP6Config *config, guint32 i, NMIP6Address *new_address);
+NMIP6Address *nm_ip6_config_get_address (NMIP6Config *config, guint32 i);
+guint32 nm_ip6_config_get_num_addresses (NMIP6Config *config);
+
+const struct in6_addr *nm_ip6_config_get_ptp_address (NMIP6Config *config);
+void nm_ip6_config_set_ptp_address (NMIP6Config *config, struct in6_addr *ptp_addr);
+
+void nm_ip6_config_add_nameserver (NMIP6Config *config, const struct in6_addr *nameserver);
+const struct in6_addr *nm_ip6_config_get_nameserver (NMIP6Config *config, guint i);
+guint32 nm_ip6_config_get_num_nameservers (NMIP6Config *config);
+void nm_ip6_config_reset_nameservers (NMIP6Config *config);
+
+void nm_ip6_config_take_route (NMIP6Config *config, NMIP6Route *route);
+void nm_ip6_config_add_route (NMIP6Config *config, NMIP6Route *route);
+void nm_ip6_config_replace_route (NMIP6Config *config, guint32 i, NMIP6Route *new_route);
+NMIP6Route * nm_ip6_config_get_route (NMIP6Config *config, guint32 i);
+guint32 nm_ip6_config_get_num_routes (NMIP6Config *config);
+void nm_ip6_config_reset_routes (NMIP6Config *config);
+
+void nm_ip6_config_add_domain (NMIP6Config *config, const char *domain);
+const char * nm_ip6_config_get_domain (NMIP6Config *config, guint i);
+guint32 nm_ip6_config_get_num_domains (NMIP6Config *config);
+void nm_ip6_config_reset_domains (NMIP6Config *config);
+
+void nm_ip6_config_add_search (NMIP6Config *config, const char *search);
+const char * nm_ip6_config_get_search (NMIP6Config *config, guint i);
+guint32 nm_ip6_config_get_num_searches (NMIP6Config *config);
+void nm_ip6_config_reset_searches (NMIP6Config *config);
+
+guint32 nm_ip6_config_get_mss (NMIP6Config *config);
+void nm_ip6_config_set_mss (NMIP6Config *config, guint32 mss);
+
+gboolean nm_ip6_config_get_never_default (NMIP6Config *config);
+void nm_ip6_config_set_never_default (NMIP6Config *config, gboolean never_default);
+
+/* Flags for nm_ip6_config_to_rtnl_addr() */
+#define NM_RTNL_ADDR_NONE 0x0000
+#define NM_RTNL_ADDR_ADDR 0x0001
+#define NM_RTNL_ADDR_PTP_ADDR 0x0002
+#define NM_RTNL_ADDR_PREFIX 0x0004
+#define NM_RTNL_ADDR_BROADCAST 0x0008
+
+#define NM_RTNL_ADDR_DEFAULT (NM_RTNL_ADDR_ADDR | NM_RTNL_ADDR_PREFIX | NM_RTNL_ADDR_BROADCAST)
+#define NM_RTNL_ADDR_PTP_DEFAULT (NM_RTNL_ADDR_ADDR | NM_RTNL_ADDR_PREFIX | NM_RTNL_ADDR_PTP_ADDR)
+
+struct rtnl_addr *nm_ip6_config_to_rtnl_addr (NMIP6Config *config, guint32 i, guint32 flags);
+
+typedef enum {
+ NM_IP6_COMPARE_FLAG_NONE = 0x00000000, /* match nothing, kinda pointless */
+ NM_IP6_COMPARE_FLAG_ADDRESSES = 0x00000001,
+ NM_IP6_COMPARE_FLAG_PTP_ADDRESS = 0x00000002,
+ NM_IP6_COMPARE_FLAG_NAMESERVERS = 0x00000004,
+ NM_IP6_COMPARE_FLAG_ROUTES = 0x00000008,
+ NM_IP6_COMPARE_FLAG_DOMAINS = 0x00000010,
+ NM_IP6_COMPARE_FLAG_SEARCHES = 0x00000020,
+ NM_IP6_COMPARE_FLAG_MSS = 0x00000080,
+ NM_IP6_COMPARE_FLAG_ALL = 0xFFFFFFFF /* match everything */
+} NMIP6ConfigCompareFlags;
+
+/* Returns a bitfield representing how the two IP6 configs differ */
+NMIP6ConfigCompareFlags nm_ip6_config_diff (NMIP6Config *a, NMIP6Config *b);
+
+#endif /* NM_IP6_CONFIG_H */
diff --git a/src/nm-manager.c b/src/nm-manager.c
index 87338a10d..5ad0ff58c 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -650,8 +650,8 @@ user_connection_get_settings_cb (DBusGProxy *proxy,
*/
g_object_set_data_full (G_OBJECT (connection),
"proxy",
- info->proxy,
- g_object_ref (info->proxy));
+ g_object_ref (info->proxy),
+ g_object_unref);
} else
g_object_unref (connection);
diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c
index 6657aa787..a4521e0e1 100644
--- a/src/vpn-manager/nm-vpn-connection.c
+++ b/src/vpn-manager/nm-vpn-connection.c
@@ -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) {
diff --git a/system-settings/plugins/ifcfg-rh/reader.c b/system-settings/plugins/ifcfg-rh/reader.c
index e41de7d56..61f3d6879 100644
--- a/system-settings/plugins/ifcfg-rh/reader.c
+++ b/system-settings/plugins/ifcfg-rh/reader.c
@@ -1204,7 +1204,9 @@ eap_peap_reader (const char *eap_method,
if (!strlen (*iter))
continue;
- if (!strcmp (*iter, "MSCHAPV2") || !strcmp (*iter, "MD5")) {
+ if ( !strcmp (*iter, "MSCHAPV2")
+ || !strcmp (*iter, "MD5")
+ || !strcmp (*iter, "GTC")) {
if (!eap_simple_reader (*iter, ifcfg, keys, s_8021x, TRUE, error))
goto done;
} else if (!strcmp (*iter, "TLS")) {
@@ -1217,7 +1219,6 @@ eap_peap_reader (const char *eap_method,
goto done;
}
- // FIXME: OTP & GTC too
lower = g_ascii_strdown (*iter, -1);
g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, lower, NULL);
g_free (lower);