Merge remote branch 'origin/master' into cli-output

This commit is contained in:
Dan Williams 2010-05-05 00:38:51 -07:00
commit 688de6d782
86 changed files with 4105 additions and 2191 deletions

View file

@ -296,7 +296,7 @@ AC_ARG_WITH([pppd-plugin-dir], AS_HELP_STRING([--with-pppd-plugin-dir=DIR], [pat
if test -n "$with_pppd_plugin_dir" ; then
PPPD_PLUGIN_DIR="$with_pppd_plugin_dir"
else
PPPD_PLUGIN_DIR="${libdir}/pppd/2.4.4"
PPPD_PLUGIN_DIR="${libdir}/pppd/2.4.5"
fi
AC_SUBST(PPPD_PLUGIN_DIR)

View file

@ -17,7 +17,7 @@
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* (C) Copyright 2009 Red Hat, Inc.
* (C) Copyright 2009 - 2010 Red Hat, Inc.
*/
#include <stdio.h>
@ -86,7 +86,7 @@ static TypeNameElement name_map[] = {
{ "GPtrArray_GArray_guint__", "array of array of uint32" },
{ "GPtrArray_GArray_guchar__", "array of byte array" },
{ "GHashTable_gchararray+gchararray_", "dict of (string::string)" },
{ "GPtrArray_GValueArray_GArray_guchar_+guint__", "array of (byte array, uint32)" },
{ "GPtrArray_GValueArray_GArray_guchar_+guint+GArray_guchar___", "array of (byte array, uint32, byte array)" },
{ "GPtrArray_GValueArray_GArray_guchar_+guint+GArray_guchar_+guint__", "array of (byte array, uint32, byte array, uint32)" },
{ NULL, NULL }
};

View file

@ -1,4 +1,8 @@
EXTRA_DIST = \
nm-state.py \
add-system-connection.py
add-system-connection.py \
vpn.py \
list-connections.py \
show-bssids.py

View file

@ -0,0 +1,112 @@
#!/bin/env python
#
# 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) 2010 Red Hat, Inc.
#
import dbus
# This example asks both the system settings service and the user settings
# service for all configured connections. It also asks for secrets, demonstrating
# the mechanisms each settings service uses to prevent unauthorized access to
# a user's network passwords
bus = dbus.SystemBus()
def merge_secrets(proxy, config, setting_name):
try:
# returns a dict of dicts mapping name::setting, where setting is a dict
# mapping key::value. Each member of the 'setting' dict is a secret
secrets = proxy.GetSecrets(setting_name, [], False)
# Copy the secrets into our connection config
for setting in secrets:
for key in secrets[setting]:
config[setting_name][key] = setting[key]
except Exception, e:
pass
def dict_to_string(d, indent):
# Try to trivially translate a dictionary's elements into nice string
# formatting.
dstr = ""
for key in d:
val = d[key]
str_val = ""
add_string = True
if type(val) == type(dbus.Array([])):
for elt in val:
if type(elt) == type(dbus.Byte(1)):
str_val += "%s " % int(elt)
elif type(elt) == type(dbus.String("")):
str_val += "%s" % elt
elif type(val) == type(dbus.Dictionary({})):
dstr += dict_to_string(val, indent + " ")
add_string = False
else:
str_val = val
if add_string:
dstr += "%s%s: %s\n" % (indent, key, str_val)
return dstr
def connection_to_string(config):
# dump a connection configuration to a the console
for setting_name in config:
print " Setting: %s" % setting_name
print dict_to_string(config[setting_name], " ")
print ""
def print_one_services_connections(service_name, desc):
# Ask the settings service for the list of connections it provides
proxy = bus.get_object(service_name, "/org/freedesktop/NetworkManagerSettings")
settings = dbus.Interface(proxy, "org.freedesktop.NetworkManagerSettings")
connection_paths = settings.ListConnections()
print "%s connections --------------------------------------------\n" % desc
# List each connection's name, UUID, and type
for path in connection_paths:
con_proxy = bus.get_object(service_name, path)
connection = dbus.Interface(con_proxy, "org.freedesktop.NetworkManagerSettings.Connection")
config = connection.GetSettings()
# Now get secrets too; we grab the secrets for each type of connection
# (since there isn't a "get all secrets" call because most of the time
# you only need 'wifi' secrets or '802.1x' secrets, not everything) and
# merge that into the configuration data
connection_secrets = dbus.Interface(con_proxy, "org.freedesktop.NetworkManagerSettings.Connection.Secrets")
merge_secrets(connection_secrets, config, '802-11-wireless')
merge_secrets(connection_secrets, config, '802-11-wireless-security')
merge_secrets(connection_secrets, config, '802-1x')
merge_secrets(connection_secrets, config, 'gsm')
merge_secrets(connection_secrets, config, 'cdma')
merge_secrets(connection_secrets, config, 'ppp')
# Get the details of the 'connection' setting
s_con = config['connection']
print "name: %s" % s_con['id']
print " uuid: %s" % s_con['uuid']
print " type: %s" % s_con['type']
print " ----------------------------"
connection_to_string(config)
print ""
# Print out connection information for all connections
print_one_services_connections("org.freedesktop.NetworkManagerSystemSettings", "System")
print_one_services_connections("org.freedesktop.NetworkManagerUserSettings", "User")

View file

@ -0,0 +1,78 @@
#!/bin/env python
#
# 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) 2010 Red Hat, Inc.
#
# This example prints out all the AP BSSIDs that all WiFi devices on the
# machine can see. Useful for location-based services like Skyhook that
# can geolocate you based on the APs you can see.
import dbus
bus = dbus.SystemBus()
# Get a proxy for the base NetworkManager object
proxy = bus.get_object("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager")
manager = dbus.Interface(proxy, "org.freedesktop.NetworkManager")
all_aps = []
print "Associated APs:"
# Get all network devices
devices = manager.GetDevices()
for d in devices:
dev_proxy = bus.get_object("org.freedesktop.NetworkManager", d)
prop_iface = dbus.Interface(dev_proxy, "org.freedesktop.DBus.Properties")
# Make sure the device is enabled before we try to use it
state = prop_iface.Get("org.freedesktop.NetworkManager.Device", "State")
if state <= 2:
continue
# Get device's type; we only want wifi devices
iface = prop_iface.Get("org.freedesktop.NetworkManager.Device", "Interface")
dtype = prop_iface.Get("org.freedesktop.NetworkManager.Device", "DeviceType")
if dtype == 2: # WiFi
# Get a proxy for the wifi interface
wifi_iface = dbus.Interface(dev_proxy, "org.freedesktop.NetworkManager.Device.Wireless")
wifi_prop_iface = dbus.Interface(dev_proxy, "org.freedesktop.DBus.Properties")
# Get the associated AP's object path
connected_path = wifi_prop_iface.Get("org.freedesktop.NetworkManager.Device.Wireless", "ActiveAccessPoint")
# Get all APs the card can see
aps = wifi_iface.GetAccessPoints()
for path in aps:
ap_proxy = bus.get_object("org.freedesktop.NetworkManager", path)
ap_prop_iface = dbus.Interface(ap_proxy, "org.freedesktop.DBus.Properties")
bssid = ap_prop_iface.Get("org.freedesktop.NetworkManager.AccessPoint", "HwAddress")
# Cache the BSSID
if not bssid in all_aps:
all_aps.append(bssid)
# Print the current AP's BSSID
if path == connected_path:
print "%s (%s)" % (bssid, iface)
# and print out all APs the wifi devices can see
print"\nFound APs:"
for bssid in all_aps:
print bssid

View file

@ -34,7 +34,7 @@
#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, G_TYPE_INVALID))
#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_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))

View file

@ -18,7 +18,10 @@
<tp:docstring>The state of this active connection.</tp:docstring>
</property>
<property name="Default" type="b" access="read">
<tp:docstring>Whether this active connection is the default connection, i.e. whether it currently owns the default route.</tp:docstring>
<tp:docstring>Whether this active connection is the default IPv4 connection, i.e. whether it currently owns the default IPv4 route.</tp:docstring>
</property>
<property name="Default6" type="b" access="read">
<tp:docstring>Whether this active connection is the default IPv6 connection, i.e. whether it currently owns the default IPv6 route.</tp:docstring>
</property>
<property name="Vpn" type="b" access="read">
<tp:docstring>Whether this active connection is also a VPN connection.</tp:docstring>

View file

@ -2,8 +2,8 @@
<node name="/" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
<interface name="org.freedesktop.NetworkManager.IP6Config">
<property name="Addresses" type="a(ayu)" access="read">
<tp:docstring>Tuples of IPv6 address/prefix.</tp:docstring>
<property name="Addresses" type="a(ayuay)" access="read">
<tp:docstring>Tuples of IPv6 address/prefix/gateway.</tp:docstring>
</property>
<property name="Nameservers" type="aay" access="read">
<tp:docstring>The nameservers in use.</tp:docstring>

View file

@ -110,7 +110,7 @@
<tp:docstring>
A combination of logging domains separated by commas (','), or "NONE"
to disable logging. Each domain enables logging for operations
related to that domain. Available domains are: [NONE, HW, RKILL,
related to that domain. Available domains are: [NONE, HW, RFKILL,
ETHER, WIFI, BT, MB, DHCP4, DHCP6, PPP, WIFI_SCAN, IP4, IP6, AUTOIP4,
DNS, VPN, SHARING, SUPPLICANT, USER_SET, SYS_SET, SUSPEND, CORE,
DEVICE, OLPC]

View file

@ -132,7 +132,7 @@ libnm_glib_la_LIBADD = \
$(GUDEV_LIBS)
libnm_glib_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libnm-glib.ver \
-version-info "4:1:2"
-version-info "4:2:2"
noinst_PROGRAMS = libnm-glib-test

View file

@ -18,6 +18,7 @@ global:
nm_access_point_new;
nm_active_connection_get_connection;
nm_active_connection_get_default;
nm_active_connection_get_default6;
nm_active_connection_get_devices;
nm_active_connection_get_scope;
nm_active_connection_get_service_name;

View file

@ -17,7 +17,7 @@
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright (C) 2007 - 2008 Red Hat, Inc.
* Copyright (C) 2007 - 2010 Red Hat, Inc.
* Copyright (C) 2008 Novell, Inc.
*/
@ -50,6 +50,7 @@ typedef struct {
GPtrArray *devices;
NMActiveConnectionState state;
gboolean is_default;
gboolean is_default6;
} NMActiveConnectionPrivate;
enum {
@ -60,6 +61,7 @@ enum {
PROP_DEVICES,
PROP_STATE,
PROP_DEFAULT,
PROP_DEFAULT6,
LAST_PROP
};
@ -70,6 +72,7 @@ enum {
#define DBUS_PROP_DEVICES "Devices"
#define DBUS_PROP_STATE "State"
#define DBUS_PROP_DEFAULT "Default"
#define DBUS_PROP_DEFAULT6 "Default6"
/**
* nm_active_connection_new:
@ -263,10 +266,10 @@ nm_active_connection_get_state (NMActiveConnection *connection)
* nm_active_connection_get_default:
* @connection: a #NMActiveConnection
*
* Whether the active connection is the default one (that is, is used for the default route
* and DNS information).
* Whether the active connection is the default IPv4 one (that is, is used for
* the default IPv4 route and DNS information).
*
* Returns: %TRUE if the active connection is the default one
* Returns: %TRUE if the active connection is the default IPv4 connection
**/
gboolean
nm_active_connection_get_default (NMActiveConnection *connection)
@ -278,13 +281,39 @@ nm_active_connection_get_default (NMActiveConnection *connection)
priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (connection);
if (!priv->is_default) {
priv->is_default = _nm_object_get_boolean_property (NM_OBJECT (connection),
NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
DBUS_PROP_DEFAULT);
NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
DBUS_PROP_DEFAULT);
}
return priv->is_default;
}
/**
* nm_active_connection_get_default6:
* @connection: a #NMActiveConnection
*
* Whether the active connection is the default IPv6 one (that is, is used for
* the default IPv6 route and DNS information).
*
* Returns: %TRUE if the active connection is the default IPv6 connection
**/
gboolean
nm_active_connection_get_default6 (NMActiveConnection *connection)
{
NMActiveConnectionPrivate *priv;
g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), FALSE);
priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (connection);
if (!priv->is_default6) {
priv->is_default6 = _nm_object_get_boolean_property (NM_OBJECT (connection),
NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
DBUS_PROP_DEFAULT6);
}
return priv->is_default6;
}
static void
nm_active_connection_init (NMActiveConnection *ap)
{
@ -350,6 +379,9 @@ get_property (GObject *object,
case PROP_DEFAULT:
g_value_set_boolean (value, nm_active_connection_get_default (self));
break;
case PROP_DEFAULT6:
g_value_set_boolean (value, nm_active_connection_get_default6 (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -392,6 +424,7 @@ register_for_property_changed (NMActiveConnection *connection)
{ NM_ACTIVE_CONNECTION_DEVICES, demarshal_devices, &priv->devices },
{ NM_ACTIVE_CONNECTION_STATE, _nm_object_demarshal_generic, &priv->state },
{ NM_ACTIVE_CONNECTION_DEFAULT, _nm_object_demarshal_generic, &priv->is_default },
{ NM_ACTIVE_CONNECTION_DEFAULT6, _nm_object_demarshal_generic, &priv->is_default6 },
{ NULL },
};
@ -512,13 +545,26 @@ nm_active_connection_class_init (NMActiveConnectionClass *ap_class)
/**
* NMActiveConnection:default:
*
* Whether the active connection is the default one.
* Whether the active connection is the default IPv4 one.
**/
g_object_class_install_property
(object_class, PROP_DEFAULT,
g_param_spec_boolean (NM_ACTIVE_CONNECTION_DEFAULT,
"Default",
"Is the default active connection",
"Is the default IPv4 active connection",
FALSE,
G_PARAM_READABLE));
/**
* NMActiveConnection:default6:
*
* Whether the active connection is the default IPv6 one.
**/
g_object_class_install_property
(object_class, PROP_DEFAULT6,
g_param_spec_boolean (NM_ACTIVE_CONNECTION_DEFAULT6,
"Default6",
"Is the default IPv6 active connection",
FALSE,
G_PARAM_READABLE));
}

View file

@ -17,7 +17,7 @@
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright (C) 2007 - 2008 Red Hat, Inc.
* Copyright (C) 2007 - 2010 Red Hat, Inc.
* Copyright (C) 2008 Novell, Inc.
*/
@ -45,6 +45,7 @@ G_BEGIN_DECLS
#define NM_ACTIVE_CONNECTION_DEVICES "devices"
#define NM_ACTIVE_CONNECTION_STATE "state"
#define NM_ACTIVE_CONNECTION_DEFAULT "default"
#define NM_ACTIVE_CONNECTION_DEFAULT6 "default6"
typedef struct {
NMObject parent;
@ -73,6 +74,7 @@ const char * nm_active_connection_get_specific_object (NMActiveConnection *c
const GPtrArray *nm_active_connection_get_devices (NMActiveConnection *connection);
NMActiveConnectionState nm_active_connection_get_state (NMActiveConnection *connection);
gboolean nm_active_connection_get_default (NMActiveConnection *connection);
gboolean nm_active_connection_get_default6 (NMActiveConnection *connection);
G_END_DECLS

View file

@ -59,7 +59,7 @@ libnm_util_la_SOURCES= \
libnm_util_la_LIBADD = $(GLIB_LIBS) $(DBUS_LIBS) $(UUID_LIBS)
libnm_util_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libnm-util.ver \
-version-info "4:2:3"
-version-info "4:4:3"
if WITH_GNUTLS
libnm_util_la_SOURCES += crypto_gnutls.c

View file

@ -168,8 +168,7 @@ 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_setting_ip4_config_get_may_fail;
nm_ip6_address_new;
nm_ip6_address_dup;
nm_ip6_address_ref;
@ -177,6 +176,8 @@ global:
nm_ip6_address_compare;
nm_ip6_address_get_address;
nm_ip6_address_set_address;
nm_ip6_address_get_gateway;
nm_ip6_address_set_gateway;
nm_ip6_address_get_prefix;
nm_ip6_address_set_prefix;
nm_ip6_route_new;
@ -192,6 +193,8 @@ global:
nm_ip6_route_set_next_hop;
nm_ip6_route_get_metric;
nm_ip6_route_set_metric;
nm_setting_ip6_config_error_get_type;
nm_setting_ip6_config_error_quark;
nm_setting_ip6_config_get_type;
nm_setting_ip6_config_new;
nm_setting_ip6_config_get_method;
@ -218,6 +221,7 @@ global:
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_ip6_config_get_may_fail;
nm_setting_need_secrets;
nm_setting_ppp_error_get_type;
nm_setting_ppp_error_quark;

View file

@ -19,7 +19,7 @@
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* (C) Copyright 2007 - 2008 Red Hat, Inc.
* (C) Copyright 2007 - 2010 Red Hat, Inc.
* (C) Copyright 2007 - 2008 Novell, Inc.
*/
@ -377,6 +377,7 @@ nm_gvalue_ip6_address_compare (const GValue *value1, const GValue *value2)
GValue *tmp_val;
GByteArray *addr1, *addr2;
guint32 prefix1, prefix2;
GByteArray *gw1, *gw2;
gint ret = 0;
int i;
@ -387,8 +388,8 @@ nm_gvalue_ip6_address_compare (const GValue *value1, const GValue *value2)
/* Since they are NM IPv6 address structures, we expect both
* to contain two elements as specified in nm-dbus-glib-types.h.
*/
g_return_val_if_fail (values1->n_values == 2, 0);
g_return_val_if_fail (values2->n_values == 2, 0);
g_return_val_if_fail (values1->n_values == 3, 0);
g_return_val_if_fail (values2->n_values == 3, 0);
/* First struct IPv6 address */
tmp_val = g_value_array_get_nth (values1, 0);
@ -396,6 +397,9 @@ nm_gvalue_ip6_address_compare (const GValue *value1, const GValue *value2)
/* First struct IPv6 prefix */
tmp_val = g_value_array_get_nth (values1, 1);
prefix1 = g_value_get_uint (tmp_val);
/* First struct IPv6 gateway */
tmp_val = g_value_array_get_nth (values1, 2);
gw1 = g_value_get_boxed (tmp_val);
/* Second struct IPv6 address */
tmp_val = g_value_array_get_nth (values2, 0);
@ -403,6 +407,9 @@ nm_gvalue_ip6_address_compare (const GValue *value1, const GValue *value2)
/* Second struct IPv6 prefix */
tmp_val = g_value_array_get_nth (values2, 1);
prefix2 = g_value_get_uint (tmp_val);
/* Second struct IPv6 gateway */
tmp_val = g_value_array_get_nth (values2, 2);
gw2 = g_value_get_boxed (tmp_val);
/* Compare IPv6 addresses */
if (prefix1 != prefix2)
@ -413,6 +420,11 @@ nm_gvalue_ip6_address_compare (const GValue *value1, const GValue *value2)
ret = addr1->data[i] < addr2->data[i] ? -1 : addr1->data[i] > addr2->data[i];
}
if (!IN6_ARE_ADDR_EQUAL ((struct in6_addr *) gw1->data, (struct in6_addr *) gw2->data)) {
for (i = 0; ret == 0 && i < gw1->len; i++)
ret = gw1->data[i] < gw2->data[i] ? -1 : gw1->data[i] > gw2->data[i];
}
return ret;
}

View file

@ -19,7 +19,7 @@
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* (C) Copyright 2007 - 2008 Red Hat, Inc.
* (C) Copyright 2007 - 2010 Red Hat, Inc.
* (C) Copyright 2007 - 2008 Novell, Inc.
*/
@ -83,6 +83,7 @@ typedef struct {
gboolean dhcp_send_hostname;
char *dhcp_hostname;
gboolean never_default;
gboolean may_fail;
} NMSettingIP4ConfigPrivate;
enum {
@ -98,6 +99,7 @@ enum {
PROP_DHCP_SEND_HOSTNAME,
PROP_DHCP_HOSTNAME,
PROP_NEVER_DEFAULT,
PROP_MAY_FAIL,
LAST_PROP
};
@ -438,6 +440,14 @@ nm_setting_ip4_config_get_never_default (NMSettingIP4Config *setting)
return NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->never_default;
}
gboolean
nm_setting_ip4_config_get_may_fail (NMSettingIP4Config *setting)
{
g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), FALSE);
return NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->may_fail;
}
static gboolean
verify (NMSetting *setting, GSList *all_settings, GError **error)
{
@ -462,7 +472,8 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
return FALSE;
}
} else if ( !strcmp (priv->method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)
|| !strcmp (priv->method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) {
|| !strcmp (priv->method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)
|| !strcmp (priv->method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) {
if (priv->dns && priv->dns->len) {
g_set_error (error,
NM_SETTING_IP4_CONFIG_ERROR,
@ -640,6 +651,9 @@ set_property (GObject *object, guint prop_id,
case PROP_NEVER_DEFAULT:
priv->never_default = g_value_get_boolean (value);
break;
case PROP_MAY_FAIL:
priv->may_fail = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -687,6 +701,9 @@ get_property (GObject *object, guint prop_id,
case PROP_NEVER_DEFAULT:
g_value_set_boolean (value, priv->never_default);
break;
case PROP_MAY_FAIL:
g_value_set_boolean (value, priv->may_fail);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -721,7 +738,8 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class)
* network access to other computers) then the interface is assigned an
* address in the 10.42.x.1/24 range and a DHCP and forwarding DNS server
* are started, and the interface is NAT-ed to the current default network
* connection. This property must be set.
* connection. 'disabled' means IPv4 will not be used on this connection.
* This property must be set.
**/
g_object_class_install_property
(object_class, PROP_METHOD,
@ -742,7 +760,8 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class)
"address in the 10.42.x.1/24 range and a DHCP and "
"forwarding DNS server are started, and the "
"interface is NAT-ed to the current default network "
"connection. This property must be set.",
"connection. 'disabled' means IPv4 will not be "
"used on this connection. This property must be set.",
NULL,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
@ -751,8 +770,8 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class)
*
* List of DNS servers (network byte order). For the 'auto' method, these
* DNS servers are appended to those (if any) returned by automatic
* configuration. DNS servers cannot be used with the 'shared' or
* 'link-local' methods as there is no usptream network. In all other
* configuration. DNS servers cannot be used with the 'shared', 'link-local',
* or 'disabled' methods as there is no usptream network. In all other
* methods, these DNS servers are used as the only DNS servers for this
* connection.
**/
@ -764,10 +783,10 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class)
"the 'auto' method, these DNS servers are "
"appended to those (if any) returned by automatic "
"configuration. DNS servers cannot be used with "
"the 'shared' or 'link-local' methods as there is "
"no usptream network. In all other methods, "
"these DNS servers are used as the only DNS "
"servers for this connection.",
"the 'shared', 'link-local', or 'disabled' "
"methods as there is no usptream network. In all "
"other methods, these DNS servers are used as the "
"only DNS servers for this connection.",
DBUS_TYPE_G_UINT_ARRAY,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
@ -776,9 +795,9 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class)
*
* List of DNS search domains. For the 'auto' method, these search domains
* are appended to those returned by automatic configuration. Search domains
* cannot be used with the 'shared' or 'link-local' methods as there is no
* upstream network. In all other methods, these search domains are used
* as the only search domains for this connection.
* cannot be used with the 'shared', 'link-local', or 'disabled' methods as
* there is no upstream network. In all other methods, these search domains
* are used as the only search domains for this connection.
**/
g_object_class_install_property
(object_class, PROP_DNS_SEARCH,
@ -787,11 +806,11 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class)
"List of DNS search domains. For the 'auto' "
"method, these search domains are appended to "
"those returned by automatic configuration. "
"Search domains cannot be used with the 'shared' "
"or 'link-local' methods as there is no upstream "
"network. In all other methods, these search "
"domains are used as the only search domains for "
"this connection.",
"Search domains cannot be used with the 'shared', "
"'link-local', or 'disabled' methods as there is "
"no upstream network. In all other methods, these "
"search domains are used as the only search domains "
"for this connection.",
DBUS_TYPE_G_LIST_OF_STRING,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
@ -804,8 +823,8 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class)
* (network byte order). The gateway may be left as 0 if no gateway exists
* for that subnet. For the 'auto' method, given IP addresses are appended
* to those returned by automatic configuration. Addresses cannot be used
* with the 'shared' or 'link-local' methods as the interface is
* automatically assigned an address with these methods.
* with the 'shared', 'link-local', or 'disabled' methods as addressing is
* either automatic or disabled with these methods.
**/
g_object_class_install_property
(object_class, PROP_ADDRESSES,
@ -820,9 +839,9 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class)
"for that subnet. For the 'auto' method, given "
"IP addresses are appended to those returned by "
"automatic configuration. Addresses cannot be "
"used with the 'shared' or 'link-local' methods "
"as the interface is automatically assigned an "
"address with these methods.",
"used with the 'shared', 'link-local', or "
"'disabled' methods as addressing is either "
"automatic or disabled with these methods.",
DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
@ -835,8 +854,8 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class)
* address prefix (1 - 32), the third being the next-hop (network byte
* order) if any, and the fourth being the route metric. For the 'auto'
* method, given IP routes are appended to those returned by automatic
* configuration. Routes cannot be used with the 'shared' or 'link-local'
* methods because there is no upstream network.
* configuration. Routes cannot be used with the 'shared', 'link-local',
* or 'disabled' methods because there is no upstream network.
**/
g_object_class_install_property
(object_class, PROP_ROUTES,
@ -852,8 +871,8 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class)
"For the 'auto' method, given IP routes are "
"appended to those returned by automatic "
"configuration. Routes cannot be used with the "
"'shared' or 'link-local' methods as there is no "
"upstream network.",
"'shared', 'link-local', or 'disabled', methods "
"as there is no upstream network.",
DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
@ -965,6 +984,31 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class)
"the default route by NetworkManager.",
FALSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
/**
* NMSettingIP4Config:may-fail:
*
* If TRUE, allow overall network configuration to proceed even if IPv4
* configuration times out. Note that at least one IP configuration
* must succeed or overall network configuration will still fail. For
* example, in IPv6-only networks, setting this property to TRUE allows
* the overall network configuration to succeed if IPv4 configuration fails
* but IPv6 configuration completes successfully.
**/
g_object_class_install_property
(object_class, PROP_MAY_FAIL,
g_param_spec_boolean (NM_SETTING_IP4_CONFIG_MAY_FAIL,
"May Fail",
"If TRUE, allow overall network configuration to "
"proceed even if IPv4 configuration times out. "
"Note that at least one IP configuration must "
"succeed or overall network configuration will still "
"fail. For example, in IPv6-only networks, setting "
"this property to TRUE allows the overall network "
"configuration to succeed if IPv4 configuration "
"fails but IPv6 configuration completes successfully.",
FALSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
}

View file

@ -19,7 +19,7 @@
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* (C) Copyright 2007 - 2008 Red Hat, Inc.
* (C) Copyright 2007 - 2010 Red Hat, Inc.
* (C) Copyright 2007 - 2008 Novell, Inc.
*/
@ -64,11 +64,13 @@ GQuark nm_setting_ip4_config_error_quark (void);
#define NM_SETTING_IP4_CONFIG_DHCP_SEND_HOSTNAME "dhcp-send-hostname"
#define NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME "dhcp-hostname"
#define NM_SETTING_IP4_CONFIG_NEVER_DEFAULT "never-default"
#define NM_SETTING_IP4_CONFIG_MAY_FAIL "may-fail"
#define NM_SETTING_IP4_CONFIG_METHOD_AUTO "auto"
#define NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL "link-local"
#define NM_SETTING_IP4_CONFIG_METHOD_MANUAL "manual"
#define NM_SETTING_IP4_CONFIG_METHOD_SHARED "shared"
#define NM_SETTING_IP4_CONFIG_METHOD_DISABLED "disabled"
typedef struct NMIP4Address NMIP4Address;
@ -168,6 +170,8 @@ const char * nm_setting_ip4_config_get_dhcp_hostname (NMSettingIP4Config *
gboolean nm_setting_ip4_config_get_never_default (NMSettingIP4Config *setting);
gboolean nm_setting_ip4_config_get_may_fail (NMSettingIP4Config *setting);
G_END_DECLS
#endif /* NM_SETTING_IP4_CONFIG_H */

View file

@ -79,6 +79,7 @@ typedef struct {
gboolean ignore_auto_routes;
gboolean ignore_auto_dns;
gboolean never_default;
gboolean may_fail;
} NMSettingIP6ConfigPrivate;
@ -92,6 +93,7 @@ enum {
PROP_IGNORE_AUTO_ROUTES,
PROP_IGNORE_AUTO_DNS,
PROP_NEVER_DEFAULT,
PROP_MAY_FAIL,
LAST_PROP
};
@ -414,6 +416,14 @@ nm_setting_ip6_config_get_never_default (NMSettingIP6Config *setting)
return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->never_default;
}
gboolean
nm_setting_ip6_config_get_may_fail (NMSettingIP6Config *setting)
{
g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE);
return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->may_fail;
}
static gboolean
verify (NMSetting *setting, GSList *all_settings, GError **error)
{
@ -535,6 +545,9 @@ set_property (GObject *object, guint prop_id,
case PROP_NEVER_DEFAULT:
priv->never_default = g_value_get_boolean (value);
break;
case PROP_MAY_FAIL:
priv->may_fail = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -572,6 +585,9 @@ get_property (GObject *object, guint prop_id,
case PROP_NEVER_DEFAULT:
g_value_set_boolean (value, priv->never_default);
break;
case PROP_MAY_FAIL:
g_value_set_boolean (value, priv->may_fail);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -684,25 +700,32 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *setting_class)
* NMSettingIP6Config:addresses:
*
* Array of IPv6 address structures. Each IPv6 address structure is
* composed of 2 members, the first being a byte array containing the IPv6
* address (network byte order) and the second a 32-bit integer containing
* the IPv6 address prefix. For the 'auto' method, given IP addresses are
* appended to those returned by automatic configuration. Addresses cannot
* be used with the 'shared' or 'link-local' methods as the interface is
* automatically assigned an address with these methods.
* composed of 3 members, the first being a byte array containing the IPv6
* address (network byte order), the second a 32-bit integer containing the
* IPv6 address prefix, and the third a byte array containing the IPv6
* address (network byte order) of the gateway associated with this address,
* if any. If no gateway is given, the third element should be given as
* all zeros. For the 'auto' method, given IP addresses are appended to
* those returned by automatic configuration. Addresses cannot be used with
* the 'shared' or 'link-local' methods as the interface is automatically
* assigned an address with these methods.
**/
g_object_class_install_property
(object_class, PROP_ADDRESSES,
_nm_param_spec_specialized (NM_SETTING_IP6_CONFIG_ADDRESSES,
"Addresses",
"Array of IPv6 address structures. Each IPv6 "
"address structure is composed of 2 members, the "
"address structure is composed of 3 members, the "
"first being a byte array containing the IPv6 "
"address (network byte order) and the second a "
"address (network byte order), the second a "
"32-bit integer containing the IPv6 address "
"prefix. For the 'auto' method, given IP "
"addresses are appended to those returned by "
"automatic configuration. Addresses cannot be "
"prefix, and the third a byte array containing "
"the IPv6 address (network byte order) of the "
"gateway associated with this address, if any. "
"If no gateway is given, the third element should "
"be given as all zeros. For the 'auto' method, "
"given IP addresses are appended to those returned "
"by automatic configuration. Addresses cannot be "
"used with the 'shared' or 'link-local' methods "
"as the interface is automatically assigned an "
"address with these methods.",
@ -795,12 +818,39 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *setting_class)
FALSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
/**
* NMSettingIP6Config:may-fail:
*
* If TRUE, allow overall network configuration to proceed even if IPv6
* configuration times out. Note that at least one IP configuration
* must succeed or overall network configuration will still fail. For
* example, in IPv4-only networks, setting this property to TRUE allows
* the overall network configuration to succeed if IPv6 configuration fails
* but IPv4 configuration completes successfully.
**/
g_object_class_install_property
(object_class, PROP_MAY_FAIL,
g_param_spec_boolean (NM_SETTING_IP6_CONFIG_MAY_FAIL,
"May Fail",
"If TRUE, allow overall network configuration to "
"proceed even if IPv6 configuration times out. "
"Note that at least one IP configuration must "
"succeed or overall network configuration will still "
"fail. For example, in IPv4-only networks, setting "
"this property to TRUE allows the overall network "
"configuration to succeed if IPv6 configuration "
"fails but IPv4 configuration completes successfully.",
FALSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
}
/********************************************************************/
struct NMIP6Address {
guint32 refcount;
struct in6_addr address;
guint32 prefix;
struct in6_addr gateway;
};
NMIP6Address *
@ -824,6 +874,7 @@ nm_ip6_address_dup (NMIP6Address *source)
address = nm_ip6_address_new ();
address->prefix = source->prefix;
memcpy (&address->address, &source->address, sizeof (struct in6_addr));
memcpy (&address->gateway, &source->gateway, sizeof (struct in6_addr));
return address;
}
@ -860,7 +911,8 @@ nm_ip6_address_compare (NMIP6Address *address, NMIP6Address *other)
g_return_val_if_fail (other->refcount > 0, FALSE);
if ( memcmp (&address->address, &other->address, sizeof (struct in6_addr))
|| address->prefix != other->prefix)
|| address->prefix != other->prefix
|| memcmp (&address->gateway, &other->gateway, sizeof (struct in6_addr)))
return FALSE;
return TRUE;
}
@ -902,6 +954,27 @@ 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 *gw)
{
g_return_if_fail (address != NULL);
g_return_if_fail (address->refcount > 0);
g_return_if_fail (gw != NULL);
memcpy (&address->gateway, gw, sizeof (struct in6_addr));
}
/********************************************************************/
struct NMIP6Route {
guint32 refcount;

View file

@ -62,6 +62,7 @@ GQuark nm_setting_ip6_config_error_quark (void);
#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_MAY_FAIL "may-fail"
#define NM_SETTING_IP6_CONFIG_METHOD_IGNORE "ignore"
#define NM_SETTING_IP6_CONFIG_METHOD_AUTO "auto"
@ -88,6 +89,10 @@ 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 *gw);
typedef struct NMIP6Route NMIP6Route;
NMIP6Route * nm_ip6_route_new (void);
@ -159,6 +164,7 @@ gboolean nm_setting_ip6_config_get_ignore_auto_routes (NMSettingIP
gboolean nm_setting_ip6_config_get_ignore_auto_dns (NMSettingIP6Config *setting);
gboolean nm_setting_ip6_config_get_never_default (NMSettingIP6Config *setting);
gboolean nm_setting_ip6_config_get_may_fail (NMSettingIP6Config *setting);
G_END_DECLS

View file

@ -275,6 +275,8 @@ nm_utils_init (GError **error)
if (!crypto_init (error))
return FALSE;
_nm_utils_register_value_transformations ();
atexit (nm_utils_deinit);
initialized = TRUE;
}
@ -745,7 +747,8 @@ nm_utils_convert_string_hash_to_string (const GValue *src_value, GValue *dest_va
hash = (GHashTable *) g_value_get_boxed (src_value);
printable = g_string_new ("[");
g_hash_table_foreach (hash, convert_one_string_hash_entry, printable);
if (hash)
g_hash_table_foreach (hash, convert_one_string_hash_entry, printable);
g_string_append (printable, " ]");
g_value_take_string (dest_value, printable->str);
@ -858,10 +861,11 @@ nm_utils_convert_ip6_addr_struct_array_to_string (const GValue *src_value, GValu
g_string_append (printable, "{ ");
elements = (GValueArray *) g_ptr_array_index (ptr_array, i++);
if ( (elements->n_values != 2)
if ( (elements->n_values != 3)
|| (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_string_append (printable, "invalid");
|| (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_string_append (printable, "invalid }");
continue;
}
@ -869,7 +873,7 @@ nm_utils_convert_ip6_addr_struct_array_to_string (const GValue *src_value, GValu
tmp = g_value_array_get_nth (elements, 0);
ba_addr = g_value_get_boxed (tmp);
if (ba_addr->len != 16) {
g_string_append (printable, "invalid");
g_string_append (printable, "invalid }");
continue;
}
addr = (struct in6_addr *) ba_addr->data;
@ -882,10 +886,23 @@ nm_utils_convert_ip6_addr_struct_array_to_string (const GValue *src_value, GValu
tmp = g_value_array_get_nth (elements, 1);
prefix = g_value_get_uint (tmp);
if (prefix > 128) {
g_string_append (printable, "invalid");
g_string_append (printable, "invalid }");
continue;
}
g_string_append_printf (printable, "px = %u", prefix);
g_string_append (printable, ", ");
/* IPv6 Gateway */
tmp = g_value_array_get_nth (elements, 2);
ba_addr = g_value_get_boxed (tmp);
if (ba_addr->len != 16) {
g_string_append (printable, "invalid }");
continue;
}
addr = (struct in6_addr *) ba_addr->data;
memset (buf, 0, sizeof (buf));
nm_utils_inet6_ntop (addr, buf);
g_string_append_printf (printable, "gw = %s", buf);
g_string_append (printable, " }");
}
g_string_append_c (printable, ']');
@ -977,6 +994,58 @@ nm_utils_convert_ip6_route_struct_array_to_string (const GValue *src_value, GVal
g_string_free (printable, FALSE);
}
#define OLD_DBUS_TYPE_G_IP6_ADDRESS (dbus_g_type_get_struct ("GValueArray", DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT, G_TYPE_INVALID))
#define OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS (dbus_g_type_get_collection ("GPtrArray", OLD_DBUS_TYPE_G_IP6_ADDRESS))
static void
nm_utils_convert_old_ip6_addr_array (const GValue *src_value, GValue *dst_value)
{
GPtrArray *src_outer_array;
GPtrArray *dst_outer_array;
guint i;
g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS));
src_outer_array = (GPtrArray *) g_value_get_boxed (src_value);
dst_outer_array = g_ptr_array_new ();
for (i = 0; src_outer_array && (i < src_outer_array->len); i++) {
GValueArray *src_addr_array;
GValueArray *dst_addr_array;
GValue element = {0, };
GValue *src_addr, *src_prefix;
GByteArray *ba;
src_addr_array = (GValueArray *) g_ptr_array_index (src_outer_array, i);
if ( (src_addr_array->n_values != 2)
|| (G_VALUE_TYPE (g_value_array_get_nth (src_addr_array, 0)) != DBUS_TYPE_G_UCHAR_ARRAY)
|| (G_VALUE_TYPE (g_value_array_get_nth (src_addr_array, 1)) != G_TYPE_UINT)) {
g_warning ("%s: invalid old IPv6 address type", __func__);
return;
}
dst_addr_array = g_value_array_new (3);
src_addr = g_value_array_get_nth (src_addr_array, 0);
g_value_array_append (dst_addr_array, src_addr);
src_prefix = g_value_array_get_nth (src_addr_array, 1);
g_value_array_append (dst_addr_array, src_prefix);
/* Blank Gateway */
g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY);
ba = g_byte_array_new ();
g_byte_array_append (ba, (guint8 *) "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16);
g_value_take_boxed (&element, ba);
g_value_array_append (dst_addr_array, &element);
g_value_unset (&element);
g_ptr_array_add (dst_outer_array, dst_addr_array);
}
g_value_take_boxed (dst_value, dst_outer_array);
}
void
_nm_utils_register_value_transformations (void)
{
@ -1013,6 +1082,9 @@ _nm_utils_register_value_transformations (void)
g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE,
G_TYPE_STRING,
nm_utils_convert_ip6_route_struct_array_to_string);
g_value_register_transform_func (OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS,
DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS,
nm_utils_convert_old_ip6_addr_array);
registered = TRUE;
}
}
@ -1459,8 +1531,8 @@ nm_utils_ip4_get_default_prefix (guint32 ip)
* @value: gvalue containing a GPtrArray of GValueArrays of (GArray of guchars) and guint32
*
* Utility function to convert a #GPtrArray of #GValueArrays of (#GArray of guchars) and guint32
* representing a list of NetworkManager IPv6 addresses (which is a pair of address
* and prefix), into a GSList of #NMIP6Address objects. The specific format of
* representing a list of NetworkManager IPv6 addresses (which is a tuple of address,
* prefix, and gateway), into a GSList of #NMIP6Address objects. The specific format of
* this serialization is not guaranteed to be stable and the #GValueArray may be
* extended in the future.
*
@ -1479,16 +1551,28 @@ nm_utils_ip6_addresses_from_gvalue (const GValue *value)
GValueArray *elements = (GValueArray *) g_ptr_array_index (addresses, i);
GValue *tmp;
GByteArray *ba_addr;
GByteArray *ba_gw = NULL;
NMIP6Address *addr;
guint32 prefix;
if ( (elements->n_values != 2)
|| (G_VALUE_TYPE (g_value_array_get_nth (elements, 0)) != DBUS_TYPE_G_UCHAR_ARRAY)
if (elements->n_values < 2 || elements->n_values > 3) {
nm_warning ("%s: ignoring invalid IP6 address structure", __func__);
continue;
}
if ( (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)) {
nm_warning ("%s: ignoring invalid IP6 address structure", __func__);
continue;
}
/* Check optional 3rd element (gateway) */
if ( elements->n_values == 3
&& (G_VALUE_TYPE (g_value_array_get_nth (elements, 2)) != DBUS_TYPE_G_UCHAR_ARRAY)) {
nm_warning ("%s: ignoring invalid IP6 address structure", __func__);
continue;
}
tmp = g_value_array_get_nth (elements, 0);
ba_addr = g_value_get_boxed (tmp);
if (ba_addr->len != 16) {
@ -1505,9 +1589,22 @@ nm_utils_ip6_addresses_from_gvalue (const GValue *value)
continue;
}
if (elements->n_values == 3) {
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 address 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);
if (ba_gw)
nm_ip6_address_set_gateway (addr, (const struct in6_addr *) ba_gw->data);
list = g_slist_prepend (list, addr);
}
@ -1522,10 +1619,10 @@ nm_utils_ip6_addresses_from_gvalue (const GValue *value)
* g_value_unset().
*
* Utility function to convert a #GSList of #NMIP6Address objects into a
* GPtrArray of GValueArrays of (GArray or guchars) and guint32 representing a list
* of NetworkManager IPv6 addresses (which is a pair of address and prefix).
* The specific format of this serialization is not guaranteed to be stable and may be
* extended in the future.
* GPtrArray of GValueArrays representing a list of NetworkManager IPv6 addresses
* (which is a tuple of address, prefix, and gateway). The specific format of
* this serialization is not guaranteed to be stable and may be extended in the
* future.
**/
void
nm_utils_ip6_addresses_to_gvalue (GSList *list, GValue *value)
@ -1541,8 +1638,9 @@ nm_utils_ip6_addresses_to_gvalue (GSList *list, GValue *value)
GValue element = {0, };
GByteArray *ba;
array = g_value_array_new (2);
array = g_value_array_new (3);
/* IP address */
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);
@ -1550,11 +1648,20 @@ nm_utils_ip6_addresses_to_gvalue (GSList *list, GValue *value)
g_value_array_append (array, &element);
g_value_unset (&element);
/* Prefix */
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);
/* Gateway */
g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY);
ba = g_byte_array_new ();
g_byte_array_append (ba, (guint8 *) nm_ip6_address_get_gateway (addr), 16);
g_value_take_boxed (&element, ba);
g_value_array_append (array, &element);
g_value_unset (&element);
g_ptr_array_add (addresses, array);
}

View file

@ -15,7 +15,7 @@
* 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 - 2009 Red Hat, Inc.
* Copyright (C) 2008 - 2010 Red Hat, Inc.
*
*/
@ -28,7 +28,8 @@
#include "nm-setting-connection.h"
#include "nm-setting-vpn.h"
#include "nm-setting-ip6-config.h"
#include "nm-dbus-glib-types.h"
static void
vpn_check_func (const char *key, const char *value, gpointer user_data)
@ -128,6 +129,99 @@ test_setting_vpn_items (void)
g_object_unref (s_vpn);
}
#define OLD_DBUS_TYPE_G_IP6_ADDRESS (dbus_g_type_get_struct ("GValueArray", DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT, G_TYPE_INVALID))
#define OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS (dbus_g_type_get_collection ("GPtrArray", OLD_DBUS_TYPE_G_IP6_ADDRESS))
/* Test that setting the IPv6 setting's 'addresses' property using the old
* IPv6 address format still works, i.e. that the GValue transformation function
* from old->new is working correctly.
*/
static void
test_setting_ip6_config_old_address_array (void)
{
NMSettingIP6Config *s_ip6;
GPtrArray *addresses, *read_addresses;
GValueArray *array, *read_array;
GValue element = {0, }, written_value = {0, }, read_value = {0, };
GByteArray *ba;
const guint8 addr[16] = { 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11,
0x11, 0x22, 0x33, 0x44, 0x66, 0x77, 0x88, 0x99 };
const guint8 gw[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
guint32 prefix = 56;
GValue *read_addr, *read_prefix, *read_gw;
s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
ASSERT (s_ip6 != NULL,
"ip6-old-addr", "error creating IP6 setting");
g_value_init (&written_value, OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS);
addresses = g_ptr_array_new ();
array = g_value_array_new (3);
/* IP address */
g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY);
ba = g_byte_array_new ();
g_byte_array_append (ba, &addr[0], sizeof (addr));
g_value_take_boxed (&element, ba);
g_value_array_append (array, &element);
g_value_unset (&element);
/* Prefix */
g_value_init (&element, G_TYPE_UINT);
g_value_set_uint (&element, prefix);
g_value_array_append (array, &element);
g_value_unset (&element);
g_ptr_array_add (addresses, array);
g_value_set_boxed (&written_value, addresses);
/* Set the address array on the object */
g_object_set_property (G_OBJECT (s_ip6), NM_SETTING_IP6_CONFIG_ADDRESSES, &written_value);
/* Get it back so we can compare it */
g_value_init (&read_value, DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS);
g_object_get_property (G_OBJECT (s_ip6), NM_SETTING_IP6_CONFIG_ADDRESSES, &read_value);
ASSERT (G_VALUE_HOLDS (&read_value, DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS),
"ip6-old-addr", "wrong addresses property value type '%s'",
G_VALUE_TYPE_NAME (&read_value));
read_addresses = (GPtrArray *) g_value_get_boxed (&read_value);
ASSERT (read_addresses != NULL,
"ip6-old-addr", "missing addresses on readback");
ASSERT (read_addresses->len == 1,
"ip6-old-addr", "expected one address on readback");
read_array = (GValueArray *) g_ptr_array_index (read_addresses, 0);
read_addr = g_value_array_get_nth (read_array, 0);
ba = g_value_get_boxed (read_addr);
ASSERT (ba->len == sizeof (addr),
"ip6-old-addr", "unexpected address item length %d", ba->len);
ASSERT (memcmp (ba->data, &addr[0], sizeof (addr)) == 0,
"ip6-old-addr", "unexpected failure comparing addresses");
read_prefix = g_value_array_get_nth (read_array, 1);
ASSERT (g_value_get_uint (read_prefix) == prefix,
"ip6-old-addr", "unexpected failure comparing prefix");
/* Ensure the gateway is all zeros, which is how the 2-item to 3-item
* conversion happens.
*/
read_gw = g_value_array_get_nth (read_array, 2);
ba = g_value_get_boxed (read_gw);
ASSERT (ba->len == sizeof (gw),
"ip6-old-addr", "unexpected gateway item length %d", ba->len);
ASSERT (memcmp (ba->data, &gw[0], sizeof (gw)) == 0,
"ip6-old-addr", "unexpected failure comparing gateways");
g_value_unset (&written_value);
g_value_unset (&read_value);
g_object_unref (s_ip6);
}
int main (int argc, char **argv)
{
GError *error = NULL;
@ -142,6 +236,7 @@ int main (int argc, char **argv)
/* The tests */
test_setting_vpn_items ();
test_setting_ip6_config_old_address_array ();
base = g_path_get_basename (argv[0]);
fprintf (stdout, "%s: SUCCESS\n", base);

View file

@ -15,8 +15,8 @@ VOID:POINTER,POINTER
VOID:STRING,STRING,STRING,UINT
VOID:OBJECT,UINT,UINT
VOID:STRING,INT
VOID:STRING,UINT
VOID:STRING,UINT,BOOLEAN
VOID:INT,UINT
VOID:INT,UINT,BOOLEAN
VOID:OBJECT,OBJECT,ENUM
VOID:POINTER,STRING
VOID:STRING,BOXED

View file

@ -14,7 +14,6 @@ src/nm-netlink-monitor.c
src/main.c
src/dhcp-manager/nm-dhcp-dhclient.c
src/dhcp-manager/nm-dhcp-manager.c
src/ip6-manager/nm-netlink-listener.c
src/logging/nm-logging.c
src/named-manager/nm-named-manager.c
src/system-settings/nm-default-wired-connection.c

View file

@ -68,9 +68,11 @@ libtest_policy_hosts_la_SOURCES = \
nm-policy-hosts.h
libtest_policy_hosts_la_CPPFLAGS = \
-DSYSCONFDIR=\"$(sysconfdir)\" \
$(GLIB_CFLAGS)
libtest_policy_hosts_la_LIBADD = \
${top_builddir}/src/logging/libnm-logging.la \
$(GLIB_LIBS)
@ -123,6 +125,8 @@ NetworkManager_SOURCES = \
nm-policy.h \
nm-policy-hosts.c \
nm-policy-hosts.h \
nm-policy-hostname.c \
nm-policy-hostname.h \
NetworkManagerUtils.c \
NetworkManagerUtils.h \
nm-system.c \
@ -137,8 +141,6 @@ NetworkManager_SOURCES = \
nm-properties-changed-signal.h \
wpa.c \
wpa.h \
nm-netlink.c \
nm-netlink.h \
nm-dhcp4-config.c \
nm-dhcp4-config.h \
nm-dhcp6-config.c \
@ -206,9 +208,7 @@ BUILT_SOURCES = \
NetworkManager_CPPFLAGS = \
$(DBUS_CFLAGS) \
$(GLIB_CFLAGS) \
$(HAL_CFLAGS) \
$(GUDEV_CFLAGS) \
$(OPENSSL_CFLAGS) \
$(LIBNL_CFLAGS) \
$(GMODULE_CFLAGS) \
-DG_DISABLE_DEPRECATED \

View file

@ -56,6 +56,10 @@
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager.VPN.Connection"/>
<deny send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager"
send_member="SetLogging"/>
</policy>
<policy context="default">
<deny own="org.freedesktop.NetworkManager"/>
@ -64,6 +68,10 @@
<deny send_destination="org.freedesktop.NetworkManager"/>
<allow send_destination="org.freedesktop.NetworkManagerSystemSettings"/>
<deny send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager"
send_member="SetLogging"/>
<!-- The org.freedesktop.NetworkManagerSettings.Connection.Secrets
interface is secured via PolicyKit.
-->

View file

@ -594,3 +594,32 @@ nm_utils_do_sysctl (const char *path, const char *value)
return TRUE;
}
gboolean
nm_utils_get_proc_sys_net_value (const char *path,
const char *iface,
guint32 *out_value)
{
GError *error = NULL;
char *contents = NULL;
gboolean success = FALSE;
long int tmp;
if (!g_file_get_contents (path, &contents, NULL, &error)) {
nm_log_dbg (LOGD_DEVICE, "(%s): error reading %s: (%d) %s",
iface, path,
error ? error->code : -1,
error && error->message ? error->message : "(unknown)");
g_clear_error (&error);
} else {
errno = 0;
tmp = strtol (contents, NULL, 10);
if ((errno == 0) && (tmp == 0 || tmp == 1)) {
*out_value = (guint32) tmp;
success = TRUE;
}
g_free (contents);
}
return success;
}

View file

@ -73,4 +73,8 @@ void value_hash_add_bool (GHashTable *hash,
gboolean nm_utils_do_sysctl (const char *path, const char *value);
gboolean nm_utils_get_proc_sys_net_value (const char *path,
const char *iface,
guint32 *out_value);
#endif /* NETWORK_MANAGER_UTILS_H */

View file

@ -1,9 +1,5 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager -- Network link manager
*
* Timothee Lecomte <timothee.lecomte@ens.fr>
*
* Heavily based on NetworkManagerRedhat.c by Dan Williams <dcbw@redhat.com>
*
* 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
@ -19,7 +15,8 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* (C) Copyright 2004 Red Hat, Inc.
* (C) Copyright 2004 - 2010 Red Hat, Inc.
* (C) Copyright 2006 Timothee Lecomte <timothee.lecomte@ens.fr>
*/
#ifdef HAVE_CONFIG_H
@ -36,8 +33,8 @@
#include "NetworkManagerGeneric.h"
#include "nm-system.h"
#include "NetworkManagerUtils.h"
#include "nm-netlink.h"
#include "nm-logging.h"
#include "nm-netlink-monitor.h"
/* Because of a bug in libnl, rtnl.h should be included before route.h */
#include <netlink/route/rtnl.h>

View file

@ -41,9 +41,13 @@ typedef struct {
guchar state;
GPid pid;
gboolean dead;
guint timeout_id;
guint watch_id;
guint32 remove_id;
GHashTable * options;
gboolean info_only;
} NMDHCPClientPrivate;
#define NM_DHCP_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DHCP_CLIENT, NMDHCPClientPrivate))
@ -53,6 +57,7 @@ G_DEFINE_TYPE_EXTENDED (NMDHCPClient, nm_dhcp_client, G_TYPE_OBJECT, G_TYPE_FLAG
enum {
STATE_CHANGED,
TIMEOUT,
REMOVE,
LAST_SIGNAL
};
@ -186,6 +191,8 @@ real_stop (NMDHCPClient *self)
watch_cleanup (self);
stop_process (priv->pid, priv->iface);
priv->info_only = FALSE;
}
static gboolean
@ -203,22 +210,68 @@ daemon_timeout (gpointer user_data)
return FALSE;
}
static gboolean
signal_remove (gpointer user_data)
{
NMDHCPClient *self = NM_DHCP_CLIENT (user_data);
NM_DHCP_CLIENT_GET_PRIVATE (self)->remove_id = 0;
g_signal_emit (G_OBJECT (self), signals[REMOVE], 0);
return FALSE;
}
static void
dhcp_client_set_state (NMDHCPClient *self,
NMDHCPState state,
gboolean emit_state,
gboolean remove_now)
{
NMDHCPClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
priv->state = state;
if (emit_state)
g_signal_emit (G_OBJECT (self), signals[STATE_CHANGED], 0, priv->state);
if (state == DHC_END || state == DHC_ABEND) {
/* Start the remove signal timer */
if (remove_now) {
g_signal_emit (G_OBJECT (self), signals[REMOVE], 0);
} else {
if (!priv->remove_id)
priv->remove_id = g_timeout_add_seconds (5, signal_remove, self);
}
}
}
static void
daemon_watch_cb (GPid pid, gint status, gpointer user_data)
{
NMDHCPClient *self = NM_DHCP_CLIENT (user_data);
NMDHCPClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
NMDHCPState new_state;
if (priv->ipv6) {
nm_log_info (LOGD_DHCP6, "(%s): DHCPv6 client pid %d exited with status %d",
priv->iface, pid,
WIFEXITED (status) ? WEXITSTATUS (status) : -1);
} else {
nm_log_info (LOGD_DHCP6, "(%s): DHCPv4 client pid %d exited with status %d",
priv->iface, pid,
WIFEXITED (status) ? WEXITSTATUS (status) : -1);
}
if (!WIFEXITED (status)) {
priv->state = DHC_ABEND;
new_state = DHC_ABEND;
nm_log_warn (LOGD_DHCP, "DHCP client died abnormally");
}
priv->pid = 0;
} else
new_state = DHC_END;
watch_cleanup (self);
timeout_cleanup (self);
priv->dead = TRUE;
g_signal_emit (G_OBJECT (self), signals[STATE_CHANGED], 0, priv->state);
dhcp_client_set_state (self, new_state, TRUE, FALSE);
}
static void
@ -278,6 +331,8 @@ nm_dhcp_client_start_ip6 (NMDHCPClient *self,
g_return_val_if_fail (priv->ipv6 == TRUE, FALSE);
g_return_val_if_fail (priv->uuid != NULL, FALSE);
priv->info_only = info_only;
nm_log_info (LOGD_DHCP, "Activation (%s) Beginning DHCPv6 transaction (timeout in %d seconds)",
priv->iface, priv->timeout);
@ -334,8 +389,9 @@ nm_dhcp_client_stop (NMDHCPClient *self)
priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
/* Kill the DHCP client */
if (priv->pid > 0) {
if (!priv->dead) {
NM_DHCP_CLIENT_GET_CLASS (self)->stop (self);
priv->dead = TRUE;
nm_log_info (LOGD_DHCP, "(%s): canceled DHCP transaction, DHCP client pid %d",
priv->iface, priv->pid);
@ -344,7 +400,7 @@ nm_dhcp_client_stop (NMDHCPClient *self)
/* And clean stuff up */
priv->pid = -1;
priv->state = DHC_END;
dhcp_client_set_state (self, DHC_END, FALSE, TRUE);
g_hash_table_remove_all (priv->options);
@ -390,11 +446,14 @@ static DhcState state_table[] = {
{ DHC_REBIND4, "rebind" },
{ DHC_REBIND6, "rebind6" },
{ DHC_STOP, "stop" },
{ DHC_STOP6, "stop6" },
{ DHC_MEDIUM, "medium" },
{ DHC_TIMEOUT, "timeout" },
{ DHC_FAIL, "fail" },
{ DHC_EXPIRE, "expire" },
{ DHC_EXPIRE6, "expire6" },
{ DHC_RELEASE, "release" },
{ DHC_RELEASE6,"release6" },
{ DHC_START, "start" },
{ DHC_ABEND, "abend" },
{ DHC_END, "end" },
@ -512,70 +571,32 @@ nm_dhcp_client_new_options (NMDHCPClient *self,
timeout_cleanup (self);
}
priv->state = new_state;
if (priv->ipv6) {
nm_log_info (LOGD_DHCP6, "(%s): DHCPv6 state changed %s -> %s",
priv->iface,
state_to_string (old_state),
state_to_string (priv->state));
state_to_string (new_state));
} else {
nm_log_info (LOGD_DHCP4, "(%s): DHCPv4 state changed %s -> %s",
priv->iface,
state_to_string (old_state),
state_to_string (priv->state));
state_to_string (new_state));
}
g_signal_emit (G_OBJECT (self),
signals[STATE_CHANGED],
0,
priv->state);
dhcp_client_set_state (self, new_state, TRUE, FALSE);
}
#define NEW_TAG "new_"
#define OLD_TAG "old_"
typedef struct {
GHFunc func;
gpointer user_data;
} DhcpForeachInfo;
static void
iterate_dhcp_config_option (gpointer key,
gpointer value,
gpointer user_data)
{
DhcpForeachInfo *info = (DhcpForeachInfo *) user_data;
char *tmp_key = NULL;
const char **p;
static const char *filter_options[] = {
"interface", "pid", "reason", "dhcp_message_type", NULL
};
/* Filter out stuff that's not actually new DHCP options */
for (p = filter_options; *p; p++) {
if (!strcmp (*p, (const char *) key))
return;
if (!strncmp ((const char *) key, OLD_TAG, strlen (OLD_TAG)))
return;
}
/* Remove the "new_" prefix that dhclient passes back */
if (!strncmp ((const char *) key, NEW_TAG, strlen (NEW_TAG)))
tmp_key = g_strdup ((const char *) (key + strlen (NEW_TAG)));
else
tmp_key = g_strdup ((const char *) key);
(*info->func) ((gpointer) tmp_key, value, info->user_data);
g_free (tmp_key);
}
gboolean
nm_dhcp_client_foreach_option (NMDHCPClient *self,
GHFunc func,
gpointer user_data)
{
NMDHCPClientPrivate *priv;
DhcpForeachInfo info = { NULL, NULL };
GHashTableIter iter;
gpointer iterkey, itervalue;
g_return_val_if_fail (self != NULL, FALSE);
g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), FALSE);
@ -589,12 +610,35 @@ nm_dhcp_client_foreach_option (NMDHCPClient *self,
} else {
nm_log_warn (LOGD_DHCP4, "(%s): DHCPv4 client didn't bind to a lease.", priv->iface);
}
return FALSE;
}
info.func = func;
info.user_data = user_data;
g_hash_table_foreach (priv->options, iterate_dhcp_config_option, &info);
g_hash_table_iter_init (&iter, priv->options);
while (g_hash_table_iter_next (&iter, &iterkey, &itervalue)) {
const char *key = iterkey, *value = itervalue;
const char **p;
static const char *filter_options[] = {
"interface", "pid", "reason", "dhcp_message_type", NULL
};
gboolean ignore = FALSE;
/* Filter out stuff that's not actually new DHCP options */
for (p = filter_options; *p; p++) {
if (!strcmp (*p, key) || !strncmp (key, OLD_TAG, strlen (OLD_TAG))) {
ignore = TRUE;
break;
}
}
if (!ignore) {
const char *tmp_key = value;
/* Remove the "new_" prefix that dhclient passes back */
if (!strncmp (key, NEW_TAG, strlen (NEW_TAG)))
tmp_key = key + strlen (NEW_TAG);
func ((gpointer) tmp_key, (gpointer) value, user_data);
}
}
return TRUE;
}
@ -867,7 +911,12 @@ nm_dhcp_client_get_ip4_config (NMDHCPClient *self, gboolean test)
priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
if (test && !state_is_bound (priv->state)) {
nm_log_warn (LOGD_DHCP4, "(%s): DHCP client didn't bind to a lease.", priv->iface);
nm_log_warn (LOGD_DHCP4, "(%s): DHCPv4 client didn't bind to a lease.", priv->iface);
return NULL;
}
if (!g_hash_table_size (priv->options)) {
/* We never got a response from the DHCP client */
return NULL;
}
@ -891,6 +940,8 @@ ip6_options_to_config (NMDHCPClient *self)
struct in6_addr tmp_addr;
NMIP6Address *addr = NULL;
char *str = NULL;
GHashTableIter iter;
gpointer key, value;
g_return_val_if_fail (self != NULL, NULL);
g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), NULL);
@ -898,6 +949,12 @@ ip6_options_to_config (NMDHCPClient *self)
priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
g_return_val_if_fail (priv->options != NULL, NULL);
g_hash_table_iter_init (&iter, priv->options);
while (g_hash_table_iter_next (&iter, &key, &value)) {
nm_log_dbg (LOGD_DHCP6, "(%s): option '%s'=>'%s'",
priv->iface, (const char *) key, (const char *) value);
}
ip6_config = nm_ip6_config_new ();
if (!ip6_config) {
nm_log_warn (LOGD_DHCP6, "(%s): couldn't allocate memory for an IP6Config!", priv->iface);
@ -911,27 +968,43 @@ ip6_options_to_config (NMDHCPClient *self)
}
str = g_hash_table_lookup (priv->options, "new_ip6_address");
if (str && (inet_pton (AF_INET6, str, &tmp_addr) > 0)) {
if (str) {
if (!inet_pton (AF_INET6, str, &tmp_addr)) {
nm_log_warn (LOGD_DHCP6, "(%s): DHCP returned invalid address '%s'",
priv->iface);
goto error;
}
nm_ip6_address_set_address (addr, &tmp_addr);
nm_log_info (LOGD_DHCP6, " address %s", str);
} else
goto error;
str = g_hash_table_lookup (priv->options, "new_ip6_prefixlen");
if (str) {
long unsigned int prefix;
errno = 0;
prefix = strtoul (str, NULL, 10);
if (errno != 0 || prefix > 128)
} else {
/* No address in managed mode is a hard error */
if (priv->info_only == FALSE)
goto error;
nm_ip6_address_set_prefix (addr, (guint32) prefix);
nm_log_info (LOGD_DHCP6, " prefix %lu", prefix);
/* But "info-only" setups don't necessarily need an address */
nm_ip6_address_unref (addr);
addr = NULL;
}
nm_ip6_config_take_address (ip6_config, addr);
addr = NULL;
/* Only care about prefix if we got an address */
if (addr) {
str = g_hash_table_lookup (priv->options, "new_ip6_prefixlen");
if (str) {
long unsigned int prefix;
errno = 0;
prefix = strtoul (str, NULL, 10);
if (errno != 0 || prefix > 128)
goto error;
nm_ip6_address_set_prefix (addr, (guint32) prefix);
nm_log_info (LOGD_DHCP6, " prefix %lu", prefix);
}
nm_ip6_config_take_address (ip6_config, addr);
addr = NULL;
}
str = g_hash_table_lookup (priv->options, "new_host_name");
if (str)
@ -976,7 +1049,12 @@ nm_dhcp_client_get_ip6_config (NMDHCPClient *self, gboolean test)
priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
if (test && !state_is_bound (priv->state)) {
nm_log_warn (LOGD_DHCP6, "(%s): dhcp client didn't bind to a lease.", priv->iface);
nm_log_warn (LOGD_DHCP6, "(%s): DHCPv6 client didn't bind to a lease.", priv->iface);
return NULL;
}
if (!g_hash_table_size (priv->options)) {
/* We never got a response from the DHCP client */
return NULL;
}
@ -1058,6 +1136,9 @@ dispose (GObject *object)
* the DHCP client.
*/
if (priv->remove_id)
g_source_remove (priv->remove_id);
g_hash_table_destroy (priv->options);
g_free (priv->iface);
@ -1128,5 +1209,14 @@ nm_dhcp_client_class_init (NMDHCPClientClass *client_class)
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
signals[REMOVE] =
g_signal_new ("remove",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMDHCPClientClass, remove),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}

View file

@ -53,11 +53,14 @@ typedef enum {
DHC_REBIND6, /* IPv6 new/different lease */
DHC_DEPREF6, /* IPv6 lease depreferred */
DHC_STOP, /* remove old lease */
DHC_STOP6, /* remove old lease */
DHC_MEDIUM, /* media selection begun */
DHC_TIMEOUT, /* timed out contacting DHCP server */
DHC_FAIL, /* all attempts to contact server timed out, sleeping */
DHC_EXPIRE, /* lease has expired, renewing */
DHC_EXPIRE6, /* lease has expired, renewing */
DHC_RELEASE, /* releasing lease */
DHC_RELEASE6, /* releasing lease */
DHC_START, /* sent when dhclient started OK */
DHC_ABEND, /* dhclient exited abnormally */
DHC_END, /* dhclient exited normally */
@ -96,6 +99,7 @@ typedef struct {
/* Signals */
void (*state_changed) (NMDHCPClient *self, NMDHCPState state);
void (*timeout) (NMDHCPClient *self);
void (*remove) (NMDHCPClient *self);
} NMDHCPClientClass;
GType nm_dhcp_client_get_type (void);

View file

@ -482,7 +482,7 @@ dhclient_start (NMDHCPClient *client,
{
NMDHCPDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (client);
GPtrArray *argv = NULL;
GPid pid = 0;
GPid pid = -1;
GError *error = NULL;
const char *iface, *uuid;
char *binary_name, *cmd_str;

View file

@ -36,7 +36,7 @@
#include "nm-utils.h"
#include "nm-logging.h"
G_DEFINE_TYPE (NMDHCPDhcpcd, nm_dhcp_dhcpcd, NM_TYPE_DHCP_DHCPCD)
G_DEFINE_TYPE (NMDHCPDhcpcd, nm_dhcp_dhcpcd, NM_TYPE_DHCP_CLIENT)
#define NM_DHCP_DHCPCD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DHCP_DHCPCD, NMDHCPDhcpcdPrivate))
@ -92,7 +92,7 @@ real_ip4_start (NMDHCPClient *client,
{
NMDHCPDhcpcdPrivate *priv = NM_DHCP_DHCPCD_GET_PRIVATE (client);
GPtrArray *argv = NULL;
GPid pid = 0;
GPid pid = -1;
GError *error = NULL;
char *pid_contents = NULL, *binary_name, *cmd_str;
const char *iface, *uuid, *hostname;
@ -147,6 +147,7 @@ real_ip4_start (NMDHCPClient *client,
&dhcpcd_child_setup, NULL, &pid, &error)) {
nm_log_warn (LOGD_DHCP4, "dhcpcd failed to start. error: '%s'", error->message);
g_error_free (error);
pid = -1;
} else
nm_log_info (LOGD_DHCP4, "dhcpcd started with pid %d", pid);

View file

@ -235,19 +235,19 @@ nm_dhcp_manager_handle_event (DBusGProxy *proxy,
client = get_client_for_pid (manager, (GPid) temp);
if (client == NULL) {
nm_log_warn (LOGD_DHCP, "unhandled DHCP event for interface %s", iface);
nm_log_warn (LOGD_DHCP, "(pid %d) unhandled DHCP event for interface %s", temp, iface);
goto out;
}
if (strcmp (iface, nm_dhcp_client_get_iface (client))) {
nm_log_warn (LOGD_DHCP, "received DHCP event from unexpected interface '%s' (expected '%s')",
iface, nm_dhcp_client_get_iface (client));
nm_log_warn (LOGD_DHCP, "(pid %d) received DHCP event from unexpected interface '%s' (expected '%s')",
temp, iface, nm_dhcp_client_get_iface (client));
goto out;
}
reason = get_option (options, "reason");
if (reason == NULL) {
nm_log_warn (LOGD_DHCP, "DHCP event didn't have a reason");
nm_log_warn (LOGD_DHCP, "(pid %d) DHCP event didn't have a reason", temp);
goto out;
}
@ -358,7 +358,7 @@ nm_dhcp_manager_new (const char *client, GError **error)
return singleton;
}
#define STATE_ID_TAG "state-id"
#define REMOVE_ID_TAG "remove-id"
#define TIMEOUT_ID_TAG "timeout-id"
static void
@ -367,7 +367,7 @@ remove_client (NMDHCPManager *self, NMDHCPClient *client)
NMDHCPManagerPrivate *priv = NM_DHCP_MANAGER_GET_PRIVATE (self);
guint id;
id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (client), STATE_ID_TAG));
id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (client), REMOVE_ID_TAG));
if (id)
g_signal_handler_disconnect (client, id);
@ -383,29 +383,16 @@ remove_client (NMDHCPManager *self, NMDHCPClient *client)
g_hash_table_remove (priv->clients, client);
}
static void
client_state_changed (NMDHCPClient *client, NMDHCPState new_state, gpointer user_data)
{
if (new_state == DHC_ABEND || new_state == DHC_END)
remove_client (NM_DHCP_MANAGER (user_data), client);
}
static void
client_timeout (NMDHCPClient *client, gpointer user_data)
{
remove_client (NM_DHCP_MANAGER (user_data), client);
}
static void
add_client (NMDHCPManager *self, NMDHCPClient *client)
{
NMDHCPManagerPrivate *priv = NM_DHCP_MANAGER_GET_PRIVATE (self);
guint id;
id = g_signal_connect (client, "state-changed", G_CALLBACK (client_state_changed), self);
g_object_set_data (G_OBJECT (client), STATE_ID_TAG, GUINT_TO_POINTER (id));
id = g_signal_connect_swapped (client, "remove", G_CALLBACK (remove_client), self);
g_object_set_data (G_OBJECT (client), REMOVE_ID_TAG, GUINT_TO_POINTER (id));
id = g_signal_connect (client, "timeout", G_CALLBACK (client_timeout), self);
id = g_signal_connect_swapped (client, "timeout", G_CALLBACK (remove_client), self);
g_object_set_data (G_OBJECT (client), TIMEOUT_ID_TAG, GUINT_TO_POINTER (id));
g_hash_table_insert (priv->clients, client, g_object_ref (client));
@ -482,6 +469,13 @@ nm_dhcp_manager_start_ip4 (NMDHCPManager *self,
priv = NM_DHCP_MANAGER_GET_PRIVATE (self);
if (s_ip4) {
const char *method = nm_setting_ip4_config_get_method (s_ip4);
if (method) {
/* Method must be 'auto' */
g_return_val_if_fail (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0, NULL);
}
if ( nm_setting_ip4_config_get_dhcp_send_hostname (s_ip4)
&& (nm_setting_ip4_config_get_dhcp_hostname (s_ip4) == NULL)
&& priv->hostname_provider != NULL) {

View file

@ -11,14 +11,11 @@ noinst_LTLIBRARIES = libip6-manager.la
libip6_manager_la_SOURCES = \
nm-ip6-manager.c \
nm-ip6-manager.h \
nm-netlink-listener.c \
nm-netlink-listener.h
nm-ip6-manager.h
libip6_manager_la_CPPFLAGS = \
$(DBUS_CFLAGS) \
$(GLIB_CFLAGS) \
$(HAL_CFLAGS) \
-DG_DISABLE_DEPRECATED
libip6_manager_la_LIBADD = \

File diff suppressed because it is too large Load diff

View file

@ -15,7 +15,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2009 Red Hat, Inc.
* Copyright (C) 2009 - 2010 Red Hat, Inc.
*/
#ifndef NM_IP6_MANAGER_H
@ -54,7 +54,7 @@ typedef struct {
* that the initial configuration is complete.
*/
void (*addrconf_complete) (NMIP6Manager *manager,
char *iface,
guint32 ifindex,
guint dhcp_opts,
gboolean success);
@ -63,22 +63,24 @@ typedef struct {
* of the interface has changed.
*/
void (*config_changed) (NMIP6Manager *manager,
char *iface,
guint dhcp_opts);
guint32 ifindex,
guint dhcp_opts,
gboolean success);
} NMIP6ManagerClass;
GType nm_ip6_manager_get_type (void);
NMIP6Manager *nm_ip6_manager_get (void);
void nm_ip6_manager_prepare_interface (NMIP6Manager *manager,
const char *iface,
NMSettingIP6Config *s_ip6);
void nm_ip6_manager_begin_addrconf (NMIP6Manager *manager,
const char *iface);
void nm_ip6_manager_cancel_addrconf (NMIP6Manager *manager,
const char *iface);
NMIP6Manager *nm_ip6_manager_get (void);
void nm_ip6_manager_prepare_interface (NMIP6Manager *manager,
int ifindex,
NMSettingIP6Config *s_ip6,
const char *accept_ra_path);
void nm_ip6_manager_begin_addrconf (NMIP6Manager *manager,
int ifindex);
void nm_ip6_manager_cancel_addrconf (NMIP6Manager *manager,
int ifindex);
NMIP6Config * nm_ip6_manager_get_ip6_config (NMIP6Manager *manager,
const char *iface);
NMIP6Config * nm_ip6_manager_get_ip6_config (NMIP6Manager *manager,
int ifindex);
#endif /* NM_IP6_MANAGER_H */

View file

@ -1,406 +0,0 @@
/* -*- 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 - 2009 Red Hat, Inc.
* Copyright (C) 2005 - 2008 Novell, Inc.
* Copyright (C) 2005 Ray Strode
*
* Some code borrowed from HAL:
*
* Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
* Copyright (C) 2004 Novell, Inc.
*/
/* FIXME: this should be merged with src/nm-netlink-monitor.c */
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/types.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/if.h>
#include <linux/unistd.h>
#include <unistd.h>
#include <stdio.h>
#include <glib.h>
#include <glib/gi18n.h>
#include "NetworkManager.h"
#include "nm-system.h"
#include "nm-netlink-listener.h"
#include "nm-marshal.h"
#include "nm-netlink.h"
#define NM_NETLINK_LISTENER_EVENT_CONDITIONS \
((GIOCondition) (G_IO_IN | G_IO_PRI))
#define NM_NETLINK_LISTENER_ERROR_CONDITIONS \
((GIOCondition) (G_IO_ERR | G_IO_NVAL))
#define NM_NETLINK_LISTENER_DISCONNECT_CONDITIONS \
((GIOCondition) (G_IO_HUP))
#define NM_NETLINK_LISTENER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
NM_TYPE_NETLINK_LISTENER, \
NMNetlinkListenerPrivate))
typedef struct {
struct nl_handle *nlh;
struct nl_cb * nlh_cb;
struct nl_cache * nlh_link_cache;
GIOChannel * io_channel;
guint event_id;
guint request_status_id;
} NMNetlinkListenerPrivate;
static gboolean nm_netlink_listener_event_handler (GIOChannel *channel,
GIOCondition io_condition,
gpointer user_data);
static gboolean nm_netlink_listener_error_handler (GIOChannel *channel,
GIOCondition io_condition,
NMNetlinkListener *listener);
static gboolean nm_netlink_listener_disconnect_handler (GIOChannel *channel,
GIOCondition io_condition,
NMNetlinkListener *listener);
static void close_connection (NMNetlinkListener *listener);
enum {
NOTIFICATION = 0,
ERROR,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE (NMNetlinkListener, nm_netlink_listener, G_TYPE_OBJECT);
NMNetlinkListener *
nm_netlink_listener_get (void)
{
static NMNetlinkListener *singleton = NULL;
if (!singleton)
singleton = NM_NETLINK_LISTENER (g_object_new (NM_TYPE_NETLINK_LISTENER, NULL));
else
g_object_ref (singleton);
return singleton;
}
static void
nm_netlink_listener_init (NMNetlinkListener *listener)
{
}
static void
finalize (GObject *object)
{
NMNetlinkListenerPrivate *priv = NM_NETLINK_LISTENER_GET_PRIVATE (object);
if (priv->request_status_id)
g_source_remove (priv->request_status_id);
if (priv->io_channel)
close_connection (NM_NETLINK_LISTENER (object));
if (priv->nlh) {
nl_handle_destroy (priv->nlh);
priv->nlh = NULL;
}
if (priv->nlh_cb) {
nl_cb_put (priv->nlh_cb);
priv->nlh_cb = NULL;
}
G_OBJECT_CLASS (nm_netlink_listener_parent_class)->finalize (object);
}
static void
nm_netlink_listener_class_init (NMNetlinkListenerClass *listener_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (listener_class);
g_type_class_add_private (listener_class, sizeof (NMNetlinkListenerPrivate));
/* Virtual methods */
object_class->finalize = finalize;
/* Signals */
signals[NOTIFICATION] =
g_signal_new ("notification",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (NMNetlinkListenerClass, notification),
NULL, NULL, g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE, 1, G_TYPE_POINTER);
signals[ERROR] =
g_signal_new ("error",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (NMNetlinkListenerClass, error),
NULL, NULL, _nm_marshal_VOID__POINTER,
G_TYPE_NONE, 1, G_TYPE_POINTER);
}
static int
netlink_event_input (struct nl_msg *msg, void *listener)
{
struct nlmsghdr *hdr = nlmsg_hdr (msg);
if (hdr->nlmsg_pid != 0)
return NL_STOP;
g_signal_emit (listener, signals[NOTIFICATION], 0, msg);
/* Stop processing messages */
return NL_STOP;
}
static gboolean
open_connection (NMNetlinkListener *listener, GError **error)
{
NMNetlinkListenerPrivate *priv = NM_NETLINK_LISTENER_GET_PRIVATE (listener);
int fd;
GError *channel_error = NULL;
GIOFlags channel_flags;
g_return_val_if_fail (priv->io_channel == NULL, FALSE);
priv->nlh_cb = nl_cb_alloc (NL_CB_DEFAULT);
priv->nlh = nl_handle_alloc_cb (priv->nlh_cb);
if (!priv->nlh) {
g_set_error (error, NM_NETLINK_LISTENER_ERROR,
NM_NETLINK_LISTENER_ERROR_NETLINK_ALLOC_HANDLE,
_("unable to allocate netlink handle: %s"),
nl_geterror ());
goto error;
}
nl_disable_sequence_check (priv->nlh);
nl_socket_modify_cb (priv->nlh, NL_CB_VALID, NL_CB_CUSTOM, netlink_event_input, listener);
if (nl_connect (priv->nlh, NETLINK_ROUTE) < 0) {
g_set_error (error, NM_NETLINK_LISTENER_ERROR,
NM_NETLINK_LISTENER_ERROR_NETLINK_CONNECT,
_("unable to connect to netlink: %s"),
nl_geterror ());
goto error;
}
fd = nl_socket_get_fd (priv->nlh);
priv->io_channel = g_io_channel_unix_new (fd);
g_io_channel_set_encoding (priv->io_channel, NULL, &channel_error);
/* Encoding is NULL, so no conversion error can possibly occur */
g_assert (channel_error == NULL);
g_io_channel_set_close_on_unref (priv->io_channel, TRUE);
channel_flags = g_io_channel_get_flags (priv->io_channel);
channel_error = NULL;
g_io_channel_set_flags (priv->io_channel,
channel_flags | G_IO_FLAG_NONBLOCK,
&channel_error);
if (channel_error != NULL) {
g_propagate_error (error, channel_error);
goto error;
}
priv->event_id = g_io_add_watch (priv->io_channel,
(NM_NETLINK_LISTENER_EVENT_CONDITIONS |
NM_NETLINK_LISTENER_ERROR_CONDITIONS |
NM_NETLINK_LISTENER_DISCONNECT_CONDITIONS),
nm_netlink_listener_event_handler,
listener);
return TRUE;
error:
if (priv->io_channel)
close_connection (listener);
if (priv->nlh) {
nl_handle_destroy (priv->nlh);
priv->nlh = NULL;
}
if (priv->nlh_cb) {
nl_cb_put (priv->nlh_cb);
priv->nlh_cb = NULL;
}
return FALSE;
}
static void
close_connection (NMNetlinkListener *listener)
{
NMNetlinkListenerPrivate *priv = NM_NETLINK_LISTENER_GET_PRIVATE (listener);
g_return_if_fail (priv->io_channel != NULL);
if (priv->event_id) {
g_source_remove (priv->event_id);
priv->event_id = 0;
}
g_io_channel_shutdown (priv->io_channel,
TRUE /* flush pending data */,
NULL);
g_io_channel_unref (priv->io_channel);
priv->io_channel = NULL;
}
GQuark
nm_netlink_listener_error_quark (void)
{
static GQuark error_quark = 0;
if (error_quark == 0)
error_quark = g_quark_from_static_string ("nm-netlink-listener-error-quark");
return error_quark;
}
gboolean
nm_netlink_listener_subscribe (NMNetlinkListener *listener,
int group,
GError **error)
{
NMNetlinkListenerPrivate *priv;
g_return_val_if_fail (NM_IS_NETLINK_LISTENER (listener), FALSE);
priv = NM_NETLINK_LISTENER_GET_PRIVATE (listener);
if (!priv->nlh) {
if (!open_connection (listener, error))
return FALSE;
}
if (nl_socket_add_membership (priv->nlh, group) < 0) {
g_set_error (error, NM_NETLINK_LISTENER_ERROR,
NM_NETLINK_LISTENER_ERROR_NETLINK_JOIN_GROUP,
_("unable to join netlink group: %s"),
nl_geterror ());
return FALSE;
}
return TRUE;
}
void
nm_netlink_listener_unsubscribe (NMNetlinkListener *listener, int group)
{
NMNetlinkListenerPrivate *priv;
g_return_if_fail (NM_IS_NETLINK_LISTENER (listener));
priv = NM_NETLINK_LISTENER_GET_PRIVATE (listener);
g_return_if_fail (priv->nlh != NULL);
nl_socket_drop_membership (priv->nlh, group);
}
static gboolean
nm_netlink_listener_event_handler (GIOChannel *channel,
GIOCondition io_condition,
gpointer user_data)
{
NMNetlinkListener *listener = (NMNetlinkListener *) user_data;
NMNetlinkListenerPrivate *priv;
GError *error = NULL;
g_return_val_if_fail (NM_IS_NETLINK_LISTENER (listener), TRUE);
priv = NM_NETLINK_LISTENER_GET_PRIVATE (listener);
g_return_val_if_fail (priv->event_id > 0, TRUE);
if (io_condition & NM_NETLINK_LISTENER_ERROR_CONDITIONS)
return nm_netlink_listener_error_handler (channel, io_condition, listener);
else if (io_condition & NM_NETLINK_LISTENER_DISCONNECT_CONDITIONS)
return nm_netlink_listener_disconnect_handler (channel, io_condition, listener);
g_return_val_if_fail (!(io_condition & ~(NM_NETLINK_LISTENER_EVENT_CONDITIONS)), FALSE);
if (nl_recvmsgs_default (priv->nlh) < 0) {
error = g_error_new (NM_NETLINK_LISTENER_ERROR,
NM_NETLINK_LISTENER_ERROR_PROCESSING_MESSAGE,
_("error processing netlink message: %s"),
nl_geterror ());
g_signal_emit (G_OBJECT (listener),
signals[ERROR],
0, error);
g_error_free (error);
}
return TRUE;
}
static gboolean
nm_netlink_listener_error_handler (GIOChannel *channel,
GIOCondition io_condition,
NMNetlinkListener *listener)
{
GError *socket_error;
const char *err_msg;
int err_code;
socklen_t err_len;
g_return_val_if_fail (io_condition & NM_NETLINK_LISTENER_ERROR_CONDITIONS, FALSE);
err_code = 0;
err_len = sizeof (err_code);
if (getsockopt (g_io_channel_unix_get_fd (channel),
SOL_SOCKET, SO_ERROR, (void *) &err_code, &err_len))
err_msg = strerror (err_code);
else
err_msg = _("error occurred while waiting for data on socket");
socket_error = g_error_new (NM_NETLINK_LISTENER_ERROR,
NM_NETLINK_LISTENER_ERROR_WAITING_FOR_SOCKET_DATA,
"%s",
err_msg);
g_signal_emit (G_OBJECT (listener),
signals[ERROR],
0, socket_error);
g_error_free (socket_error);
return TRUE;
}
static gboolean
nm_netlink_listener_disconnect_handler (GIOChannel *channel,
GIOCondition io_condition,
NMNetlinkListener *listener)
{
g_return_val_if_fail (!(io_condition & ~(NM_NETLINK_LISTENER_DISCONNECT_CONDITIONS)), FALSE);
return FALSE;
}

View file

@ -1,78 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager -- Netlink socket listener
*
* 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 - 2009 Red Hat, Inc.
* Copyright (C) 2005 - 2008 Novell, Inc.
* Copyright (C) 2005 Ray Strode
*/
#ifndef NM_NETLINK_LISTENER_H
#define NM_NETLINK_LISTENER_H
#include <glib.h>
#include <glib-object.h>
#include "nm-netlink.h"
G_BEGIN_DECLS
#define NM_TYPE_NETLINK_LISTENER (nm_netlink_listener_get_type ())
#define NM_NETLINK_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_NETLINK_LISTENER, NMNetlinkListener))
#define NM_NETLINK_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_NETLINK_LISTENER, NMNetlinkListenerClass))
#define NM_IS_NETLINK_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_NETLINK_LISTENER))
#define NM_IS_NETLINK_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_NETLINK_LISTENER))
#define NM_NETLINK_LISTENER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_NETLINK_LISTENER, NMNetlinkListenerClass))
#define NM_NETLINK_LISTENER_ERROR (nm_netlink_listener_error_quark ())
typedef enum {
NM_NETLINK_LISTENER_ERROR_GENERIC = 0,
NM_NETLINK_LISTENER_ERROR_NETLINK_ALLOC_HANDLE,
NM_NETLINK_LISTENER_ERROR_NETLINK_CONNECT,
NM_NETLINK_LISTENER_ERROR_NETLINK_JOIN_GROUP,
NM_NETLINK_LISTENER_ERROR_NETLINK_ALLOC_LINK_CACHE,
NM_NETLINK_LISTENER_ERROR_PROCESSING_MESSAGE,
NM_NETLINK_LISTENER_ERROR_BAD_ALLOC,
NM_NETLINK_LISTENER_ERROR_WAITING_FOR_SOCKET_DATA,
NM_NETLINK_LISTENER_ERROR_LINK_CACHE_UPDATE
} NMNetlinkListenerError;
typedef struct {
GObject parent;
} NMNetlinkListener;
typedef struct {
GObjectClass parent_class;
/* Signals */
void (*notification) (NMNetlinkListener *listener, struct nl_msg *msg);
void (*error) (NMNetlinkListener *listener, GError *error);
} NMNetlinkListenerClass;
GType nm_netlink_listener_get_type (void) G_GNUC_CONST;
GQuark nm_netlink_listener_error_quark (void) G_GNUC_CONST;
NMNetlinkListener *nm_netlink_listener_get (void);
gboolean nm_netlink_listener_subscribe (NMNetlinkListener *listener,
int group,
GError **error);
void nm_netlink_listener_unsubscribe (NMNetlinkListener *listener,
int group);
G_END_DECLS
#endif /* NM_NETLINK_LISTENER_H */

View file

@ -10,5 +10,6 @@ libnm_logging_la_CPPFLAGS = \
-DG_DISABLE_DEPRECATED
libnm_logging_la_LIBADD = \
-ldl \
$(GLIB_LIBS)

View file

@ -179,6 +179,36 @@ nm_logging_setup (const char *level, const char *domains, GError **error)
return TRUE;
}
const char *
nm_logging_level_to_string (void)
{
const LogDesc *diter;
for (diter = &level_descs[0]; diter->name; diter++) {
if (diter->num == log_level)
return diter->name;
}
g_warn_if_reached ();
return "";
}
char *
nm_logging_domains_to_string (void)
{
const LogDesc *diter;
GString *str;
str = g_string_sized_new (75);
for (diter = &domain_descs[0]; diter->name; diter++) {
if (diter->num & log_domains) {
if (str->len)
g_string_append_c (str, ',');
g_string_append (str, diter->name);
}
}
return g_string_free (str, FALSE);
}
void _nm_log (const char *loc,
const char *func,
guint32 domain,
@ -330,9 +360,9 @@ void
nm_logging_start (gboolean become_daemon)
{
if (become_daemon)
openlog (G_LOG_DOMAIN, 0, LOG_DAEMON);
openlog (G_LOG_DOMAIN, LOG_PID, LOG_DAEMON);
else
openlog (G_LOG_DOMAIN, LOG_CONS | LOG_PERROR, LOG_USER);
openlog (G_LOG_DOMAIN, LOG_CONS | LOG_PERROR | LOG_PID, LOG_USER);
g_log_set_handler (G_LOG_DOMAIN,
G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,

View file

@ -88,6 +88,9 @@ void _nm_log (const char *loc, const char *func,
guint32 domain, guint32 level,
const char *fmt, ...);
const char *nm_logging_level_to_string (void);
char *nm_logging_domains_to_string (void);
/* Undefine the nm-utils.h logging stuff to ensure errors */
#undef nm_print_backtrace
#undef nm_get_timestamp

View file

@ -661,7 +661,8 @@ real_deactivate_quickly (NMModem *self, NMDevice *device)
case MM_MODEM_IP_METHOD_STATIC:
case MM_MODEM_IP_METHOD_DHCP:
iface = nm_device_get_ip_iface (device);
nm_system_device_flush_routes_with_iface (iface);
/* FIXME: use AF_UNSPEC here when we have IPv6 support */
nm_system_device_flush_routes_with_iface (iface, AF_INET);
nm_system_device_flush_addresses_with_iface (iface);
nm_system_device_set_up_down_with_iface (iface, FALSE, NULL);
break;

View file

@ -38,6 +38,7 @@
#include "nm-named-manager.h"
#include "nm-ip4-config.h"
#include "nm-ip6-config.h"
#include "nm-logging.h"
#include "nm-system.h"
#include "NetworkManagerUtils.h"
@ -60,8 +61,10 @@ G_DEFINE_TYPE(NMNamedManager, nm_named_manager, G_TYPE_OBJECT)
struct NMNamedManagerPrivate {
NMIP4Config *vpn_config;
NMIP4Config *device_config;
NMIP4Config *ip4_vpn_config;
NMIP4Config *ip4_device_config;
NMIP6Config *ip6_vpn_config;
NMIP6Config *ip6_device_config;
GSList *configs;
};
@ -97,6 +100,26 @@ typedef struct {
GPtrArray *searches;
} NMResolvConfData;
static void
add_string_item (GPtrArray *array, const char *str)
{
int i;
g_return_if_fail (array != NULL);
g_return_if_fail (str != NULL);
/* Check for dupes before adding */
for (i = 0; i < array->len; i++) {
const char *candidate = g_ptr_array_index (array, i);
if (candidate && !strcmp (candidate, str))
return;
}
/* No dupes, add the new item */
g_ptr_array_add (array, g_strdup (str));
}
static void
merge_one_ip4_config (NMResolvConfData *rc, NMIP4Config *src)
{
@ -109,19 +132,22 @@ merge_one_ip4_config (NMResolvConfData *rc, NMIP4Config *src)
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));
add_string_item (rc->nameservers, buf);
}
num = nm_ip4_config_get_num_domains (src);
for (i = 0; i < num; i++) {
const char *domain;
domain = nm_ip4_config_get_domain (src, 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)));
rc->domain = domain;
add_string_item (rc->searches, domain);
}
num = nm_ip4_config_get_num_searches (src);
for (i = 0; i < num; i++)
g_ptr_array_add (rc->searches, g_strdup (nm_ip4_config_get_search (src, i)));
add_string_item (rc->searches, nm_ip4_config_get_search (src, i));
}
static void
@ -139,23 +165,26 @@ merge_one_ip6_config (NMResolvConfData *rc, NMIP6Config *src)
/* 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));
add_string_item (rc->nameservers, buf);
} else {
if (inet_ntop (AF_INET6, addr, buf, INET6_ADDRSTRLEN) > 0)
g_ptr_array_add (rc->nameservers, g_strdup (buf));
add_string_item (rc->nameservers, buf);
}
}
num = nm_ip6_config_get_num_domains (src);
for (i = 0; i < num; i++) {
const char *domain;
domain = nm_ip6_config_get_domain (src, 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)));
rc->domain = domain;
add_string_item (rc->searches, domain);
}
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)));
add_string_item (rc->searches, nm_ip6_config_get_search (src, i));
}
@ -487,25 +516,33 @@ rewrite_resolv_conf (NMNamedManager *mgr, const char *iface, GError **error)
rc.domain = NULL;
rc.searches = g_ptr_array_new ();
if (priv->vpn_config)
merge_one_ip4_config (&rc, priv->vpn_config);
if (priv->ip4_vpn_config)
merge_one_ip4_config (&rc, priv->ip4_vpn_config);
if (priv->ip4_device_config)
merge_one_ip4_config (&rc, priv->ip4_device_config);
if (priv->device_config)
merge_one_ip4_config (&rc, priv->device_config);
if (priv->ip6_vpn_config)
merge_one_ip6_config (&rc, priv->ip6_vpn_config);
if (priv->ip6_device_config)
merge_one_ip6_config (&rc, priv->ip6_device_config);
for (iter = priv->configs; iter; iter = g_slist_next (iter)) {
if ( (iter->data == priv->ip4_vpn_config)
|| (iter->data == priv->ip4_device_config)
|| (iter->data == priv->ip6_vpn_config)
|| (iter->data == priv->ip6_device_config))
continue;
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 (&rc, config);
} else {
} else if (NM_IS_IP6_CONFIG (iter->data)) {
NMIP6Config *config = NM_IP6_CONFIG (iter->data);
merge_one_ip6_config (&rc, config);
}
} else
g_assert_not_reached ();
}
domain = rc.domain;
@ -572,10 +609,10 @@ nm_named_manager_add_ip4_config (NMNamedManager *mgr,
switch (cfg_type) {
case NM_NAMED_IP_CONFIG_TYPE_VPN:
priv->vpn_config = config;
priv->ip4_vpn_config = config;
break;
case NM_NAMED_IP_CONFIG_TYPE_BEST_DEVICE:
priv->device_config = config;
priv->ip4_device_config = config;
break;
default:
break;
@ -613,11 +650,10 @@ nm_named_manager_remove_ip4_config (NMNamedManager *mgr,
priv->configs = g_slist_remove (priv->configs, config);
if (config == priv->vpn_config)
priv->vpn_config = NULL;
if (config == priv->device_config)
priv->device_config = NULL;
if (config == priv->ip4_vpn_config)
priv->ip4_vpn_config = NULL;
if (config == priv->ip4_device_config)
priv->ip4_device_config = NULL;
g_object_unref (config);
@ -643,10 +679,21 @@ nm_named_manager_add_ip6_config (NMNamedManager *mgr,
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);
switch (cfg_type) {
case NM_NAMED_IP_CONFIG_TYPE_VPN:
/* FIXME: not quite yet... */
g_return_val_if_fail (cfg_type != NM_NAMED_IP_CONFIG_TYPE_VPN, FALSE);
priv->ip6_vpn_config = config;
break;
case NM_NAMED_IP_CONFIG_TYPE_BEST_DEVICE:
priv->ip6_device_config = config;
break;
default:
break;
}
/* 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));
@ -679,6 +726,11 @@ nm_named_manager_remove_ip6_config (NMNamedManager *mgr,
priv->configs = g_slist_remove (priv->configs, config);
if (config == priv->ip6_vpn_config)
priv->ip6_vpn_config = NULL;
if (config == priv->ip6_device_config)
priv->ip6_device_config = NULL;
g_object_unref (config);
if (!rewrite_resolv_conf (mgr, iface, &error)) {

View file

@ -72,6 +72,7 @@ typedef struct {
NMActiveConnectionState state;
gboolean is_default;
gboolean is_default6;
gboolean shared;
GSList *share_rules;
@ -88,6 +89,7 @@ enum {
PROP_DEVICES,
PROP_STATE,
PROP_DEFAULT,
PROP_DEFAULT6,
PROP_VPN,
LAST_PROP
@ -104,7 +106,7 @@ device_state_changed (NMDevice *device,
NMActRequest *self = NM_ACT_REQUEST (user_data);
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (self);
NMActiveConnectionState new_ac_state;
gboolean new_default = FALSE;
gboolean new_default = FALSE, new_default6 = FALSE;
/* Set NMActiveConnection state based on the device's state */
switch (new_state) {
@ -117,6 +119,7 @@ device_state_changed (NMDevice *device,
case NM_DEVICE_STATE_ACTIVATED:
new_ac_state = NM_ACTIVE_CONNECTION_STATE_ACTIVATED;
new_default = priv->is_default;
new_default6 = priv->is_default6;
break;
default:
new_ac_state = NM_ACTIVE_CONNECTION_STATE_UNKNOWN;
@ -132,6 +135,11 @@ device_state_changed (NMDevice *device,
priv->is_default = new_default;
g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_DEFAULT);
}
if (new_default6 != priv->is_default6) {
priv->is_default6 = new_default6;
g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_DEFAULT6);
}
}
NMActRequest *
@ -271,6 +279,9 @@ get_property (GObject *object, guint prop_id,
case PROP_DEFAULT:
g_value_set_boolean (value, priv->is_default);
break;
case PROP_DEFAULT6:
g_value_set_boolean (value, priv->is_default6);
break;
case PROP_VPN:
g_value_set_boolean (value, FALSE);
break;
@ -334,7 +345,14 @@ nm_act_request_class_init (NMActRequestClass *req_class)
(object_class, PROP_DEFAULT,
g_param_spec_boolean (NM_ACTIVE_CONNECTION_DEFAULT,
"Default",
"Is the default active connection",
"Is the default IPv4 active connection",
FALSE,
G_PARAM_READABLE));
g_object_class_install_property
(object_class, PROP_DEFAULT6,
g_param_spec_boolean (NM_ACTIVE_CONNECTION_DEFAULT6,
"Default6",
"Is the default IPv6 active connection",
FALSE,
G_PARAM_READABLE));
g_object_class_install_property
@ -548,6 +566,29 @@ nm_act_request_get_default (NMActRequest *req)
return NM_ACT_REQUEST_GET_PRIVATE (req)->is_default;
}
void
nm_act_request_set_default6 (NMActRequest *req, gboolean is_default6)
{
NMActRequestPrivate *priv;
g_return_if_fail (NM_IS_ACT_REQUEST (req));
priv = NM_ACT_REQUEST_GET_PRIVATE (req);
if (priv->is_default6 == is_default6)
return;
priv->is_default6 = is_default6;
g_object_notify (G_OBJECT (req), NM_ACTIVE_CONNECTION_DEFAULT6);
}
gboolean
nm_act_request_get_default6 (NMActRequest *req)
{
g_return_val_if_fail (NM_IS_ACT_REQUEST (req), FALSE);
return NM_ACT_REQUEST_GET_PRIVATE (req)->is_default6;
}
static void
share_child_setup (gpointer user_data G_GNUC_UNUSED)
{

View file

@ -15,7 +15,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* (C) Copyright 2005 - 2008 Red Hat, Inc.
* (C) Copyright 2005 - 2010 Red Hat, Inc.
*/
#ifndef NM_ACTIVATION_REQUEST_H
@ -76,6 +76,10 @@ void nm_act_request_set_default (NMActRequest *req, gboolean is_default
gboolean nm_act_request_get_default (NMActRequest *req);
void nm_act_request_set_default6 (NMActRequest *req, gboolean is_default6);
gboolean nm_act_request_get_default6 (NMActRequest *req);
gboolean nm_act_request_get_shared (NMActRequest *req);
void nm_act_request_set_shared (NMActRequest *req, gboolean shared);

View file

@ -15,7 +15,7 @@
* 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.
* Copyright (C) 2008 - 2010 Red Hat, Inc.
*/
#ifndef NM_ACTIVE_CONNECTION_H
@ -30,6 +30,7 @@
#define NM_ACTIVE_CONNECTION_DEVICES "devices"
#define NM_ACTIVE_CONNECTION_STATE "state"
#define NM_ACTIVE_CONNECTION_DEFAULT "default"
#define NM_ACTIVE_CONNECTION_DEFAULT6 "default6"
#define NM_ACTIVE_CONNECTION_VPN "vpn"
char *nm_active_connection_get_next_object_path (void);

View file

@ -275,10 +275,16 @@ ppp_failed (NMModem *modem, NMDeviceStateReason reason, gpointer user_data)
case NM_DEVICE_STATE_PREPARE:
case NM_DEVICE_STATE_CONFIG:
case NM_DEVICE_STATE_NEED_AUTH:
case NM_DEVICE_STATE_IP_CONFIG:
case NM_DEVICE_STATE_ACTIVATED:
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason);
break;
case NM_DEVICE_STATE_IP_CONFIG:
if (nm_device_ip_config_should_fail (device, FALSE)) {
nm_device_state_changed (device,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
}
break;
default:
break;
}

View file

@ -34,6 +34,8 @@
#include <linux/if.h>
#include <errno.h>
#include <netlink/route/addr.h>
#include "nm-glib-compat.h"
#include "nm-device-ethernet.h"
#include "nm-device-interface.h"
@ -43,7 +45,6 @@
#include "nm-supplicant-manager.h"
#include "nm-supplicant-interface.h"
#include "nm-supplicant-config.h"
#include "nm-netlink.h"
#include "nm-netlink-monitor.h"
#include "nm-system.h"
#include "nm-setting-connection.h"
@ -105,7 +106,6 @@ typedef struct {
struct ether_addr hw_addr;
gboolean carrier;
guint32 ifindex;
NMNetlinkMonitor * monitor;
gulong link_connected_id;
@ -133,7 +133,6 @@ enum {
PROP_HW_ADDRESS,
PROP_SPEED,
PROP_CARRIER,
PROP_IFINDEX,
LAST_PROP
};
@ -246,11 +245,10 @@ carrier_on (NMNetlinkMonitor *monitor,
{
NMDevice *device = NM_DEVICE (user_data);
NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device);
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
guint32 caps;
/* Make sure signal is for us */
if (idx == priv->ifindex) {
if (idx == nm_device_get_ifindex (device)) {
/* Ignore spurious netlink messages */
caps = nm_device_get_capabilities (device);
if (!(caps & NM_DEVICE_CAP_CARRIER_DETECT))
@ -267,11 +265,10 @@ carrier_off (NMNetlinkMonitor *monitor,
{
NMDevice *device = NM_DEVICE (user_data);
NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device);
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
guint32 caps;
/* Make sure signal is for us */
if (idx == priv->ifindex) {
if (idx == nm_device_get_ifindex (device)) {
NMDeviceState state;
gboolean defer = FALSE;
@ -312,7 +309,8 @@ constructor (GType type,
priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
nm_log_dbg (LOGD_HW | LOGD_OLPC_MESH, "(%s): kernel ifindex %d",
nm_device_get_iface (NM_DEVICE (self)), priv->ifindex);
nm_device_get_iface (NM_DEVICE (self)),
nm_device_get_ifindex (NM_DEVICE (self)));
caps = nm_device_get_capabilities (self);
if (caps & NM_DEVICE_CAP_CARRIER_DETECT) {
@ -331,7 +329,7 @@ constructor (GType type,
/* Get initial link state */
if (!nm_netlink_monitor_get_flags_sync (priv->monitor,
priv->ifindex,
nm_device_get_ifindex (NM_DEVICE (self)),
&ifflags,
&error)) {
nm_log_warn (LOGD_HW | LOGD_ETHER,
@ -426,8 +424,7 @@ real_hw_take_down (NMDevice *dev)
NMDevice *
nm_device_ethernet_new (const char *udi,
const char *iface,
const char *driver,
guint32 ifindex)
const char *driver)
{
g_return_val_if_fail (udi != NULL, NULL);
g_return_val_if_fail (iface != NULL, NULL);
@ -437,7 +434,6 @@ nm_device_ethernet_new (const char *udi,
NM_DEVICE_INTERFACE_UDI, udi,
NM_DEVICE_INTERFACE_IFACE, iface,
NM_DEVICE_INTERFACE_DRIVER, driver,
NM_DEVICE_ETHERNET_IFINDEX, ifindex,
NM_DEVICE_INTERFACE_TYPE_DESC, "Ethernet",
NM_DEVICE_INTERFACE_DEVICE_TYPE, NM_DEVICE_TYPE_ETHERNET,
NULL);
@ -459,14 +455,6 @@ nm_device_ethernet_get_address (NMDeviceEthernet *self, struct ether_addr *addr)
memcpy (addr, &(NM_DEVICE_ETHERNET_GET_PRIVATE (self)->hw_addr), sizeof (struct ether_addr));
}
guint32
nm_device_ethernet_get_ifindex (NMDeviceEthernet *self)
{
g_return_val_if_fail (self != NULL, FALSE);
return NM_DEVICE_ETHERNET_GET_PRIVATE (self)->ifindex;
}
/* Returns speed in Mb/s */
static guint32
nm_device_ethernet_get_speed (NMDeviceEthernet *self)
@ -1618,7 +1606,7 @@ ip4_match_config (NMDevice *self, NMConnection *connection)
int ifindex;
AddrData check_data;
ifindex = nm_device_ethernet_get_ifindex (NM_DEVICE_ETHERNET (self));
ifindex = nm_device_get_ifindex (self);
s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
g_assert (s_con);
@ -1790,9 +1778,6 @@ get_property (GObject *object, guint prop_id,
case PROP_CARRIER:
g_value_set_boolean (value, priv->carrier);
break;
case PROP_IFINDEX:
g_value_set_uint (value, priv->ifindex);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -1803,13 +1788,7 @@ static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (object);
switch (prop_id) {
case PROP_IFINDEX:
/* construct-only */
priv->ifindex = g_value_get_uint (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -1876,14 +1855,6 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass)
FALSE,
G_PARAM_READABLE));
g_object_class_install_property
(object_class, PROP_IFINDEX,
g_param_spec_uint (NM_DEVICE_ETHERNET_IFINDEX,
"Ifindex",
"Interface index",
0, G_MAXUINT32, 0,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT));
/* Signals */
signals[PROPERTIES_CHANGED] =
nm_properties_changed_signal_new (object_class,

View file

@ -39,7 +39,6 @@ G_BEGIN_DECLS
#define NM_DEVICE_ETHERNET_HW_ADDRESS "hw-address"
#define NM_DEVICE_ETHERNET_SPEED "speed"
#define NM_DEVICE_ETHERNET_CARRIER "carrier"
#define NM_DEVICE_ETHERNET_IFINDEX "ifindex"
typedef struct {
NMDevice parent;
@ -58,14 +57,11 @@ GType nm_device_ethernet_get_type (void);
NMDevice *nm_device_ethernet_new (const char *udi,
const char *iface,
const char *driver,
guint32 ifindex);
const char *driver);
void nm_device_ethernet_get_address (NMDeviceEthernet *dev,
struct ether_addr *addr);
guint32 nm_device_ethernet_get_ifindex (NMDeviceEthernet *dev);
G_END_DECLS
#endif /* NM_DEVICE_ETHERNET_H */

View file

@ -16,7 +16,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2007 - 2008 Novell, Inc.
* Copyright (C) 2007 - 2008 Red Hat, Inc.
* Copyright (C) 2007 - 2010 Red Hat, Inc.
*/
#include "nm-marshal.h"
@ -186,6 +186,14 @@ nm_device_interface_init (gpointer g_iface)
RFKILL_TYPE_UNKNOWN,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT));
g_object_interface_install_property
(g_iface,
g_param_spec_int (NM_DEVICE_INTERFACE_IFINDEX,
"Ifindex",
"Ifindex",
0, G_MAXINT, 0,
G_PARAM_READABLE | NM_PROPERTY_PARAM_NO_EXPORT));
/* Signals */
g_signal_new ("state-changed",
iface_type,

View file

@ -57,8 +57,9 @@ typedef enum
#define NM_DEVICE_INTERFACE_STATE "state"
#define NM_DEVICE_INTERFACE_DEVICE_TYPE "device-type" /* ugh */
#define NM_DEVICE_INTERFACE_MANAGED "managed"
#define NM_DEVICE_INTERFACE_TYPE_DESC "type-desc" /* Internal only */
#define NM_DEVICE_INTERFACE_TYPE_DESC "type-desc" /* Internal only */
#define NM_DEVICE_INTERFACE_RFKILL_TYPE "rfkill-type" /* Internal only */
#define NM_DEVICE_INTERFACE_IFINDEX "ifindex" /* Internal only */
typedef enum {
NM_DEVICE_INTERFACE_PROP_FIRST = 0x1000,
@ -77,6 +78,7 @@ typedef enum {
NM_DEVICE_INTERFACE_PROP_MANAGED,
NM_DEVICE_INTERFACE_PROP_TYPE_DESC,
NM_DEVICE_INTERFACE_PROP_RFKILL_TYPE,
NM_DEVICE_INTERFACE_PROP_IFINDEX,
} NMDeviceInterfaceProp;

View file

@ -72,10 +72,16 @@ ppp_failed (NMModem *modem, NMDeviceStateReason reason, gpointer user_data)
case NM_DEVICE_STATE_PREPARE:
case NM_DEVICE_STATE_CONFIG:
case NM_DEVICE_STATE_NEED_AUTH:
case NM_DEVICE_STATE_IP_CONFIG:
case NM_DEVICE_STATE_ACTIVATED:
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason);
break;
case NM_DEVICE_STATE_IP_CONFIG:
if (nm_device_ip_config_should_fail (device, FALSE)) {
nm_device_state_changed (device,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
}
break;
default:
break;
}

View file

@ -69,7 +69,6 @@ enum {
PROP_HW_ADDRESS,
PROP_COMPANION,
PROP_ACTIVE_CHANNEL,
PROP_IFINDEX,
LAST_PROP
};
@ -98,7 +97,6 @@ struct _NMDeviceOlpcMeshPrivate
gboolean dispose_has_run;
struct ether_addr hw_addr;
guint32 ifindex;
GByteArray * ssid;
@ -263,7 +261,8 @@ constructor (GType type,
priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self);
nm_log_dbg (LOGD_HW | LOGD_OLPC_MESH, "(%s): kernel ifindex %d",
nm_device_get_iface (NM_DEVICE (self)), priv->ifindex);
nm_device_get_iface (NM_DEVICE (self)),
nm_device_get_ifindex (NM_DEVICE (self)));
iface = nm_device_get_iface (NM_DEVICE (self));
fd = socket (PF_INET, SOCK_DGRAM, 0);
@ -539,15 +538,6 @@ nm_device_olpc_mesh_set_ssid (NMDeviceOlpcMesh *self, const GByteArray * ssid)
close (sk);
}
guint32
nm_device_olpc_mesh_get_ifindex (NMDeviceOlpcMesh *self)
{
g_return_val_if_fail (self != NULL, FALSE);
return NM_DEVICE_OLPC_MESH_GET_PRIVATE (self)->ifindex;
}
/****************************************************************************/
static void
@ -647,15 +637,6 @@ real_act_stage2_config (NMDevice *dev, NMDeviceStateReason *reason)
return NM_ACT_STAGE_RETURN_SUCCESS;
}
static NMActStageReturn
real_act_stage4_ip4_config_timeout (NMDevice *dev,
NMIP4Config **config,
NMDeviceStateReason *reason)
{
return NM_ACT_STAGE_RETURN_FAILURE;
}
static void
dispose (GObject *object)
{
@ -701,9 +682,6 @@ get_property (GObject *object, guint prop_id,
case PROP_ACTIVE_CHANNEL:
g_value_set_uint (value, nm_device_olpc_mesh_get_channel (device));
break;
case PROP_IFINDEX:
g_value_set_uint (value, nm_device_olpc_mesh_get_ifindex (device));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -714,13 +692,7 @@ static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (object);
switch (prop_id) {
case PROP_IFINDEX:
/* construct-only */
priv->ifindex = g_value_get_uint (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -753,7 +725,6 @@ nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass)
parent_class->act_stage1_prepare = real_act_stage1_prepare;
parent_class->act_stage2_config = real_act_stage2_config;
parent_class->act_stage4_ip4_config_timeout = real_act_stage4_ip4_config_timeout;
/* Properties */
g_object_class_install_property
@ -780,13 +751,6 @@ nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass)
0, G_MAXUINT32, 0,
G_PARAM_READABLE));
g_object_class_install_property (object_class, PROP_IFINDEX,
g_param_spec_uint (NM_DEVICE_OLPC_MESH_IFINDEX,
"Ifindex",
"Interface index",
0, G_MAXUINT32, 0,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
signals[PROPERTIES_CHANGED] =
nm_properties_changed_signal_new (object_class,
G_STRUCT_OFFSET (NMDeviceOlpcMeshClass, properties_changed));
@ -986,8 +950,7 @@ state_changed_cb (NMDevice *device, NMDeviceState state, gpointer user_data)
NMDevice *
nm_device_olpc_mesh_new (const char *udi,
const char *iface,
const char *driver,
guint32 ifindex)
const char *driver)
{
GObject *obj;
@ -999,7 +962,6 @@ nm_device_olpc_mesh_new (const char *udi,
NM_DEVICE_INTERFACE_UDI, udi,
NM_DEVICE_INTERFACE_IFACE, iface,
NM_DEVICE_INTERFACE_DRIVER, driver,
NM_DEVICE_OLPC_MESH_IFINDEX, ifindex,
NM_DEVICE_INTERFACE_TYPE_DESC, "802.11 OLPC Mesh",
NM_DEVICE_INTERFACE_DEVICE_TYPE, NM_DEVICE_TYPE_OLPC_MESH,
NULL);

View file

@ -46,7 +46,6 @@ G_BEGIN_DECLS
#define NM_DEVICE_OLPC_MESH_COMPANION "companion"
#define NM_DEVICE_OLPC_MESH_BITRATE "bitrate"
#define NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL "active-channel"
#define NM_DEVICE_OLPC_MESH_IFINDEX "ifindex"
#ifndef NM_DEVICE_OLPC_MESH_DEFINED
#define NM_DEVICE_OLPC_MESH_DEFINED
@ -75,10 +74,7 @@ GType nm_device_olpc_mesh_get_type (void);
NMDevice *nm_device_olpc_mesh_new (const char *udi,
const char *iface,
const char *driver,
guint32 ifindex);
guint32 nm_device_olpc_mesh_get_ifindex (NMDeviceOlpcMesh *self);
const char *driver);
G_END_DECLS

View file

@ -40,4 +40,6 @@ void nm_device_handle_autoip4_event (NMDevice *self,
const char *event,
const char *address);
gboolean nm_device_ip_config_should_fail (NMDevice *self, gboolean ip6);
#endif /* NM_DEVICE_PRIVATE_H */

View file

@ -82,7 +82,6 @@ enum {
PROP_BITRATE,
PROP_ACTIVE_ACCESS_POINT,
PROP_CAPABILITIES,
PROP_IFINDEX,
PROP_SCANNING,
PROP_IPW_RFKILL_STATE,
@ -144,7 +143,6 @@ struct _NMDeviceWifiPrivate {
gboolean disposed;
struct ether_addr hw_addr;
guint32 ifindex;
/* Legacy rfkill for ipw2x00; will be fixed with 2.6.33 kernel */
char * ipw_rfkill_path;
@ -579,7 +577,8 @@ constructor (GType type,
priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
nm_log_dbg (LOGD_HW | LOGD_WIFI, "(%s): kernel ifindex %d",
nm_device_get_iface (NM_DEVICE (self)), priv->ifindex);
nm_device_get_iface (NM_DEVICE (self)),
nm_device_get_ifindex (NM_DEVICE (self)));
memset (&range, 0, sizeof (struct iw_range));
success = wireless_get_range (NM_DEVICE_WIFI (object), &range, &response_len);
@ -2677,7 +2676,11 @@ handle_auth_or_fail (NMDeviceWifi *self,
NMConnection *connection;
g_return_val_if_fail (NM_IS_DEVICE_WIFI (self), NM_ACT_STAGE_RETURN_FAILURE);
g_return_val_if_fail (NM_IS_ACT_REQUEST (req), NM_ACT_STAGE_RETURN_FAILURE);
if (!req) {
req = nm_device_get_act_request (NM_DEVICE (self));
g_assert (req);
}
connection = nm_act_request_get_connection (req);
g_assert (connection);
@ -3188,21 +3191,19 @@ real_act_stage4_get_ip4_config (NMDevice *dev,
static NMActStageReturn
real_act_stage4_ip4_config_timeout (NMDevice *dev,
NMIP4Config **config,
NMDeviceStateReason *reason)
handle_ip_config_timeout (NMDeviceWifi *self,
NMConnection *connection,
gboolean may_fail,
gboolean *chain_up,
NMDeviceStateReason *reason)
{
NMDeviceWifi *self = NM_DEVICE_WIFI (dev);
NMAccessPoint *ap = nm_device_wifi_get_activation_ap (self);
NMAccessPoint *ap;
NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
NMIP4Config *real_config = NULL;
NMActRequest *req = nm_device_get_act_request (dev);
NMConnection *connection;
gboolean auth_enforced = FALSE, encrypted = FALSE;
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 (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE);
ap = nm_device_wifi_get_activation_ap (self);
g_assert (ap);
/* If nothing checks the security authentication information (as in
@ -3210,9 +3211,8 @@ real_act_stage4_ip4_config_timeout (NMDevice *dev,
* the encryption key is likely wrong. Ask the user for a new one.
* Otherwise the failure likely happened after a successful authentication.
*/
connection = nm_act_request_get_connection (req);
auth_enforced = ap_auth_enforced (connection, ap, &encrypted);
if (encrypted && !auth_enforced) {
if (encrypted && !auth_enforced && !may_fail) {
NMSettingConnection *s_con;
s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
@ -3221,39 +3221,83 @@ real_act_stage4_ip4_config_timeout (NMDevice *dev,
nm_log_warn (LOGD_DEVICE | LOGD_WIFI,
"Activation (%s/wireless): could not get IP configuration for "
"connection '%s'.",
nm_device_get_iface (dev), nm_setting_connection_get_id (s_con));
nm_device_get_iface (NM_DEVICE (self)),
nm_setting_connection_get_id (s_con));
ret = handle_auth_or_fail (self, req, TRUE);
ret = handle_auth_or_fail (self, NULL, TRUE);
if (ret == NM_ACT_STAGE_RETURN_POSTPONE) {
nm_log_info (LOGD_DEVICE | LOGD_WIFI,
"Activation (%s/wireless): asking for new secrets",
nm_device_get_iface (dev));
nm_device_get_iface (NM_DEVICE (self)));
} else {
*reason = NM_DEVICE_STATE_REASON_NO_SECRETS;
}
} else if (nm_ap_get_mode (ap) == NM_802_11_MODE_ADHOC) {
NMDeviceWifiClass *klass;
NMDeviceClass * parent_class;
/* 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_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
* the user.
* entity (AP, RADIUS server, etc), but IP configure failed. Let the
* superclass handle it.
*/
*reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE;
ret = NM_ACT_STAGE_RETURN_FAILURE;
*chain_up = TRUE;
}
*config = real_config;
return ret;
}
static NMActStageReturn
real_act_stage4_ip4_config_timeout (NMDevice *dev,
NMIP4Config **config,
NMDeviceStateReason *reason)
{
NMActRequest *req;
NMConnection *connection;
NMSettingIP4Config *s_ip4;
gboolean may_fail = FALSE, chain_up = FALSE;
NMActStageReturn ret;
req = nm_device_get_act_request (dev);
g_assert (req);
connection = nm_act_request_get_connection (req);
g_assert (connection);
s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
if (s_ip4)
may_fail = nm_setting_ip4_config_get_may_fail (s_ip4);
ret = handle_ip_config_timeout (NM_DEVICE_WIFI (dev), connection, may_fail, &chain_up, reason);
if (chain_up)
ret = NM_DEVICE_CLASS (nm_device_wifi_parent_class)->act_stage4_ip4_config_timeout (dev, config, reason);
return ret;
}
static NMActStageReturn
real_act_stage4_ip6_config_timeout (NMDevice *dev,
NMIP6Config **config,
NMDeviceStateReason *reason)
{
NMActRequest *req;
NMConnection *connection;
NMSettingIP6Config *s_ip6;
gboolean may_fail = FALSE, chain_up = FALSE;
NMActStageReturn ret;
req = nm_device_get_act_request (dev);
g_assert (req);
connection = nm_act_request_get_connection (req);
g_assert (connection);
s_ip6 = (NMSettingIP6Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG);
if (s_ip6)
may_fail = nm_setting_ip6_config_get_may_fail (s_ip6);
ret = handle_ip_config_timeout (NM_DEVICE_WIFI (dev), connection, may_fail, &chain_up, reason);
if (chain_up)
ret = NM_DEVICE_CLASS (nm_device_wifi_parent_class)->act_stage4_ip6_config_timeout (dev, config, reason);
return ret;
}
static void
activation_success_handler (NMDevice *dev)
{
@ -3462,14 +3506,6 @@ device_state_changed (NMDevice *device,
remove_all_aps (self);
}
guint32
nm_device_wifi_get_ifindex (NMDeviceWifi *self)
{
g_return_val_if_fail (self != NULL, FALSE);
return NM_DEVICE_WIFI_GET_PRIVATE (self)->ifindex;
}
NMAccessPoint *
nm_device_wifi_get_activation_ap (NMDeviceWifi *self)
{
@ -3563,8 +3599,7 @@ real_set_enabled (NMDeviceInterface *device, gboolean enabled)
NMDevice *
nm_device_wifi_new (const char *udi,
const char *iface,
const char *driver,
guint32 ifindex)
const char *driver)
{
g_return_val_if_fail (udi != NULL, NULL);
g_return_val_if_fail (iface != NULL, NULL);
@ -3574,7 +3609,6 @@ nm_device_wifi_new (const char *udi,
NM_DEVICE_INTERFACE_UDI, udi,
NM_DEVICE_INTERFACE_IFACE, iface,
NM_DEVICE_INTERFACE_DRIVER, driver,
NM_DEVICE_WIFI_IFINDEX, ifindex,
NM_DEVICE_INTERFACE_TYPE_DESC, "802.11 WiFi",
NM_DEVICE_INTERFACE_DEVICE_TYPE, NM_DEVICE_TYPE_WIFI,
NM_DEVICE_INTERFACE_RFKILL_TYPE, RFKILL_TYPE_WLAN,
@ -3675,9 +3709,6 @@ get_property (GObject *object, guint prop_id,
else
g_value_set_boxed (value, "/");
break;
case PROP_IFINDEX:
g_value_set_uint (value, nm_device_wifi_get_ifindex (device));
break;
case PROP_SCANNING:
g_value_set_boolean (value, nm_supplicant_interface_get_scanning (priv->supplicant.iface));
break;
@ -3697,10 +3728,6 @@ set_property (GObject *object, guint prop_id,
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (object);
switch (prop_id) {
case PROP_IFINDEX:
/* construct-only */
priv->ifindex = g_value_get_uint (value);
break;
case PROP_IPW_RFKILL_STATE:
/* construct only */
priv->ipw_rfkill_state = g_value_get_uint (value);
@ -3743,6 +3770,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
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_ip4_config_timeout = real_act_stage4_ip4_config_timeout;
parent_class->act_stage4_ip6_config_timeout = real_act_stage4_ip6_config_timeout;
parent_class->deactivate = real_deactivate;
parent_class->deactivate_quickly = real_deactivate_quickly;
parent_class->can_interrupt_activation = real_can_interrupt_activation;
@ -3788,13 +3816,6 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
0, G_MAXUINT32, NM_WIFI_DEVICE_CAP_NONE,
G_PARAM_READABLE));
g_object_class_install_property (object_class, PROP_IFINDEX,
g_param_spec_uint (NM_DEVICE_WIFI_IFINDEX,
"Ifindex",
"Interface index",
0, G_MAXUINT32, 0,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT));
g_object_class_install_property (object_class, PROP_SCANNING,
g_param_spec_boolean (NM_DEVICE_WIFI_SCANNING,
"Scanning",

View file

@ -47,7 +47,6 @@ G_BEGIN_DECLS
#define NM_DEVICE_WIFI_BITRATE "bitrate"
#define NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT "active-access-point"
#define NM_DEVICE_WIFI_CAPABILITIES "wireless-capabilities"
#define NM_DEVICE_WIFI_IFINDEX "ifindex"
#define NM_DEVICE_WIFI_SCANNING "scanning"
#define NM_DEVICE_WIFI_IPW_RFKILL_STATE "ipw-rfkill-state"
@ -84,8 +83,7 @@ GType nm_device_wifi_get_type (void);
NMDevice *nm_device_wifi_new (const char *udi,
const char *iface,
const char *driver,
guint32 ifindex);
const char *driver);
void nm_device_wifi_get_address (NMDeviceWifi *dev,
struct ether_addr *addr);
@ -102,8 +100,6 @@ NM80211Mode nm_device_wifi_get_mode (NMDeviceWifi *self);
NMAccessPoint * nm_device_wifi_get_activation_ap (NMDeviceWifi *self);
guint32 nm_device_wifi_get_ifindex (NMDeviceWifi *self);
RfKillState nm_device_wifi_get_ipw_rfkill_state (NMDeviceWifi *self);
G_END_DECLS

View file

@ -45,7 +45,7 @@
#include "nm-named-manager.h"
#include "nm-utils.h"
#include "nm-logging.h"
#include "nm-netlink.h"
#include "nm-netlink-monitor.h"
#include "nm-setting-ip4-config.h"
#include "nm-setting-ip6-config.h"
#include "nm-setting-connection.h"
@ -83,7 +83,9 @@ typedef struct {
char * udi;
char * path;
char * iface; /* may change, could be renamed by user */
int ifindex;
char * ip_iface;
int ip_ifindex;
NMDeviceType type;
char * type_desc;
guint32 capabilities;
@ -132,9 +134,12 @@ typedef struct {
gulong ip6_addrconf_sigid;
gulong ip6_config_changed_sigid;
gboolean ip6_waiting_for_config;
guint32 ip6_dhcp_opt;
char * ip6_accept_ra_path;
guint32 ip6_accept_ra_save;
NMDHCPClient * dhcp6_client;
guint32 dhcp6_mode;
gulong dhcp6_state_sigid;
gulong dhcp6_timeout_sigid;
NMDHCP6Config * dhcp6_config;
@ -175,6 +180,11 @@ static NMActStageReturn dhcp6_start (NMDevice *self,
guint32 dhcp_opt,
NMDeviceStateReason *reason);
static void addrconf6_cleanup (NMDevice *self);
static void dhcp6_cleanup (NMDevice *self, gboolean stop);
static void dhcp4_cleanup (NMDevice *self, gboolean stop);
static void
device_interface_init (NMDeviceInterface *device_interface_class)
{
@ -200,6 +210,41 @@ nm_device_init (NMDevice *self)
priv->rfkill_type = RFKILL_TYPE_UNKNOWN;
}
static void
update_accept_ra_save (NMDevice *self)
{
NMDevicePrivate *priv;
const char *ip_iface;
char *new_path;
g_return_if_fail (self != NULL);
g_return_if_fail (NM_IS_DEVICE (self));
priv = NM_DEVICE_GET_PRIVATE (self);
ip_iface = nm_device_get_ip_iface (self);
new_path = g_strdup_printf ("/proc/sys/net/ipv6/conf/%s/accept_ra", ip_iface);
g_assert (new_path);
if (priv->ip6_accept_ra_path) {
/* If the IP iface is different from before, use the new value */
if (!strcmp (new_path, priv->ip6_accept_ra_path)) {
g_free (new_path);
return;
}
g_free (priv->ip6_accept_ra_path);
}
/* Grab the original value of "accept_ra" so we can restore it when NM exits */
priv->ip6_accept_ra_path = new_path;
if (!nm_utils_get_proc_sys_net_value (priv->ip6_accept_ra_path,
ip_iface,
&priv->ip6_accept_ra_save)) {
g_free (priv->ip6_accept_ra_path);
priv->ip6_accept_ra_path = NULL;
}
}
static GObject*
constructor (GType type,
guint n_construct_params,
@ -239,6 +284,8 @@ constructor (GType type,
priv->dhcp_manager = nm_dhcp_manager_get ();
update_accept_ra_save (dev);
priv->initialized = TRUE;
return object;
@ -304,6 +351,13 @@ nm_device_get_iface (NMDevice *self)
return NM_DEVICE_GET_PRIVATE (self)->iface;
}
int
nm_device_get_ifindex (NMDevice *self)
{
g_return_val_if_fail (self != NULL, 0);
return NM_DEVICE_GET_PRIVATE (self)->ifindex;
}
const char *
nm_device_get_ip_iface (NMDevice *self)
@ -317,14 +371,36 @@ nm_device_get_ip_iface (NMDevice *self)
return priv->ip_iface ? priv->ip_iface : priv->iface;
}
int
nm_device_get_ip_ifindex (NMDevice *self)
{
NMDevicePrivate *priv;
g_return_val_if_fail (self != NULL, 0);
priv = NM_DEVICE_GET_PRIVATE (self);
/* If it's not set, default to iface */
return priv->ip_iface ? priv->ip_ifindex : priv->ifindex;
}
void
nm_device_set_ip_iface (NMDevice *self, const char *iface)
{
NMDevicePrivate *priv;
g_return_if_fail (NM_IS_DEVICE (self));
g_free (NM_DEVICE_GET_PRIVATE (self)->ip_iface);
NM_DEVICE_GET_PRIVATE (self)->ip_iface = iface ? g_strdup (iface) : NULL;
priv = NM_DEVICE_GET_PRIVATE (self);
g_free (priv->ip_iface);
priv->ip_ifindex = 0;
priv->ip_iface = g_strdup (iface);
if (priv->ip_iface) {
priv->ip_ifindex = nm_netlink_iface_to_index (priv->ip_iface);
if (!priv->ip_ifindex) {
nm_log_warn (LOGD_HW, "(%s): failed to look up interface index", iface);
}
}
}
@ -543,9 +619,38 @@ activation_source_schedule (NMDevice *self, GSourceFunc func, int family)
}
}
gboolean
nm_device_ip_config_should_fail (NMDevice *self, gboolean ip6)
{
NMActRequest *req;
NMConnection *connection;
NMSettingIP4Config *s_ip4;
NMSettingIP6Config *s_ip6;
g_return_val_if_fail (self != NULL, TRUE);
req = nm_device_get_act_request (self);
g_assert (req);
connection = nm_act_request_get_connection (req);
g_assert (connection);
/* Fail the connection if the failed IP method is required to complete */
if (ip6) {
s_ip6 = (NMSettingIP6Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG);
if (s_ip6 && !nm_setting_ip6_config_get_may_fail (s_ip6))
return TRUE;
} else {
s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
if (s_ip4 && !nm_setting_ip4_config_get_may_fail (s_ip4))
return TRUE;
}
return FALSE;
}
static void
ip6_addrconf_complete (NMIP6Manager *ip6_manager,
const char *iface,
int ifindex,
guint dhcp_opts,
gboolean success,
gpointer user_data)
@ -558,7 +663,7 @@ ip6_addrconf_complete (NMIP6Manager *ip6_manager,
NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
NMDeviceState state;
if (strcmp (nm_device_get_ip_iface (self), iface) != 0)
if (ifindex != nm_device_get_ip_ifindex (self))
return;
req = nm_device_get_act_request (self);
if (!req)
@ -576,10 +681,10 @@ ip6_addrconf_complete (NMIP6Manager *ip6_manager,
return;
}
priv->ip6_dhcp_opt = dhcp_opts;
priv->dhcp6_mode = dhcp_opts;
/* If addrconf is all that's required, we're done */
if (dhcp_opts == IP6_DHCP_OPT_NONE) {
if (priv->dhcp6_mode == IP6_DHCP_OPT_NONE) {
nm_device_activate_schedule_stage4_ip6_config_get (self);
return;
}
@ -596,7 +701,7 @@ ip6_addrconf_complete (NMIP6Manager *ip6_manager,
" as requested by IPv6 router...",
priv->iface);
ret = dhcp6_start (self, connection, dhcp_opts, &reason);
ret = dhcp6_start (self, connection, priv->dhcp6_mode, &reason);
switch (ret) {
case NM_ACT_STAGE_RETURN_SUCCESS:
/* Shouldn't get this, but handle it anyway */
@ -614,17 +719,27 @@ ip6_addrconf_complete (NMIP6Manager *ip6_manager,
static void
ip6_config_changed (NMIP6Manager *ip6_manager,
const char *iface,
int ifindex,
guint dhcp_opts,
gboolean success,
gpointer user_data)
{
NMDevice *self = NM_DEVICE (user_data);
if (strcmp (nm_device_get_ip_iface (self), iface) != 0)
if (ifindex != nm_device_get_ip_ifindex (self))
return;
if (!nm_device_get_act_request (self))
return;
/* FIXME: re-run DHCPv6 here to get any new nameservers or whatever */
if (!success && (nm_device_get_state (self) == NM_DEVICE_STATE_ACTIVATED)) {
nm_device_state_changed (self,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
return;
}
nm_device_activate_schedule_stage4_ip6_config_get (self);
}
@ -635,32 +750,31 @@ ip6_method_matches (NMConnection *connection, const char *match)
const char *method = NULL;
s_ip6 = (NMSettingIP6Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG);
if (s_ip6)
if (s_ip6) {
method = nm_setting_ip6_config_get_method (s_ip6);
g_assert (method);
}
/* Treat missing IP6 setting as IGNORE */
if (!s_ip6 && !strcmp (match, NM_SETTING_IP6_CONFIG_METHOD_IGNORE))
return TRUE;
return method && !strcmp (method, match);
}
static void
static gboolean
addrconf6_setup (NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
NMActRequest *req;
NMConnection *connection;
const char *ip_iface;
NMSettingIP6Config *s_ip6;
priv->ip6_waiting_for_config = FALSE;
priv->ip6_dhcp_opt = IP6_DHCP_OPT_NONE;
req = nm_device_get_act_request (self);
g_assert (req);
connection = nm_act_request_get_connection (req);
g_assert (connection);
if (!ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_AUTO))
return;
if (!priv->ip6_manager) {
priv->ip6_manager = nm_ip6_manager_get ();
priv->ip6_addrconf_sigid = g_signal_connect (priv->ip6_manager,
@ -673,9 +787,14 @@ addrconf6_setup (NMDevice *self)
self);
}
ip_iface = nm_device_get_ip_iface (self);
s_ip6 = (NMSettingIP6Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG);
nm_ip6_manager_prepare_interface (priv->ip6_manager, ip_iface, s_ip6);
nm_ip6_manager_prepare_interface (priv->ip6_manager,
nm_device_get_ip_ifindex (self),
s_ip6,
priv->ip6_accept_ra_path);
priv->ip6_waiting_for_config = TRUE;
return TRUE;
}
static void
@ -697,6 +816,7 @@ addrconf6_cleanup (NMDevice *self)
priv->ip6_config_changed_sigid = 0;
}
nm_ip6_manager_cancel_addrconf (priv->ip6_manager, nm_device_get_ip_ifindex (self));
g_object_unref (priv->ip6_manager);
priv->ip6_manager = NULL;
}
@ -704,7 +824,6 @@ addrconf6_cleanup (NMDevice *self)
static NMActStageReturn
real_act_stage1_prepare (NMDevice *self, NMDeviceStateReason *reason)
{
addrconf6_setup (self);
return NM_ACT_STAGE_RETURN_SUCCESS;
}
@ -1237,6 +1356,14 @@ dhcp_state_changed (NMDHCPClient *client,
ipv6 = nm_dhcp_client_get_ipv6 (client);
dev_state = nm_device_get_state (device);
if (ipv6) {
nm_log_dbg (LOGD_DHCP6, "(%s): new DHCPv6 client state %d",
nm_device_get_iface (device), dev_state);
} else {
nm_log_dbg (LOGD_DHCP4, "(%s): new DHCPv4 client state %d",
nm_device_get_iface (device), dev_state);
}
switch (state) {
case DHC_BOUND4: /* lease obtained */
case DHC_BOUND6:
@ -1264,20 +1391,46 @@ dhcp_state_changed (NMDHCPClient *client,
nm_device_activate_schedule_stage4_ip4_config_timeout (device);
}
break;
case DHC_END: /* dhclient exited normally */
/* In IPv6 info-only mode, the client doesn't handle leases so it
* may exit right after getting a response from the server. That's
* normal. In that case we just ignore the exit.
*/
if (ipv6 && (priv->dhcp6_mode == IP6_DHCP_OPT_OTHERCONF))
break;
/* Otherwise, fall through */
case DHC_FAIL: /* all attempts to contact server timed out, sleeping */
case DHC_ABEND: /* dhclient exited abnormally */
case DHC_END: /* dhclient exited normally */
if (ipv6)
nm_dhcp6_config_reset (priv->dhcp6_config);
else
nm_dhcp4_config_reset (priv->dhcp4_config);
/* dhclient quit and can't get/renew a lease; so kill the connection */
if (nm_device_get_state (device) == NM_DEVICE_STATE_IP_CONFIG)
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_DHCP_FAILED);
else if (nm_device_get_state (device) == NM_DEVICE_STATE_ACTIVATED)
if (nm_device_get_state (device) == NM_DEVICE_STATE_IP_CONFIG) {
if (ipv6)
nm_device_activate_schedule_stage4_ip6_config_timeout (device);
else
nm_device_activate_schedule_stage4_ip4_config_timeout (device);
} else if (nm_device_get_state (device) == NM_DEVICE_STATE_ACTIVATED)
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED);
break;
case DHC_STOP:
case DHC_STOP6:
case DHC_EXPIRE:
case DHC_EXPIRE6:
if (dev_state == NM_DEVICE_STATE_ACTIVATED) {
if (ipv6)
nm_dhcp6_config_reset (priv->dhcp6_config);
else
nm_dhcp4_config_reset (priv->dhcp4_config);
/* dhclient quit and can't get/renew a lease; so kill the connection */
nm_device_state_changed (device,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED);
}
break;
default:
break;
}
@ -1304,6 +1457,7 @@ dhcp_timeout (NMDHCPClient *client, gpointer user_data)
static NMActStageReturn
real_act_stage3_ip4_config_start (NMDevice *self, NMDeviceStateReason *reason)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
NMConnection *connection;
NMSettingConnection *s_con;
NMSettingIP4Config *s_ip4;
@ -1333,7 +1487,6 @@ real_act_stage3_ip4_config_start (NMDevice *self, NMDeviceStateReason *reason)
method = nm_setting_ip4_config_get_method (s_ip4);
if (!s_ip4 || !method || !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) {
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
guint8 *anycast = NULL;
/* Begin a DHCP transaction on the interface */
@ -1389,6 +1542,10 @@ real_act_stage3_ip4_config_start (NMDevice *self, NMDeviceStateReason *reason)
*reason = NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED;
ret = NM_ACT_STAGE_RETURN_FAILURE;
}
} else if (s_ip4 && !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) {
/* Nothing to do... */
priv->ip4_ready = TRUE;
ret = NM_ACT_STAGE_RETURN_STOP;
}
return ret;
@ -1466,7 +1623,7 @@ real_act_stage3_ip6_config_start (NMDevice *self, NMDeviceStateReason *reason)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
const char *ip_iface;
NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
NMActRequest *req;
NMConnection *connection;
@ -1479,13 +1636,38 @@ real_act_stage3_ip6_config_start (NMDevice *self, NMDeviceStateReason *reason)
ip_iface = nm_device_get_ip_iface (self);
if (ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) {
priv->ip6_waiting_for_config = TRUE;
nm_ip6_manager_begin_addrconf (priv->ip6_manager, ip_iface);
ret = NM_ACT_STAGE_RETURN_POSTPONE;
} else if (ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_DHCP))
ret = dhcp6_start (self, connection, IP6_DHCP_OPT_MANAGED, reason);
update_accept_ra_save (self);
priv->dhcp6_mode = IP6_DHCP_OPT_NONE;
if ( ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_AUTO)
|| ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)) {
if (!addrconf6_setup (self)) {
*reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE;
goto out;
}
nm_ip6_manager_begin_addrconf (priv->ip6_manager, nm_device_get_ip_ifindex (self));
ret = NM_ACT_STAGE_RETURN_POSTPONE;
} else if (ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) {
/* Router advertisements shouldn't be used in pure DHCP mode */
if (priv->ip6_accept_ra_path)
nm_utils_do_sysctl (priv->ip6_accept_ra_path, "0\n");
priv->dhcp6_mode = IP6_DHCP_OPT_MANAGED;
ret = dhcp6_start (self, connection, priv->dhcp6_mode, reason);
} else if (ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) {
priv->ip6_ready = TRUE;
ret = NM_ACT_STAGE_RETURN_STOP;
} else if (ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
/* Router advertisements shouldn't be used in manual mode */
if (priv->ip6_accept_ra_path)
nm_utils_do_sysctl (priv->ip6_accept_ra_path, "0\n");
ret = NM_ACT_STAGE_RETURN_SUCCESS;
}
/* Other methods (shared) aren't implemented yet */
out:
return ret;
}
@ -1517,6 +1699,8 @@ nm_device_activate_stage3_ip_config_start (gpointer user_data)
else if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
goto out;
} else if (ret == NM_ACT_STAGE_RETURN_STOP) {
/* Nothing to do */
} else
g_assert (ret == NM_ACT_STAGE_RETURN_POSTPONE);
@ -1526,6 +1710,8 @@ nm_device_activate_stage3_ip_config_start (gpointer user_data)
else if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
goto out;
} else if (ret == NM_ACT_STAGE_RETURN_STOP) {
/* Nothing to do */
} else
g_assert (ret == NM_ACT_STAGE_RETURN_POSTPONE);
@ -1674,7 +1860,8 @@ real_act_stage4_get_ip4_config (NMDevice *self,
*config = nm_device_new_ip4_shared_config (self, reason);
if (*config)
priv->dnsmasq_manager = nm_dnsmasq_manager_new (ip_iface);
}
} else if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED))
ret = NM_ACT_STAGE_RETURN_SUCCESS;
}
if (!*config) {
@ -1712,8 +1899,7 @@ nm_device_activate_stage4_ip4_config_get (gpointer user_data)
ret = NM_DEVICE_GET_CLASS (self)->act_stage4_get_ip4_config (self, &ip4_config, &reason);
if (ret == NM_ACT_STAGE_RETURN_POSTPONE)
goto out;
else if (!ip4_config || (ret == NM_ACT_STAGE_RETURN_FAILURE))
{
else if (!ip4_config || (ret == NM_ACT_STAGE_RETURN_FAILURE)) {
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
goto out;
}
@ -1767,9 +1953,12 @@ real_act_stage4_ip4_config_timeout (NMDevice *self,
/* Notify of invalid DHCP4 config object */
g_object_notify (G_OBJECT (self), NM_DEVICE_INTERFACE_DHCP4_CONFIG);
/* DHCP failed; connection must fail */
*reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE;
return NM_ACT_STAGE_RETURN_FAILURE;
if (nm_device_ip_config_should_fail (self, FALSE)) {
*reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE;
return NM_ACT_STAGE_RETURN_FAILURE;
}
return NM_ACT_STAGE_RETURN_SUCCESS;
}
@ -1797,17 +1986,18 @@ nm_device_activate_stage4_ip4_config_timeout (gpointer user_data)
iface);
ret = NM_DEVICE_GET_CLASS (self)->act_stage4_ip4_config_timeout (self, &ip4_config, &reason);
if (ret == NM_ACT_STAGE_RETURN_POSTPONE) {
if (ret == NM_ACT_STAGE_RETURN_POSTPONE)
goto out;
} else if (!ip4_config || (ret == NM_ACT_STAGE_RETURN_FAILURE)) {
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_assert (ip4_config);
g_object_set_data (G_OBJECT (nm_device_get_act_request (self)),
NM_ACT_REQUEST_IP4_CONFIG, ip4_config);
if (ip4_config) {
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, AF_INET);
@ -1842,13 +2032,48 @@ nm_device_activate_schedule_stage4_ip4_config_timeout (NMDevice *self)
nm_device_get_iface (self));
}
static void
merge_dhcp_config_to_master (NMIP6Config *dst, NMIP6Config *src)
{
guint32 i;
g_return_if_fail (src != NULL);
g_return_if_fail (dst != NULL);
/* addresses */
for (i = 0; i < nm_ip6_config_get_num_addresses (src); i++)
nm_ip6_config_add_address (dst, nm_ip6_config_get_address (src, i));
/* ptp address; only replace if src doesn't have one */
if (!nm_ip6_config_get_ptp_address (dst))
nm_ip6_config_set_ptp_address (dst, nm_ip6_config_get_ptp_address (src));
/* nameservers */
for (i = 0; i < nm_ip6_config_get_num_nameservers (src); i++)
nm_ip6_config_add_nameserver (dst, nm_ip6_config_get_nameserver (src, i));
/* routes */
for (i = 0; i < nm_ip6_config_get_num_routes (src); i++)
nm_ip6_config_add_route (dst, nm_ip6_config_get_route (src, i));
/* domains */
for (i = 0; i < nm_ip6_config_get_num_domains (src); i++)
nm_ip6_config_add_domain (dst, nm_ip6_config_get_domain (src, i));
/* dns searches */
for (i = 0; i < nm_ip6_config_get_num_searches (src); i++)
nm_ip6_config_add_search (dst, nm_ip6_config_get_search (src, i));
if (!nm_ip6_config_get_mss (dst))
nm_ip6_config_set_mss (dst, nm_ip6_config_get_mss (src));
}
static NMActStageReturn
real_act_stage4_get_ip6_config (NMDevice *self,
NMIP6Config **config,
NMDeviceStateReason *reason)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
NMConnection *connection;
NMSettingIP6Config *s_ip6;
const char *ip_iface;
@ -1863,15 +2088,17 @@ real_act_stage4_get_ip6_config (NMDevice *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 (ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) {
*config = nm_ip6_manager_get_ip6_config (priv->ip6_manager, ip_iface);
if (*config) {
/* Merge user-defined overrides into the IP6Config to be applied */
nm_utils_merge_ip6_config (*config, s_ip6);
ret = NM_ACT_STAGE_RETURN_SUCCESS;
} else {
if ( ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_AUTO)
|| ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)) {
*config = nm_ip6_manager_get_ip6_config (priv->ip6_manager,
nm_device_get_ip_ifindex (self));
if (!*config) {
*reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE;
goto out;
}
} else if (ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
*config = nm_ip6_config_new ();
if (!*config) {
*reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE;
goto out;
}
@ -1880,29 +2107,49 @@ real_act_stage4_get_ip6_config (NMDevice *self,
/* Autoconf might have triggered DHCPv6 too */
if (priv->dhcp6_client) {
*config = nm_dhcp_client_get_ip6_config (priv->dhcp6_client, FALSE);
if (*config) {
/* Merge user-defined overrides into the IP4Config to be applied */
nm_utils_merge_ip6_config (*config, s_ip6);
NMIP6Config *dhcp;
nm_dhcp6_config_reset (priv->dhcp6_config);
nm_dhcp_client_foreach_option (priv->dhcp6_client,
dhcp6_add_option_cb,
priv->dhcp6_config);
/* Notify of new DHCP4 config */
g_object_notify (G_OBJECT (self), NM_DEVICE_INTERFACE_DHCP6_CONFIG);
ret = NM_ACT_STAGE_RETURN_SUCCESS;
} else {
dhcp = nm_dhcp_client_get_ip6_config (priv->dhcp6_client, FALSE);
if (!dhcp) {
*reason = NM_DEVICE_STATE_REASON_DHCP_ERROR;
goto out;
}
} else {
*config = NULL;
ret = NM_ACT_STAGE_RETURN_SUCCESS;
/* For "managed" and DHCP-only setups, we use only the DHCP-supplied
* IPv6 config. But when autoconf is enabled, we have to merge the
* autoconf config and the DHCP-supplied config, then merge the
* user's overrides from the connection to get the final configuration
* that gets applied to the device.
*/
if (*config) {
/* Merge autoconf and DHCP configs */
merge_dhcp_config_to_master (*config, dhcp);
g_object_unref (dhcp);
dhcp = NULL;
} else {
*config = dhcp;
}
/* Copy the new DHCPv6 configuration into the DHCP config object that's
* exported over D-Bus to clients.
*/
nm_dhcp6_config_reset (priv->dhcp6_config);
nm_dhcp_client_foreach_option (priv->dhcp6_client,
dhcp6_add_option_cb,
priv->dhcp6_config);
/* Notify of new DHCP6 config */
g_object_notify (G_OBJECT (self), NM_DEVICE_INTERFACE_DHCP6_CONFIG);
}
/* Merge user-defined overrides into the IP6Config to be applied */
if (*config) {
s_ip6 = (NMSettingIP6Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG);
nm_utils_merge_ip6_config (*config, s_ip6);
}
out:
return ret;
return *config ? NM_ACT_STAGE_RETURN_SUCCESS : NM_ACT_STAGE_RETURN_FAILURE;
}
/*
@ -1983,11 +2230,15 @@ real_act_stage4_ip6_config_timeout (NMDevice *self,
g_return_val_if_fail (config != NULL, NM_ACT_STAGE_RETURN_FAILURE);
g_return_val_if_fail (*config == NULL, NM_ACT_STAGE_RETURN_FAILURE);
/* Notify of invalid DHCP6 config object */
/* Notify of invalid DHCP4 config object */
g_object_notify (G_OBJECT (self), NM_DEVICE_INTERFACE_DHCP6_CONFIG);
*reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE;
return NM_ACT_STAGE_RETURN_FAILURE;
if (nm_device_ip_config_should_fail (self, TRUE)) {
*reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE;
return NM_ACT_STAGE_RETURN_FAILURE;
}
return NM_ACT_STAGE_RETURN_SUCCESS;
}
@ -2015,17 +2266,18 @@ nm_device_activate_stage4_ip6_config_timeout (gpointer user_data)
iface);
ret = NM_DEVICE_GET_CLASS (self)->act_stage4_ip6_config_timeout (self, &ip6_config, &reason);
if (ret == NM_ACT_STAGE_RETURN_POSTPONE) {
if (ret == NM_ACT_STAGE_RETURN_POSTPONE)
goto out;
} else if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
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);
if (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);
@ -2230,6 +2482,16 @@ nm_device_activate_stage5_ip_config_commit (gpointer user_data)
assumed = nm_act_request_get_assumed (priv->act_request);
if (!ip6_config && !ip4_config) {
nm_log_info (LOGD_DEVICE,
"Activation (%s) Stage 5 of 5 (IP Configure Commit) failed (no IP configuration found)",
iface);
nm_device_state_changed (self,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
goto out;
}
if (ip4_config && !nm_device_set_ip4_config (self, ip4_config, assumed, &reason)) {
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
goto out;
@ -2239,6 +2501,8 @@ nm_device_activate_stage5_ip_config_commit (gpointer user_data)
nm_log_info (LOGD_DEVICE | LOGD_IP6,
"Activation (%s) Stage 5 of 5 (IP Configure Commit) IPv6 failed",
iface);
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
goto out;
}
connection = nm_act_request_get_connection (nm_device_get_act_request (self));
@ -2248,7 +2512,7 @@ nm_device_activate_stage5_ip_config_commit (gpointer user_data)
if (s_ip4)
method = nm_setting_ip4_config_get_method (s_ip4);
if (s_ip4 && !strcmp (method, "shared")) {
if (s_ip4 && !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) {
if (!start_sharing (self)) {
nm_log_warn (LOGD_SHARING, "Activation (%s) Stage 5 of 5 (IP Configure Commit) start sharing failed.", iface);
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SHARED_START_FAILED);
@ -2394,6 +2658,8 @@ dhcp6_cleanup (NMDevice *self, gboolean stop)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
priv->dhcp6_mode = IP6_DHCP_OPT_NONE;
if (priv->dhcp6_config) {
g_object_notify (G_OBJECT (self), NM_DEVICE_INTERFACE_DHCP6_CONFIG);
g_object_unref (priv->dhcp6_config);
@ -2467,6 +2733,10 @@ nm_device_deactivate_quickly (NMDevice *self)
dnsmasq_cleanup (self);
aipd_cleanup (self);
/* Turn off router advertisements until they are needed */
if (priv->ip6_accept_ra_path)
nm_utils_do_sysctl (priv->ip6_accept_ra_path, "0\n");
/* Call device type-specific deactivation */
if (NM_DEVICE_GET_CLASS (self)->deactivate_quickly)
NM_DEVICE_GET_CLASS (self)->deactivate_quickly (self);
@ -2497,7 +2767,7 @@ nm_device_deactivate (NMDeviceInterface *device, NMDeviceStateReason reason)
nm_device_deactivate_quickly (self);
/* Take out any entries in the routing table and any IP address the device had. */
nm_system_device_flush_routes (self);
nm_system_device_flush_routes (self, nm_device_get_ip6_config (self) ? AF_UNSPEC : AF_INET);
nm_system_device_flush_addresses (self);
nm_device_update_ip4_address (self);
@ -3038,6 +3308,13 @@ dispose (GObject *object)
addrconf6_cleanup (self);
dnsmasq_cleanup (self);
/* reset the saved RA value */
if (priv->ip6_accept_ra_path) {
nm_utils_do_sysctl (priv->ip6_accept_ra_path,
priv->ip6_accept_ra_save ? "1\n" : "0\n");
}
g_free (priv->ip6_accept_ra_path);
/* Take the device itself down and clear its IPv4 configuration */
if (priv->managed && take_down) {
NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE;
@ -3088,7 +3365,14 @@ set_property (GObject *object, guint prop_id,
break;
case NM_DEVICE_INTERFACE_PROP_IFACE:
g_free (priv->iface);
priv->ifindex = 0;
priv->iface = g_value_dup_string (value);
if (priv->iface) {
priv->ifindex = nm_netlink_iface_to_index (priv->iface);
if (priv->ifindex < 0) {
nm_log_warn (LOGD_HW, "(%s): failed to look up interface index", priv->iface);
}
}
break;
case NM_DEVICE_INTERFACE_PROP_DRIVER:
priv->driver = g_strdup (g_value_get_string (value));
@ -3136,6 +3420,9 @@ get_property (GObject *object, guint prop_id,
case NM_DEVICE_INTERFACE_PROP_IFACE:
g_value_set_string (value, priv->iface);
break;
case NM_DEVICE_INTERFACE_PROP_IFINDEX:
g_value_set_int (value, priv->ifindex);
break;
case NM_DEVICE_INTERFACE_PROP_DRIVER:
g_value_set_string (value, priv->driver);
break;
@ -3234,6 +3521,10 @@ nm_device_class_init (NMDeviceClass *klass)
NM_DEVICE_INTERFACE_PROP_IFACE,
NM_DEVICE_INTERFACE_IFACE);
g_object_class_override_property (object_class,
NM_DEVICE_INTERFACE_PROP_IFINDEX,
NM_DEVICE_INTERFACE_IFINDEX);
g_object_class_override_property (object_class,
NM_DEVICE_INTERFACE_PROP_DRIVER,
NM_DEVICE_INTERFACE_DRIVER);

View file

@ -38,7 +38,8 @@ typedef enum NMActStageReturn
{
NM_ACT_STAGE_RETURN_FAILURE = 0,
NM_ACT_STAGE_RETURN_SUCCESS,
NM_ACT_STAGE_RETURN_POSTPONE
NM_ACT_STAGE_RETURN_POSTPONE,
NM_ACT_STAGE_RETURN_STOP /* This activation chain is done */
} NMActStageReturn;
@ -128,7 +129,9 @@ void nm_device_set_path (NMDevice *dev, const char *path);
const char * nm_device_get_udi (NMDevice *dev);
const char * nm_device_get_iface (NMDevice *dev);
int nm_device_get_ifindex (NMDevice *dev);
const char * nm_device_get_ip_iface (NMDevice *dev);
int nm_device_get_ip_ifindex(NMDevice *dev);
const char * nm_device_get_driver (NMDevice *dev);
const char * nm_device_get_type_desc (NMDevice *dev);

View file

@ -15,7 +15,7 @@
* 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) 2005 - 2010 Red Hat, Inc.
* Copyright (C) 2006 - 2008 Novell, Inc.
*/
@ -183,7 +183,7 @@ const struct in6_addr *nm_ip6_config_get_ptp_address (NMIP6Config *config)
return &NM_IP6_CONFIG_GET_PRIVATE (config)->ptp_address;
}
void nm_ip6_config_set_ptp_address (NMIP6Config *config, struct in6_addr *ptp_addr)
void nm_ip6_config_set_ptp_address (NMIP6Config *config, const struct in6_addr *ptp_addr)
{
g_return_if_fail (NM_IS_IP6_CONFIG (config));
@ -197,15 +197,14 @@ void nm_ip6_config_add_nameserver (NMIP6Config *config, const struct in6_addr *n
int i;
g_return_if_fail (NM_IS_IP6_CONFIG (config));
g_return_if_fail (nameserver > 0);
g_return_if_fail (nameserver != NULL);
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);
}
for (i = 0; i < priv->nameservers->len; i++)
g_return_if_fail (IN6_ARE_ADDR_EQUAL (nameserver, &nameservers[i]) == FALSE);
g_array_append_val (priv->nameservers, *nameserver);
}
@ -572,7 +571,7 @@ addr_array_compare (GArray *a, GArray *b)
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) {
if (IN6_ARE_ADDR_EQUAL (&addrs_a[i], &addrs_b[j])) {
found = TRUE;
break;
}
@ -692,34 +691,33 @@ nm_ip6_config_class_init (NMIP6ConfigClass *config_class)
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));
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_IP6_ADDRESS,
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_ARRAY_OF_ARRAY_OF_UCHAR,
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_IP6_ROUTE,
G_PARAM_READABLE));
dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (config_class),
&dbus_glib_nm_ip6_config_object_info);

View file

@ -60,7 +60,7 @@ 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_set_ptp_address (NMIP6Config *config, const 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);

View file

@ -1523,7 +1523,8 @@ add_device (NMManager *self, NMDevice *device)
driver = nm_device_get_driver (device);
if (!driver)
driver = "unknown";
nm_log_info (LOGD_HW, "(%s): new %s device (driver: '%s')", iface, type_desc, driver);
nm_log_info (LOGD_HW, "(%s): new %s device (driver: '%s' ifindex: %d)",
iface, type_desc, driver, nm_device_get_ifindex (device));
path = g_strdup_printf ("/org/freedesktop/NetworkManager/Devices/%d", devcount++);
nm_device_set_path (device, path);
@ -1794,20 +1795,11 @@ find_device_by_ifindex (NMManager *self, guint32 ifindex)
GSList *iter;
for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
NMDevice *device = NM_DEVICE (iter->data);
gint candidate_idx = 0;
NMDevice *candidate = NM_DEVICE (iter->data);
if (NM_IS_DEVICE_ETHERNET (device))
candidate_idx = nm_device_ethernet_get_ifindex (NM_DEVICE_ETHERNET (device));
else if (NM_IS_DEVICE_WIFI (device))
candidate_idx = nm_device_wifi_get_ifindex (NM_DEVICE_WIFI (device));
else if (NM_IS_DEVICE_OLPC_MESH (device))
candidate_idx = nm_device_olpc_mesh_get_ifindex (NM_DEVICE_OLPC_MESH (device));
if (candidate_idx == ifindex)
return device;
if (ifindex == nm_device_get_ifindex (candidate))
return candidate;
}
return NULL;
}
@ -2782,7 +2774,12 @@ impl_manager_set_logging (NMManager *manager,
GError **error)
{
if (nm_logging_setup (level, domains, error)) {
nm_log_info (LOGD_CORE, "logging: level '%s' domains '%s'", level, domains);
char *new_domains = nm_logging_domains_to_string ();
nm_log_info (LOGD_CORE, "logging: level '%s' domains '%s'",
nm_logging_level_to_string (),
new_domains);
g_free (new_domains);
return TRUE;
}
return FALSE;

File diff suppressed because it is too large Load diff

View file

@ -15,7 +15,7 @@
* 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) 2005 - 2010 Red Hat, Inc.
* Copyright (C) 2005 - 2008 Novell, Inc.
* Copyright (C) 2005 Ray Strode
*/
@ -25,16 +25,15 @@
#include <glib.h>
#include <glib-object.h>
#include <netlink/netlink.h>
#include <netlink/route/link.h>
G_BEGIN_DECLS
#define NM_TYPE_NETLINK_MONITOR (nm_netlink_monitor_get_type ())
#define NM_NETLINK_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_NETLINK_MONITOR, NMNetlinkMonitor))
#define NM_TYPE_NETLINK_MONITOR (nm_netlink_monitor_get_type ())
#define NM_NETLINK_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_NETLINK_MONITOR, NMNetlinkMonitor))
#define NM_NETLINK_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_NETLINK_MONITOR, NMNetlinkMonitorClass))
#define NM_IS_NETLINK_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_NETLINK_MONITOR))
#define NM_IS_NETLINK_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_NETLINK_MONITOR))
#define NM_IS_NETLINK_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_NETLINK_MONITOR))
#define NM_NETLINK_MONITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_NETLINK_MONITOR, NMNetlinkMonitorClass))
#define NM_NETLINK_MONITOR_ERROR (nm_netlink_monitor_error_quark ())
typedef enum {
NM_NETLINK_MONITOR_ERROR_GENERIC = 0,
@ -56,29 +55,45 @@ typedef struct {
GObjectClass parent_class;
/* Signals */
void (*carrier_on) (NMNetlinkMonitor *monitor, int index);
void (*carrier_off) (NMNetlinkMonitor *monitor, int index);
void (*error) (NMNetlinkMonitor *monitor, GError *error);
void (*notification) (NMNetlinkMonitor *monitor, struct nl_msg *msg);
void (*carrier_on) (NMNetlinkMonitor *monitor, int index);
void (*carrier_off) (NMNetlinkMonitor *monitor, int index);
void (*error) (NMNetlinkMonitor *monitor, GError *error);
} NMNetlinkMonitorClass;
GType nm_netlink_monitor_get_type (void) G_GNUC_CONST;
GQuark nm_netlink_monitor_error_quark (void) G_GNUC_CONST;
#define NM_NETLINK_MONITOR_ERROR (nm_netlink_monitor_error_quark ())
GType nm_netlink_monitor_get_type (void) G_GNUC_CONST;
GQuark nm_netlink_monitor_error_quark (void) G_GNUC_CONST;
NMNetlinkMonitor *nm_netlink_monitor_get (void);
gboolean nm_netlink_monitor_open_connection (NMNetlinkMonitor *monitor,
GError **error);
gboolean nm_netlink_monitor_open_connection (NMNetlinkMonitor *monitor,
GError **error);
void nm_netlink_monitor_close_connection (NMNetlinkMonitor *monitor);
void nm_netlink_monitor_attach (NMNetlinkMonitor *monitor);
void nm_netlink_monitor_detach (NMNetlinkMonitor *monitor);
void nm_netlink_monitor_attach (NMNetlinkMonitor *monitor);
void nm_netlink_monitor_detach (NMNetlinkMonitor *monitor);
gboolean nm_netlink_monitor_subscribe (NMNetlinkMonitor *monitor,
int group,
GError **error);
void nm_netlink_monitor_unsubscribe (NMNetlinkMonitor *monitor,
int group);
gboolean nm_netlink_monitor_request_ip6_info (NMNetlinkMonitor *monitor,
GError **error);
gboolean nm_netlink_monitor_request_status (NMNetlinkMonitor *monitor,
GError **error);
GError **error);
gboolean nm_netlink_monitor_get_flags_sync (NMNetlinkMonitor *monitor,
guint32 ifindex,
guint32 *ifflags,
GError **error);
G_END_DECLS
/* Generic utility functions */
int nm_netlink_iface_to_index (const char *iface);
char * nm_netlink_index_to_iface (int idx);
struct rtnl_link *nm_netlink_index_to_rtnl_link (int idx);
struct nl_handle *nm_netlink_get_default_handle (void);
#endif /* NM_NETLINK_MONITOR_H */

View file

@ -1,149 +0,0 @@
/* -*- 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) 2007 - 2008 Red Hat, Inc.
*/
#include "config.h"
#include "nm-netlink.h"
#include "nm-logging.h"
#include <glib.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>
#include <netlink/object-api.h>
static struct nl_cache * link_cache = NULL;
static struct nl_handle * def_nl_handle = NULL;
static struct nl_cache *
get_link_cache (void)
{
struct nl_handle * nlh;
nlh = nm_netlink_get_default_handle ();
if (G_UNLIKELY (!nlh)) {
nm_log_err (LOGD_HW, "couldn't allocate netlink handle.");
return NULL;
}
if (G_UNLIKELY (!link_cache))
link_cache = rtnl_link_alloc_cache (nlh);
if (G_UNLIKELY (!link_cache)) {
nm_log_err (LOGD_HW, "couldn't allocate netlink link cache: %s", nl_geterror ());
return NULL;
}
nl_cache_update (nlh, link_cache);
return link_cache;
}
struct nl_handle *
nm_netlink_get_default_handle (void)
{
struct nl_cb *cb;
#ifdef LIBNL_NEEDS_ADDR_CACHING_WORKAROUND
struct nl_cache *addr_cache;
#endif
if (def_nl_handle)
return def_nl_handle;
cb = nl_cb_alloc(NL_CB_VERBOSE);
def_nl_handle = nl_handle_alloc_cb (cb);
if (!def_nl_handle) {
nm_log_err (LOGD_HW, "couldn't allocate netlink handle.");
return NULL;
}
if (nl_connect (def_nl_handle, NETLINK_ROUTE) < 0) {
nm_log_err (LOGD_HW, "couldn't connect to netlink: %s", nl_geterror ());
return NULL;
}
#ifdef LIBNL_NEEDS_ADDR_CACHING_WORKAROUND
/* Work around apparent libnl bug; rtnl_addr requires that all
* addresses have the "peer" attribute set in order to be compared
* for equality, but this attribute is not normally set. As a
* result, most addresses will not compare as equal even to
* themselves, busting caching.
*/
addr_cache = rtnl_addr_alloc_cache (def_nl_handle);
nl_cache_get_ops (addr_cache)->co_obj_ops->oo_id_attrs &= ~0x80;
nl_cache_free (addr_cache);
#endif
return def_nl_handle;
}
int
nm_netlink_iface_to_index (const char *iface)
{
struct nl_cache * cache;
g_return_val_if_fail (iface != NULL, -1);
cache = get_link_cache ();
if (!cache)
return RTNL_LINK_NOT_FOUND;
return rtnl_link_name2i (cache, iface);
}
#define MAX_IFACE_LEN 33
char *
nm_netlink_index_to_iface (int idx)
{
struct nl_cache * cache;
char * buf = NULL;
cache = get_link_cache ();
if (!cache)
return NULL;
buf = g_malloc0 (MAX_IFACE_LEN);
if (buf == NULL) {
nm_log_warn (LOGD_HW, "Not enough memory to allocate interface name buffer.");
return NULL;
}
if (rtnl_link_i2name (cache, idx, buf, MAX_IFACE_LEN - 1) == NULL) {
g_free (buf);
buf = NULL;
}
return buf;
}
struct rtnl_link *
nm_netlink_index_to_rtnl_link (int idx)
{
struct nl_cache *cache;
cache = get_link_cache ();
if (!cache)
return NULL;
return rtnl_link_get (cache, idx);
}

View file

@ -1,36 +0,0 @@
/* -*- 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) 2007 - 2008 Red Hat, Inc.
*/
#ifndef NM_NETLINK_H
#define NM_NETLINK_H
#include <asm/types.h>
#include <netlink/route/addr.h>
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/route/link.h>
int nm_netlink_iface_to_index (const char *iface);
char * nm_netlink_index_to_iface (int idx);
struct rtnl_link * nm_netlink_index_to_rtnl_link (int idx);
struct nl_handle * nm_netlink_get_default_handle (void);
#endif /* NM_NETLINK_H */

205
src/nm-policy-hostname.c Normal file
View file

@ -0,0 +1,205 @@
/* -*- 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) 2004 - 2010 Red Hat, Inc.
* Copyright (C) 2007 - 2008 Novell, Inc.
*/
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <netdb.h>
#include <ctype.h>
#include <glib.h>
#include "nm-logging.h"
#include "nm-policy-hostname.h"
#include "nm-policy-hosts.h"
/************************************************************************/
struct HostnameThread {
GThread *thread;
GMutex *lock;
gboolean dead;
int ret;
guint32 ip4_addr;
char hostname[NI_MAXHOST + 1];
HostnameThreadCallback callback;
gpointer user_data;
};
static gboolean
hostname_thread_run_cb (gpointer user_data)
{
HostnameThread *ht = (HostnameThread *) user_data;
const char *hostname = NULL;
if (strlen (ht->hostname))
hostname = ht->hostname;
(*ht->callback) (ht, ht->ret, hostname, ht->user_data);
return FALSE;
}
static gpointer
hostname_thread_worker (gpointer data)
{
HostnameThread *ht = (HostnameThread *) data;
struct sockaddr_in addr;
int i;
g_mutex_lock (ht->lock);
if (ht->dead) {
g_mutex_unlock (ht->lock);
return (gpointer) NULL;
}
g_mutex_unlock (ht->lock);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = ht->ip4_addr;
ht->ret = getnameinfo ((struct sockaddr *) &addr, sizeof (struct sockaddr_in),
ht->hostname, NI_MAXHOST, NULL, 0,
NI_NAMEREQD);
if (ht->ret == 0) {
for (i = 0; i < strlen (ht->hostname); i++)
ht->hostname[i] = tolower (ht->hostname[i]);
}
/* Don't track the idle handler ID because by the time the g_idle_add()
* returns the ID, the handler may already have run and freed the
* HostnameThread.
*/
g_idle_add (hostname_thread_run_cb, ht);
return (gpointer) TRUE;
}
void
hostname_thread_free (HostnameThread *ht)
{
g_return_if_fail (ht != NULL);
g_mutex_free (ht->lock);
memset (ht, 0, sizeof (HostnameThread));
g_free (ht);
}
HostnameThread *
hostname_thread_new (guint32 ip4_addr, HostnameThreadCallback callback, gpointer user_data)
{
HostnameThread *ht;
ht = g_malloc0 (sizeof (HostnameThread));
g_assert (ht);
ht->lock = g_mutex_new ();
ht->callback = callback;
ht->user_data = user_data;
ht->ip4_addr = ip4_addr;
ht->thread = g_thread_create (hostname_thread_worker, ht, FALSE, NULL);
if (!ht->thread) {
hostname_thread_free (ht);
ht = NULL;
}
return ht;
}
void
hostname_thread_kill (HostnameThread *ht)
{
g_return_if_fail (ht != NULL);
g_mutex_lock (ht->lock);
ht->dead = TRUE;
g_mutex_unlock (ht->lock);
}
gboolean
hostname_thread_is_dead (HostnameThread *ht)
{
g_return_val_if_fail (ht != NULL, TRUE);
return ht->dead;
}
/************************************************************************/
#define FALLBACK_HOSTNAME "localhost.localdomain"
gboolean
nm_policy_set_system_hostname (const char *new_hostname, const char *msg)
{
char old_hostname[HOST_NAME_MAX + 1];
int ret = 0;
const char *name;
gboolean set_hostname = TRUE, changed = FALSE;
if (new_hostname)
g_warn_if_fail (strlen (new_hostname));
name = (new_hostname && strlen (new_hostname)) ? new_hostname : FALLBACK_HOSTNAME;
old_hostname[HOST_NAME_MAX] = '\0';
errno = 0;
ret = gethostname (old_hostname, HOST_NAME_MAX);
if (ret != 0) {
nm_log_warn (LOGD_DNS, "couldn't get the system hostname: (%d) %s",
errno, strerror (errno));
} else {
/* Don't set the hostname if it isn't actually changing */
if ( (new_hostname && !strcmp (old_hostname, new_hostname))
|| (!new_hostname && !strcmp (old_hostname, FALLBACK_HOSTNAME)))
set_hostname = FALSE;
}
if (set_hostname) {
nm_log_info (LOGD_DNS, "Setting system hostname to '%s' (%s)", name, msg);
ret = sethostname (name, strlen (name));
if (ret != 0) {
nm_log_warn (LOGD_DNS, "couldn't set the system hostname to '%s': (%d) %s",
name, errno, strerror (errno));
return FALSE;
}
}
/* But even if the hostname isn't changing, always try updating /etc/hosts
* just in case the hostname changed while NM wasn't running; we need to
* make sure that /etc/hosts has valid mappings for '127.0.0.1' and the
* current system hostname. If those exist,
* nm_policy_hosts_update_etc_hosts() will just return and won't touch
* /etc/hosts at all.
*/
if (!nm_policy_hosts_update_etc_hosts (name, FALLBACK_HOSTNAME, &changed)) {
/* error updating /etc/hosts; fallback to localhost.localdomain */
nm_log_info (LOGD_DNS, "Setting system hostname to '" FALLBACK_HOSTNAME "' (error updating /etc/hosts)");
ret = sethostname (FALLBACK_HOSTNAME, strlen (FALLBACK_HOSTNAME));
if (ret != 0) {
nm_log_warn (LOGD_DNS, "couldn't set the fallback system hostname (%s): (%d) %s",
FALLBACK_HOSTNAME, errno, strerror (errno));
}
}
return changed;
}

47
src/nm-policy-hostname.h Normal file
View file

@ -0,0 +1,47 @@
/* -*- 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) 2004 - 2010 Red Hat, Inc.
* Copyright (C) 2007 - 2008 Novell, Inc.
*/
#ifndef NM_POLICY_HOSTNAME_H
#define NM_POLICY_HOSTNAME_H
#include <glib.h>
gboolean nm_policy_set_system_hostname (const char *new_hostname, const char *msg);
typedef struct HostnameThread HostnameThread;
typedef void (*HostnameThreadCallback) (HostnameThread *ht,
int error,
const char *hostname,
gpointer user_data);
HostnameThread * hostname_thread_new (guint32 ip4_addr,
HostnameThreadCallback callback,
gpointer user_data);
void hostname_thread_free (HostnameThread *ht);
gboolean hostname_thread_is_dead (HostnameThread *ht);
void hostname_thread_kill (HostnameThread *ht);
#endif /* NM_POLICY_HOSTNAME_H */

View file

@ -25,6 +25,7 @@
#include <ctype.h>
#include "nm-policy-hosts.h"
#include "nm-logging.h"
gboolean
nm_policy_hosts_find_token (const char *line, const char *token)
@ -171,3 +172,64 @@ nm_policy_get_etc_hosts (const char **lines,
return contents;
}
gboolean
nm_policy_hosts_update_etc_hosts (const char *hostname,
const char *fallback_hostname,
gboolean *out_changed)
{
char *contents = NULL;
char **lines = NULL;
GError *error = NULL;
GString *new_contents = NULL;
gsize contents_len = 0;
gboolean success = FALSE;
g_return_val_if_fail (hostname != NULL, FALSE);
g_return_val_if_fail (out_changed != NULL, FALSE);
if (!g_file_get_contents (SYSCONFDIR "/hosts", &contents, &contents_len, &error)) {
nm_log_warn (LOGD_DNS, "couldn't read " SYSCONFDIR "/hosts: (%d) %s",
error ? error->code : 0,
(error && error->message) ? error->message : "(unknown)");
g_clear_error (&error);
return FALSE;
}
/* Get the new /etc/hosts contents */
lines = g_strsplit_set (contents, "\n\r", 0);
new_contents = nm_policy_get_etc_hosts ((const char **) lines,
contents_len,
hostname,
fallback_hostname,
&error);
g_strfreev (lines);
g_free (contents);
if (new_contents) {
nm_log_info (LOGD_DNS, "Updating /etc/hosts with new system hostname");
g_clear_error (&error);
/* And actually update /etc/hosts */
if (!g_file_set_contents (SYSCONFDIR "/hosts", new_contents->str, -1, &error)) {
nm_log_warn (LOGD_DNS, "couldn't update " SYSCONFDIR "/hosts: (%d) %s",
error ? error->code : 0,
(error && error->message) ? error->message : "(unknown)");
g_clear_error (&error);
} else {
success = TRUE;
*out_changed = TRUE;
}
g_string_free (new_contents, TRUE);
} else if (!error) {
/* No change required */
success = TRUE;
} else {
nm_log_warn (LOGD_DNS, "couldn't read " SYSCONFDIR "/hosts: (%d) %s",
error->code, error->message ? error->message : "(unknown)");
g_clear_error (&error);
}
return success;
}

View file

@ -23,14 +23,18 @@
#include <glib.h>
gboolean nm_policy_hosts_update_etc_hosts (const char *hostname,
const char *fallback_hostname,
gboolean *out_changed);
/* Only for testcases; don't use outside of nm-policy-hosts.c */
gboolean nm_policy_hosts_find_token (const char *line, const char *token);
GString *nm_policy_get_etc_hosts (const char **lines,
gsize existing_len,
const char *hostname,
const char *fallback_hostname,
GError **error);
/* Only for testcases; don't use outside of nm-policy-hosts.c */
gboolean nm_policy_hosts_find_token (const char *line, const char *token);
#endif /* NM_POLICY_HOSTS_H */

View file

@ -42,24 +42,7 @@
#include "nm-named-manager.h"
#include "nm-vpn-manager.h"
#include "nm-policy-hosts.h"
typedef struct LookupThread LookupThread;
typedef void (*LookupCallback) (LookupThread *thread, gpointer user_data);
struct LookupThread {
GThread *thread;
GMutex *lock;
gboolean die;
int ret;
guint32 ip4_addr;
char hostname[NI_MAXHOST + 1];
LookupCallback callback;
gpointer user_data;
};
#include "nm-policy-hostname.h"
struct NMPolicy {
NMManager *manager;
@ -72,99 +55,14 @@ struct NMPolicy {
gulong vpn_activated_id;
gulong vpn_deactivated_id;
NMDevice *default_device;
NMDevice *default_device4;
NMDevice *default_device6;
LookupThread *lookup;
HostnameThread *lookup;
char *orig_hostname; /* hostname at NM start time */
};
static gboolean
lookup_thread_run_cb (gpointer user_data)
{
LookupThread *thread = (LookupThread *) user_data;
(*thread->callback) (thread, thread->user_data);
return FALSE;
}
static gpointer
lookup_thread_worker (gpointer data)
{
LookupThread *thread = (LookupThread *) data;
struct sockaddr_in addr;
g_mutex_lock (thread->lock);
if (thread->die) {
g_mutex_unlock (thread->lock);
return (gpointer) NULL;
}
g_mutex_unlock (thread->lock);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = thread->ip4_addr;
thread->ret = getnameinfo ((struct sockaddr *) &addr, sizeof (struct sockaddr_in),
thread->hostname, NI_MAXHOST, NULL, 0,
NI_NAMEREQD);
if (thread->ret == 0) {
int i;
for (i = 0; i < strlen (thread->hostname); i++)
thread->hostname[i] = tolower (thread->hostname[i]);
}
/* Don't track the idle handler ID because by the time the g_idle_add()
* returns the ID, the handler may already have run and freed the
* LookupThread.
*/
g_idle_add (lookup_thread_run_cb, thread);
return (gpointer) TRUE;
}
static void
lookup_thread_free (LookupThread *thread)
{
g_return_if_fail (thread != NULL);
g_mutex_free (thread->lock);
memset (thread, 0, sizeof (LookupThread));
g_free (thread);
}
static LookupThread *
lookup_thread_new (guint32 ip4_addr, LookupCallback callback, gpointer user_data)
{
LookupThread *thread;
thread = g_malloc0 (sizeof (LookupThread));
if (!thread)
return NULL;
thread->lock = g_mutex_new ();
thread->callback = callback;
thread->user_data = user_data;
thread->ip4_addr = ip4_addr;
thread->thread = g_thread_create (lookup_thread_worker, thread, FALSE, NULL);
if (!thread->thread) {
lookup_thread_free (thread);
return NULL;
}
return thread;
}
static void
lookup_thread_die (LookupThread *thread)
{
g_return_if_fail (thread != NULL);
g_mutex_lock (thread->lock);
thread->die = TRUE;
g_mutex_unlock (thread->lock);
}
#define INVALID_TAG "invalid"
static const char *
@ -181,7 +79,7 @@ get_connection_id (NMConnection *connection)
}
static NMDevice *
get_best_device (NMManager *manager, NMActRequest **out_req)
get_best_ip4_device (NMManager *manager, NMActRequest **out_req)
{
GSList *devices, *iter;
NMDevice *best = NULL;
@ -253,142 +151,107 @@ get_best_device (NMManager *manager, NMActRequest **out_req)
return best;
}
#define FALLBACK_HOSTNAME "localhost.localdomain"
static gboolean
update_etc_hosts (const char *hostname, gboolean *out_changed)
static NMDevice *
get_best_ip6_device (NMManager *manager, NMActRequest **out_req)
{
char *contents = NULL;
char **lines = NULL;
GError *error = NULL;
GString *new_contents = NULL;
gsize contents_len = 0;
gboolean success = FALSE;
GSList *devices, *iter;
NMDevice *best = NULL;
int best_prio = G_MAXINT;
g_return_val_if_fail (hostname != NULL, FALSE);
g_return_val_if_fail (out_changed != NULL, FALSE);
g_return_val_if_fail (manager != NULL, NULL);
g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
g_return_val_if_fail (out_req != NULL, NULL);
g_return_val_if_fail (*out_req == NULL, NULL);
if (!g_file_get_contents (SYSCONFDIR "/hosts", &contents, &contents_len, &error)) {
nm_log_warn (LOGD_DNS, "couldn't read " SYSCONFDIR "/hosts: (%d) %s",
error ? error->code : 0,
(error && error->message) ? error->message : "(unknown)");
g_clear_error (&error);
return FALSE;
}
devices = nm_manager_get_devices (manager);
for (iter = devices; iter; iter = g_slist_next (iter)) {
NMDevice *dev = NM_DEVICE (iter->data);
NMActRequest *req;
NMConnection *connection;
NMIP6Config *ip6_config;
NMSettingIP6Config *s_ip6;
int prio;
guint i;
gboolean can_default = FALSE;
const char *method = NULL;
/* Get the new /etc/hosts contents */
lines = g_strsplit_set (contents, "\n\r", 0);
new_contents = nm_policy_get_etc_hosts ((const char **) lines,
contents_len,
hostname,
FALLBACK_HOSTNAME,
&error);
g_strfreev (lines);
g_free (contents);
if (nm_device_get_state (dev) != NM_DEVICE_STATE_ACTIVATED)
continue;
if (new_contents) {
nm_log_info (LOGD_DNS, "Updating /etc/hosts with new system hostname");
ip6_config = nm_device_get_ip6_config (dev);
if (!ip6_config)
continue;
g_clear_error (&error);
/* And actually update /etc/hosts */
if (!g_file_set_contents (SYSCONFDIR "/hosts", new_contents->str, -1, &error)) {
nm_log_warn (LOGD_DNS, "couldn't update " SYSCONFDIR "/hosts: (%d) %s",
error ? error->code : 0,
(error && error->message) ? error->message : "(unknown)");
g_clear_error (&error);
} else {
success = TRUE;
*out_changed = TRUE;
req = nm_device_get_act_request (dev);
g_assert (req);
connection = nm_act_request_get_connection (req);
g_assert (connection);
/* Never set the default route through an IPv4LL-addressed device */
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_LINK_LOCAL))
continue;
/* Make sure at least one of this device's IP addresses has a gateway */
for (i = 0; i < nm_ip6_config_get_num_addresses (ip6_config); i++) {
NMIP6Address *addr;
addr = nm_ip6_config_get_address (ip6_config, i);
if (nm_ip6_address_get_gateway (addr)) {
can_default = TRUE;
break;
}
}
g_string_free (new_contents, TRUE);
} else if (!error) {
/* No change required */
success = TRUE;
} else {
nm_log_warn (LOGD_DNS, "couldn't read " SYSCONFDIR "/hosts: (%d) %s",
error->code, error->message ? error->message : "(unknown)");
g_clear_error (&error);
if (!can_default && !NM_IS_DEVICE_MODEM (dev))
continue;
/* 'never-default' devices can't ever be the default */
if (s_ip6 && nm_setting_ip6_config_get_never_default (s_ip6))
continue;
prio = nm_device_get_priority (dev);
if (prio > 0 && prio < best_prio) {
best = dev;
best_prio = prio;
*out_req = req;
}
}
return success;
return best;
}
static void
set_system_hostname (const char *new_hostname, const char *msg)
_set_hostname (const char *new_hostname, const char *msg)
{
char old_hostname[HOST_NAME_MAX + 1];
int ret = 0;
const char *name = new_hostname ? new_hostname : FALLBACK_HOSTNAME;
gboolean set_hostname = TRUE, changed = FALSE;
old_hostname[HOST_NAME_MAX] = '\0';
errno = 0;
ret = gethostname (old_hostname, HOST_NAME_MAX);
if (ret != 0) {
nm_log_warn (LOGD_DNS, "couldn't get the system hostname: (%d) %s",
errno, strerror (errno));
} else {
/* Don't set the hostname if it isn't actually changing */
if ( (new_hostname && !strcmp (old_hostname, new_hostname))
|| (!new_hostname && !strcmp (old_hostname, FALLBACK_HOSTNAME)))
set_hostname = FALSE;
}
if (set_hostname) {
nm_log_info (LOGD_DNS, "Setting system hostname to '%s' (%s)", name, msg);
ret = sethostname (name, strlen (name));
if (ret != 0) {
nm_log_warn (LOGD_DNS, "couldn't set the system hostname to '%s': (%d) %s",
name, errno, strerror (errno));
return;
}
}
/* But still always try updating /etc/hosts just in case the hostname
* changed while NM wasn't running; we need to make sure that /etc/hosts
* has valid mappings for '127.0.0.1' and the current system hostname. If
* those exist, update_etc_hosts() will just return and won't touch
* /etc/hosts at all.
*/
if (!update_etc_hosts (name, &changed)) {
/* error updating /etc/hosts; fallback to localhost.localdomain */
nm_log_info (LOGD_DNS, "Setting system hostname to '" FALLBACK_HOSTNAME "' (error updating /etc/hosts)");
ret = sethostname (FALLBACK_HOSTNAME, strlen (FALLBACK_HOSTNAME));
if (ret != 0) {
nm_log_warn (LOGD_DNS, "couldn't set the fallback system hostname (%s): (%d) %s",
FALLBACK_HOSTNAME, errno, strerror (errno));
}
}
if (changed)
if (nm_policy_set_system_hostname (new_hostname, msg))
nm_utils_call_dispatcher ("hostname", NULL, NULL, NULL);
}
static void
lookup_callback (LookupThread *thread, gpointer user_data)
lookup_callback (HostnameThread *thread,
int result,
const char *hostname,
gpointer user_data)
{
NMPolicy *policy = (NMPolicy *) user_data;
char *msg;
/* If the thread was told to die or it's not the current in-progress
* hostname lookup, nothing to do.
*/
if (thread->die || (thread != policy->lookup))
goto done;
policy->lookup = NULL;
if (!strlen (thread->hostname)) {
char *msg;
/* No valid IP4 config (!!); fall back to localhost.localdomain */
msg = g_strdup_printf ("address lookup failed: %d", thread->ret);
set_system_hostname (NULL, msg);
g_free (msg);
} else
set_system_hostname (thread->hostname, "from address lookup");
done:
lookup_thread_free (thread);
/* Update the hostname if the calling lookup thread is the in-progress one */
if (!hostname_thread_is_dead (thread) && (thread == policy->lookup)) {
policy->lookup = NULL;
if (!hostname) {
/* No valid IP4 config (!!); fall back to localhost.localdomain */
msg = g_strdup_printf ("address lookup failed: %d", result);
_set_hostname (NULL, msg);
g_free (msg);
} else
_set_hostname (hostname, "from address lookup");
}
hostname_thread_free (thread);
}
static void
@ -403,7 +266,7 @@ update_system_hostname (NMPolicy *policy, NMDevice *best)
g_return_if_fail (policy != NULL);
if (policy->lookup) {
lookup_thread_die (policy->lookup);
hostname_thread_kill (policy->lookup);
policy->lookup = NULL;
}
@ -419,20 +282,20 @@ update_system_hostname (NMPolicy *policy, NMDevice *best)
/* Try a persistent hostname first */
g_object_get (G_OBJECT (policy->manager), NM_MANAGER_HOSTNAME, &configured_hostname, NULL);
if (configured_hostname) {
set_system_hostname (configured_hostname, "from system configuration");
_set_hostname (configured_hostname, "from system configuration");
g_free (configured_hostname);
return;
}
/* Try automatically determined hostname from the best device's IP config */
if (!best)
best = get_best_device (policy->manager, &best_req);
best = get_best_ip4_device (policy->manager, &best_req);
if (!best) {
/* No best device; fall back to original hostname or if there wasn't
* one, 'localhost.localdomain'
*/
set_system_hostname (policy->orig_hostname, "no default device");
_set_hostname (policy->orig_hostname, "no default device");
return;
}
@ -446,7 +309,7 @@ update_system_hostname (NMPolicy *policy, NMDevice *best)
/* Sanity check */
while (*p) {
if (!isblank (*p++)) {
set_system_hostname (dhcp4_hostname, "from DHCP");
_set_hostname (dhcp4_hostname, "from DHCP");
return;
}
}
@ -459,7 +322,7 @@ update_system_hostname (NMPolicy *policy, NMDevice *best)
* when NM started up.
*/
if (policy->orig_hostname) {
set_system_hostname (policy->orig_hostname, "from system startup");
_set_hostname (policy->orig_hostname, "from system startup");
return;
}
@ -471,7 +334,7 @@ update_system_hostname (NMPolicy *policy, NMDevice *best)
|| (nm_ip4_config_get_num_nameservers (ip4_config) == 0)
|| (nm_ip4_config_get_num_addresses (ip4_config) == 0)) {
/* No valid IP4 config (!!); fall back to localhost.localdomain */
set_system_hostname (NULL, "no IPv4 config");
_set_hostname (NULL, "no IPv4 config");
return;
}
@ -479,15 +342,15 @@ update_system_hostname (NMPolicy *policy, NMDevice *best)
g_assert (addr); /* checked for > 1 address above */
/* Start the hostname lookup thread */
policy->lookup = lookup_thread_new (nm_ip4_address_get_address (addr), lookup_callback, policy);
policy->lookup = hostname_thread_new (nm_ip4_address_get_address (addr), lookup_callback, policy);
if (!policy->lookup) {
/* Fall back to 'localhost.localdomain' */
set_system_hostname (NULL, "error starting hostname thread");
_set_hostname (NULL, "error starting hostname thread");
}
}
static void
update_routing_and_dns (NMPolicy *policy, gboolean force_update)
update_ip4_routing_and_dns (NMPolicy *policy, gboolean force_update)
{
NMNamedIPConfigType dns_type = NM_NAMED_IP_CONFIG_TYPE_BEST_DEVICE;
NMDevice *best = NULL;
@ -501,10 +364,10 @@ update_routing_and_dns (NMPolicy *policy, gboolean force_update)
NMSettingConnection *s_con = NULL;
const char *connection_id;
best = get_best_device (policy->manager, &best_req);
best = get_best_ip4_device (policy->manager, &best_req);
if (!best)
goto out;
if (!force_update && (best == policy->default_device))
if (!force_update && (best == policy->default_device4))
goto out;
/* If a VPN connection is active, it is preferred */
@ -598,16 +461,149 @@ update_routing_and_dns (NMPolicy *policy, gboolean force_update)
connection_id = s_con ? nm_setting_connection_get_id (s_con) : NULL;
if (connection_id) {
nm_log_info (LOGD_CORE, "Policy set '%s' (%s) as default for routing and DNS.", connection_id, ip_iface);
nm_log_info (LOGD_CORE, "Policy set '%s' (%s) as default for IPv4 routing and DNS.", connection_id, ip_iface);
} else {
nm_log_info (LOGD_CORE, "Policy set (%s) as default for routing and DNS.", ip_iface);
nm_log_info (LOGD_CORE, "Policy set (%s) as default for IPv4 routing and DNS.", ip_iface);
}
out:
/* Update the system hostname */
update_system_hostname (policy, best);
policy->default_device4 = best;
}
policy->default_device = best;
static void
update_ip6_routing_and_dns (NMPolicy *policy, gboolean force_update)
{
NMNamedIPConfigType dns_type = NM_NAMED_IP_CONFIG_TYPE_BEST_DEVICE;
NMDevice *best = NULL;
NMActRequest *best_req = NULL;
NMNamedManager *named_mgr;
GSList *devices = NULL, *iter;
#if NOT_YET
GSList *vpns;
#endif
NMIP6Config *ip6_config = NULL;
NMIP6Address *addr;
const char *ip_iface = NULL;
NMConnection *connection = NULL;
NMSettingConnection *s_con = NULL;
const char *connection_id;
best = get_best_ip6_device (policy->manager, &best_req);
if (!best)
goto out;
if (!force_update && (best == policy->default_device6))
goto out;
#if NOT_YET
/* If a VPN connection is active, it is preferred */
vpns = nm_vpn_manager_get_active_connections (policy->vpn_manager);
for (iter = vpns; iter; iter = g_slist_next (iter)) {
NMVPNConnection *candidate = NM_VPN_CONNECTION (iter->data);
NMConnection *vpn_connection;
NMSettingIP6Config *s_ip6;
gboolean can_default = TRUE;
NMVPNConnectionState vpn_state;
/* If it's marked 'never-default', don't make it default */
vpn_connection = nm_vpn_connection_get_connection (candidate);
g_assert (vpn_connection);
s_ip6 = (NMSettingIP6Config *) nm_connection_get_setting (vpn_connection, NM_TYPE_SETTING_IP6_CONFIG);
if (s_ip6 && nm_setting_ip6_config_get_never_default (s_ip6))
can_default = FALSE;
vpn_state = nm_vpn_connection_get_vpn_state (candidate);
if (can_default && (vpn_state == NM_VPN_CONNECTION_STATE_ACTIVATED)) {
NMIP6Config *parent_ip6;
NMDevice *parent;
ip_iface = nm_vpn_connection_get_ip_iface (candidate);
connection = nm_vpn_connection_get_connection (candidate);
ip6_config = nm_vpn_connection_get_ip6_config (candidate);
addr = nm_ip6_config_get_address (ip6_config, 0);
parent = nm_vpn_connection_get_parent_device (candidate);
parent_ip6 = nm_device_get_ip6_config (parent);
nm_system_replace_default_ip6_route_vpn (ip_iface,
nm_ip6_address_get_gateway (addr),
nm_vpn_connection_get_ip4_internal_gateway (candidate),
nm_ip6_config_get_mss (ip4_config),
nm_device_get_ip_iface (parent),
nm_ip6_config_get_mss (parent_ip4));
dns_type = NM_NAMED_IP_CONFIG_TYPE_VPN;
}
g_object_unref (candidate);
}
g_slist_free (vpns);
#endif
/* The best device gets the default route if a VPN connection didn't */
if (!ip_iface || !ip6_config) {
connection = nm_act_request_get_connection (best_req);
ip_iface = nm_device_get_ip_iface (best);
ip6_config = nm_device_get_ip6_config (best);
g_assert (ip6_config);
addr = nm_ip6_config_get_address (ip6_config, 0);
nm_system_replace_default_ip6_route (ip_iface, nm_ip6_address_get_gateway (addr));
dns_type = NM_NAMED_IP_CONFIG_TYPE_BEST_DEVICE;
}
if (!ip_iface || !ip6_config) {
nm_log_warn (LOGD_CORE, "couldn't determine IP interface (%p) or IPv6 config (%p)!",
ip_iface, ip6_config);
goto out;
}
/* Update the default active connection. Only mark the new default
* active connection after setting default = FALSE on all other connections
* first. The order is important, we don't want two connections marked
* default at the same time ever.
*/
devices = nm_manager_get_devices (policy->manager);
for (iter = devices; iter; iter = g_slist_next (iter)) {
NMDevice *dev = NM_DEVICE (iter->data);
NMActRequest *req;
req = nm_device_get_act_request (dev);
if (req && (req != best_req))
nm_act_request_set_default6 (req, FALSE);
}
named_mgr = nm_named_manager_get ();
nm_named_manager_add_ip6_config (named_mgr, ip_iface, ip6_config, dns_type);
g_object_unref (named_mgr);
/* Now set new default active connection _after_ updating DNS info, so that
* if the connection is shared dnsmasq picks up the right stuff.
*/
if (best_req)
nm_act_request_set_default6 (best_req, TRUE);
if (connection)
s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
connection_id = s_con ? nm_setting_connection_get_id (s_con) : NULL;
if (connection_id) {
nm_log_info (LOGD_CORE, "Policy set '%s' (%s) as default for IPv6 routing and DNS.", connection_id, ip_iface);
} else {
nm_log_info (LOGD_CORE, "Policy set (%s) as default for IPv6 routing and DNS.", ip_iface);
}
out:
policy->default_device6 = best;
}
static void
update_routing_and_dns (NMPolicy *policy, gboolean force_update)
{
update_ip4_routing_and_dns (policy, force_update);
update_ip6_routing_and_dns (policy, force_update);
/* Update the system hostname */
update_system_hostname (policy, policy->default_device4);
}
typedef struct {
@ -796,10 +792,23 @@ device_state_changed (NMDevice *device,
/* Mark the connection invalid if it failed during activation so that
* it doesn't get automatically chosen over and over and over again.
*/
if (connection && IS_ACTIVATING_STATE (old_state)) {
g_object_set_data (G_OBJECT (connection), INVALID_TAG, GUINT_TO_POINTER (TRUE));
nm_log_info (LOGD_DEVICE, "Marking connection '%s' invalid.", get_connection_id (connection));
nm_connection_clear_secrets (connection);
if (connection) {
gboolean fail = FALSE;
if (IS_ACTIVATING_STATE (old_state)) {
nm_log_info (LOGD_DEVICE, "Marking connection '%s' invalid.", get_connection_id (connection));
fail = TRUE;
} else if ( (old_state == NM_DEVICE_STATE_ACTIVATED)
&& (reason == NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED)) {
nm_log_info (LOGD_DEVICE, "Marking connection '%s' invalid because IP configuration expired.",
get_connection_id (connection));
fail = TRUE;
}
if (fail) {
g_object_set_data (G_OBJECT (connection), INVALID_TAG, GUINT_TO_POINTER (TRUE));
nm_connection_clear_secrets (connection);
}
}
schedule_activate_check (policy, device, 3);
break;
@ -828,9 +837,9 @@ device_state_changed (NMDevice *device,
}
static void
device_ip4_config_changed (NMDevice *device,
GParamSpec *pspec,
gpointer user_data)
device_ip_config_changed (NMDevice *device,
GParamSpec *pspec,
gpointer user_data)
{
update_routing_and_dns ((NMPolicy *) user_data, TRUE);
}
@ -872,7 +881,12 @@ device_added (NMManager *manager, NMDevice *device, gpointer user_data)
policy->dev_signal_ids = add_device_signal_id (policy->dev_signal_ids, id, device);
id = g_signal_connect (device, "notify::" NM_DEVICE_INTERFACE_IP4_CONFIG,
G_CALLBACK (device_ip4_config_changed),
G_CALLBACK (device_ip_config_changed),
policy);
policy->dev_signal_ids = add_device_signal_id (policy->dev_signal_ids, id, device);
id = g_signal_connect (device, "notify::" NM_DEVICE_INTERFACE_IP6_CONFIG,
G_CALLBACK (device_ip_config_changed),
policy);
policy->dev_signal_ids = add_device_signal_id (policy->dev_signal_ids, id, device);
@ -1083,7 +1097,7 @@ nm_policy_destroy (NMPolicy *policy)
* by the lookup thread callback.
*/
if (policy->lookup) {
lookup_thread_die (policy->lookup);
hostname_thread_kill (policy->lookup);
policy->lookup = NULL;
}

View file

@ -48,7 +48,7 @@
#include "NetworkManagerUtils.h"
#include "nm-utils.h"
#include "nm-logging.h"
#include "nm-netlink.h"
#include "nm-netlink-monitor.h"
/* Because of a bug in libnl, rtnl.h should be included before route.h */
#include <netlink/route/rtnl.h>
@ -196,8 +196,10 @@ sync_addresses (const char *iface, int ifindex, int family,
struct nl_cache *addr_cache;
struct rtnl_addr *filter_addr, *match_addr;
struct nl_object *match;
struct nl_addr *nladdr;
int i, err;
guint32 log_domain = (family == AF_INET) ? LOGD_IP4 : LOGD_IP6;
char buf[INET6_ADDRSTRLEN + 1];
log_domain |= LOGD_DEVICE;
@ -218,20 +220,22 @@ sync_addresses (const char *iface, int ifindex, int family,
if (family)
rtnl_addr_set_family (filter_addr, family);
nm_log_dbg (log_domain, "(%s): syncing addresses (family %d)", iface, family);
/* Walk through the cache, comparing the addresses already on
* the interface to the addresses in addrs.
*/
for (match = nl_cache_get_first (addr_cache); match; match = nl_cache_get_next (match)) {
match_addr = (struct rtnl_addr *)match;
gboolean buf_valid = FALSE;
match_addr = (struct rtnl_addr *) match;
/* Skip addresses not on our interface */
if (!nl_object_match_filter (match, (struct nl_object *)filter_addr))
if (!nl_object_match_filter (match, (struct nl_object *) filter_addr))
continue;
if (addrs) {
for (i = 0; i < num_addrs; i++) {
if (addrs[i] &&
nl_object_identical (match, (struct nl_object *)addrs[i]))
if (addrs[i] && nl_object_identical (match, (struct nl_object *) addrs[i]))
break;
}
@ -245,10 +249,31 @@ sync_addresses (const char *iface, int ifindex, int family,
}
}
nladdr = rtnl_addr_get_local (match_addr);
/* Don't delete IPv6 link-local addresses; they don't belong to NM */
if (rtnl_addr_get_family (match_addr) == AF_INET6 &&
rtnl_addr_get_scope (match_addr) == RT_SCOPE_LINK) {
continue;
if (rtnl_addr_get_family (match_addr) == AF_INET6) {
struct in6_addr *tmp;
if (rtnl_addr_get_scope (match_addr) == RT_SCOPE_LINK) {
nm_log_dbg (log_domain, "(%s): ignoring IPv6 link-local address", iface);
continue;
}
tmp = nl_addr_get_binary_addr (nladdr);
if (inet_ntop (AF_INET6, tmp, buf, sizeof (buf)))
buf_valid = TRUE;
} else if (rtnl_addr_get_family (match_addr) == AF_INET) {
struct in_addr *tmp;
tmp = nl_addr_get_binary_addr (nladdr);
if (inet_ntop (AF_INET, tmp, buf, sizeof (buf)))
buf_valid = TRUE;
}
if (buf_valid) {
nm_log_dbg (log_domain, "(%s): removing address '%s/%d'",
iface, buf, nl_addr_get_prefixlen (nladdr));
}
/* Otherwise, match_addr should be removed from the interface. */
@ -264,9 +289,29 @@ sync_addresses (const char *iface, int ifindex, int family,
/* Now add the remaining new addresses */
for (i = 0; i < num_addrs; i++) {
struct in6_addr *in6tmp;
struct in_addr *in4tmp;
gboolean buf_valid = FALSE;
if (!addrs[i])
continue;
nladdr = rtnl_addr_get_local (addrs[i]);
if (rtnl_addr_get_family (addrs[i]) == AF_INET6) {
in6tmp = nl_addr_get_binary_addr (nladdr);
if (inet_ntop (AF_INET6, in6tmp, buf, sizeof (buf)))
buf_valid = TRUE;
} else if (rtnl_addr_get_family (addrs[i]) == AF_INET) {
in4tmp = nl_addr_get_binary_addr (nladdr);
if (inet_ntop (AF_INET, in4tmp, buf, sizeof (buf)))
buf_valid = TRUE;
}
if (buf_valid) {
nm_log_dbg (log_domain, "(%s): adding address '%s/%d'",
iface, buf, nl_addr_get_prefixlen (nladdr));
}
err = rtnl_addr_add (nlh, addrs[i], 0);
if (err < 0) {
nm_log_err (log_domain,
@ -460,7 +505,7 @@ nm_system_device_set_ip6_route (const char *iface,
g_return_val_if_fail (route != NULL, NULL);
/* Destination */
dest_addr = nl_addr_build (AF_INET6, (struct in6_addr *)ip6_dest, sizeof (*ip6_dest));
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);
@ -469,7 +514,7 @@ nm_system_device_set_ip6_route (const char *iface,
/* 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));
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);
@ -940,6 +985,153 @@ nm_system_replace_default_ip4_route (const char *iface, guint32 gw, guint32 mss)
return success;
}
static struct rtnl_route *
add_ip6_route_to_gateway (const char *iface, const struct in6_addr *gw)
{
struct nl_handle *nlh;
struct rtnl_route *route = NULL;
struct nl_addr *gw_addr = NULL;
int iface_idx, err;
nlh = nm_netlink_get_default_handle ();
g_return_val_if_fail (nlh != NULL, NULL);
iface_idx = nm_netlink_iface_to_index (iface);
if (iface_idx < 0)
return NULL;
/* Gateway might be over a bridge; try adding a route to gateway first */
route = rtnl_route_alloc ();
if (route == NULL)
return NULL;
rtnl_route_set_family (route, AF_INET6);
rtnl_route_set_table (route, RT_TABLE_MAIN);
rtnl_route_set_oif (route, iface_idx);
rtnl_route_set_scope (route, RT_SCOPE_LINK);
gw_addr = nl_addr_build (AF_INET, (void *) gw, sizeof (*gw));
if (!gw_addr)
goto error;
nl_addr_set_prefixlen (gw_addr, 128);
rtnl_route_set_dst (route, gw_addr);
nl_addr_put (gw_addr);
/* Add direct route to the gateway */
err = rtnl_route_add (nlh, route, 0);
if (err) {
nm_log_err (LOGD_DEVICE | LOGD_IP6,
"(%s): failed to add IPv4 route to gateway (%d)",
iface, err);
goto error;
}
return route;
error:
rtnl_route_put (route);
return NULL;
}
static int
replace_default_ip6_route (const char *iface, const struct in6_addr *gw)
{
struct rtnl_route *route = NULL;
struct nl_handle *nlh;
struct nl_addr *gw_addr = NULL;
int iface_idx, err = -1;
g_return_val_if_fail (iface != NULL, -ENODEV);
nlh = nm_netlink_get_default_handle ();
g_return_val_if_fail (nlh != NULL, -ENOMEM);
iface_idx = nm_netlink_iface_to_index (iface);
if (iface_idx < 0)
return -ENODEV;
route = rtnl_route_alloc();
g_return_val_if_fail (route != NULL, -ENOMEM);
rtnl_route_set_family (route, AF_INET6);
rtnl_route_set_table (route, RT_TABLE_MAIN);
rtnl_route_set_scope (route, RT_SCOPE_UNIVERSE);
rtnl_route_set_oif (route, iface_idx);
if (gw && !IN6_IS_ADDR_UNSPECIFIED (gw)) {
/* Build up the gateway address */
gw_addr = nl_addr_build (AF_INET6, (void *) gw, sizeof (*gw));
if (!gw_addr) {
err = -ENOMEM;
goto out;
}
nl_addr_set_prefixlen (gw_addr, -1);
rtnl_route_set_gateway (route, gw_addr);
}
/* Add the new default route */
err = rtnl_route_add (nlh, route, NLM_F_REPLACE);
if (err == -EEXIST) {
/* FIXME: even though we use NLM_F_REPLACE the kernel won't replace
* the route if it's the same. Should try to remove it first, then
* add the new one again here.
*/
err = 0;
}
out:
if (gw_addr)
nl_addr_put (gw_addr);
rtnl_route_put (route);
return err;
}
/*
* nm_system_replace_default_ip6_route
*
* Replace default IPv6 route with one via the given gateway
*
*/
gboolean
nm_system_replace_default_ip6_route (const char *iface, const struct in6_addr *gw)
{
struct rtnl_route *gw_route = NULL;
struct nl_handle *nlh;
gboolean success = FALSE;
int err;
nlh = nm_netlink_get_default_handle ();
g_return_val_if_fail (nlh != NULL, FALSE);
err = replace_default_ip6_route (iface, gw);
if (err == 0) {
return TRUE;
} else if (err != -ESRCH) {
nm_log_err (LOGD_DEVICE | LOGD_IP6,
"(%s): failed to set IPv6 default route: %d",
iface, err);
return FALSE;
}
/* Try adding a direct route to the gateway first */
gw_route = add_ip6_route_to_gateway (iface, gw);
if (!gw_route)
return FALSE;
/* Try adding the original route again */
err = replace_default_ip6_route (iface, gw);
if (err != 0) {
rtnl_route_del (nlh, gw_route, 0);
nm_log_err (LOGD_DEVICE | LOGD_IP6,
"(%s): failed to set IPv6 default route (pass #2): %d",
iface, err);
} else
success = TRUE;
rtnl_route_put (gw_route);
return success;
}
static void flush_addresses (const char *iface, gboolean ipv4_only)
{
int iface_idx;
@ -947,7 +1139,7 @@ static void flush_addresses (const char *iface, gboolean ipv4_only)
g_return_if_fail (iface != NULL);
iface_idx = nm_netlink_iface_to_index (iface);
if (iface_idx >= 0)
sync_addresses (iface, iface_idx, ipv4_only ? AF_INET : 0, NULL, 0);
sync_addresses (iface, iface_idx, ipv4_only ? AF_INET : AF_UNSPEC, NULL, 0);
}
/*
@ -986,7 +1178,7 @@ foreach_route (void (*callback)(struct nl_object *, gpointer),
nlh = nm_netlink_get_default_handle ();
route_cache = rtnl_route_alloc_cache (nlh);
nl_cache_mngt_provide (route_cache);
g_assert (route_cache);
nl_cache_foreach (route_cache, callback, user_data);
nl_cache_free (route_cache);
}
@ -1011,6 +1203,25 @@ check_one_route (struct nl_object *object, void *user_data)
if (data->family && rtnl_route_get_family (route) != data->family)
return;
/* We don't want to flush IPv6 link-local routes that may exist on the
* the interface since the LL address and routes should normally stay
* assigned all the time.
*/
if ( (data->family == AF_INET6 || data->family == AF_UNSPEC)
&& (rtnl_route_get_family (route) == AF_INET6)) {
struct nl_addr *nl;
struct in6_addr *addr = NULL;
nl = rtnl_route_get_dst (route);
if (nl)
addr = nl_addr_get_binary_addr (nl);
if (addr) {
if (IN6_IS_ADDR_LINKLOCAL (addr) || IN6_IS_ADDR_MC_LINKLOCAL (addr))
return;
}
}
err = rtnl_route_del (nm_netlink_get_default_handle (), route, 0);
if (err < 0) {
nm_log_err (LOGD_DEVICE,
@ -1019,21 +1230,25 @@ check_one_route (struct nl_object *object, void *user_data)
}
}
static void flush_routes (const char *iface, gboolean ipv4_only)
static void flush_routes (int ifindex, const char *iface, int family)
{
int iface_idx;
RouteCheckData check_data;
g_return_if_fail (iface != NULL);
iface_idx = nm_netlink_iface_to_index (iface);
if (iface_idx >= 0) {
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);
if (ifindex < 0) {
ifindex = nm_netlink_iface_to_index (iface);
if (ifindex < 0) {
nm_log_dbg (LOGD_DEVICE, "(%s) failed to lookup interface index", iface);
return;
}
}
memset (&check_data, 0, sizeof (check_data));
check_data.iface = iface;
check_data.iface_idx = ifindex;
check_data.family = family;
foreach_route (check_one_route, &check_data);
}
/*
@ -1042,23 +1257,25 @@ static void flush_routes (const char *iface, gboolean ipv4_only)
* Flush all network addresses associated with a network device
*
*/
void nm_system_device_flush_routes (NMDevice *dev)
void nm_system_device_flush_routes (NMDevice *dev, int family)
{
g_return_if_fail (dev != NULL);
flush_routes (nm_device_get_ip_iface (dev),
nm_device_get_ip6_config (dev) == NULL);
flush_routes (nm_device_get_ip_ifindex (dev),
nm_device_get_ip_iface (dev),
family);
}
/*
* nm_system_device_flush_routes_with_iface
*
* Flush all routes associated with a network device
* Flush all routes associated with a network device. 'family' is an
* address family, either AF_INET, AF_INET6, or AF_UNSPEC.
*
*/
void nm_system_device_flush_routes_with_iface (const char *iface)
void nm_system_device_flush_routes_with_iface (const char *iface, int family)
{
flush_routes (iface, FALSE);
flush_routes (-1, iface, family);
}
typedef struct {

View file

@ -33,13 +33,16 @@
* implemented in the backend files in backends/ directory
*/
void nm_system_device_flush_routes (NMDevice *dev);
void nm_system_device_flush_routes_with_iface (const char *iface);
void nm_system_device_flush_routes (NMDevice *dev, int family);
void nm_system_device_flush_routes_with_iface (const char *iface, int family);
gboolean nm_system_replace_default_ip4_route (const char *iface,
guint32 gw,
guint32 mss);
gboolean nm_system_replace_default_ip6_route (const char *iface,
const struct in6_addr *gw);
gboolean nm_system_replace_default_ip4_route_vpn (const char *iface,
guint32 ext_gw,
guint32 int_gw,

View file

@ -384,11 +384,11 @@ device_creator (NMUdevManager *manager,
}
if (is_olpc_mesh (udev_device)) /* must be before is_wireless */
device = (GObject *) nm_device_olpc_mesh_new (path, ifname, driver, ifindex);
device = (GObject *) nm_device_olpc_mesh_new (path, ifname, driver);
else if (is_wireless (udev_device))
device = (GObject *) nm_device_wifi_new (path, ifname, driver, ifindex);
device = (GObject *) nm_device_wifi_new (path, ifname, driver);
else
device = (GObject *) nm_device_ethernet_new (path, ifname, driver, ifindex);
device = (GObject *) nm_device_ethernet_new (path, ifname, driver);
out:
if (grandparent)

View file

@ -35,6 +35,7 @@ test_policy_hosts_CPPFLAGS = \
$(GLIB_CFLAGS)
test_policy_hosts_LDADD = \
-ldl \
$(top_builddir)/src/libtest-policy-hosts.la \
$(GLIB_LIBS)

View file

@ -45,7 +45,7 @@
#include "nm-dbus-glib-types.h"
#include "NetworkManagerUtils.h"
#include "nm-named-manager.h"
#include "nm-netlink.h"
#include "nm-netlink-monitor.h"
#include "nm-glib-compat.h"
#include "nm-vpn-connection-glue.h"
@ -69,6 +69,7 @@ typedef struct {
gulong device_ip4;
gboolean is_default;
gboolean is_default6;
NMActiveConnectionState state;
NMVPNConnectionState vpn_state;
@ -102,6 +103,7 @@ enum {
PROP_DEVICES,
PROP_STATE,
PROP_DEFAULT,
PROP_DEFAULT6,
PROP_VPN,
PROP_VPN_STATE,
PROP_BANNER,
@ -876,7 +878,8 @@ vpn_cleanup (NMVPNConnection *connection)
if (priv->tundev) {
nm_system_device_set_up_down_with_iface (priv->tundev, FALSE, NULL);
nm_system_device_flush_routes_with_iface (priv->tundev);
/* FIXME: use AF_UNSPEC here when we have IPv6 support */
nm_system_device_flush_routes_with_iface (priv->tundev, AF_INET);
nm_system_device_flush_addresses_with_iface (priv->tundev);
}
@ -1052,6 +1055,9 @@ get_property (GObject *object, guint prop_id,
case PROP_DEFAULT:
g_value_set_boolean (value, priv->is_default);
break;
case PROP_DEFAULT6:
g_value_set_boolean (value, priv->is_default6);
break;
case PROP_VPN:
g_value_set_boolean (value, TRUE);
break;
@ -1122,7 +1128,14 @@ nm_vpn_connection_class_init (NMVPNConnectionClass *connection_class)
(object_class, PROP_DEFAULT,
g_param_spec_boolean (NM_ACTIVE_CONNECTION_DEFAULT,
"Default",
"Is the default active connection",
"Is the default IPv4 active connection",
FALSE,
G_PARAM_READABLE));
g_object_class_install_property
(object_class, PROP_DEFAULT6,
g_param_spec_boolean (NM_ACTIVE_CONNECTION_DEFAULT6,
"Default6",
"Is the default IPv6 active connection",
FALSE,
G_PARAM_READABLE));
g_object_class_install_property

View file

@ -1215,7 +1215,10 @@ make_ip4_setting (shvarFile *ifcfg,
if (!tmp_ip4 && !tmp_prefix && !tmp_netmask) {
if (valid_ip6_config) {
/* Nope, no IPv4 */
goto done;
g_object_set (s_ip4,
NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
NULL);
return NM_SETTING (s_ip4);
}
method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
@ -1230,6 +1233,7 @@ make_ip4_setting (shvarFile *ifcfg,
NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS, !svTrueValue (ifcfg, "PEERDNS", TRUE),
NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES, !svTrueValue (ifcfg, "PEERROUTES", TRUE),
NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, never_default,
NM_SETTING_IP4_CONFIG_MAY_FAIL, !svTrueValue (ifcfg, "IPV4_FAILURE_FATAL", TRUE),
NULL);
/* Handle manual settings */
@ -1485,6 +1489,7 @@ make_ip6_setting (shvarFile *ifcfg,
NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS, !svTrueValue (ifcfg, "IPV6_PEERDNS", TRUE),
NM_SETTING_IP6_CONFIG_IGNORE_AUTO_ROUTES, !svTrueValue (ifcfg, "IPV6_PEERROUTES", TRUE),
NM_SETTING_IP6_CONFIG_NEVER_DEFAULT, never_default,
NM_SETTING_IP6_CONFIG_MAY_FAIL, !svTrueValue (ifcfg, "IPV6_FAILURE_FATAL", FALSE),
NULL);
if (!strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {

View file

@ -16,3 +16,4 @@ IPV6INIT=yes
IPV6_AUTOCONF=no
IPV6ADDR="1001:abba::1234/56"
IPV6ADDR_SECONDARIES="2001:abba::2234/64 3001:abba::3234/96"
IPV6_FAILURE_FATAL=no

View file

@ -560,6 +560,13 @@ test_read_wired_static (const char *file, const char *expected_id)
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_METHOD);
/* Implicit may-fail */
ASSERT (nm_setting_ip4_config_get_may_fail (s_ip4) == FALSE,
"wired-static-verify-ip6", "failed to verify %s: unexpected %s / %s key value",
file,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_MAY_FAIL);
/* DNS Addresses */
ASSERT (nm_setting_ip4_config_get_num_dns (s_ip4) == 2,
"wired-static-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
@ -648,6 +655,13 @@ test_read_wired_static (const char *file, const char *expected_id)
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_METHOD);
/* Implicit may-fail */
ASSERT (nm_setting_ip6_config_get_may_fail (s_ip6) == TRUE,
"wired-static-verify-ip6", "failed to verify %s: unexpected %s / %s key value",
file,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_MAY_FAIL);
/* DNS Addresses */
ASSERT (nm_setting_ip6_config_get_num_dns (s_ip6) == 2,
"wired-static-verify-ip6", "failed to verify %s: unexpected %s / %s key value",
@ -2011,6 +2025,12 @@ test_read_wired_ipv6_manual (void)
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_NEVER_DEFAULT);
ASSERT (nm_setting_ip6_config_get_may_fail (s_ip6) == TRUE,
"wired-ipv6-manual-verify-ip6", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_WIRED_IPV6_MANUAL,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_MAY_FAIL);
/* IP addresses */
ASSERT (nm_setting_ip6_config_get_num_addresses (s_ip6) == 3,
"wired-ipv6-manual-verify-ip6", "failed to verify %s: unexpected %s / %s key value",
@ -2165,6 +2185,7 @@ test_read_wired_ipv6_only (void)
const char *expected_dns1 = "1:2:3:4::a";
NMIP6Address *ip6_addr;
struct in6_addr addr;
const char *method;
connection = connection_from_file (TEST_IFCFG_WIRED_IPV6_ONLY,
NULL,
@ -2217,11 +2238,18 @@ test_read_wired_ipv6_only (void)
/* ===== IPv4 SETTING ===== */
s_ip4 = NM_SETTING_IP4_CONFIG (nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG));
ASSERT (s_ip4 == NULL,
"wired-ipv6-only-verify-ip4", "failed to verify %s: unexpected %s setting",
ASSERT (s_ip4 != NULL,
"wired-ipv6-only-verify-ip4", "failed to verify %s: missing %s setting",
TEST_IFCFG_WIRED_IPV6_MANUAL,
NM_SETTING_IP4_CONFIG_SETTING_NAME);
method = nm_setting_ip4_config_get_method (s_ip4);
ASSERT (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0,
"wired-ipv6-only-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_WIRED_IPV6_MANUAL,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_METHOD);
/* ===== IPv6 SETTING ===== */
s_ip6 = NM_SETTING_IP6_CONFIG (nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG));
@ -5149,6 +5177,7 @@ test_write_wired_static (void)
g_object_set (s_ip4,
NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
NM_SETTING_IP4_CONFIG_MAY_FAIL, TRUE,
NULL);
addr = nm_ip4_address_new ();
@ -5180,6 +5209,7 @@ test_write_wired_static (void)
g_object_set (s_ip6,
NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_MANUAL,
NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE,
NULL);
/* Add addresses */
@ -5408,6 +5438,7 @@ test_write_wired_static_ip6_only (void)
NMConnection *reread;
NMSettingConnection *s_con;
NMSettingWired *s_wired;
NMSettingIP4Config *s_ip4;
NMSettingIP6Config *s_ip6;
static unsigned char tmpmac[] = { 0x31, 0x33, 0x33, 0x37, 0xbe, 0xcd };
GByteArray *mac;
@ -5461,6 +5492,17 @@ test_write_wired_static_ip6_only (void)
g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, mac, NULL);
g_byte_array_free (mac, TRUE);
/* IP4 setting */
s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
ASSERT (s_ip4 != NULL,
"wired-static-ip6-only-write", "failed to allocate new %s setting",
NM_SETTING_IP4_CONFIG_SETTING_NAME);
nm_connection_add_setting (connection, NM_SETTING (s_ip4));
g_object_set (s_ip4,
NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
NULL);
/* IP6 setting */
s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
ASSERT (s_ip6 != NULL,
@ -5517,9 +5559,6 @@ test_write_wired_static_ip6_only (void)
ASSERT (nm_connection_verify (reread, &error),
"wired-static-ip6-only-write-reread-verify", "failed to verify %s: %s", testfile, error->message);
ASSERT (nm_connection_get_setting (reread, NM_TYPE_SETTING_IP4_CONFIG) == NULL,
"wired-static-ip6-only-write-reread-verify", "unexpected IPv4 setting");
ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
"wired-static-ip6-only-write", "written and re-read connection weren't the same.");

View file

@ -934,9 +934,17 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
guint32 i, num;
GString *searches;
gboolean success = FALSE;
const char *method = NULL;
s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
if (!s_ip4) {
if (s_ip4)
method = nm_setting_ip4_config_get_method (s_ip4);
/* Missing IP4 setting is assumed to be DHCP */
if (!method)
method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) {
int result;
/* IPv4 disabled, clear IPv4 related parameters */
@ -1079,6 +1087,10 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
svSetValue (ifcfg, "DHCP_CLIENT_ID", value, FALSE);
}
svSetValue (ifcfg, "IPV4_FAILURE_FATAL",
nm_setting_ip4_config_get_may_fail (s_ip4) ? "no" : "yes",
FALSE);
/* Static routes - route-<name> file */
route_path = utils_get_route_path (ifcfg->fileName);
if (!route_path) {
@ -1365,6 +1377,10 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
FALSE);
}
svSetValue (ifcfg, "IPV6_FAILURE_FATAL",
nm_setting_ip6_config_get_may_fail (s_ip6) ? "no" : "yes",
FALSE);
/* Static routes go to route6-<dev> file */
route6_path = utils_get_route6_path (ifcfg->fileName);
if (!route6_path) {

View file

@ -337,13 +337,30 @@ split_prefix (char *addr)
return slash;
}
static char *
split_gw (char *str)
{
char *comma;
g_return_val_if_fail (str != NULL, NULL);
/* Find the prefix and split the string */
comma = strchr (str, ',');
if (comma && comma > str) {
comma++;
*(comma - 1) = '\0';
return comma;
}
return NULL;
}
static GPtrArray *
read_ip6_addresses (GKeyFile *file,
const char *setting_name,
const char *key)
{
GPtrArray *addresses;
struct in6_addr addr;
struct in6_addr addr, gw;
guint32 prefix;
int i = 0;
@ -351,10 +368,11 @@ read_ip6_addresses (GKeyFile *file,
/* Look for individual addresses */
while (i++ < 1000) {
char *tmp, *key_name, *str_prefix;
char *tmp, *key_name, *str_prefix, *str_gw;
int ret;
GValueArray *values;
GByteArray *address;
GByteArray *gateway;
GValue value = { 0 };
key_name = g_strdup_printf ("%s%d", key, i);
@ -377,6 +395,7 @@ read_ip6_addresses (GKeyFile *file,
g_value_array_free (values);
goto next;
}
address = g_byte_array_new ();
g_byte_array_append (address, (guint8 *) addr.s6_addr, 16);
g_value_init (&value, DBUS_TYPE_G_UCHAR_ARRAY);
@ -401,6 +420,26 @@ read_ip6_addresses (GKeyFile *file,
g_value_array_append (values, &value);
g_value_unset (&value);
/* Gateway (optional) */
str_gw = split_gw (str_prefix);
if (str_gw) {
ret = inet_pton (AF_INET6, str_gw, &gw);
if (ret <= 0) {
g_warning ("%s: ignoring invalid IPv6 %s gateway '%s'", __func__, key_name, tmp);
g_value_array_free (values);
goto next;
}
if (!IN6_IS_ADDR_UNSPECIFIED (&gw)) {
gateway = g_byte_array_new ();
g_byte_array_append (gateway, (guint8 *) gw.s6_addr, 16);
g_value_init (&value, DBUS_TYPE_G_UCHAR_ARRAY);
g_value_take_boxed (&value, gateway);
g_value_array_append (values, &value);
g_value_unset (&value);
}
}
g_ptr_array_add (addresses, values);
next:
@ -422,7 +461,6 @@ ip6_addr_parser (NMSetting *setting, const char *key, GKeyFile *keyfile)
const char *setting_name = nm_setting_get_name (setting);
addresses = read_ip6_addresses (keyfile, setting_name, key);
if (addresses) {
g_object_set (setting, key, addresses, NULL);
g_ptr_array_foreach (addresses, free_one_ip6_address, NULL);

View file

@ -226,18 +226,27 @@ ip6_dns_writer (GKeyFile *file,
}
static gboolean
ip6_array_to_addr (GValueArray *values, guint32 idx, char *buf, size_t buflen)
ip6_array_to_addr (GValueArray *values,
guint32 idx,
char *buf,
size_t buflen,
gboolean *out_is_unspec)
{
GByteArray *byte_array;
GValue *addr_val;
struct in6_addr *addr;
g_return_val_if_fail (buflen >= INET6_ADDRSTRLEN, FALSE);
/* address */
addr_val = g_value_array_get_nth (values, idx);
byte_array = g_value_get_boxed (addr_val);
addr = (struct in6_addr *) byte_array->data;
if (out_is_unspec && IN6_IS_ADDR_UNSPECIFIED (addr))
*out_is_unspec = TRUE;
errno = 0;
if (!inet_ntop (AF_INET6, (struct in6_addr *) byte_array->data, buf, buflen)) {
if (!inet_ntop (AF_INET6, addr, buf, buflen)) {
GString *ip6_str = g_string_sized_new (INET6_ADDRSTRLEN + 10);
/* error converting the address */
@ -259,18 +268,24 @@ ip6_array_to_addr_prefix (GValueArray *values)
GValue *prefix_val;
char *ret = NULL;
GString *ip6_str;
char buf[INET6_ADDRSTRLEN];
char buf[INET6_ADDRSTRLEN + 1];
gboolean is_unspec = FALSE;
/* address */
if (ip6_array_to_addr (values, 0, buf, sizeof (buf))) {
if (ip6_array_to_addr (values, 0, buf, sizeof (buf), NULL)) {
/* Enough space for the address, '/', and the prefix */
ip6_str = g_string_sized_new (INET6_ADDRSTRLEN + 5);
ip6_str = g_string_sized_new ((INET6_ADDRSTRLEN * 2) + 5);
/* prefix */
g_string_append (ip6_str, buf);
prefix_val = g_value_array_get_nth (values, 1);
g_string_append_printf (ip6_str, "/%u", g_value_get_uint (prefix_val));
if (ip6_array_to_addr (values, 2, buf, sizeof (buf), &is_unspec)) {
if (!is_unspec)
g_string_append_printf (ip6_str, ",%s", buf);
}
ret = ip6_str->str;
g_string_free (ip6_str, FALSE);
}
@ -298,9 +313,9 @@ ip6_addr_writer (GKeyFile *file,
GValueArray *values = g_ptr_array_index (array, i);
char *key_name, *ip6_addr;
if (values->n_values % 2) {
nm_warning ("%s: error writing IP6 address %d; address array length"
" %d is not a multiple of 2.",
if (values->n_values != 3) {
nm_warning ("%s: error writing IP6 address %d (address array length "
"%d is not 3)",
__func__, i, values->n_values);
continue;
}
@ -337,7 +352,8 @@ ip6_route_writer (GKeyFile *file,
GValueArray *values = g_ptr_array_index (array, i);
char *key_name;
guint32 int_val;
char buf[INET6_ADDRSTRLEN];
char buf[INET6_ADDRSTRLEN + 1];
gboolean is_unspec = FALSE;
memset (list, 0, sizeof (list));
@ -347,7 +363,9 @@ ip6_route_writer (GKeyFile *file,
continue;
/* Next Hop */
if (!ip6_array_to_addr (values, 2, buf, sizeof (buf)))
if (!ip6_array_to_addr (values, 2, buf, sizeof (buf), &is_unspec))
continue;
if (is_unspec)
continue;
list[1] = g_strdup (buf);

View file

@ -2,7 +2,8 @@ EXTRA_DIST = \
Test_Wired_Connection \
Test_GSM_Connection \
Test_Wireless_Connection \
Test_Wired_Connection_MAC_Case
Test_Wired_Connection_MAC_Case \
Test_Wired_Connection_IP6
check-local:
@for f in $(EXTRA_DIST); do \

View file

@ -0,0 +1,20 @@
[connection]
id=Test Wired Connection IP6
uuid=4e80a56d-c99f-4aad-a6dd-b449bc398c57
type=802-3-ethernet
autoconnect=true
timestamp=6654332
[802-3-ethernet]
auto-negotiate=true
mtu=1400
[ipv4]
method=disabled
[ipv6]
method=manual
addresses1=abcd:1234:ffff::cdde/64,abcd:1234:ffff::cdd1
dns=1111:dddd::aaaa;1::cafe;

View file

@ -15,7 +15,7 @@
* 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.
* Copyright (C) 2008 - 2010 Red Hat, Inc.
*/
#include <stdio.h>
@ -510,7 +510,8 @@ add_one_ip4_route (NMSettingIP4Config *s_ip4,
static void
add_one_ip6_address (NMSettingIP6Config *s_ip6,
const char *addr,
guint32 prefix)
guint32 prefix,
const char *gw)
{
struct in6_addr tmp;
NMIP6Address *ip6_addr;
@ -521,6 +522,11 @@ add_one_ip6_address (NMSettingIP6Config *s_ip6,
inet_pton (AF_INET6, addr, &tmp);
nm_ip6_address_set_address (ip6_addr, &tmp);
if (gw) {
inet_pton (AF_INET6, gw, &tmp);
nm_ip6_address_set_gateway (ip6_addr, &tmp);
}
nm_setting_ip6_config_add_address (s_ip6, ip6_addr);
nm_ip6_address_unref (ip6_addr);
}
@ -666,8 +672,8 @@ test_write_wired_connection (void)
NULL);
/* Addresses */
add_one_ip6_address (s_ip6, address6_1, 64);
add_one_ip6_address (s_ip6, address6_2, 56);
add_one_ip6_address (s_ip6, address6_1, 64, NULL);
add_one_ip6_address (s_ip6, address6_2, 56, NULL);
/* Routes */
add_one_ip6_route (s_ip6, route6_1, route6_1_nh, 64, 3);
@ -708,6 +714,266 @@ test_write_wired_connection (void)
g_object_unref (connection);
}
#define TEST_WIRED_IP6_FILE TEST_KEYFILES_DIR"/Test_Wired_Connection_IP6"
static void
test_read_ip6_wired_connection (void)
{
NMConnection *connection;
NMSettingConnection *s_con;
NMSettingWired *s_wired;
NMSettingIP4Config *s_ip4;
NMSettingIP6Config *s_ip6;
GError *error = NULL;
const char *tmp;
const char *expected_id = "Test Wired Connection IP6";
const char *expected_uuid = "4e80a56d-c99f-4aad-a6dd-b449bc398c57";
struct in6_addr addr6;
const char *expected6_address1 = "abcd:1234:ffff::cdde";
const char *expected6_gw1 = "abcd:1234:ffff::cdd1";
NMIP6Address *ip6_addr;
connection = connection_from_file (TEST_WIRED_IP6_FILE);
ASSERT (connection != NULL,
"connection-read", "failed to read %s", TEST_WIRED_IP6_FILE);
ASSERT (nm_connection_verify (connection, &error),
"connection-verify", "failed to verify %s: %s", TEST_WIRED_IP6_FILE, error->message);
/* ===== CONNECTION SETTING ===== */
s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
ASSERT (s_con != NULL,
"connection-verify-connection", "failed to verify %s: missing %s setting",
TEST_WIRED_IP6_FILE,
NM_SETTING_CONNECTION_SETTING_NAME);
/* ID */
tmp = nm_setting_connection_get_id (s_con);
ASSERT (tmp != NULL,
"connection-verify-connection", "failed to verify %s: missing %s / %s key",
TEST_WIRED_IP6_FILE,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_ID);
ASSERT (strcmp (tmp, expected_id) == 0,
"connection-verify-connection", "failed to verify %s: unexpected %s / %s key value",
TEST_WIRED_IP6_FILE,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_ID);
/* UUID */
tmp = nm_setting_connection_get_uuid (s_con);
ASSERT (tmp != NULL,
"connection-verify-connection", "failed to verify %s: missing %s / %s key",
TEST_WIRED_IP6_FILE,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_UUID);
ASSERT (strcmp (tmp, expected_uuid) == 0,
"connection-verify-connection", "failed to verify %s: unexpected %s / %s key value",
TEST_WIRED_IP6_FILE,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_UUID);
/* ===== WIRED SETTING ===== */
s_wired = NM_SETTING_WIRED (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED));
ASSERT (s_wired != NULL,
"connection-verify-wired", "failed to verify %s: missing %s setting",
TEST_WIRED_IP6_FILE,
NM_SETTING_WIRED_SETTING_NAME);
/* ===== IPv4 SETTING ===== */
s_ip4 = NM_SETTING_IP4_CONFIG (nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG));
ASSERT (s_ip4 != NULL,
"connection-verify-ip4", "failed to verify %s: missing %s setting",
TEST_WIRED_IP6_FILE,
NM_SETTING_IP4_CONFIG_SETTING_NAME);
/* Method */
tmp = nm_setting_ip4_config_get_method (s_ip4);
ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0,
"connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
TEST_WIRED_IP6_FILE,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_METHOD);
ASSERT (nm_setting_ip4_config_get_num_addresses (s_ip4) == 0,
"connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
TEST_WIRED_IP6_FILE,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_DNS);
/* ===== IPv6 SETTING ===== */
s_ip6 = NM_SETTING_IP6_CONFIG (nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG));
ASSERT (s_ip6 != NULL,
"connection-verify-ip6", "failed to verify %s: missing %s setting",
TEST_WIRED_IP6_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME);
/* Method */
tmp = nm_setting_ip6_config_get_method (s_ip6);
ASSERT (strcmp (tmp, NM_SETTING_IP6_CONFIG_METHOD_MANUAL) == 0,
"connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
TEST_WIRED_IP6_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_METHOD);
ASSERT (nm_setting_ip6_config_get_num_addresses (s_ip6) == 1,
"connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
TEST_WIRED_IP6_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_DNS);
/* Address #1 */
ip6_addr = nm_setting_ip6_config_get_address (s_ip6, 0);
ASSERT (ip6_addr,
"connection-verify-wired", "failed to verify %s: missing IP6 address #1",
TEST_WIRED_IP6_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_ADDRESSES);
ASSERT (nm_ip6_address_get_prefix (ip6_addr) == 64,
"connection-verify-wired", "failed to verify %s: unexpected IP6 address #1 prefix",
TEST_WIRED_IP6_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_ADDRESSES);
ASSERT (inet_pton (AF_INET6, expected6_address1, &addr6) > 0,
"connection-verify-wired", "failed to verify %s: couldn't convert IP address #1",
TEST_WIRED_IP6_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_ADDRESSES);
ASSERT (IN6_ARE_ADDR_EQUAL (nm_ip6_address_get_address (ip6_addr), &addr6),
"connection-verify-wired", "failed to verify %s: unexpected IP4 address #1",
TEST_WIRED_IP6_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_ADDRESSES);
ASSERT (inet_pton (AF_INET6, expected6_gw1, &addr6) > 0,
"connection-verify-wired", "failed to verify %s: couldn't convert GW address #1",
TEST_WIRED_IP6_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_ADDRESSES);
ASSERT (IN6_ARE_ADDR_EQUAL (nm_ip6_address_get_gateway (ip6_addr), &addr6),
"connection-verify-wired", "failed to verify %s: unexpected IP4 address #1",
TEST_WIRED_IP6_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_ADDRESSES);
g_object_unref (connection);
}
static void
test_write_ip6_wired_connection (void)
{
NMConnection *connection;
NMSettingConnection *s_con;
NMSettingWired *s_wired;
NMSettingIP4Config *s_ip4;
NMSettingIP6Config *s_ip6;
char *uuid;
gboolean success;
NMConnection *reread;
char *testfile = NULL;
GError *error = NULL;
pid_t owner_grp;
uid_t owner_uid;
struct in6_addr addr6;
const char *dns = "1::cafe";
const char *address = "abcd::beef";
const char *gw = "dcba::beef";
connection = nm_connection_new ();
ASSERT (connection != NULL,
"connection-write", "failed to allocate new connection");
/* Connection setting */
s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
ASSERT (s_con != NULL,
"connection-write", "failed to allocate new %s setting",
NM_SETTING_CONNECTION_SETTING_NAME);
nm_connection_add_setting (connection, NM_SETTING (s_con));
uuid = nm_utils_uuid_generate ();
g_object_set (s_con,
NM_SETTING_CONNECTION_ID, "Work Wired IP6",
NM_SETTING_CONNECTION_UUID, uuid,
NM_SETTING_CONNECTION_AUTOCONNECT, FALSE,
NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
NULL);
g_free (uuid);
/* Wired setting */
s_wired = NM_SETTING_WIRED (nm_setting_wired_new ());
ASSERT (s_wired != NULL,
"connection-write", "failed to allocate new %s setting",
NM_SETTING_WIRED_SETTING_NAME);
nm_connection_add_setting (connection, NM_SETTING (s_wired));
/* IP4 setting */
s_ip4 = NM_SETTING_IP4_CONFIG (nm_setting_ip4_config_new ());
ASSERT (s_ip4 != NULL,
"connection-write", "failed to allocate new %s setting",
NM_SETTING_IP4_CONFIG_SETTING_NAME);
nm_connection_add_setting (connection, NM_SETTING (s_ip4));
g_object_set (s_ip4,
NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
NULL);
/* IP6 setting */
s_ip6 = NM_SETTING_IP6_CONFIG (nm_setting_ip6_config_new ());
ASSERT (s_ip6 != NULL,
"connection-write", "failed to allocate new %s setting",
NM_SETTING_IP6_CONFIG_SETTING_NAME);
nm_connection_add_setting (connection, NM_SETTING (s_ip6));
g_object_set (s_ip6,
NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_MANUAL,
NULL);
/* Addresses */
add_one_ip6_address (s_ip6, address, 64, gw);
/* DNS servers */
inet_pton (AF_INET6, dns, &addr6);
nm_setting_ip6_config_add_dns (s_ip6, &addr6);
/* DNS searches */
nm_setting_ip6_config_add_dns_search (s_ip6, "wallaceandgromit.com");
/* Write out the connection */
owner_uid = geteuid ();
owner_grp = getegid ();
success = write_connection (connection, TEST_SCRATCH_DIR, owner_uid, owner_grp, &testfile, &error);
ASSERT (success == TRUE,
"connection-write", "failed to allocate write keyfile: %s",
error ? error->message : "(none)");
ASSERT (testfile != NULL,
"connection-write", "didn't get keyfile name back after writing connection");
/* Read the connection back in and compare it to the one we just wrote out */
reread = connection_from_file (testfile);
ASSERT (reread != NULL, "connection-write", "failed to re-read test connection");
ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
"connection-write", "written and re-read connection weren't the same");
g_clear_error (&error);
unlink (testfile);
g_free (testfile);
g_object_unref (reread);
g_object_unref (connection);
}
#define TEST_WIRED_MAC_CASE_FILE TEST_KEYFILES_DIR"/Test_Wired_Connection_MAC_Case"
static void
@ -1042,6 +1308,9 @@ int main (int argc, char **argv)
test_read_valid_wired_connection ();
test_write_wired_connection ();
test_read_ip6_wired_connection ();
test_write_ip6_wired_connection ();
test_read_wired_mac_case ();
test_read_valid_wireless_connection ();