Merge commit 'origin/master' into polkit1

Conflicts:
	system-settings/plugins/ifcfg-rh/nm-ifcfg-connection.c
This commit is contained in:
Dan Williams 2009-08-10 16:27:16 -05:00
commit f64354d0cc
68 changed files with 5374 additions and 643 deletions

View file

@ -27,7 +27,7 @@ EXTRA_DIST = \
intltool-merge.in \
intltool-update.in
DISTCHECK_CONFIGURE_FLAGS = --with-tests=yes --with-docs=yes
DISTCHECK_CONFIGURE_FLAGS = --with-tests=yes --with-docs=yes --with-udev-dir=$$dc_install_base/lib/udev
DISTCLEANFILES = intltool-extract intltool-merge intltool-update

View file

@ -0,0 +1,6 @@
# do not edit this file, it will be overwritten on update
# The fact that this device is driven by libertas is not currently exposed
# in the sysfs tree..?
KERNEL=="msh*", SUBSYSTEM=="net", DRIVERS=="usb", ATTRS{idVendor}=="1286", ATTRS{idProduct}=="2001", ENV{ID_NM_OLPC_MESH}="1"

View file

@ -62,6 +62,9 @@ nm_dispatcher_action_LDADD = \
nm-dispatcher-glue.h: nm-dispatcher.xml
dbus-binding-tool --prefix=nm_dispatcher --mode=glib-server --output=$@ $<
udevrulesdir = $(UDEV_BASE_DIR)/rules.d
udevrules_DATA = 77-nm-olpc-mesh.rules
dbusactivationdir = $(datadir)/dbus-1/system-services
dbusactivation_in_files = org.freedesktop.nm_dispatcher.service.in
dbusactivation_DATA = $(dbusactivation_in_files:.service.in=.service)
@ -85,6 +88,7 @@ CLEANFILES = $(BUILT_SOURCES) $(dbusactivation_DATA)
EXTRA_DIST = \
$(dbusservice_DATA) \
$(udevrules_DATA) \
$(dbusactivation_in_files) \
nm-dispatcher.xml

View file

@ -193,6 +193,14 @@ PKG_CHECK_MODULES(GUDEV, gudev-1.0)
AC_SUBST(GUDEV_CFLAGS)
AC_SUBST(GUDEV_LIBS)
AC_ARG_WITH(udev-dir, AS_HELP_STRING([--with-udev-dir=DIR], [where the udev base directory is]))
if test -n "$with_udev_dir" ; then
UDEV_BASE_DIR="$with_udev_dir"
else
UDEV_BASE_DIR="/lib/udev"
fi
AC_SUBST(UDEV_BASE_DIR)
PKG_CHECK_EXISTS(gio-2.0,[have_gio=yes],[have_gio=no])
if test x"$have_gio" = "xno"; then
AC_DEFINE([NO_GIO],[1],[Define if you don't have GIO])

View file

@ -77,7 +77,8 @@ typedef enum NMDeviceType
NM_DEVICE_TYPE_WIFI,
NM_DEVICE_TYPE_GSM,
NM_DEVICE_TYPE_CDMA,
NM_DEVICE_TYPE_BT /* Bluetooth */
NM_DEVICE_TYPE_BT, /* Bluetooth */
NM_DEVICE_TYPE_OLPC_MESH
} NMDeviceType;
/* DEPRECATED TYPE NAMES */
@ -357,6 +358,9 @@ typedef enum {
/* Carrier/link changed */
NM_DEVICE_STATE_REASON_CARRIER,
/* The device's existing connection was assumed */
NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED,
/* Unused */
NM_DEVICE_STATE_REASON_LAST = 0xFFFF
} NMDeviceStateReason;

View file

@ -34,8 +34,10 @@
#define DBUS_TYPE_G_MAP_OF_STRING (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING))
#define DBUS_TYPE_G_LIST_OF_STRING (dbus_g_type_get_collection ("GSList", G_TYPE_STRING))
#define DBUS_TYPE_G_IP6_ADDRESS (dbus_g_type_get_struct ("GValueArray", DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT, DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_INVALID))
#define DBUS_TYPE_G_IP6_ADDRESS (dbus_g_type_get_struct ("GValueArray", DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT, G_TYPE_INVALID))
#define DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_IP6_ADDRESS))
#define DBUS_TYPE_G_IP6_ROUTE (dbus_g_type_get_struct ("GValueArray", DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT, DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT, G_TYPE_INVALID))
#define DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_IP6_ROUTE))
#endif /* DBUS_GLIB_TYPES_H */

View file

@ -4,13 +4,16 @@ EXTRA_DIST = \
errors.xml \
vpn-errors.xml \
nm-access-point.xml \
nm-device-bt.xml \
nm-device-wifi.xml \
nm-device-olpc-mesh.xml \
nm-device-ethernet.xml \
nm-device-cdma.xml \
nm-device-gsm.xml \
nm-device-serial.xml \
nm-device.xml \
nm-ip4-config.xml \
nm-ip6-config.xml \
nm-manager.xml \
nm-manager-client.xml \
nm-settings.xml \

View file

@ -34,7 +34,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</
<xi:include href="nm-device-gsm.xml"/>
<xi:include href="nm-device-serial.xml"/>
<xi:include href="nm-device-bt.xml"/>
<xi:include href="nm-device-olpc-mesh.xml"/>
<xi:include href="nm-ip4-config.xml"/>
<xi:include href="nm-ip6-config.xml"/>
<xi:include href="nm-dhcp4-config.xml"/>
<xi:include href="nm-settings.xml"/>
<xi:include href="nm-exported-connection.xml"/>

View file

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8" ?>
<node name="/" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
<interface name="org.freedesktop.NetworkManager.Device.OlpcMesh">
<property name="HwAddress" type="s" access="read">
<tp:docstring>
The hardware address of the device.
</tp:docstring>
</property>
<property name="Companion" type="s" access="read">
<tp:docstring>
The object path of the companion device.
</tp:docstring>
</property>
<property name="ActiveChannel" type="o" access="read">
<tp:docstring>
The currently active channel.
</tp:docstring>
</property>
<signal name="PropertiesChanged">
<arg name="properties" type="a{sv}" tp:type="String_Variant_Map">
<tp:docstring>
A dictionary containing the FIXME: check changed parameters.
</tp:docstring>
</arg>
<tp:docstring>
Emitted when the wireless device's properties changed.
</tp:docstring>
</signal>
</interface>
</node>

View file

@ -370,6 +370,11 @@
<tp:docstring>
The device's carrier/link changed.
</tp:docstring>
</tp:enumvalue>
<tp:enumvalue suffix="CONNECTION_ASSUMED" value="41">
<tp:docstring>
The device's existing connection was assumed.
</tp:docstring>
</tp:enumvalue>
</tp:enum>

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-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>
<property name="Nameservers" type="aay" access="read">
<tp:docstring>The nameservers in use.</tp:docstring>
</property>
<property name="Domains" type="as" access="read">
<tp:docstring>A list of domains this address belongs to.</tp:docstring>
</property>
<property name="Routes" type="a(ayuayu)" access="read">
<tp:docstring>Tuples of IPv6 route/prefix/next-hop/metric.</tp:docstring>
</property>
</interface>
</node>

View file

@ -17,11 +17,13 @@ libnm_util_include_HEADERS = \
nm-setting-bluetooth.h \
nm-setting-connection.h \
nm-setting-ip4-config.h \
nm-setting-ip6-config.h \
nm-setting-ppp.h \
nm-setting-pppoe.h \
nm-setting-serial.h \
nm-setting-gsm.h \
nm-setting-cdma.h \
nm-setting-olpc-mesh.h \
nm-setting-wired.h \
nm-setting-wireless.h \
nm-setting-wireless-security.h \
@ -45,6 +47,7 @@ libnm_util_la_SOURCES= \
nm-setting-serial.c \
nm-setting-gsm.c \
nm-setting-cdma.c \
nm-setting-olpc-mesh.c \
nm-setting-wired.c \
nm-setting-wireless.c \
nm-setting-wireless-security.c \
@ -106,5 +109,5 @@ pkgconfig_DATA = libnm-util.pc
DISTCLEANFILES = libnm-util.pc
EXTRA_DIST = libnm-util.pc.in libnm-util.ver nm-setting-ip6-config.h
EXTRA_DIST = libnm-util.pc.in libnm-util.ver

View file

@ -140,6 +140,56 @@ global:
nm_setting_ip4_config_get_dhcp_hostname;
nm_setting_ip4_config_get_dhcp_send_hostname;
nm_setting_ip4_config_get_never_default;
nm_setting_ip6_config_error_get_type;
nm_setting_ip6_config_error_quark;
nm_ip6_address_new;
nm_ip6_address_dup;
nm_ip6_address_ref;
nm_ip6_address_unref;
nm_ip6_address_compare;
nm_ip6_address_get_address;
nm_ip6_address_set_address;
nm_ip6_address_get_prefix;
nm_ip6_address_set_prefix;
nm_ip6_route_new;
nm_ip6_route_dup;
nm_ip6_route_ref;
nm_ip6_route_unref;
nm_ip6_route_compare;
nm_ip6_route_get_dest;
nm_ip6_route_set_dest;
nm_ip6_route_get_prefix;
nm_ip6_route_set_prefix;
nm_ip6_route_get_next_hop;
nm_ip6_route_set_next_hop;
nm_ip6_route_get_metric;
nm_ip6_route_set_metric;
nm_setting_ip6_config_get_type;
nm_setting_ip6_config_new;
nm_setting_ip6_config_get_method;
nm_setting_ip6_config_get_num_dns;
nm_setting_ip6_config_get_dns;
nm_setting_ip6_config_add_dns;
nm_setting_ip6_config_remove_dns;
nm_setting_ip6_config_clear_dns;
nm_setting_ip6_config_get_num_dns_searches;
nm_setting_ip6_config_get_dns_search;
nm_setting_ip6_config_add_dns_search;
nm_setting_ip6_config_remove_dns_search;
nm_setting_ip6_config_clear_dns_searches;
nm_setting_ip6_config_get_num_addresses;
nm_setting_ip6_config_get_address;
nm_setting_ip6_config_add_address;
nm_setting_ip6_config_remove_address;
nm_setting_ip6_config_clear_addresses;
nm_setting_ip6_config_get_num_routes;
nm_setting_ip6_config_get_route;
nm_setting_ip6_config_add_route;
nm_setting_ip6_config_remove_route;
nm_setting_ip6_config_clear_routes;
nm_setting_ip6_config_get_ignore_auto_routes;
nm_setting_ip6_config_get_ignore_auto_dns;
nm_setting_ip6_config_get_never_default;
nm_setting_need_secrets;
nm_setting_ppp_error_get_type;
nm_setting_ppp_error_quark;
@ -253,6 +303,10 @@ global:
nm_setting_wireless_security_remove_pairwise;
nm_setting_wireless_security_remove_proto;
nm_setting_wireless_security_set_wep_key;
nm_setting_olpc_mesh_get_type;
nm_setting_olpc_mesh_get_ssid;
nm_setting_olpc_mesh_get_channel;
nm_setting_olpc_mesh_get_dhcp_anycast_address;
nm_utils_deinit;
nm_utils_escape_ssid;
nm_utils_gvalue_hash_dup;
@ -263,6 +317,10 @@ global:
nm_utils_ip4_prefix_to_netmask;
nm_utils_ip4_routes_from_gvalue;
nm_utils_ip4_routes_to_gvalue;
nm_utils_ip6_addresses_from_gvalue;
nm_utils_ip6_addresses_to_gvalue;
nm_utils_ip6_routes_from_gvalue;
nm_utils_ip6_routes_to_gvalue;
nm_utils_is_empty_ssid;
nm_utils_same_ssid;
nm_utils_security_valid;

View file

@ -41,6 +41,7 @@
#include "nm-setting-wireless.h"
#include "nm-setting-wireless-security.h"
#include "nm-setting-vpn.h"
#include "nm-setting-olpc-mesh.h"
#include "nm-setting-serial.h"
#include "nm-setting-gsm.h"
@ -140,7 +141,7 @@ static guint signals[LAST_SIGNAL] = { 0 };
static GHashTable *registered_settings = NULL;
#define DEFAULT_MAP_SIZE 14
#define DEFAULT_MAP_SIZE 15
static struct SettingInfo {
const char *name;
@ -216,6 +217,11 @@ register_default_settings (void)
NM_SETTING_WIRELESS_ERROR,
1);
register_one_setting (NM_SETTING_OLPC_MESH_SETTING_NAME,
NM_TYPE_SETTING_OLPC_MESH,
NM_SETTING_OLPC_MESH_ERROR,
1);
register_one_setting (NM_SETTING_GSM_SETTING_NAME,
NM_TYPE_SETTING_GSM,
NM_SETTING_GSM_ERROR,
@ -266,6 +272,11 @@ register_default_settings (void)
NM_SETTING_IP4_CONFIG_ERROR,
6);
register_one_setting (NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_TYPE_SETTING_IP6_CONFIG,
NM_SETTING_IP6_CONFIG_ERROR,
6);
/* Be sure to update DEFAULT_MAP_SIZE if you add another setting!! */
}

View file

@ -947,7 +947,7 @@ static EAPMethodsTable eap_methods_table[] = {
{ "peap", need_secrets_phase2, verify_ttls },
{ "ttls", need_secrets_phase2, verify_ttls },
{ "sim", need_secrets_sim, NULL },
{ "gtc", NULL, NULL }, // FIXME: implement
{ "gtc", need_secrets_password, verify_identity },
{ "otp", NULL, NULL }, // FIXME: implement
{ NULL, NULL, NULL }
};

View file

@ -30,13 +30,6 @@
#include "nm-utils.h"
#include "nm-dbus-glib-types.h"
GSList *nm_utils_ip6_addresses_from_gvalue (const GValue *value);
void nm_utils_ip6_addresses_to_gvalue (GSList *list, GValue *value);
GSList *nm_utils_ip6_dns_from_gvalue (const GValue *value);
void nm_utils_ip6_dns_to_gvalue (GSList *list, GValue *value);
GQuark
nm_setting_ip6_config_error_quark (void)
{
@ -83,9 +76,9 @@ typedef struct {
GSList *dns_search; /* list of strings */
GSList *addresses; /* array of NMIP6Address */
GSList *routes; /* array of NMIP6Route */
gboolean ignore_auto_routes;
gboolean ignore_auto_dns;
gboolean ignore_ra;
char *dhcp_mode;
gboolean never_default;
} NMSettingIP6ConfigPrivate;
@ -96,9 +89,9 @@ enum {
PROP_DNS_SEARCH,
PROP_ADDRESSES,
PROP_ROUTES,
PROP_IGNORE_AUTO_ROUTES,
PROP_IGNORE_AUTO_DNS,
PROP_IGNORE_ROUTER_ADV,
PROP_DHCP_MODE,
PROP_NEVER_DEFAULT,
LAST_PROP
};
@ -397,6 +390,14 @@ nm_setting_ip6_config_clear_routes (NMSettingIP6Config *setting)
priv->routes = NULL;
}
gboolean
nm_setting_ip6_config_get_ignore_auto_routes (NMSettingIP6Config *setting)
{
g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE);
return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->ignore_auto_routes;
}
gboolean
nm_setting_ip6_config_get_ignore_auto_dns (NMSettingIP6Config *setting)
{
@ -406,19 +407,11 @@ nm_setting_ip6_config_get_ignore_auto_dns (NMSettingIP6Config *setting)
}
gboolean
nm_setting_ip6_config_get_ignore_router_adv (NMSettingIP6Config *setting)
nm_setting_ip6_config_get_never_default (NMSettingIP6Config *setting)
{
g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE);
return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->ignore_ra;
}
const char *
nm_setting_ip6_config_get_dhcp_mode (NMSettingIP6Config *setting)
{
g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE);
return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->dhcp_mode;
return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->never_default;
}
static gboolean
@ -443,6 +436,7 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
return FALSE;
}
} else if ( !strcmp (priv->method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)
|| !strcmp (priv->method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)
|| !strcmp (priv->method, NM_SETTING_IP6_CONFIG_METHOD_SHARED)) {
if (!priv->ignore_auto_dns) {
if (priv->dns && g_slist_length (priv->dns)) {
@ -469,17 +463,6 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
NM_SETTING_IP6_CONFIG_ADDRESSES);
return FALSE;
}
/* if router advertisement autoconf is disabled, dhcpv6 mode must
* be SOMETHING as long as the user has selected the auto method
*/
if (priv->ignore_ra && (priv->dhcp_mode == NULL)) {
g_set_error (error,
NM_SETTING_IP6_CONFIG_ERROR,
NM_SETTING_IP6_CONFIG_ERROR_INVALID_PROPERTY,
NM_SETTING_IP6_CONFIG_DHCP_MODE);
return FALSE;
}
} else {
g_set_error (error,
NM_SETTING_IP6_CONFIG_ERROR,
@ -540,17 +523,16 @@ set_property (GObject *object, guint prop_id,
break;
case PROP_ROUTES:
nm_utils_slist_free (priv->routes, g_free);
priv->routes = nm_utils_ip6_addresses_from_gvalue (value);
priv->routes = nm_utils_ip6_routes_from_gvalue (value);
break;
case PROP_IGNORE_AUTO_ROUTES:
priv->ignore_auto_routes = g_value_get_boolean (value);
break;
case PROP_IGNORE_AUTO_DNS:
priv->ignore_auto_dns = g_value_get_boolean (value);
break;
case PROP_IGNORE_ROUTER_ADV:
priv->ignore_ra = g_value_get_boolean (value);
break;
case PROP_DHCP_MODE:
g_free (priv->dhcp_mode);
priv->dhcp_mode = g_value_dup_string (value);
case PROP_NEVER_DEFAULT:
priv->never_default = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -578,16 +560,16 @@ get_property (GObject *object, guint prop_id,
nm_utils_ip6_addresses_to_gvalue (priv->addresses, value);
break;
case PROP_ROUTES:
nm_utils_ip6_addresses_to_gvalue (priv->routes, value);
nm_utils_ip6_routes_to_gvalue (priv->routes, value);
break;
case PROP_IGNORE_AUTO_ROUTES:
g_value_set_boolean (value, priv->ignore_auto_routes);
break;
case PROP_IGNORE_AUTO_DNS:
g_value_set_boolean (value, priv->ignore_auto_dns);
break;
case PROP_IGNORE_ROUTER_ADV:
g_value_set_boolean (value, priv->ignore_ra);
break;
case PROP_DHCP_MODE:
g_value_set_string (value, priv->dhcp_mode);
case PROP_NEVER_DEFAULT:
g_value_set_boolean (value, priv->never_default);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -601,6 +583,8 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *setting_class)
GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
g_type_class_add_private (setting_class, sizeof (NMSettingIP6ConfigPrivate));
/* virtual methods */
object_class->set_property = set_property;
object_class->get_property = get_property;
@ -645,39 +629,39 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *setting_class)
_nm_param_spec_specialized (NM_SETTING_IP6_CONFIG_ROUTES,
"Routes",
"List of NMSettingIP6Addresses",
DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS,
DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
g_object_class_install_property
(object_class, PROP_IGNORE_AUTO_ROUTES,
g_param_spec_boolean (NM_SETTING_IP6_CONFIG_IGNORE_AUTO_ROUTES,
"Ignore automatic routes",
"Ignore automatic routes",
FALSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
g_object_class_install_property
(object_class, PROP_IGNORE_AUTO_DNS,
g_param_spec_boolean (NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS,
"Ignore DHCPv6 DNS",
"Ignore DHCPv6 DNS",
"Ignore DHCPv6/RDNSS DNS",
"Ignore DHCPv6/RDNSS DNS",
FALSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
g_object_class_install_property
(object_class, PROP_IGNORE_ROUTER_ADV,
g_param_spec_boolean (NM_SETTING_IP6_CONFIG_IGNORE_ROUTER_ADV,
"Ignore Router Advertisements",
"Ignore Router Advertisements",
(object_class, PROP_NEVER_DEFAULT,
g_param_spec_boolean (NM_SETTING_IP6_CONFIG_NEVER_DEFAULT,
"Never default",
"Never make this connection the default IPv6 connection",
FALSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
g_object_class_install_property
(object_class, PROP_DHCP_MODE,
g_param_spec_string (NM_SETTING_IP6_CONFIG_DHCP_MODE,
"DHCPv6 Client Mode",
"DHCPv6 Client Mode",
NULL,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
}
struct NMIP6Address {
guint32 refcount;
struct in6_addr *address; /* network byte order */
struct in6_addr address;
guint32 prefix;
struct in6_addr *gateway; /* network byte order */
};
NMIP6Address *
@ -700,16 +684,7 @@ nm_ip6_address_dup (NMIP6Address *source)
address = nm_ip6_address_new ();
address->prefix = source->prefix;
if (source->address) {
address->address = g_malloc0 (sizeof (struct in6_addr));
memcpy (address->address, source->address, sizeof (struct in6_addr));
}
if (source->gateway) {
address->gateway = g_malloc0 (sizeof (struct in6_addr));
memcpy (address->gateway, source->gateway, sizeof (struct in6_addr));
}
memcpy (&address->address, &source->address, sizeof (struct in6_addr));
return address;
}
@ -731,8 +706,6 @@ nm_ip6_address_unref (NMIP6Address *address)
address->refcount--;
if (address->refcount == 0) {
g_free (address->address);
g_free (address->gateway);
memset (address, 0, sizeof (NMIP6Address));
g_free (address);
}
@ -747,9 +720,8 @@ nm_ip6_address_compare (NMIP6Address *address, NMIP6Address *other)
g_return_val_if_fail (other != NULL, FALSE);
g_return_val_if_fail (other->refcount > 0, FALSE);
if ( memcmp (address->address, other->address, sizeof (struct in6_addr))
|| address->prefix != other->prefix
|| memcmp (address->gateway, other->gateway, sizeof (struct in6_addr)))
if ( memcmp (&address->address, &other->address, sizeof (struct in6_addr))
|| address->prefix != other->prefix)
return FALSE;
return TRUE;
}
@ -760,7 +732,7 @@ nm_ip6_address_get_address (NMIP6Address *address)
g_return_val_if_fail (address != NULL, 0);
g_return_val_if_fail (address->refcount > 0, 0);
return address->address;
return &address->address;
}
void
@ -768,14 +740,9 @@ nm_ip6_address_set_address (NMIP6Address *address, const struct in6_addr *addr)
{
g_return_if_fail (address != NULL);
g_return_if_fail (address->refcount > 0);
g_return_if_fail (addr != NULL);
g_free (address->address);
address->address = NULL;
if (addr) {
address->address = g_malloc0 (sizeof (struct in6_addr));
memcpy (address->address, addr, sizeof (struct in6_addr));
}
memcpy (&address->address, addr, sizeof (struct in6_addr));
}
guint32
@ -796,37 +763,12 @@ nm_ip6_address_set_prefix (NMIP6Address *address, guint32 prefix)
address->prefix = prefix;
}
const struct in6_addr *
nm_ip6_address_get_gateway (NMIP6Address *address)
{
g_return_val_if_fail (address != NULL, 0);
g_return_val_if_fail (address->refcount > 0, 0);
return address->gateway;
}
void
nm_ip6_address_set_gateway (NMIP6Address *address, const struct in6_addr *gateway)
{
g_return_if_fail (address != NULL);
g_return_if_fail (address->refcount > 0);
g_free (address->gateway);
address->gateway = NULL;
if (gateway) {
address->gateway = g_malloc0 (sizeof (struct in6_addr));
memcpy (address->gateway, gateway, sizeof (struct in6_addr));
}
}
struct NMIP6Route {
guint32 refcount;
struct in6_addr *dest; /* network byte order */
struct in6_addr dest;
guint32 prefix;
struct in6_addr *next_hop; /* network byte order */
struct in6_addr next_hop;
guint32 metric; /* lower metric == more preferred */
};
@ -851,16 +793,8 @@ nm_ip6_route_dup (NMIP6Route *source)
route = nm_ip6_route_new ();
route->prefix = source->prefix;
route->metric = source->metric;
if (source->dest) {
route->dest = g_malloc0 (sizeof (struct in6_addr));
memcpy (route->dest, source->dest, sizeof (struct in6_addr));
}
if (source->next_hop) {
route->next_hop = g_malloc0 (sizeof (struct in6_addr));
memcpy (route->next_hop, source->next_hop, sizeof (struct in6_addr));
}
memcpy (&route->dest, &source->dest, sizeof (struct in6_addr));
memcpy (&route->next_hop, &source->next_hop, sizeof (struct in6_addr));
return route;
}
@ -882,8 +816,6 @@ nm_ip6_route_unref (NMIP6Route *route)
route->refcount--;
if (route->refcount == 0) {
g_free (route->dest);
g_free (route->next_hop);
memset (route, 0, sizeof (NMIP6Route));
g_free (route);
}
@ -898,9 +830,9 @@ nm_ip6_route_compare (NMIP6Route *route, NMIP6Route *other)
g_return_val_if_fail (other != NULL, FALSE);
g_return_val_if_fail (other->refcount > 0, FALSE);
if ( memcmp (route->dest, other->dest, sizeof (struct in6_addr))
if ( memcmp (&route->dest, &other->dest, sizeof (struct in6_addr))
|| route->prefix != other->prefix
|| memcmp (route->next_hop, other->next_hop, sizeof (struct in6_addr))
|| memcmp (&route->next_hop, &other->next_hop, sizeof (struct in6_addr))
|| route->metric != other->metric)
return FALSE;
return TRUE;
@ -912,7 +844,7 @@ nm_ip6_route_get_dest (NMIP6Route *route)
g_return_val_if_fail (route != NULL, 0);
g_return_val_if_fail (route->refcount > 0, 0);
return route->dest;
return &route->dest;
}
void
@ -920,14 +852,9 @@ nm_ip6_route_set_dest (NMIP6Route *route, const struct in6_addr *dest)
{
g_return_if_fail (route != NULL);
g_return_if_fail (route->refcount > 0);
g_return_if_fail (dest != NULL);
g_free (route->dest);
route->dest = NULL;
if (dest) {
route->dest = g_malloc0 (sizeof (struct in6_addr));
memcpy (route->dest, dest, sizeof (struct in6_addr));
}
memcpy (&route->dest, dest, sizeof (struct in6_addr));
}
guint32
@ -954,7 +881,7 @@ nm_ip6_route_get_next_hop (NMIP6Route *route)
g_return_val_if_fail (route != NULL, 0);
g_return_val_if_fail (route->refcount > 0, 0);
return route->next_hop;
return &route->next_hop;
}
void
@ -962,14 +889,9 @@ nm_ip6_route_set_next_hop (NMIP6Route *route, const struct in6_addr *next_hop)
{
g_return_if_fail (route != NULL);
g_return_if_fail (route->refcount > 0);
g_return_if_fail (next_hop != NULL);
g_free (route->next_hop);
route->next_hop = NULL;
if (next_hop) {
route->next_hop = g_malloc0 (sizeof (struct in6_addr));
memcpy (route->next_hop, next_hop, sizeof (struct in6_addr));
}
memcpy (&route->next_hop, next_hop, sizeof (struct in6_addr));
}
guint32
@ -989,4 +911,3 @@ nm_ip6_route_set_metric (NMIP6Route *route, guint32 metric)
route->metric = metric;
}

View file

@ -54,21 +54,20 @@ GType nm_setting_ip6_config_error_get_type (void);
#define NM_SETTING_IP6_CONFIG_ERROR nm_setting_ip6_config_error_quark ()
GQuark nm_setting_ip6_config_error_quark (void);
#define NM_SETTING_IP6_CONFIG_METHOD "method"
#define NM_SETTING_IP6_CONFIG_DNS "dns"
#define NM_SETTING_IP6_CONFIG_DNS_SEARCH "dns-search"
#define NM_SETTING_IP6_CONFIG_ADDRESSES "addresses"
#define NM_SETTING_IP6_CONFIG_ROUTES "routes"
#define NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS "ignore-auto-dns"
#define NM_SETTING_IP6_CONFIG_IGNORE_ROUTER_ADV "ignore-router-adv"
#define NM_SETTING_IP6_CONFIG_DHCP_MODE "dhcp-mode"
#define NM_SETTING_IP6_CONFIG_METHOD "method"
#define NM_SETTING_IP6_CONFIG_DNS "dns"
#define NM_SETTING_IP6_CONFIG_DNS_SEARCH "dns-search"
#define NM_SETTING_IP6_CONFIG_ADDRESSES "addresses"
#define NM_SETTING_IP6_CONFIG_ROUTES "routes"
#define NM_SETTING_IP6_CONFIG_IGNORE_AUTO_ROUTES "ignore-auto-routes"
#define NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS "ignore-auto-dns"
#define NM_SETTING_IP6_CONFIG_NEVER_DEFAULT "never-default"
#define NM_SETTING_IP6_CONFIG_METHOD_AUTO "auto"
#define NM_SETTING_IP6_CONFIG_METHOD_MANUAL "manual"
#define NM_SETTING_IP6_CONFIG_METHOD_SHARED "shared"
#define NM_SETTING_IP6_CONFIG_DHCPV6_MODE_INFO "info"
#define NM_SETTING_IP6_CONFIG_DHCPV6_MODE_REQUEST "request"
#define NM_SETTING_IP6_CONFIG_METHOD_IGNORE "ignore"
#define NM_SETTING_IP6_CONFIG_METHOD_AUTO "auto"
#define NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL "link-local"
#define NM_SETTING_IP6_CONFIG_METHOD_MANUAL "manual"
#define NM_SETTING_IP6_CONFIG_METHOD_SHARED "shared"
typedef struct NMIP6Address NMIP6Address;
@ -82,16 +81,12 @@ gboolean nm_ip6_address_compare (NMIP6Address *address, NMIP6A
const struct in6_addr *nm_ip6_address_get_address (NMIP6Address *address);
void nm_ip6_address_set_address (NMIP6Address *address,
const struct in6_addr *addr); /* network byte order */
const struct in6_addr *addr);
guint32 nm_ip6_address_get_prefix (NMIP6Address *address);
void nm_ip6_address_set_prefix (NMIP6Address *address,
guint32 prefix);
const struct in6_addr *nm_ip6_address_get_gateway (NMIP6Address *address);
void nm_ip6_address_set_gateway (NMIP6Address *address,
const struct in6_addr *addr); /* network byte order */
typedef struct NMIP6Route NMIP6Route;
NMIP6Route * nm_ip6_route_new (void);
@ -103,7 +98,7 @@ gboolean nm_ip6_route_compare (NMIP6Route *route, NMIP6Route
const struct in6_addr *nm_ip6_route_get_dest (NMIP6Route *route);
void nm_ip6_route_set_dest (NMIP6Route *route,
const struct in6_addr *dest); /* network byte order */
const struct in6_addr *dest);
guint32 nm_ip6_route_get_prefix (NMIP6Route *route);
void nm_ip6_route_set_prefix (NMIP6Route *route,
@ -111,7 +106,7 @@ void nm_ip6_route_set_prefix (NMIP6Route *route,
const struct in6_addr *nm_ip6_route_get_next_hop (NMIP6Route *route);
void nm_ip6_route_set_next_hop (NMIP6Route *route,
const struct in6_addr *next_hop); /* network byte order */
const struct in6_addr *next_hop);
guint32 nm_ip6_route_get_metric (NMIP6Route *route);
void nm_ip6_route_set_metric (NMIP6Route *route,
@ -125,40 +120,38 @@ typedef struct {
NMSettingClass parent;
} NMSettingIP6ConfigClass;
/* IPv6 support is currently incomplete. Do not use. */
GType nm_setting_ip6_config_get_type (void);
NMSetting * nm_setting_ip6_config_new (void);
const char * nm_setting_ip6_config_get_method (NMSettingIP6Config *setting);
NMSetting * nm_setting_ip6_config_new (void);
const char * nm_setting_ip6_config_get_method (NMSettingIP6Config *setting);
guint32 nm_setting_ip6_config_get_num_dns (NMSettingIP6Config *setting);
const struct in6_addr *nm_setting_ip6_config_get_dns (NMSettingIP6Config *setting, guint32 i);
gboolean nm_setting_ip6_config_add_dns (NMSettingIP6Config *setting, const struct in6_addr *dns);
void nm_setting_ip6_config_remove_dns (NMSettingIP6Config *setting, guint32 i);
void nm_setting_ip6_config_clear_dns (NMSettingIP6Config *setting);
guint32 nm_setting_ip6_config_get_num_dns (NMSettingIP6Config *setting);
const struct in6_addr *nm_setting_ip6_config_get_dns (NMSettingIP6Config *setting, guint32 i);
gboolean nm_setting_ip6_config_add_dns (NMSettingIP6Config *setting, const struct in6_addr *dns);
void nm_setting_ip6_config_remove_dns (NMSettingIP6Config *setting, guint32 i);
void nm_setting_ip6_config_clear_dns (NMSettingIP6Config *setting);
guint32 nm_setting_ip6_config_get_num_dns_searches (NMSettingIP6Config *setting);
const char * nm_setting_ip6_config_get_dns_search (NMSettingIP6Config *setting, guint32 i);
gboolean nm_setting_ip6_config_add_dns_search (NMSettingIP6Config *setting, const char *dns_search);
void nm_setting_ip6_config_remove_dns_search (NMSettingIP6Config *setting, guint32 i);
void nm_setting_ip6_config_clear_dns_searches (NMSettingIP6Config *setting);
guint32 nm_setting_ip6_config_get_num_dns_searches (NMSettingIP6Config *setting);
const char * nm_setting_ip6_config_get_dns_search (NMSettingIP6Config *setting, guint32 i);
gboolean nm_setting_ip6_config_add_dns_search (NMSettingIP6Config *setting, const char *dns_search);
void nm_setting_ip6_config_remove_dns_search (NMSettingIP6Config *setting, guint32 i);
void nm_setting_ip6_config_clear_dns_searches (NMSettingIP6Config *setting);
guint32 nm_setting_ip6_config_get_num_addresses (NMSettingIP6Config *setting);
NMIP6Address * nm_setting_ip6_config_get_address (NMSettingIP6Config *setting, guint32 i);
gboolean nm_setting_ip6_config_add_address (NMSettingIP6Config *setting, NMIP6Address *address);
void nm_setting_ip6_config_remove_address (NMSettingIP6Config *setting, guint32 i);
void nm_setting_ip6_config_clear_addresses (NMSettingIP6Config *setting);
guint32 nm_setting_ip6_config_get_num_addresses (NMSettingIP6Config *setting);
NMIP6Address * nm_setting_ip6_config_get_address (NMSettingIP6Config *setting, guint32 i);
gboolean nm_setting_ip6_config_add_address (NMSettingIP6Config *setting, NMIP6Address *address);
void nm_setting_ip6_config_remove_address (NMSettingIP6Config *setting, guint32 i);
void nm_setting_ip6_config_clear_addresses (NMSettingIP6Config *setting);
guint32 nm_setting_ip6_config_get_num_routes (NMSettingIP6Config *setting);
NMIP6Route * nm_setting_ip6_config_get_route (NMSettingIP6Config *setting, guint32 i);
gboolean nm_setting_ip6_config_add_route (NMSettingIP6Config *setting, NMIP6Route *route);
void nm_setting_ip6_config_remove_route (NMSettingIP6Config *setting, guint32 i);
void nm_setting_ip6_config_clear_routes (NMSettingIP6Config *setting);
guint32 nm_setting_ip6_config_get_num_routes (NMSettingIP6Config *setting);
NMIP6Route * nm_setting_ip6_config_get_route (NMSettingIP6Config *setting, guint32 i);
gboolean nm_setting_ip6_config_add_route (NMSettingIP6Config *setting, NMIP6Route *route);
void nm_setting_ip6_config_remove_route (NMSettingIP6Config *setting, guint32 i);
void nm_setting_ip6_config_clear_routes (NMSettingIP6Config *setting);
gboolean nm_setting_ip6_config_get_ignore_auto_routes (NMSettingIP6Config *setting);
gboolean nm_setting_ip6_config_get_ignore_auto_dns (NMSettingIP6Config *setting);
gboolean nm_setting_ip6_config_get_ignore_router_adv (NMSettingIP6Config *setting);
const char * nm_setting_ip6_config_get_dhcp_mode (NMSettingIP6Config *setting);
gboolean nm_setting_ip6_config_get_ignore_auto_dns (NMSettingIP6Config *setting);
gboolean nm_setting_ip6_config_get_never_default (NMSettingIP6Config *setting);
G_END_DECLS

View file

@ -0,0 +1,265 @@
/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
/*
* Dan Williams <dcbw@redhat.com>
* Tambet Ingo <tambet@gmail.com>
* Sjoerd Simons <sjoerd.simons@collabora.co.uk>
* Daniel Drake <dsd@laptop.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* (C) Copyright 2007 - 2008 Red Hat, Inc.
* (C) Copyright 2007 - 2008 Novell, Inc.
* (C) Copyright 2009 One Laptop per Child
*/
#include <string.h>
#include <netinet/ether.h>
#include <dbus/dbus-glib.h>
#include "NetworkManager.h"
#include "nm-setting-olpc-mesh.h"
#include "nm-param-spec-specialized.h"
#include "nm-utils.h"
#include "nm-dbus-glib-types.h"
#include "nm-utils-private.h"
GQuark
nm_setting_olpc_mesh_error_quark (void)
{
static GQuark quark;
if (G_UNLIKELY (!quark))
quark = g_quark_from_static_string ("nm-setting-wireless-mesh-error-quark");
return quark;
}
/* This should really be standard. */
#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
GType
nm_setting_olpc_mesh_error_get_type (void)
{
static GType etype = 0;
if (etype == 0) {
static const GEnumValue values[] = {
/* Unknown error. */
ENUM_ENTRY (NM_SETTING_OLPC_MESH_ERROR_UNKNOWN, "UnknownError"),
/* The specified property was invalid. */
ENUM_ENTRY (NM_SETTING_OLPC_MESH_ERROR_INVALID_PROPERTY, "InvalidProperty"),
/* The specified property was missing and is required. */
ENUM_ENTRY (NM_SETTING_OLPC_MESH_ERROR_MISSING_PROPERTY, "MissingProperty"),
{ 0, 0, 0 }
};
etype = g_enum_register_static ("NMSettingWirelessError", values);
}
return etype;
}
static void nm_setting_olpc_mesh_init (NMSettingOlpcMesh *setting);
G_DEFINE_TYPE (NMSettingOlpcMesh, nm_setting_olpc_mesh, NM_TYPE_SETTING)
#define NM_SETTING_OLPC_MESH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMeshPrivate))
typedef struct {
GByteArray *ssid;
guint32 channel;
GByteArray *dhcp_anycast_addr;
} NMSettingOlpcMeshPrivate;
enum {
PROP_0,
PROP_SSID,
PROP_CHANNEL,
PROP_DHCP_ANYCAST_ADDRESS,
LAST_PROP
};
static void
nm_setting_olpc_mesh_init (NMSettingOlpcMesh *setting)
{
g_object_set (setting, NM_SETTING_NAME, NM_SETTING_OLPC_MESH_SETTING_NAME, NULL);
}
const GByteArray *
nm_setting_olpc_mesh_get_ssid (NMSettingOlpcMesh *setting)
{
g_return_val_if_fail (NM_IS_SETTING_OLPC_MESH (setting), NULL);
return NM_SETTING_OLPC_MESH_GET_PRIVATE (setting)->ssid;
}
guint32
nm_setting_olpc_mesh_get_channel (NMSettingOlpcMesh *setting)
{
g_return_val_if_fail (NM_IS_SETTING_OLPC_MESH (setting), 0);
return NM_SETTING_OLPC_MESH_GET_PRIVATE (setting)->channel;
}
const GByteArray *
nm_setting_olpc_mesh_get_dhcp_anycast_address (NMSettingOlpcMesh *setting)
{
g_return_val_if_fail (NM_IS_SETTING_OLPC_MESH (setting), NULL);
return NM_SETTING_OLPC_MESH_GET_PRIVATE (setting)->dhcp_anycast_addr;
}
static gboolean
verify (NMSetting *setting, GSList *all_settings, GError **error)
{
NMSettingOlpcMeshPrivate *priv = NM_SETTING_OLPC_MESH_GET_PRIVATE (setting);
if (!priv->ssid) {
g_set_error (error,
NM_SETTING_OLPC_MESH_ERROR,
NM_SETTING_OLPC_MESH_ERROR_MISSING_PROPERTY,
NM_SETTING_OLPC_MESH_SSID);
return FALSE;
}
if (!priv->ssid->len || priv->ssid->len > 32) {
g_set_error (error,
NM_SETTING_OLPC_MESH_ERROR,
NM_SETTING_OLPC_MESH_ERROR_INVALID_PROPERTY,
NM_SETTING_OLPC_MESH_SSID);
return FALSE;
}
if (priv->channel == 0 || priv->channel > 13) {
g_set_error (error,
NM_SETTING_OLPC_MESH_ERROR,
NM_SETTING_OLPC_MESH_ERROR_INVALID_PROPERTY,
NM_SETTING_OLPC_MESH_CHANNEL);
return FALSE;
}
if (priv->dhcp_anycast_addr && priv->dhcp_anycast_addr->len != ETH_ALEN) {
g_set_error (error,
NM_SETTING_OLPC_MESH_ERROR,
NM_SETTING_OLPC_MESH_ERROR_INVALID_PROPERTY,
NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS);
return FALSE;
}
return TRUE;
}
static void
finalize (GObject *object)
{
NMSettingOlpcMeshPrivate *priv = NM_SETTING_OLPC_MESH_GET_PRIVATE (object);
if (priv->ssid)
g_byte_array_free (priv->ssid, TRUE);
if (priv->dhcp_anycast_addr)
g_byte_array_free (priv->dhcp_anycast_addr, TRUE);
G_OBJECT_CLASS (nm_setting_olpc_mesh_parent_class)->finalize (object);
}
static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
NMSettingOlpcMeshPrivate *priv = NM_SETTING_OLPC_MESH_GET_PRIVATE (object);
switch (prop_id) {
case PROP_SSID:
if (priv->ssid)
g_byte_array_free (priv->ssid, TRUE);
priv->ssid = g_value_dup_boxed (value);
break;
case PROP_CHANNEL:
priv->channel = g_value_get_uint (value);
break;
case PROP_DHCP_ANYCAST_ADDRESS:
if (priv->dhcp_anycast_addr)
g_byte_array_free (priv->dhcp_anycast_addr, TRUE);
priv->dhcp_anycast_addr = g_value_dup_boxed (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
NMSettingOlpcMesh *setting = NM_SETTING_OLPC_MESH (object);
switch (prop_id) {
case PROP_SSID:
g_value_set_boxed (value, nm_setting_olpc_mesh_get_ssid (setting));
break;
case PROP_CHANNEL:
g_value_set_uint (value, nm_setting_olpc_mesh_get_channel (setting));
break;
case PROP_DHCP_ANYCAST_ADDRESS:
g_value_set_boxed (value, nm_setting_olpc_mesh_get_dhcp_anycast_address (setting));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
nm_setting_olpc_mesh_class_init (NMSettingOlpcMeshClass *setting_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
g_type_class_add_private (setting_class, sizeof (NMSettingOlpcMeshPrivate));
/* virtual methods */
object_class->set_property = set_property;
object_class->get_property = get_property;
object_class->finalize = finalize;
parent_class->verify = verify;
/* Properties */
g_object_class_install_property
(object_class, PROP_SSID,
_nm_param_spec_specialized (NM_SETTING_OLPC_MESH_SSID,
"SSID",
"SSID",
DBUS_TYPE_G_UCHAR_ARRAY,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
g_object_class_install_property
(object_class, PROP_CHANNEL,
g_param_spec_uint (NM_SETTING_OLPC_MESH_CHANNEL,
"Channel",
"Channel",
0, G_MAXUINT32, 0,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
g_object_class_install_property
(object_class, PROP_DHCP_ANYCAST_ADDRESS,
_nm_param_spec_specialized (NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS,
"Anycast DHCP MAC address",
"Anycast DHCP MAC address",
DBUS_TYPE_G_UCHAR_ARRAY,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
}

View file

@ -0,0 +1,52 @@
/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
#ifndef NM_SETTING_OLPC_MESH_H
#define NM_SETTING_OLPC_MESH_H
#include <nm-setting.h>
G_BEGIN_DECLS
#define NM_TYPE_SETTING_OLPC_MESH (nm_setting_olpc_mesh_get_type ())
#define NM_SETTING_OLPC_MESH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMesh))
#define NM_SETTING_OLPC_MESH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMeshClass))
#define NM_IS_SETTING_OLPC_MESH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_OLPC_MESH))
#define NM_IS_SETTING_OLPC_MESH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTING_OLPC_MESH))
#define NM_SETTING_OLPC_MESH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMeshClass))
#define NM_SETTING_OLPC_MESH_SETTING_NAME "802-11-olpc-mesh"
typedef enum
{
NM_SETTING_OLPC_MESH_ERROR_UNKNOWN = 0,
NM_SETTING_OLPC_MESH_ERROR_INVALID_PROPERTY,
NM_SETTING_OLPC_MESH_ERROR_MISSING_PROPERTY
} NMSettingOlpcMeshError;
#define NM_TYPE_SETTING_OLPC_MESH_ERROR (nm_setting_olpc_mesh_error_get_type ())
GType nm_setting_olpc_mesh_error_get_type (void);
#define NM_SETTING_OLPC_MESH_ERROR nm_setting_olpc_mesh_error_quark ()
GQuark nm_setting_olpc_mesh_error_quark (void);
#define NM_SETTING_OLPC_MESH_SSID "ssid"
#define NM_SETTING_OLPC_MESH_CHANNEL "channel"
#define NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS "dhcp-anycast-address"
typedef struct {
NMSetting parent;
} NMSettingOlpcMesh;
typedef struct {
NMSettingClass parent;
} NMSettingOlpcMeshClass;
GType nm_setting_olpc_mesh_get_type (void);
const GByteArray *nm_setting_olpc_mesh_get_ssid (NMSettingOlpcMesh *setting);
guint32 nm_setting_olpc_mesh_get_channel (NMSettingOlpcMesh *setting);
const GByteArray *nm_setting_olpc_mesh_get_dhcp_anycast_address (NMSettingOlpcMesh *setting);
G_END_DECLS
#endif /* NM_SETTING_OLPC_MESH_H */

View file

@ -54,14 +54,6 @@
* access points and devices, among other things.
*/
/* IP6 currently incomplete */
GSList *nm_utils_ip6_addresses_from_gvalue (const GValue *value);
void nm_utils_ip6_addresses_to_gvalue (GSList *list, GValue *value);
GSList *nm_utils_ip6_dns_from_gvalue (const GValue *value);
void nm_utils_ip6_dns_to_gvalue (GSList *list, GValue *value);
struct EncodingTriplet
{
const char *encoding1;
@ -1228,14 +1220,13 @@ nm_utils_ip6_addresses_from_gvalue (const GValue *value)
for (i = 0; addresses && (i < addresses->len); i++) {
GValueArray *elements = (GValueArray *) g_ptr_array_index (addresses, i);
GValue *tmp;
GByteArray *ba_addr, *ba_gw;
GByteArray *ba_addr;
NMIP6Address *addr;
guint32 prefix;
if ( (elements->n_values != 3)
if ( (elements->n_values != 2)
|| (G_VALUE_TYPE (g_value_array_get_nth (elements, 0)) != DBUS_TYPE_G_UCHAR_ARRAY)
|| (G_VALUE_TYPE (g_value_array_get_nth (elements, 1)) != G_TYPE_UINT)
|| (G_VALUE_TYPE (g_value_array_get_nth (elements, 2)) != DBUS_TYPE_G_UCHAR_ARRAY)) {
|| (G_VALUE_TYPE (g_value_array_get_nth (elements, 1)) != G_TYPE_UINT)) {
nm_warning ("%s: ignoring invalid IP6 address structure", __func__);
continue;
}
@ -1256,18 +1247,9 @@ nm_utils_ip6_addresses_from_gvalue (const GValue *value)
continue;
}
tmp = g_value_array_get_nth (elements, 2);
ba_gw = g_value_get_boxed (tmp);
if (ba_gw->len != 16) {
nm_warning ("%s: ignoring invalid IP6 gateway of length %d",
__func__, ba_gw->len);
continue;
}
addr = nm_ip6_address_new ();
nm_ip6_address_set_prefix (addr, prefix);
nm_ip6_address_set_address (addr, (const struct in6_addr *) ba_addr->data);
nm_ip6_address_set_gateway (addr, (const struct in6_addr *) ba_gw->data);
list = g_slist_prepend (list, addr);
}
@ -1284,31 +1266,131 @@ nm_utils_ip6_addresses_to_gvalue (GSList *list, GValue *value)
for (iter = list; iter; iter = iter->next) {
NMIP6Address *addr = (NMIP6Address *) iter->data;
GValue element = { 0, };
GByteArray *ba_addr, *ba_gw;
GValueArray *array;
GValue element = {0, };
GByteArray *ba;
g_value_init (&element, DBUS_TYPE_G_IP6_ADDRESS);
g_value_take_boxed (&element, dbus_g_type_specialized_construct (DBUS_TYPE_G_IP6_ADDRESS));
array = g_value_array_new (2);
ba_addr = g_byte_array_sized_new (16);
g_byte_array_append (ba_addr, (guint8 *) nm_ip6_address_get_address (addr), 16);
ba_gw = g_byte_array_sized_new (16);
g_byte_array_append (ba_gw, (guint8 *) nm_ip6_address_get_gateway (addr), 16);
dbus_g_type_struct_set (&element,
0, ba_addr,
1, nm_ip6_address_get_prefix (addr),
2, ba_gw,
G_MAXUINT);
g_ptr_array_add (addresses, g_value_get_boxed (&element));
g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY);
ba = g_byte_array_new ();
g_byte_array_append (ba, (guint8 *) nm_ip6_address_get_address (addr), 16);
g_value_take_boxed (&element, ba);
g_value_array_append (array, &element);
g_value_unset (&element);
g_value_init (&element, G_TYPE_UINT);
g_value_set_uint (&element, nm_ip6_address_get_prefix (addr));
g_value_array_append (array, &element);
g_value_unset (&element);
g_ptr_array_add (addresses, array);
}
g_value_take_boxed (value, addresses);
}
GSList *
nm_utils_ip6_routes_from_gvalue (const GValue *value)
{
GPtrArray *routes;
int i;
GSList *list = NULL;
routes = (GPtrArray *) g_value_get_boxed (value);
for (i = 0; routes && (i < routes->len); i++) {
GValueArray *route_values = (GValueArray *) g_ptr_array_index (routes, i);
GByteArray *dest, *next_hop;
guint prefix, metric;
NMIP6Route *route;
if ( (route_values->n_values != 4)
|| (G_VALUE_TYPE (g_value_array_get_nth (route_values, 0)) != DBUS_TYPE_G_UCHAR_ARRAY)
|| (G_VALUE_TYPE (g_value_array_get_nth (route_values, 1)) != G_TYPE_UINT)
|| (G_VALUE_TYPE (g_value_array_get_nth (route_values, 2)) != DBUS_TYPE_G_UCHAR_ARRAY)
|| (G_VALUE_TYPE (g_value_array_get_nth (route_values, 3)) != G_TYPE_UINT)) {
nm_warning ("Ignoring invalid IP6 route");
continue;
}
dest = g_value_get_boxed (g_value_array_get_nth (route_values, 0));
if (dest->len != 16) {
nm_warning ("%s: ignoring invalid IP6 dest address of length %d",
__func__, dest->len);
continue;
}
prefix = g_value_get_uint (g_value_array_get_nth (route_values, 1));
next_hop = g_value_get_boxed (g_value_array_get_nth (route_values, 2));
if (next_hop->len != 16) {
nm_warning ("%s: ignoring invalid IP6 next_hop address of length %d",
__func__, next_hop->len);
continue;
}
metric = g_value_get_uint (g_value_array_get_nth (route_values, 3));
route = nm_ip6_route_new ();
nm_ip6_route_set_dest (route, (struct in6_addr *)dest->data);
nm_ip6_route_set_prefix (route, prefix);
nm_ip6_route_set_next_hop (route, (struct in6_addr *)next_hop->data);
nm_ip6_route_set_metric (route, metric);
list = g_slist_prepend (list, route);
}
return g_slist_reverse (list);
}
void
nm_utils_ip6_routes_to_gvalue (GSList *list, GValue *value)
{
GPtrArray *routes;
GSList *iter;
routes = g_ptr_array_new ();
for (iter = list; iter; iter = iter->next) {
NMIP6Route *route = (NMIP6Route *) iter->data;
GValueArray *array;
const struct in6_addr *addr;
GByteArray *ba;
GValue element = {0, };
array = g_value_array_new (4);
g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY);
addr = nm_ip6_route_get_dest (route);
ba = g_byte_array_new ();
g_byte_array_append (ba, (guchar *)addr, sizeof (*addr));
g_value_take_boxed (&element, ba);
g_value_array_append (array, &element);
g_value_unset (&element);
g_value_init (&element, G_TYPE_UINT);
g_value_set_uint (&element, nm_ip6_route_get_prefix (route));
g_value_array_append (array, &element);
g_value_unset (&element);
g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY);
addr = nm_ip6_route_get_next_hop (route);
ba = g_byte_array_new ();
g_byte_array_append (ba, (guchar *)addr, sizeof (*addr));
g_value_take_boxed (&element, ba);
g_value_array_append (array, &element);
g_value_unset (&element);
g_value_init (&element, G_TYPE_UINT);
g_value_set_uint (&element, nm_ip6_route_get_metric (route));
g_value_array_append (array, &element);
g_value_unset (&element);
g_ptr_array_add (routes, array);
}
g_value_take_boxed (value, routes);
}
GSList *
nm_utils_ip6_dns_from_gvalue (const GValue *value)
{

View file

@ -193,6 +193,15 @@ void nm_utils_ip4_routes_to_gvalue (GSList *list, GValue *value);
guint32 nm_utils_ip4_netmask_to_prefix (guint32 netmask);
guint32 nm_utils_ip4_prefix_to_netmask (guint32 prefix);
GSList *nm_utils_ip6_addresses_from_gvalue (const GValue *value);
void nm_utils_ip6_addresses_to_gvalue (GSList *list, GValue *value);
GSList *nm_utils_ip6_routes_from_gvalue (const GValue *value);
void nm_utils_ip6_routes_to_gvalue (GSList *list, GValue *value);
GSList *nm_utils_ip6_dns_from_gvalue (const GValue *value);
void nm_utils_ip6_dns_to_gvalue (GSList *list, GValue *value);
char *nm_utils_uuid_generate (void);
char *nm_utils_uuid_generate_from_string (const char *s);

View file

@ -5,8 +5,6 @@ dist_polkit_policy_DATA = $(dist_polkit_policy_in_files:.policy.in=.policy)
@INTLTOOL_POLICY_RULE@
EXTRA_DIST = $(dist_polkit_policy_in_files)
check:
@for f in $(dist_polkit_policy_DATA); do \
echo -n "Validate PolicyKit policy in $$f : "; \

View file

@ -68,6 +68,8 @@ NetworkManager_SOURCES = \
nm-device-ethernet.h \
nm-device-wifi.c \
nm-device-wifi.h \
nm-device-olpc-mesh.c \
nm-device-olpc-mesh.h \
nm-device-bt.c \
nm-device-bt.h \
NetworkManagerAP.c \
@ -80,6 +82,8 @@ NetworkManager_SOURCES = \
nm-hostname-provider.h \
nm-ip4-config.c \
nm-ip4-config.h \
nm-ip6-config.c \
nm-ip6-config.h \
nm-secrets-provider-interface.c \
nm-secrets-provider-interface.h \
nm-active-connection.h \
@ -126,9 +130,15 @@ nm-device-wifi-glue.h: $(top_srcdir)/introspection/nm-device-wifi.xml
nm-device-bt-glue.h: $(top_srcdir)/introspection/nm-device-bt.xml
dbus-binding-tool --prefix=nm_device_bt --mode=glib-server --output=$@ $<
nm-device-olpc-mesh-glue.h: $(top_srcdir)/introspection/nm-device-olpc-mesh.xml
dbus-binding-tool --prefix=nm_device_olpc_mesh --mode=glib-server --output=$@ $<
nm-ip4-config-glue.h: $(top_srcdir)/introspection/nm-ip4-config.xml
dbus-binding-tool --prefix=nm_ip4_config --mode=glib-server --output=$@ $<
nm-ip6-config-glue.h: $(top_srcdir)/introspection/nm-ip6-config.xml
dbus-binding-tool --prefix=nm_ip6_config --mode=glib-server --output=$@ $<
nm-active-connection-glue.h: $(top_srcdir)/introspection/nm-active-connection.xml
dbus-binding-tool --prefix=nm_active_connection --mode=glib-server --output=$@ $<
@ -141,8 +151,10 @@ BUILT_SOURCES = \
nm-device-interface-glue.h \
nm-device-ethernet-glue.h \
nm-device-wifi-glue.h \
nm-device-olpc-mesh-glue.h \
nm-device-bt-glue.h \
nm-ip4-config-glue.h \
nm-ip6-config-glue.h \
nm-active-connection-glue.h \
nm-dhcp4-config-glue.h

View file

@ -4,10 +4,10 @@
<busconfig>
<policy user="root">
<allow own="org.freedesktop.NetworkManager"/>
<allow own="org.freedesktop.NetworkManagerSystemSettings"/>
<allow own="org.freedesktop.NetworkManagerSystemSettings"/>
<allow send_destination="org.freedesktop.NetworkManager"/>
<allow send_destination="org.freedesktop.NetworkManagerSystemSettings"/>
<allow send_destination="org.freedesktop.NetworkManagerSystemSettings"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager.PPP"/>
@ -15,58 +15,58 @@
<policy at_console="true">
<allow send_destination="org.freedesktop.NetworkManager"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.DBus.Introspectable"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.DBus.Introspectable"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.DBus.Properties"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.DBus.Properties"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager.AccessPoint"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager.AccessPoint"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager.Connection.Active"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager.Connection.Active"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager.Device.Cdma"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager.Device.Cdma"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager.Device.Wired"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager.Device.Wired"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager.Device.Gsm"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager.Device.Gsm"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager.Device.Serial"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager.Device.Serial"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager.Device.Wireless"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager.Device.Wireless"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager.Device"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager.Device"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager.DHCP4Config"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager.DHCP4Config"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager.IP4Config"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager.IP4Config"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager.VPN.Connection"/>
<allow send_destination="org.freedesktop.NetworkManager"
send_interface="org.freedesktop.NetworkManager.VPN.Connection"/>
</policy>
<policy context="default">
<deny own="org.freedesktop.NetworkManager"/>
<deny own="org.freedesktop.NetworkManagerSystemSettings"/>
<deny own="org.freedesktop.NetworkManagerSystemSettings"/>
<deny send_destination="org.freedesktop.NetworkManager"/>
<allow send_destination="org.freedesktop.NetworkManagerSystemSettings"/>
<allow send_destination="org.freedesktop.NetworkManagerSystemSettings"/>
<!-- The org.freedesktop.NetworkManagerSettings.Connection.Secrets
interface is secured via PolicyKit.
-->
<!-- The org.freedesktop.NetworkManagerSettings.Connection.Secrets
interface is secured via PolicyKit.
-->
</policy>
<limit name="max_replies_per_connection">512</limit>

View file

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

View file

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

View file

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

View file

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

View file

@ -18,6 +18,10 @@
* Copyright (C) 2005 - 2008 Red Hat, Inc.
*/
#define _XOPEN_SOURCE
#include <time.h>
#undef _XOPEN_SOURCE
#include <glib.h>
#include <glib/gi18n.h>
#include <dbus/dbus.h>
@ -74,6 +78,206 @@ get_leasefile_for_iface (const char * iface, const char *uuid)
NM_DHCP_MANAGER_LEASE_FILE_EXT);
}
static void
add_lease_option (GHashTable *hash, char *line)
{
char *spc;
spc = strchr (line, ' ');
if (!spc) {
g_warning ("%s: line '%s' did not contain a space", __func__, line);
return;
}
/* If it's an 'option' line, split at second space */
if (g_str_has_prefix (line, "option ")) {
spc = strchr (spc + 1, ' ');
if (!spc) {
g_warning ("%s: option line '%s' did not contain a second space",
__func__, line);
return;
}
}
/* Split the line at the space */
*spc = '\0';
spc++;
/* Kill the ';' at the end of the line, if any */
if (*(spc + strlen (spc) - 1) == ';')
*(spc + strlen (spc) - 1) = '\0';
/* Treat 'interface' specially */
if (g_str_has_prefix (line, "interface")) {
if (*(spc) == '"')
spc++; /* Jump past the " */
if (*(spc + strlen (spc) - 1) == '"')
*(spc + strlen (spc) - 1) = '\0'; /* Kill trailing " */
}
g_hash_table_insert (hash, g_strdup (line), g_strdup (spc));
}
GSList *
nm_dhcp_client_get_lease_ip4_config (const char *iface, const char *uuid)
{
GSList *parsed = NULL, *iter, *leases = NULL;
char *contents = NULL;
char *leasefile;
char **line, **split = NULL;
GHashTable *hash = NULL;
leasefile = get_leasefile_for_iface (iface, uuid);
if (!leasefile)
return NULL;
if (!g_file_test (leasefile, G_FILE_TEST_EXISTS))
goto out;
if (!g_file_get_contents (leasefile, &contents, NULL, NULL))
goto out;
split = g_strsplit_set (contents, "\n\r", -1);
g_free (contents);
if (!split)
goto out;
for (line = split; line && *line; line++) {
*line = g_strstrip (*line);
if (!strcmp (*line, "}")) {
/* Lease ends */
parsed = g_slist_append (parsed, hash);
hash = NULL;
} else if (!strcmp (*line, "lease {")) {
/* Beginning of a new lease */
if (hash) {
g_warning ("%s: lease file %s malformed; new lease started "
"without ending previous lease",
__func__, leasefile);
g_hash_table_destroy (hash);
}
hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
} else if (strlen (*line))
add_lease_option (hash, *line);
}
g_strfreev (split);
/* Check if the last lease in the file was properly ended */
if (hash) {
g_warning ("%s: lease file %s malformed; new lease started "
"without ending previous lease",
__func__, leasefile);
g_hash_table_destroy (hash);
hash = NULL;
}
for (iter = parsed; iter; iter = g_slist_next (iter)) {
NMIP4Config *ip4;
NMIP4Address *addr;
const char *data;
struct in_addr tmp;
guint32 prefix;
struct tm expire;
hash = iter->data;
/* Make sure this lease is for the interface we want */
data = g_hash_table_lookup (hash, "interface");
if (!data || strcmp (data, iface))
continue;
data = g_hash_table_lookup (hash, "expire");
if (data) {
time_t now_tt;
struct tm *now;
/* Read lease expiration (in UTC) */
if (!strptime (data, "%w %Y/%m/%d %H:%M:%S", &expire)) {
g_warning ("%s: couldn't parse expire time '%s'",
__func__, data);
continue;
}
now_tt = time (NULL);
now = gmtime(&now_tt);
/* Ignore this lease if it's already expired */
if (expire.tm_year < now->tm_year)
continue;
else if (expire.tm_year == now->tm_year) {
if (expire.tm_mon < now->tm_mon)
continue;
else if (expire.tm_mon == now->tm_mon) {
if (expire.tm_mday < now->tm_mday)
continue;
else if (expire.tm_mday == now->tm_mday) {
if (expire.tm_hour < now->tm_hour)
continue;
else if (expire.tm_hour == now->tm_hour) {
if (expire.tm_min < now->tm_min)
continue;
else if (expire.tm_min == now->tm_min) {
if (expire.tm_sec <= now->tm_sec)
continue;
}
}
}
}
}
/* If we get this far, the lease hasn't expired */
}
data = g_hash_table_lookup (hash, "fixed-address");
if (!data)
continue;
ip4 = nm_ip4_config_new ();
addr = nm_ip4_address_new ();
/* IP4 address */
if (!inet_pton (AF_INET, data, &tmp)) {
g_warning ("%s: couldn't parse IP4 address '%s'", __func__, data);
goto error;
}
nm_ip4_address_set_address (addr, tmp.s_addr);
/* Netmask */
data = g_hash_table_lookup (hash, "option subnet-mask");
if (!data)
data = "255.255.255.0"; /* FIXME: assume class C? */
if (!inet_pton (AF_INET, data, &tmp)) {
g_warning ("%s: couldn't parse IP4 subnet mask '%s'", __func__, data);
goto error;
}
prefix = nm_utils_ip4_netmask_to_prefix (tmp.s_addr);
nm_ip4_address_set_prefix (addr, prefix);
/* Gateway */
data = g_hash_table_lookup (hash, "option routers");
if (data) {
if (!inet_pton (AF_INET, data, &tmp)) {
g_warning ("%s: couldn't parse IP4 gateway '%s'", __func__, data);
goto error;
}
nm_ip4_address_set_gateway (addr, tmp.s_addr);
}
nm_ip4_config_take_address (ip4, addr);
leases = g_slist_append (leases, ip4);
continue;
error:
nm_ip4_address_unref (addr);
g_object_unref (ip4);
}
out:
g_slist_foreach (parsed, (GFunc) g_hash_table_destroy, NULL);
g_free (leasefile);
return leases;
}
#define DHCP_CLIENT_ID_TAG "send dhcp-client-identifier"

View file

@ -49,6 +49,11 @@ get_pidfile_for_iface (const char * iface)
NM_DHCP_MANAGER_PID_FILE_EXT);
}
GSList *
nm_dhcp_client_get_lease_ip4_config (const char *iface, const char *uuid)
{
return NULL;
}
static void
dhcpcd_child_setup (gpointer user_data G_GNUC_UNUSED)

View file

@ -1121,3 +1121,16 @@ nm_dhcp_manager_set_hostname_provider (NMDHCPManager *manager,
g_object_weak_ref (G_OBJECT (provider), hostname_provider_destroyed, manager);
}
}
GSList *
nm_dhcp_manager_get_lease_ip4_config (NMDHCPManager *self,
const char *iface,
const char *uuid)
{
g_return_val_if_fail (NM_IS_DHCP_MANAGER (self), NULL);
g_return_val_if_fail (iface != NULL, NULL);
g_return_val_if_fail (uuid != NULL, NULL);
return nm_dhcp_client_get_lease_ip4_config (iface, uuid);
}

View file

@ -107,6 +107,10 @@ gboolean nm_dhcp_manager_foreach_dhcp4_option (NMDHCPManager *self,
GHFunc func,
gpointer user_data);
GSList * nm_dhcp_manager_get_lease_ip4_config (NMDHCPManager *self,
const char *iface,
const char *uuid);
/* The following are implemented by the DHCP client backends */
GPid nm_dhcp_client_start (NMDHCPDevice *device,
const char *uuid,
@ -118,6 +122,9 @@ gboolean nm_dhcp_client_process_classless_routes (GHashTable *options,
NMIP4Config *ip4_config,
guint32 *gwaddr);
GSList * nm_dhcp_client_get_lease_ip4_config (const char *iface,
const char *uuid);
/* Test functions */
NMIP4Config *nm_dhcp_manager_options_to_ip4_config (const char *iface,
GHashTable *options);

View file

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

View file

@ -63,8 +63,6 @@ struct NMNamedManagerPrivate {
NMIP4Config * vpn_config;
NMIP4Config * device_config;
GSList * configs;
gboolean disposed;
};
@ -94,29 +92,71 @@ nm_named_manager_error_quark (void)
return quark;
}
typedef struct {
GPtrArray *nameservers;
const char *domain;
GPtrArray *searches;
} NMResolvConfData;
static void
merge_one_ip4_config (NMIP4Config *dst, NMIP4Config *src)
merge_one_ip4_config (NMResolvConfData *rc, NMIP4Config *src)
{
guint32 num, num_domains, i;
guint32 num, i;
num = nm_ip4_config_get_num_nameservers (src);
for (i = 0; i < num; i++)
nm_ip4_config_add_nameserver (dst, nm_ip4_config_get_nameserver (src, i));
for (i = 0; i < num; i++) {
struct in_addr addr;
char buf[INET_ADDRSTRLEN];
num_domains = nm_ip4_config_get_num_domains (src);
for (i = 0; i < num_domains; i++)
nm_ip4_config_add_domain (dst, nm_ip4_config_get_domain (src, i));
addr.s_addr = nm_ip4_config_get_nameserver (src, i);
if (inet_ntop (AF_INET, &addr, buf, INET_ADDRSTRLEN) > 0)
g_ptr_array_add (rc->nameservers, g_strdup (buf));
}
num = nm_ip4_config_get_num_domains (src);
for (i = 0; i < num; i++) {
if (!rc->domain)
rc->domain = nm_ip4_config_get_domain (src, i);
g_ptr_array_add (rc->searches, g_strdup (nm_ip4_config_get_domain (src, i)));
}
num = nm_ip4_config_get_num_searches (src);
for (i = 0; i < num; i++)
nm_ip4_config_add_search (dst, nm_ip4_config_get_search (src, i));
g_ptr_array_add (rc->searches, g_strdup (nm_ip4_config_get_search (src, i)));
}
/* Add the 'domain' list to searches as well since overloading the
* 'domain_name' DHCP field used to be the way you got searches
* into resolv.conf.
*/
for (i = 0; i < num_domains; i++)
nm_ip4_config_add_search (dst, nm_ip4_config_get_domain (src, i));
static void
merge_one_ip6_config (NMResolvConfData *rc, NMIP6Config *src)
{
guint32 num, i;
num = nm_ip6_config_get_num_nameservers (src);
for (i = 0; i < num; i++) {
const struct in6_addr *addr;
char buf[INET6_ADDRSTRLEN];
addr = nm_ip6_config_get_nameserver (src, i);
/* inet_ntop is probably supposed to do this for us, but it doesn't */
if (IN6_IS_ADDR_V4MAPPED (addr)) {
if (inet_ntop (AF_INET, &(addr->s6_addr32[3]), buf, INET_ADDRSTRLEN) > 0)
g_ptr_array_add (rc->nameservers, g_strdup (buf));
} else {
if (inet_ntop (AF_INET6, addr, buf, INET6_ADDRSTRLEN) > 0)
g_ptr_array_add (rc->nameservers, g_strdup (buf));
}
}
num = nm_ip6_config_get_num_domains (src);
for (i = 0; i < num; i++) {
if (!rc->domain)
rc->domain = nm_ip6_config_get_domain (src, i);
g_ptr_array_add (rc->searches, g_strdup (nm_ip6_config_get_domain (src, i)));
}
num = nm_ip6_config_get_num_searches (src);
for (i = 0; i < num; i++)
g_ptr_array_add (rc->searches, g_strdup (nm_ip6_config_get_search (src, i)));
}
@ -183,6 +223,15 @@ dispatch_netconfig (const char *domain,
if (pid < 0)
return FALSE;
// FIXME: this is wrong. We are not writing out the iface-specific
// resolv.conf data, we are writing out an already-fully-merged
// resolv.conf. Assuming netconfig works in the obvious way, then
// there are various failure modes, such as, eg, bringing up a VPN on
// eth0, then bringing up wlan0, then bringing down the VPN. Because
// NMNamedManager would have claimed that the VPN DNS server was also
// part of the wlan0 config, it will remain in resolv.conf after the
// VPN goes down, even though it is presumably no longer reachable
// at that point.
write_to_netconfig (fd, "INTERFACE", iface);
if (searches) {
@ -391,50 +440,16 @@ update_resolv_conf (const char *domain,
return *error ? FALSE : TRUE;
}
static char **
compute_searches (guint32 num, NMIP4Config *config, gboolean searches)
{
GPtrArray *array;
size_t len, elem_len;
const char *elem;
int i;
/* Search list is limited to 6 domains total per 'man resolv.conf' */
if (num > 6)
num = 6;
array = g_ptr_array_sized_new (num + 1);
for (i = 0, len = 0; i < num; i++) {
elem = searches ? nm_ip4_config_get_search (config, i)
: nm_ip4_config_get_domain (config, i);
elem_len = strlen (elem);
/* The search list is limited to 256 characters per 'man resolv.conf' */
if (len + elem_len > 255)
break;
g_ptr_array_add (array, g_strdup (elem));
len += elem_len + 1; /* +1 for spaces */
}
g_ptr_array_add (array, NULL);
return (char **) g_ptr_array_free (array, FALSE);
}
static gboolean
rewrite_resolv_conf (NMNamedManager *mgr, const char *iface, GError **error)
{
NMNamedManagerPrivate *priv;
NMIP4Config *composite;
NMResolvConfData rc;
GSList *iter;
GPtrArray *array;
const char *domain = NULL;
char **searches = NULL;
char **nameservers = NULL;
int num_domains;
int num_searches;
int num_nameservers;
int i;
int num, i, len;
gboolean success = FALSE;
g_return_val_if_fail (error != NULL, FALSE);
@ -442,66 +457,54 @@ rewrite_resolv_conf (NMNamedManager *mgr, const char *iface, GError **error)
priv = NM_NAMED_MANAGER_GET_PRIVATE (mgr);
/* Construct the composite config from all the currently active IP4Configs */
composite = nm_ip4_config_new ();
rc.nameservers = g_ptr_array_new ();
rc.domain = NULL;
rc.searches = g_ptr_array_new ();
if (priv->vpn_config)
merge_one_ip4_config (composite, priv->vpn_config);
merge_one_ip4_config (&rc, priv->vpn_config);
if (priv->device_config)
merge_one_ip4_config (composite, priv->device_config);
merge_one_ip4_config (&rc, priv->device_config);
for (iter = priv->configs; iter; iter = g_slist_next (iter)) {
NMIP4Config *config = NM_IP4_CONFIG (iter->data);
if (NM_IS_IP4_CONFIG (iter->data)) {
NMIP4Config *config = NM_IP4_CONFIG (iter->data);
if ((config == priv->vpn_config) || (config == priv->device_config))
continue;
merge_one_ip4_config (composite, config);
}
/* Some DHCP servers like to put multiple search paths into the domain
* option as the domain-search option wasn't around in the first RFC.
* We should try and support these old servers as best we can. */
num_domains = nm_ip4_config_get_num_domains (composite);
num_searches = nm_ip4_config_get_num_searches (composite);
/* Domain */
if (num_domains > 0)
domain = nm_ip4_config_get_domain (composite, 0);
/* Searches */
if (num_searches > 0)
searches = compute_searches (num_searches, composite, TRUE);
else if (num_domains > 0)
searches = compute_searches (num_searches, composite, FALSE);
/* Name servers */
num_nameservers = nm_ip4_config_get_num_nameservers (composite);
if (num_nameservers > 0) {
array = g_ptr_array_sized_new (num_nameservers + 1);
for (i = 0; i < num_nameservers; i++) {
struct in_addr addr;
char *buf;
addr.s_addr = nm_ip4_config_get_nameserver (composite, i);
buf = g_malloc0 (ADDR_BUF_LEN);
if (!buf)
if ((config == priv->vpn_config) || (config == priv->device_config))
continue;
if (inet_ntop (AF_INET, &addr, buf, ADDR_BUF_LEN))
g_ptr_array_add (array, buf);
else
nm_warning ("%s: error converting IP4 address 0x%X",
__func__, ntohl (addr.s_addr));
}
merge_one_ip4_config (&rc, config);
} else {
NMIP6Config *config = NM_IP6_CONFIG (iter->data);
g_ptr_array_add (array, NULL);
nameservers = (char **) g_ptr_array_free (array, FALSE);
merge_one_ip6_config (&rc, config);
}
}
g_object_unref (composite);
domain = rc.domain;
/* Per 'man resolv.conf', the search list is limited to 6 domains
* totalling 256 characters.
*/
num = MIN (rc.searches->len, 6);
for (i = 0, len = 0; i < num; i++) {
len += strlen (rc.searches->pdata[i]) + 1; /* +1 for spaces */
if (len > 256)
break;
}
g_ptr_array_set_size (rc.searches, i);
if (rc.searches->len) {
g_ptr_array_add (rc.searches, NULL);
searches = (char **) g_ptr_array_free (rc.searches, FALSE);
} else
g_ptr_array_free (rc.searches, TRUE);
if (rc.nameservers->len) {
g_ptr_array_add (rc.nameservers, NULL);
nameservers = (char **) g_ptr_array_free (rc.nameservers, FALSE);
} else
g_ptr_array_free (rc.nameservers, TRUE);
#ifdef RESOLVCONF_PATH
success = dispatch_resolvconf (domain, searches, nameservers, iface, error);
@ -518,17 +521,19 @@ rewrite_resolv_conf (NMNamedManager *mgr, const char *iface, GError **error)
if (success)
nm_system_update_dns ();
g_strfreev (searches);
g_strfreev (nameservers);
if (searches)
g_strfreev (searches);
if (nameservers)
g_strfreev (nameservers);
return success;
}
gboolean
nm_named_manager_add_ip4_config (NMNamedManager *mgr,
const char *iface,
NMIP4Config *config,
NMNamedIPConfigType cfg_type)
const char *iface,
NMIP4Config *config,
NMNamedIPConfigType cfg_type)
{
NMNamedManagerPrivate *priv;
GError *error = NULL;
@ -564,8 +569,8 @@ nm_named_manager_add_ip4_config (NMNamedManager *mgr,
gboolean
nm_named_manager_remove_ip4_config (NMNamedManager *mgr,
const char *iface,
NMIP4Config *config)
const char *iface,
NMIP4Config *config)
{
NMNamedManagerPrivate *priv;
GError *error = NULL;
@ -588,6 +593,66 @@ nm_named_manager_remove_ip4_config (NMNamedManager *mgr,
if (config == priv->device_config)
priv->device_config = NULL;
g_object_unref (config);
if (!rewrite_resolv_conf (mgr, iface, &error)) {
nm_warning ("Could not commit DNS changes. Error: '%s'", error ? error->message : "(none)");
if (error)
g_error_free (error);
}
return TRUE;
}
gboolean
nm_named_manager_add_ip6_config (NMNamedManager *mgr,
const char *iface,
NMIP6Config *config,
NMNamedIPConfigType cfg_type)
{
NMNamedManagerPrivate *priv;
GError *error = NULL;
g_return_val_if_fail (mgr != NULL, FALSE);
g_return_val_if_fail (iface != NULL, FALSE);
g_return_val_if_fail (config != NULL, FALSE);
g_return_val_if_fail (cfg_type == NM_NAMED_IP_CONFIG_TYPE_DEFAULT, FALSE);
priv = NM_NAMED_MANAGER_GET_PRIVATE (mgr);
/* Don't allow the same zone added twice */
if (!g_slist_find (priv->configs, config))
priv->configs = g_slist_append (priv->configs, g_object_ref (config));
if (!rewrite_resolv_conf (mgr, iface, &error)) {
nm_warning ("Could not commit DNS changes. Error: '%s'", error ? error->message : "(none)");
g_error_free (error);
}
return TRUE;
}
gboolean
nm_named_manager_remove_ip6_config (NMNamedManager *mgr,
const char *iface,
NMIP6Config *config)
{
NMNamedManagerPrivate *priv;
GError *error = NULL;
g_return_val_if_fail (mgr != NULL, FALSE);
g_return_val_if_fail (iface != NULL, FALSE);
g_return_val_if_fail (config != NULL, FALSE);
priv = NM_NAMED_MANAGER_GET_PRIVATE (mgr);
/* Can't remove it if it wasn't in the list to begin with */
if (!g_slist_find (priv->configs, config))
return FALSE;
priv->configs = g_slist_remove (priv->configs, config);
g_object_unref (config);
if (!rewrite_resolv_conf (mgr, iface, &error)) {

View file

@ -28,6 +28,7 @@
#include <glib-object.h>
#include <dbus/dbus.h>
#include "nm-ip4-config.h"
#include "nm-ip6-config.h"
typedef enum {
NM_NAMED_MANAGER_ERROR_SYSTEM,
@ -69,13 +70,22 @@ GType nm_named_manager_get_type (void);
NMNamedManager * nm_named_manager_get (void);
gboolean nm_named_manager_add_ip4_config (NMNamedManager *mgr,
const char *iface,
const char *iface,
NMIP4Config *config,
NMNamedIPConfigType cfg_type);
gboolean nm_named_manager_remove_ip4_config (NMNamedManager *mgr,
const char *iface,
NMIP4Config *config);
const char *iface,
NMIP4Config *config);
gboolean nm_named_manager_add_ip6_config (NMNamedManager *mgr,
const char *iface,
NMIP6Config *config,
NMNamedIPConfigType cfg_type);
gboolean nm_named_manager_remove_ip6_config (NMNamedManager *mgr,
const char *iface,
NMIP6Config *config);
G_END_DECLS

View file

@ -76,6 +76,8 @@ typedef struct {
GSList *share_rules;
char *ac_path;
gboolean assumed;
} NMActRequestPrivate;
enum {
@ -136,6 +138,7 @@ NMActRequest *
nm_act_request_new (NMConnection *connection,
const char *specific_object,
gboolean user_requested,
gboolean assumed,
gpointer *device)
{
GObject *object;
@ -160,6 +163,7 @@ nm_act_request_new (NMConnection *connection,
NM_ACT_REQUEST (object));
priv->user_requested = user_requested;
priv->assumed = assumed;
return NM_ACT_REQUEST (object);
}
@ -643,3 +647,11 @@ nm_act_request_get_device (NMActRequest *req)
return G_OBJECT (NM_ACT_REQUEST_GET_PRIVATE (req)->device);
}
gboolean
nm_act_request_get_assumed (NMActRequest *req)
{
g_return_val_if_fail (NM_IS_ACT_REQUEST (req), FALSE);
return NM_ACT_REQUEST_GET_PRIVATE (req)->assumed;
}

View file

@ -59,6 +59,7 @@ GType nm_act_request_get_type (void);
NMActRequest *nm_act_request_new (NMConnection *connection,
const char *specific_object,
gboolean user_requested,
gboolean assumed,
gpointer *device); /* An NMDevice */
NMConnection *nm_act_request_get_connection (NMActRequest *req);
@ -85,6 +86,8 @@ void nm_act_request_add_share_rule (NMActRequest *req,
GObject * nm_act_request_get_device (NMActRequest *req);
gboolean nm_act_request_get_assumed (NMActRequest *req);
gboolean nm_act_request_get_secrets (NMActRequest *req,
const char *setting_name,
gboolean request_new,

View file

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

View file

@ -53,6 +53,7 @@
#include "ppp-manager/nm-ppp-manager.h"
#include "nm-utils.h"
#include "nm-properties-changed-signal.h"
#include "nm-dhcp-manager.h"
#include "nm-device-ethernet-glue.h"
@ -280,8 +281,8 @@ constructor (GType type,
guint32 caps;
object = G_OBJECT_CLASS (nm_device_ethernet_parent_class)->constructor (type,
n_construct_params,
construct_params);
n_construct_params,
construct_params);
if (!object)
return NULL;
@ -1255,7 +1256,7 @@ ppp_ip4_config (NMPPPManager *ppp_manager,
nm_device_set_ip_iface (device, iface);
NM_DEVICE_ETHERNET_GET_PRIVATE (device)->pending_ip4_config = g_object_ref (config);
nm_device_activate_schedule_stage4_ip_config_get (device);
nm_device_activate_schedule_stage4_ip4_config_get (device);
}
static NMActStageReturn
@ -1472,6 +1473,196 @@ spec_match_list (NMDevice *device, const GSList *specs)
return matched;
}
static gboolean
wired_match_config (NMDevice *self, NMConnection *connection)
{
NMSettingWired *s_wired;
struct ether_addr ether;
const GByteArray *s_ether;
s_wired = (NMSettingWired *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED);
if (!s_wired)
return FALSE;
/* MAC address check */
s_ether = nm_setting_wired_get_mac_address (s_wired);
if (s_ether) {
nm_device_ethernet_get_address (NM_DEVICE_ETHERNET (self), &ether);
if (memcmp (s_ether->data, ether.ether_addr_octet, ETH_ALEN))
return FALSE;
}
return TRUE;
}
typedef struct {
int ifindex;
NMIP4Address *addr;
gboolean found;
} AddrData;
static void
check_one_address (struct nl_object *object, void *user_data)
{
AddrData *data = user_data;
struct rtnl_addr *addr = (struct rtnl_addr *) object;
struct nl_addr *local;
struct in_addr tmp;
if (rtnl_addr_get_ifindex (addr) != data->ifindex)
return;
if (rtnl_addr_get_family (addr) != AF_INET)
return;
if (nm_ip4_address_get_prefix (data->addr) != rtnl_addr_get_prefixlen (addr))
return;
local = rtnl_addr_get_local (addr);
if (nl_addr_get_family (local) != AF_INET)
return;
if (nl_addr_get_len (local) != sizeof (struct in_addr))
return;
if (!nl_addr_get_binary_addr (local))
return;
memcpy (&tmp, nl_addr_get_binary_addr (local), nl_addr_get_len (local));
if (tmp.s_addr != nm_ip4_address_get_address (data->addr))
return;
/* Yay, found it */
data->found = TRUE;
}
static gboolean
ip4_match_config (NMDevice *self, NMConnection *connection)
{
NMSettingIP4Config *s_ip4;
NMSettingConnection *s_con;
struct nl_handle *nlh = NULL;
struct nl_cache *addr_cache = NULL;
int i, num;
GSList *leases, *iter;
NMDHCPManager *dhcp_mgr;
const char *method;
int ifindex;
AddrData check_data;
ifindex = nm_device_ethernet_get_ifindex (NM_DEVICE_ETHERNET (self));
s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
g_assert (s_con);
g_assert (nm_setting_connection_get_uuid (s_con));
s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
if (!s_ip4)
return FALSE;
/* Read all the device's IP addresses */
nlh = nm_netlink_get_default_handle ();
if (!nlh)
return FALSE;
addr_cache = rtnl_addr_alloc_cache (nlh);
if (!addr_cache)
return FALSE;
nl_cache_mngt_provide (addr_cache);
/* Get any saved leases that apply to this connection */
dhcp_mgr = nm_dhcp_manager_get ();
leases = nm_dhcp_manager_get_lease_ip4_config (dhcp_mgr,
nm_device_get_iface (self),
nm_setting_connection_get_uuid (s_con));
g_object_unref (dhcp_mgr);
method = nm_setting_ip4_config_get_method (s_ip4);
if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) {
gboolean found = FALSE;
/* Find at least one lease's address on the device */
for (iter = leases; iter; iter = g_slist_next (iter)) {
NMIP4Config *addr = iter->data;
memset (&check_data, 0, sizeof (check_data));
check_data.ifindex = ifindex;
check_data.found = FALSE;
check_data.addr = nm_ip4_config_get_address (addr, 0);
nl_cache_foreach (addr_cache, check_one_address, &check_data);
if (check_data.found) {
found = TRUE; /* Yay, device has same address as a lease */
break;
}
}
g_slist_foreach (leases, (GFunc) g_object_unref, NULL);
g_slist_free (leases);
return found;
} else {
/* Maybe the connection used to be DHCP and there are stale leases; ignore them */
g_slist_foreach (leases, (GFunc) g_object_unref, NULL);
g_slist_free (leases);
}
/* 'shared' and 'link-local' aren't supported methods because 'shared'
* requires too much iptables and dnsmasq state to be reclaimed, and
* avahi-autoipd isn't smart enough to allow the link-local address to be
* determined at any point other than when it was first assigned.
*/
if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL))
return FALSE;
/* Everything below for static addressing */
/* Find all IP4 addresses of this connection in the device's address list */
num = nm_setting_ip4_config_get_num_addresses (s_ip4);
for (i = 0; i < num; i++) {
memset (&check_data, 0, sizeof (check_data));
check_data.ifindex = ifindex;
check_data.found = FALSE;
check_data.addr = nm_setting_ip4_config_get_address (s_ip4, i);
nl_cache_foreach (addr_cache, check_one_address, &check_data);
if (!check_data.found)
return FALSE;
}
/* Success; all the connection's static IP addresses are assigned to the device */
return TRUE;
}
static NMConnection *
connection_match_config (NMDevice *self, const GSList *connections)
{
GSList *iter;
NMSettingConnection *s_con;
for (iter = (GSList *) connections; iter; iter = g_slist_next (iter)) {
NMConnection *candidate = NM_CONNECTION (iter->data);
s_con = (NMSettingConnection *) nm_connection_get_setting (candidate, NM_TYPE_SETTING_CONNECTION);
g_assert (s_con);
if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_WIRED_SETTING_NAME))
continue;
/* Can't assume 802.1x or PPPoE connections; they have too much state
* that's impossible to get on-the-fly from PPPoE or the supplicant.
*/
if ( nm_connection_get_setting (candidate, NM_TYPE_SETTING_802_1X)
|| nm_connection_get_setting (candidate, NM_TYPE_SETTING_PPPOE))
continue;
if (!wired_match_config (self, candidate))
continue;
if (!ip4_match_config (self, candidate))
continue;
return candidate;
}
return NULL;
}
static void
dispose (GObject *object)
{
@ -1587,6 +1778,7 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass)
parent_class->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config;
parent_class->deactivate_quickly = real_deactivate_quickly;
parent_class->spec_match_list = spec_match_list;
parent_class->connection_match_config = connection_match_config;
/* properties */
g_object_class_install_property

View file

@ -23,6 +23,7 @@
#include "nm-setting-connection.h"
#include "nm-device-interface.h"
#include "nm-utils.h"
#include "nm-properties-changed-signal.h"
#include "nm-device-interface-glue.h"
@ -123,6 +124,14 @@ nm_device_interface_init (gpointer g_iface)
DBUS_TYPE_G_OBJECT_PATH,
G_PARAM_READWRITE));
g_object_interface_install_property
(g_iface,
g_param_spec_boxed (NM_DEVICE_INTERFACE_IP6_CONFIG,
"IP6 Config",
"IP6 Config",
DBUS_TYPE_G_OBJECT_PATH,
G_PARAM_READWRITE));
g_object_interface_install_property
(g_iface,
g_param_spec_uint (NM_DEVICE_INTERFACE_STATE,
@ -152,7 +161,7 @@ nm_device_interface_init (gpointer g_iface)
"Type Description",
"Device type description",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT));
/* Signals */
g_signal_new ("state-changed",
@ -282,8 +291,29 @@ gboolean
nm_device_interface_spec_match_list (NMDeviceInterface *device,
const GSList *specs)
{
g_return_val_if_fail (NM_IS_DEVICE_INTERFACE (device), FALSE);
if (NM_DEVICE_INTERFACE_GET_INTERFACE (device)->spec_match_list)
return NM_DEVICE_INTERFACE_GET_INTERFACE (device)->spec_match_list (device, specs);
return FALSE;
}
NMConnection *
nm_device_interface_connection_match_config (NMDeviceInterface *device,
const GSList *connections)
{
g_return_val_if_fail (NM_IS_DEVICE_INTERFACE (device), NULL);
if (NM_DEVICE_INTERFACE_GET_INTERFACE (device)->connection_match_config)
return NM_DEVICE_INTERFACE_GET_INTERFACE (device)->connection_match_config (device, connections);
return NULL;
}
gboolean
nm_device_interface_can_assume_connection (NMDeviceInterface *device)
{
g_return_val_if_fail (NM_IS_DEVICE_INTERFACE (device), FALSE);
return !!NM_DEVICE_INTERFACE_GET_INTERFACE (device)->connection_match_config;
}

View file

@ -48,6 +48,7 @@ typedef enum
#define NM_DEVICE_INTERFACE_IP4_ADDRESS "ip4-address"
#define NM_DEVICE_INTERFACE_IP4_CONFIG "ip4-config"
#define NM_DEVICE_INTERFACE_DHCP4_CONFIG "dhcp4-config"
#define NM_DEVICE_INTERFACE_IP6_CONFIG "ip6-config"
#define NM_DEVICE_INTERFACE_STATE "state"
#define NM_DEVICE_INTERFACE_DEVICE_TYPE "device-type" /* ugh */
#define NM_DEVICE_INTERFACE_MANAGED "managed"
@ -63,6 +64,7 @@ typedef enum {
NM_DEVICE_INTERFACE_PROP_IP4_ADDRESS,
NM_DEVICE_INTERFACE_PROP_IP4_CONFIG,
NM_DEVICE_INTERFACE_PROP_DHCP4_CONFIG,
NM_DEVICE_INTERFACE_PROP_IP6_CONFIG,
NM_DEVICE_INTERFACE_PROP_STATE,
NM_DEVICE_INTERFACE_PROP_DEVICE_TYPE,
NM_DEVICE_INTERFACE_PROP_MANAGED,
@ -88,6 +90,8 @@ struct _NMDeviceInterface {
gboolean (*spec_match_list) (NMDeviceInterface *device, const GSList *specs);
NMConnection * (*connection_match_config) (NMDeviceInterface *device, const GSList *specs);
/* Signals */
void (*state_changed) (NMDeviceInterface *device,
NMDeviceState new_state,
@ -115,4 +119,9 @@ NMDeviceState nm_device_interface_get_state (NMDeviceInterface *device);
gboolean nm_device_interface_spec_match_list (NMDeviceInterface *device,
const GSList *specs);
NMConnection * nm_device_interface_connection_match_config (NMDeviceInterface *device,
const GSList *connections);
gboolean nm_device_interface_can_assume_connection (NMDeviceInterface *device);
#endif /* NM_DEVICE_INTERFACE_H */

979
src/nm-device-olpc-mesh.c Normal file
View file

@ -0,0 +1,979 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager -- Network link manager
*
* Dan Williams <dcbw@redhat.com>
* Sjoerd Simons <sjoerd.simons@collabora.co.uk>
* Daniel Drake <dsd@laptop.org>
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* (C) Copyright 2005 - 2008 Red Hat, Inc.
* (C) Copyright 2008 Collabora Ltd.
* (C) Copyright 2009 One Laptop per Child
*/
#include <glib.h>
#include <glib/gi18n.h>
#include <dbus/dbus.h>
#include <netinet/in.h>
#include <string.h>
#include <net/ethernet.h>
#include <iwlib.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
#include "nm-device.h"
#include "nm-device-wifi.h"
#include "nm-device-olpc-mesh.h"
#include "nm-device-interface.h"
#include "nm-device-private.h"
#include "nm-utils.h"
#include "NetworkManagerUtils.h"
#include "NetworkManagerPolicy.h"
#include "nm-activation-request.h"
#include "nm-properties-changed-signal.h"
#include "nm-setting-connection.h"
#include "nm-setting-olpc-mesh.h"
#include "NetworkManagerSystem.h"
#include "nm-manager.h"
#include "nm-device-olpc-mesh-glue.h"
static void nm_device_olpc_mesh_set_ssid (NMDeviceOlpcMesh *self, const GByteArray * ssid);
G_DEFINE_TYPE (NMDeviceOlpcMesh, nm_device_olpc_mesh, NM_TYPE_DEVICE)
#define NM_DEVICE_OLPC_MESH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMeshPrivate))
enum {
PROP_0,
PROP_HW_ADDRESS,
PROP_COMPANION,
PROP_ACTIVE_CHANNEL,
PROP_IFINDEX,
LAST_PROP
};
enum {
PROPERTIES_CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
typedef enum
{
NM_OLPC_MESH_ERROR_CONNECTION_NOT_MESH = 0,
NM_OLPC_MESH_ERROR_CONNECTION_INVALID,
NM_OLPC_MESH_ERROR_CONNECTION_INCOMPATIBLE,
} NMOlpcMeshError;
#define NM_OLPC_MESH_ERROR (nm_olpc_mesh_error_quark ())
#define NM_TYPE_OLPC_MESH_ERROR (nm_olpc_mesh_error_get_type ())
struct _NMDeviceOlpcMeshPrivate
{
gboolean dispose_has_run;
struct ether_addr hw_addr;
guint32 ifindex;
GByteArray * ssid;
gint8 num_freqs;
guint32 freqs[IW_MAX_FREQUENCIES];
guint8 we_version;
gboolean up;
NMDevice * companion;
gboolean stage1_waiting;
guint device_added_cb;
};
static GQuark
nm_olpc_mesh_error_quark (void)
{
static GQuark quark = 0;
if (!quark)
quark = g_quark_from_static_string ("nm-mesh-error");
return quark;
}
/* This should really be standard. */
#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
static GType
nm_olpc_mesh_error_get_type (void)
{
static GType etype = 0;
if (etype == 0) {
static const GEnumValue values[] = {
/* Connection was not a wireless connection. */
ENUM_ENTRY (NM_OLPC_MESH_ERROR_CONNECTION_NOT_MESH, "ConnectionNotMesh"),
/* Connection was not a valid wireless connection. */
ENUM_ENTRY (NM_OLPC_MESH_ERROR_CONNECTION_INVALID, "ConnectionInvalid"),
/* Connection does not apply to this device. */
ENUM_ENTRY (NM_OLPC_MESH_ERROR_CONNECTION_INCOMPATIBLE, "ConnectionIncompatible"),
{ 0, 0, 0 }
};
etype = g_enum_register_static ("NMOlpcMeshError", values);
}
return etype;
}
static guint32
real_get_generic_capabilities (NMDevice *dev)
{
int fd;
guint32 caps = NM_DEVICE_CAP_NONE;
struct iw_range range;
struct iwreq wrq;
const char *iface = nm_device_get_iface (dev);
/* Check for Wireless Extensions support >= 16 for wireless devices */
fd = socket (PF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
nm_warning ("couldn't open control socket.");
goto out;
}
memset (&wrq, 0, sizeof (struct iwreq));
memset (&range, 0, sizeof (struct iw_range));
strncpy (wrq.ifr_name, iface, IFNAMSIZ);
wrq.u.data.pointer = (caddr_t) &range;
wrq.u.data.length = sizeof (struct iw_range);
if (ioctl (fd, SIOCGIWRANGE, &wrq) < 0) {
nm_warning ("couldn't get driver range information.");
goto out;
}
if ((wrq.u.data.length < 300) || (range.we_version_compiled < 16)) {
nm_warning ("%s: driver's Wireless Extensions version (%d) is too old.",
iface, range.we_version_compiled);
goto out;
} else {
caps |= NM_DEVICE_CAP_NM_SUPPORTED;
}
out:
if (fd >= 0)
close (fd);
return caps;
}
static void
nm_device_olpc_mesh_init (NMDeviceOlpcMesh * self)
{
NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self);
priv->dispose_has_run = FALSE;
priv->we_version = 0;
priv->companion = NULL;
priv->stage1_waiting = FALSE;
memset (&(priv->hw_addr), 0, sizeof (struct ether_addr));
}
static guint32 iw_freq_to_uint32 (struct iw_freq *freq)
{
if (freq->e == 0) {
/* Some drivers report channel not frequency. Convert to a
* frequency; but this assumes that the device is in b/g mode.
*/
if ((freq->m >= 1) && (freq->m <= 13))
return 2407 + (5 * freq->m);
else if (freq->m == 14)
return 2484;
}
return (guint32) (((double) freq->m) * pow (10, freq->e) / 1000000);
}
/* Until a new wireless-tools comes out that has the defs and the structure,
* need to copy them here.
*/
/* Scan capability flags - in (struct iw_range *)->scan_capa */
#define NM_IW_SCAN_CAPA_NONE 0x00
#define NM_IW_SCAN_CAPA_ESSID 0x01
struct iw_range_with_scan_capa
{
guint32 throughput;
guint32 min_nwid;
guint32 max_nwid;
guint16 old_num_channels;
guint8 old_num_frequency;
guint8 scan_capa;
/* don't need the rest... */
};
static GObject*
constructor (GType type,
guint n_construct_params,
GObjectConstructParam *construct_params)
{
GObject *object;
GObjectClass *klass;
NMDeviceOlpcMesh *self;
NMDeviceOlpcMeshPrivate *priv;
const char *iface;
int fd;
struct iw_range range;
struct iwreq wrq;
int i;
klass = G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class);
object = klass->constructor (type, n_construct_params, construct_params);
if (!object)
return NULL;
self = NM_DEVICE_OLPC_MESH (object);
priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self);
iface = nm_device_get_iface (NM_DEVICE (self));
fd = socket (PF_INET, SOCK_DGRAM, 0);
if (fd < 0)
goto error;
memset (&wrq, 0, sizeof (struct iwreq));
memset (&range, 0, sizeof (struct iw_range));
strncpy (wrq.ifr_name, iface, IFNAMSIZ);
wrq.u.data.pointer = (caddr_t) &range;
wrq.u.data.length = sizeof (struct iw_range);
if (ioctl (fd, SIOCGIWRANGE, &wrq) < 0)
goto error;
priv->num_freqs = MIN (range.num_frequency, IW_MAX_FREQUENCIES);
for (i = 0; i < priv->num_freqs; i++)
priv->freqs[i] = iw_freq_to_uint32 (&range.freq[i]);
priv->we_version = range.we_version_compiled;
close (fd);
/* shorter timeout for mesh connectivity */
nm_device_set_dhcp_timeout (NM_DEVICE (self), 20);
return object;
error:
if (fd >= 0)
close (fd);
g_object_unref (object);
return NULL;
}
static gboolean
real_hw_is_up (NMDevice *device)
{
return nm_system_device_is_up (device);
}
static gboolean
real_hw_bring_up (NMDevice *dev, gboolean *no_firmware)
{
return nm_system_device_set_up_down (dev, TRUE, no_firmware);
}
static void
real_hw_take_down (NMDevice *dev)
{
nm_system_device_set_up_down (dev, FALSE, NULL);
}
static gboolean
real_is_up (NMDevice *device)
{
NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (device);
NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self);
return priv->up;
}
static gboolean
real_bring_up (NMDevice *dev)
{
NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (dev);
NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self);
priv->up = TRUE;
return TRUE;
}
static void
device_cleanup (NMDeviceOlpcMesh *self)
{
NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self);
if (priv->ssid) {
g_byte_array_free (priv->ssid, TRUE);
priv->ssid = NULL;
}
priv->up = FALSE;
}
static void
real_take_down (NMDevice *dev)
{
NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (dev);
device_cleanup (self);
}
static gboolean
real_check_connection_compatible (NMDevice *device,
NMConnection *connection,
GError **error)
{
NMSettingConnection *s_con;
NMSettingOlpcMesh *s_mesh;
s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
g_assert (s_con);
if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_OLPC_MESH_SETTING_NAME)) {
g_set_error (error,
NM_OLPC_MESH_ERROR, NM_OLPC_MESH_ERROR_CONNECTION_NOT_MESH,
"The connection was not a Mesh connection.");
return FALSE;
}
s_mesh = NM_SETTING_OLPC_MESH (nm_connection_get_setting (connection, NM_TYPE_SETTING_OLPC_MESH));
if (!s_mesh) {
g_set_error (error,
NM_OLPC_MESH_ERROR, NM_OLPC_MESH_ERROR_CONNECTION_INVALID,
"The connection was not a valid Mesh connection.");
return FALSE;
}
return TRUE;
}
/*
* nm_device_olpc_mesh_get_address
*
* Get a device's hardware address
*
*/
static void
nm_device_olpc_mesh_get_address (NMDeviceOlpcMesh *self,
struct ether_addr *addr)
{
NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self);
g_return_if_fail (self != NULL);
g_return_if_fail (addr != NULL);
memcpy (addr, &(priv->hw_addr), sizeof (struct ether_addr));
}
static int
create_socket_with_request (NMDevice *self, struct iwreq *req)
{
int sk;
const char * iface;
g_return_val_if_fail (self != NULL, -1);
sk = socket (AF_INET, SOCK_DGRAM, 0);
if (!sk) {
nm_error ("Couldn't create socket: %d.", errno);
return -1;
}
memset (req, 0, sizeof (struct iwreq));
iface = nm_device_get_iface (NM_DEVICE (self));
strncpy (req->ifr_name, iface, IFNAMSIZ);
return sk;
}
static guint32
nm_device_olpc_mesh_get_channel (NMDeviceOlpcMesh *self)
{
NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self);
int sk;
struct iwreq req;
int ret = 0;
int i;
guint32 freq;
sk = create_socket_with_request (NM_DEVICE (self), &req);
if (sk == -1)
return 0;
if ((ioctl (sk, SIOCGIWFREQ, &req)) != 0) {
nm_warning ("%s: failed to get channel (errno: %d))",
nm_device_get_iface (NM_DEVICE (self)), errno);
goto out;
}
freq = iw_freq_to_uint32 (&req.u.freq);
for (i = 0 ; i < priv->num_freqs; i++) {
if (freq == priv->freqs[i])
break;
}
if (i < priv->num_freqs)
ret = i + 1;
out:
if (sk >= 0)
close (sk);
return ret;
}
static void
nm_device_olpc_mesh_set_channel (NMDeviceOlpcMesh *self, guint32 channel)
{
int sk;
struct iwreq req;
if (nm_device_olpc_mesh_get_channel (self) == channel)
return;
sk = create_socket_with_request (NM_DEVICE (self), &req);
if (sk < 0)
return;
if (channel > 0) {
req.u.freq.flags = IW_FREQ_FIXED;
req.u.freq.e = 0;
req.u.freq.m = channel;
}
if (ioctl (sk, SIOCSIWFREQ, &req) != 0)
nm_warning ("%s: failed to set to channel %d (errno: %d))",
nm_device_get_iface (NM_DEVICE (self)), channel, errno);
else
g_object_notify (G_OBJECT (self), NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL);
close (sk);
}
static void
nm_device_olpc_mesh_set_ssid (NMDeviceOlpcMesh *self, const GByteArray * ssid)
{
NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self);
int sk;
struct iwreq wrq;
const char * iface;
guint32 len = 0;
char buf[IW_ESSID_MAX_SIZE + 1];
g_return_if_fail (self != NULL);
sk = socket (AF_INET, SOCK_DGRAM, 0);
if (!sk) {
nm_error ("Couldn't create socket: %d.", errno);
return;
}
iface = nm_device_get_iface (NM_DEVICE (self));
memset (buf, 0, sizeof (buf));
if (ssid) {
len = ssid->len;
memcpy (buf, ssid->data, MIN (sizeof (buf) - 1, len));
}
wrq.u.essid.pointer = (caddr_t) buf;
if (priv->we_version < 21) {
/* For historic reasons, set SSID length to include one extra
* character, C string nul termination, even though SSID is
* really an octet string that should not be presented as a C
* string. Some Linux drivers decrement the length by one and
* can thus end up missing the last octet of the SSID if the
* length is not incremented here. WE-21 changes this to
* explicitly require the length _not_ to include nul
* termination. */
if (len)
len++;
}
wrq.u.essid.length = len;
wrq.u.essid.flags = (len > 0) ? 1 : 0; /* 1=enable SSID, 0=disable/any */
strncpy (wrq.ifr_name, iface, IFNAMSIZ);
if (ioctl (sk, SIOCSIWESSID, &wrq) < 0) {
if (errno != ENODEV) {
nm_warning ("error setting SSID to '%s' for device %s: %s",
ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(null)",
iface, strerror (errno));
}
}
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
real_update_hw_address (NMDevice *dev)
{
NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (dev);
NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self);
struct ifreq req;
int ret, fd;
fd = socket (PF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
g_warning ("could not open control socket.");
return;
}
memset (&req, 0, sizeof (struct ifreq));
strncpy (req.ifr_name, nm_device_get_iface (dev), IFNAMSIZ);
ret = ioctl (fd, SIOCGIFHWADDR, &req);
if (ret) {
nm_warning ("%s: (%s) error getting hardware address: %d",
__func__, nm_device_get_iface (dev), errno);
goto out;
}
if (memcmp (&priv->hw_addr, &req.ifr_hwaddr.sa_data, sizeof (struct ether_addr))) {
memcpy (&priv->hw_addr, &req.ifr_hwaddr.sa_data, sizeof (struct ether_addr));
g_object_notify (G_OBJECT (dev), NM_DEVICE_OLPC_MESH_HW_ADDRESS);
}
out:
close (fd);
}
static NMActStageReturn
real_act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
{
NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (dev);
gboolean scanning;
/* disconnect companion device, if it is connected */
if (nm_device_get_act_request (NM_DEVICE (priv->companion))) {
nm_warning ("disconnecting companion device");
nm_device_state_changed (NM_DEVICE (priv->companion),
NM_DEVICE_STATE_DISCONNECTED,
NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED);
nm_warning ("companion disconnected");
}
/* wait with continuing configuration untill the companion device is done
* scanning */
g_object_get (priv->companion, "scanning", &scanning, NULL);
if (scanning) {
priv->stage1_waiting = TRUE;
return NM_ACT_STAGE_RETURN_POSTPONE;
}
return NM_ACT_STAGE_RETURN_SUCCESS;
}
static NMActStageReturn
real_act_stage2_config (NMDevice *dev, NMDeviceStateReason *reason)
{
NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (dev);
NMConnection *connection;
NMSettingOlpcMesh *s_mesh;
NMActRequest *req;
guint32 channel;
const GByteArray *anycast_addr_array;
guint8 *anycast_addr = NULL;
req = nm_device_get_act_request (dev);
g_assert (req);
connection = nm_act_request_get_connection (req);
g_assert (connection);
s_mesh = NM_SETTING_OLPC_MESH (nm_connection_get_setting (connection, NM_TYPE_SETTING_OLPC_MESH));
g_assert (s_mesh);
channel = nm_setting_olpc_mesh_get_channel (s_mesh);
if (channel != 0)
nm_device_olpc_mesh_set_channel (self, channel);
nm_device_olpc_mesh_set_ssid (self, nm_setting_olpc_mesh_get_ssid (s_mesh));
anycast_addr_array = nm_setting_olpc_mesh_get_dhcp_anycast_address (s_mesh);
if (anycast_addr_array)
anycast_addr = anycast_addr_array->data;
nm_device_set_dhcp_anycast_address (dev, anycast_addr);
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
nm_device_olpc_mesh_dispose (GObject *object)
{
NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (object);
NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self);
if (priv->dispose_has_run) {
G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->dispose (object);
return;
}
priv->dispose_has_run = TRUE;
device_cleanup (self);
if (priv->device_added_cb != 0)
g_source_remove (priv->device_added_cb);
priv->device_added_cb = 0;
G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->dispose (object);
}
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
NMDeviceOlpcMesh *device = NM_DEVICE_OLPC_MESH (object);
NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (device);
struct ether_addr hw_addr;
switch (prop_id) {
case PROP_HW_ADDRESS:
nm_device_olpc_mesh_get_address (device, &hw_addr);
g_value_take_string (value, nm_ether_ntop (&hw_addr));
break;
case PROP_COMPANION:
g_value_set_string (value, nm_device_get_path (priv->companion));
break;
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;
}
}
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;
}
}
static void
nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
g_type_class_add_private (object_class, sizeof (NMDeviceOlpcMeshPrivate));
object_class->constructor = constructor;
object_class->get_property = get_property;
object_class->set_property = set_property;
object_class->dispose = nm_device_olpc_mesh_dispose;
parent_class->get_type_capabilities = NULL;
parent_class->get_generic_capabilities = real_get_generic_capabilities;
parent_class->hw_is_up = real_hw_is_up;
parent_class->hw_bring_up = real_hw_bring_up;
parent_class->hw_take_down = real_hw_take_down;
parent_class->is_up = real_is_up;
parent_class->bring_up = real_bring_up;
parent_class->take_down = real_take_down;
parent_class->update_hw_address = real_update_hw_address;
parent_class->check_connection_compatible = real_check_connection_compatible;
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
(object_class, PROP_HW_ADDRESS,
g_param_spec_string (NM_DEVICE_OLPC_MESH_HW_ADDRESS,
"MAC Address",
"Hardware MAC address",
NULL,
G_PARAM_READABLE));
g_object_class_install_property
(object_class, PROP_COMPANION,
g_param_spec_string (NM_DEVICE_OLPC_MESH_COMPANION,
"Companion device",
"Companion device object path",
NULL,
G_PARAM_READABLE));
g_object_class_install_property
(object_class, PROP_ACTIVE_CHANNEL,
g_param_spec_uint (NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL,
"Active channel",
"Active channel",
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));
dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), &dbus_glib_nm_device_olpc_mesh_object_info);
dbus_g_error_domain_register (NM_OLPC_MESH_ERROR, NULL,
NM_TYPE_OLPC_MESH_ERROR);
}
static void
companion_notify_cb (NMDeviceWifi *companion, GParamSpec *pspec, gpointer user_data)
{
NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data);
NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self);
gboolean scanning;
if (!priv->stage1_waiting)
return;
g_object_get (companion, "scanning", &scanning, NULL);
if (!scanning) {
priv->stage1_waiting = FALSE;
nm_device_activate_schedule_stage2_device_config (NM_DEVICE (self));
}
}
/* disconnect from mesh if someone starts using the companion */
static void
companion_state_changed_cb (NMDeviceWifi *companion, NMDeviceState state, NMDeviceState old_state, NMDeviceStateReason reason, gpointer user_data)
{
NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data);
NMDeviceState self_state = nm_device_get_state (NM_DEVICE (self));
if ( self_state < NM_DEVICE_STATE_PREPARE
|| self_state > NM_DEVICE_STATE_ACTIVATED
|| state < NM_DEVICE_STATE_PREPARE
|| state > NM_DEVICE_STATE_ACTIVATED)
return;
nm_debug ("disconnecting mesh due to companion connectivity");
nm_device_state_changed (NM_DEVICE (self),
NM_DEVICE_STATE_DISCONNECTED,
NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED);
}
static gboolean
companion_scan_allowed_cb (NMDeviceWifi *companion, gpointer user_data)
{
NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data);
NMDeviceState state;
g_object_get (G_OBJECT (self), NM_DEVICE_INTERFACE_STATE, &state, NULL);
/* Don't allow the companion to scan while configure the mesh interface */
return (state < NM_DEVICE_STATE_PREPARE) || (state > NM_DEVICE_STATE_IP_CONFIG);
}
static gboolean
companion_autoconnect_allowed_cb (NMDeviceWifi *companion, gpointer user_data)
{
NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data);
NMDeviceState state;
g_object_get (G_OBJECT (self), NM_DEVICE_INTERFACE_STATE, &state, NULL);
/* Don't allow the companion to autoconnect while a mesh connection is
* active */
return (state < NM_DEVICE_STATE_PREPARE) || (state > NM_DEVICE_STATE_ACTIVATED);
}
static gboolean
is_companion (NMDeviceOlpcMesh *self, NMDevice *other)
{
NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self);
struct ether_addr their_addr;
if (!NM_IS_DEVICE_WIFI (other))
return FALSE;
nm_device_wifi_get_address (NM_DEVICE_WIFI (other), &their_addr);
if (memcmp (priv->hw_addr.ether_addr_octet,
their_addr.ether_addr_octet, ETH_ALEN) != 0) {
return FALSE;
}
/* FIXME detect when our companion leaves */
priv->companion = other;
g_source_remove (priv->device_added_cb);
priv->device_added_cb = 0;
nm_device_state_changed (NM_DEVICE (self),
NM_DEVICE_STATE_DISCONNECTED,
NM_DEVICE_STATE_REASON_NONE);
nm_debug ("Found companion device: %s", nm_device_get_iface (other));
g_signal_connect (G_OBJECT (other), "state-changed",
G_CALLBACK (companion_state_changed_cb), self);
g_signal_connect (G_OBJECT (other), "notify::scanning",
G_CALLBACK (companion_notify_cb), self);
g_signal_connect (G_OBJECT (other), "scanning-allowed",
G_CALLBACK (companion_scan_allowed_cb), self);
g_signal_connect (G_OBJECT (other), "autoconnect-allowed",
G_CALLBACK (companion_autoconnect_allowed_cb), self);
return TRUE;
}
static void
device_added_cb (NMDevice *other, gpointer user_data)
{
NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data);
is_companion (self, other);
}
static gboolean
check_companion_cb (gpointer user_data)
{
NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data);
NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self);
NMManager *manager;
GSList *list;
if (priv->companion != NULL) {
nm_device_state_changed (NM_DEVICE (user_data),
NM_DEVICE_STATE_DISCONNECTED,
NM_DEVICE_STATE_REASON_NONE);
return FALSE;
}
if (priv->device_added_cb != 0)
return FALSE;
manager = nm_manager_get (NULL, NULL, NULL);
priv->device_added_cb = g_signal_connect (manager, "device-added",
G_CALLBACK (device_added_cb), self);
list = nm_manager_get_devices (manager);
for (; list != NULL ; list = list->next)
if (is_companion (self, NM_DEVICE (list->data)))
break;
g_object_unref (manager);
return FALSE;
}
static void
state_changed_cb (NMDevice *device, NMDeviceState state, gpointer user_data)
{
NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (device);
switch (state) {
case NM_DEVICE_STATE_UNMANAGED:
break;
case NM_DEVICE_STATE_UNAVAILABLE:
/* If transitioning to UNAVAILBLE and the companion device is known then
* transition to DISCONNECTED otherwise wait for our companion.
*/
g_idle_add (check_companion_cb, self);
break;
case NM_DEVICE_STATE_ACTIVATED:
break;
case NM_DEVICE_STATE_FAILED:
break;
case NM_DEVICE_STATE_DISCONNECTED:
break;
default:
break;
}
}
NMDevice *
nm_device_olpc_mesh_new (const char *udi,
const char *iface,
const char *driver,
guint32 ifindex)
{
GObject *obj;
g_return_val_if_fail (udi != NULL, NULL);
g_return_val_if_fail (iface != NULL, NULL);
g_return_val_if_fail (driver != NULL, NULL);
obj = g_object_new (NM_TYPE_DEVICE_OLPC_MESH,
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);
if (obj == NULL)
return NULL;
g_signal_connect (obj, "state-changed", G_CALLBACK (state_changed_cb), NULL);
return NM_DEVICE (obj);
}

85
src/nm-device-olpc-mesh.h Normal file
View file

@ -0,0 +1,85 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager -- Network link manager
*
* Dan Williams <dcbw@redhat.com>
* Sjoerd Simons <sjoerd.simons@collabora.co.uk>
* Daniel Drake <dsd@laptop.org>
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* (C) Copyright 2005 Red Hat, Inc.
* (C) Copyright 2008 Collabora Ltd.
* (C) Copyright 2009 One Laptop per Child
*/
#ifndef NM_DEVICE_OLPC_MESH_H
#define NM_DEVICE_OLPC_MESH_H
#include <glib-object.h>
#include <dbus/dbus.h>
#include "nm-device.h"
G_BEGIN_DECLS
#define NM_TYPE_DEVICE_OLPC_MESH (nm_device_olpc_mesh_get_type ())
#define NM_DEVICE_OLPC_MESH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMesh))
#define NM_DEVICE_OLPC_MESH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMeshClass))
#define NM_IS_DEVICE_OLPC_MESH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_OLPC_MESH))
#define NM_IS_DEVICE_OLPC_MESH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_OLPC_MESH))
#define NM_DEVICE_OLPC_MESH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMeshClass))
#define NM_DEVICE_OLPC_MESH_HW_ADDRESS "hw-address"
#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
typedef struct _NMDeviceOlpcMesh NMDeviceOlpcMesh;
#endif
typedef struct _NMDeviceOlpcMeshClass NMDeviceOlpcMeshClass;
typedef struct _NMDeviceOlpcMeshPrivate NMDeviceOlpcMeshPrivate;
struct _NMDeviceOlpcMesh
{
NMDevice parent;
};
struct _NMDeviceOlpcMeshClass
{
NMDeviceClass parent;
/* Signals */
void (*properties_changed) (NMDeviceOlpcMesh *device,
GHashTable *properties);
};
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);
G_END_DECLS
#endif /* NM_DEVICE_OLPC_MESH_H */

View file

@ -3022,9 +3022,9 @@ real_act_stage4_get_ip4_config (NMDevice *dev,
static NMActStageReturn
real_act_stage4_ip_config_timeout (NMDevice *dev,
NMIP4Config **config,
NMDeviceStateReason *reason)
real_act_stage4_ip4_config_timeout (NMDevice *dev,
NMIP4Config **config,
NMDeviceStateReason *reason)
{
NMDeviceWifi *self = NM_DEVICE_WIFI (dev);
NMAccessPoint *ap = nm_device_wifi_get_activation_ap (self);
@ -3070,7 +3070,7 @@ real_act_stage4_ip_config_timeout (NMDevice *dev,
/* For Ad-Hoc networks, chain up to parent to get a Zeroconf IP */
klass = NM_DEVICE_WIFI_GET_CLASS (self);
parent_class = NM_DEVICE_CLASS (g_type_class_peek_parent (klass));
ret = parent_class->act_stage4_ip_config_timeout (dev, &real_config, reason);
ret = parent_class->act_stage4_ip4_config_timeout (dev, &real_config, reason);
} else {
/* Non-encrypted network or authentication is enforced by some
* entity (AP, RADIUS server, etc), but IP configure failed. Alert
@ -3555,7 +3555,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
parent_class->act_stage1_prepare = real_act_stage1_prepare;
parent_class->act_stage2_config = real_act_stage2_config;
parent_class->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config;
parent_class->act_stage4_ip_config_timeout = real_act_stage4_ip_config_timeout;
parent_class->act_stage4_ip4_config_timeout = real_act_stage4_ip4_config_timeout;
parent_class->deactivate = real_deactivate;
parent_class->deactivate_quickly = real_deactivate_quickly;
parent_class->can_interrupt_activation = real_can_interrupt_activation;
@ -3610,7 +3610,8 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
g_param_spec_boolean (NM_DEVICE_WIFI_SCANNING,
"Scanning",
"Scanning",
0, G_PARAM_READABLE));
FALSE,
G_PARAM_READABLE | NM_PROPERTY_PARAM_NO_EXPORT));
/* Signals */
signals[ACCESS_POINT_ADDED] =

File diff suppressed because it is too large Load diff

View file

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

726
src/nm-ip6-config.c Normal file
View file

@ -0,0 +1,726 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager -- Network link manager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2005 - 2008 Red Hat, Inc.
* Copyright (C) 2006 - 2008 Novell, Inc.
*/
#include <glib.h>
#include <stdio.h>
#include <string.h>
#include "nm-ip6-config.h"
#include "nm-dbus-manager.h"
#include "NetworkManager.h"
#include "NetworkManagerUtils.h"
#include "nm-setting-ip6-config.h"
#include "nm-utils.h"
#include <netlink/route/addr.h>
#include <netlink/utils.h>
#include <netinet/in.h>
#include "nm-ip6-config-glue.h"
#include "nm-dbus-glib-types.h"
G_DEFINE_TYPE (NMIP6Config, nm_ip6_config, G_TYPE_OBJECT)
#define NM_IP6_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_IP6_CONFIG, NMIP6ConfigPrivate))
typedef struct {
char *path;
GSList *addresses;
struct in6_addr ptp_address;
guint32 mss; /* Maximum Segment Size of the route */
GArray *nameservers;
GPtrArray *domains;
GPtrArray *searches;
GSList *routes;
gboolean never_default;
} NMIP6ConfigPrivate;
enum {
PROP_0,
PROP_ADDRESSES,
PROP_NAMESERVERS,
PROP_DOMAINS,
PROP_ROUTES,
LAST_PROP
};
static struct nl_addr *
nm_utils_ip6_addr_to_nl_addr (const struct in6_addr *ip6_addr)
{
struct nl_addr * nla = NULL;
if (!(nla = nl_addr_alloc (sizeof (struct in6_addr))))
return NULL;
nl_addr_set_family (nla, AF_INET6);
nl_addr_set_binary_addr (nla, (struct in6_addr *)ip6_addr, sizeof (struct in6_addr));
return nla;
}
NMIP6Config *
nm_ip6_config_new (void)
{
return (NMIP6Config *) g_object_new (NM_TYPE_IP6_CONFIG, NULL);
}
void
nm_ip6_config_export (NMIP6Config *config)
{
NMIP6ConfigPrivate *priv;
NMDBusManager *dbus_mgr;
DBusGConnection *connection;
static guint32 counter = 0;
g_return_if_fail (NM_IS_IP6_CONFIG (config));
priv = NM_IP6_CONFIG_GET_PRIVATE (config);
g_return_if_fail (priv->path == NULL);
dbus_mgr = nm_dbus_manager_get ();
connection = nm_dbus_manager_get_connection (dbus_mgr);
priv->path = g_strdup_printf (NM_DBUS_PATH "/IP6Config/%d", counter++);
dbus_g_connection_register_g_object (connection, priv->path, G_OBJECT (config));
g_object_unref (dbus_mgr);
}
const char *
nm_ip6_config_get_dbus_path (NMIP6Config *config)
{
g_return_val_if_fail (NM_IS_IP6_CONFIG (config), FALSE);
return NM_IP6_CONFIG_GET_PRIVATE (config)->path;
}
void
nm_ip6_config_take_address (NMIP6Config *config, NMIP6Address *address)
{
NMIP6ConfigPrivate *priv;
g_return_if_fail (NM_IS_IP6_CONFIG (config));
g_return_if_fail (address != NULL);
priv = NM_IP6_CONFIG_GET_PRIVATE (config);
priv->addresses = g_slist_append (priv->addresses, address);
}
void
nm_ip6_config_add_address (NMIP6Config *config,
NMIP6Address *address)
{
NMIP6ConfigPrivate *priv;
g_return_if_fail (NM_IS_IP6_CONFIG (config));
g_return_if_fail (address != NULL);
priv = NM_IP6_CONFIG_GET_PRIVATE (config);
priv->addresses = g_slist_append (priv->addresses, nm_ip6_address_dup (address));
}
void
nm_ip6_config_replace_address (NMIP6Config *config,
guint i,
NMIP6Address *new_address)
{
NMIP6ConfigPrivate *priv;
GSList *old;
g_return_if_fail (NM_IS_IP6_CONFIG (config));
priv = NM_IP6_CONFIG_GET_PRIVATE (config);
old = g_slist_nth (priv->addresses, i);
g_return_if_fail (old != NULL);
nm_ip6_address_unref ((NMIP6Address *) old->data);
old->data = nm_ip6_address_dup (new_address);
}
NMIP6Address *nm_ip6_config_get_address (NMIP6Config *config, guint i)
{
g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL);
return (NMIP6Address *) g_slist_nth_data (NM_IP6_CONFIG_GET_PRIVATE (config)->addresses, i);
}
guint32 nm_ip6_config_get_num_addresses (NMIP6Config *config)
{
g_return_val_if_fail (NM_IS_IP6_CONFIG (config), 0);
return g_slist_length (NM_IP6_CONFIG_GET_PRIVATE (config)->addresses);
}
const struct in6_addr *nm_ip6_config_get_ptp_address (NMIP6Config *config)
{
g_return_val_if_fail (NM_IS_IP6_CONFIG (config), 0);
return &NM_IP6_CONFIG_GET_PRIVATE (config)->ptp_address;
}
void nm_ip6_config_set_ptp_address (NMIP6Config *config, struct in6_addr *ptp_addr)
{
g_return_if_fail (NM_IS_IP6_CONFIG (config));
NM_IP6_CONFIG_GET_PRIVATE (config)->ptp_address = *ptp_addr;
}
void nm_ip6_config_add_nameserver (NMIP6Config *config, const struct in6_addr *nameserver)
{
NMIP6ConfigPrivate *priv;
struct in6_addr *nameservers;
int i;
g_return_if_fail (NM_IS_IP6_CONFIG (config));
g_return_if_fail (nameserver > 0);
priv = NM_IP6_CONFIG_GET_PRIVATE (config);
/* No dupes */
nameservers = (struct in6_addr *)priv->nameservers->data;
for (i = 0; i < priv->nameservers->len; i++) {
g_return_if_fail (memcmp (nameserver, &nameservers[i], sizeof (struct in6_addr)) == 0);
}
g_array_append_val (priv->nameservers, *nameserver);
}
const struct in6_addr *nm_ip6_config_get_nameserver (NMIP6Config *config, guint i)
{
g_return_val_if_fail (NM_IS_IP6_CONFIG (config), 0);
return &g_array_index (NM_IP6_CONFIG_GET_PRIVATE (config)->nameservers, struct in6_addr, i);
}
guint32 nm_ip6_config_get_num_nameservers (NMIP6Config *config)
{
g_return_val_if_fail (NM_IS_IP6_CONFIG (config), 0);
return NM_IP6_CONFIG_GET_PRIVATE (config)->nameservers->len;
}
void nm_ip6_config_reset_nameservers (NMIP6Config *config)
{
NMIP6ConfigPrivate *priv;
g_return_if_fail (NM_IS_IP6_CONFIG (config));
priv = NM_IP6_CONFIG_GET_PRIVATE (config);
if (priv->nameservers->len)
g_array_remove_range (priv->nameservers, 0, priv->nameservers->len);
}
void
nm_ip6_config_take_route (NMIP6Config *config, NMIP6Route *route)
{
NMIP6ConfigPrivate *priv;
g_return_if_fail (NM_IS_IP6_CONFIG (config));
g_return_if_fail (route != NULL);
priv = NM_IP6_CONFIG_GET_PRIVATE (config);
priv->routes = g_slist_append (priv->routes, route);
}
void
nm_ip6_config_add_route (NMIP6Config *config, NMIP6Route *route)
{
NMIP6ConfigPrivate *priv;
g_return_if_fail (NM_IS_IP6_CONFIG (config));
g_return_if_fail (route != NULL);
priv = NM_IP6_CONFIG_GET_PRIVATE (config);
priv->routes = g_slist_append (priv->routes, nm_ip6_route_dup (route));
}
void
nm_ip6_config_replace_route (NMIP6Config *config,
guint i,
NMIP6Route *new_route)
{
NMIP6ConfigPrivate *priv;
GSList *old;
g_return_if_fail (NM_IS_IP6_CONFIG (config));
priv = NM_IP6_CONFIG_GET_PRIVATE (config);
old = g_slist_nth (priv->routes, i);
g_return_if_fail (old != NULL);
nm_ip6_route_unref ((NMIP6Route *) old->data);
old->data = nm_ip6_route_dup (new_route);
}
NMIP6Route *
nm_ip6_config_get_route (NMIP6Config *config, guint i)
{
g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL);
return (NMIP6Route *) g_slist_nth_data (NM_IP6_CONFIG_GET_PRIVATE (config)->routes, i);
}
guint32 nm_ip6_config_get_num_routes (NMIP6Config *config)
{
g_return_val_if_fail (NM_IS_IP6_CONFIG (config), 0);
return g_slist_length (NM_IP6_CONFIG_GET_PRIVATE (config)->routes);
}
void nm_ip6_config_reset_routes (NMIP6Config *config)
{
NMIP6ConfigPrivate *priv;
g_return_if_fail (NM_IS_IP6_CONFIG (config));
priv = NM_IP6_CONFIG_GET_PRIVATE (config);
g_slist_foreach (priv->routes, (GFunc) g_free, NULL);
priv->routes = NULL;
}
void nm_ip6_config_add_domain (NMIP6Config *config, const char *domain)
{
NMIP6ConfigPrivate *priv;
int i;
g_return_if_fail (NM_IS_IP6_CONFIG (config));
g_return_if_fail (domain != NULL);
g_return_if_fail (strlen (domain) > 0);
priv = NM_IP6_CONFIG_GET_PRIVATE (config);
for (i = 0; i < priv->domains->len; i++) {
if (!strcmp (g_ptr_array_index (priv->domains, i), domain))
return;
}
g_ptr_array_add (priv->domains, g_strdup (domain));
}
const char *nm_ip6_config_get_domain (NMIP6Config *config, guint i)
{
g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL);
return (const char *) g_ptr_array_index (NM_IP6_CONFIG_GET_PRIVATE (config)->domains, i);
}
guint32 nm_ip6_config_get_num_domains (NMIP6Config *config)
{
g_return_val_if_fail (NM_IS_IP6_CONFIG (config), 0);
return NM_IP6_CONFIG_GET_PRIVATE (config)->domains->len;
}
void nm_ip6_config_reset_domains (NMIP6Config *config)
{
NMIP6ConfigPrivate *priv;
int i;
g_return_if_fail (NM_IS_IP6_CONFIG (config));
priv = NM_IP6_CONFIG_GET_PRIVATE (config);
for (i = 0; i < priv->domains->len; i++)
g_free (g_ptr_array_index (priv->domains, i));
g_ptr_array_free (priv->domains, TRUE);
priv->domains = g_ptr_array_sized_new (3);
}
void nm_ip6_config_add_search (NMIP6Config *config, const char *search)
{
NMIP6ConfigPrivate *priv;
int i;
g_return_if_fail (config != NULL);
g_return_if_fail (search != NULL);
g_return_if_fail (strlen (search) > 0);
priv = NM_IP6_CONFIG_GET_PRIVATE (config);
for (i = 0; i < priv->searches->len; i++) {
if (!strcmp (g_ptr_array_index (priv->searches, i), search))
return;
}
g_ptr_array_add (priv->searches, g_strdup (search));
}
const char *nm_ip6_config_get_search (NMIP6Config *config, guint i)
{
g_return_val_if_fail (config != NULL, NULL);
return (const char *) g_ptr_array_index (NM_IP6_CONFIG_GET_PRIVATE (config)->searches, i);
}
guint32 nm_ip6_config_get_num_searches (NMIP6Config *config)
{
g_return_val_if_fail (config != NULL, 0);
return NM_IP6_CONFIG_GET_PRIVATE (config)->searches->len;
}
void nm_ip6_config_reset_searches (NMIP6Config *config)
{
NMIP6ConfigPrivate *priv;
int i;
g_return_if_fail (NM_IS_IP6_CONFIG (config));
priv = NM_IP6_CONFIG_GET_PRIVATE (config);
for (i = 0; i < priv->searches->len; i++)
g_free (g_ptr_array_index (priv->searches, i));
g_ptr_array_free (priv->searches, TRUE);
priv->searches = g_ptr_array_sized_new (3);
}
guint32 nm_ip6_config_get_mss (NMIP6Config *config)
{
g_return_val_if_fail (NM_IS_IP6_CONFIG (config), 0);
return NM_IP6_CONFIG_GET_PRIVATE (config)->mss;
}
void nm_ip6_config_set_mss (NMIP6Config *config, guint32 mss)
{
g_return_if_fail (NM_IS_IP6_CONFIG (config));
NM_IP6_CONFIG_GET_PRIVATE (config)->mss = mss;
}
gboolean
nm_ip6_config_get_never_default (NMIP6Config *config)
{
g_return_val_if_fail (NM_IS_IP6_CONFIG (config), FALSE);
return NM_IP6_CONFIG_GET_PRIVATE (config)->never_default;
}
void
nm_ip6_config_set_never_default (NMIP6Config *config, gboolean never_default)
{
g_return_if_fail (NM_IS_IP6_CONFIG (config));
NM_IP6_CONFIG_GET_PRIVATE (config)->never_default = never_default;
}
/* libnl convenience/conversion functions */
static int ip6_addr_to_rtnl_local (const struct in6_addr *ip6_address, struct rtnl_addr *addr)
{
struct nl_addr * local = NULL;
int err = 0;
g_return_val_if_fail (addr != NULL, -1);
local = nm_utils_ip6_addr_to_nl_addr (ip6_address);
err = rtnl_addr_set_local (addr, local);
nl_addr_put (local);
return err;
}
static int ip6_addr_to_rtnl_peer (const struct in6_addr *ip6_address, struct rtnl_addr *addr)
{
struct nl_addr * peer = NULL;
int err = 0;
g_return_val_if_fail (addr != NULL, -1);
peer = nm_utils_ip6_addr_to_nl_addr (ip6_address);
err = rtnl_addr_set_peer (addr, peer);
nl_addr_put (peer);
return err;
}
struct rtnl_addr *
nm_ip6_config_to_rtnl_addr (NMIP6Config *config, guint32 i, guint32 flags)
{
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config);
NMIP6Address *config_addr;
struct rtnl_addr *addr;
gboolean success = TRUE;
g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL);
config_addr = nm_ip6_config_get_address (config, i);
g_return_val_if_fail (config_addr != NULL, NULL);
if (!(addr = rtnl_addr_alloc()))
return NULL;
if (flags & NM_RTNL_ADDR_ADDR)
success = (ip6_addr_to_rtnl_local (nm_ip6_address_get_address (config_addr), addr) >= 0);
if (flags & NM_RTNL_ADDR_PTP_ADDR)
success = (ip6_addr_to_rtnl_peer (&priv->ptp_address, addr) >= 0);
if (flags & NM_RTNL_ADDR_PREFIX)
rtnl_addr_set_prefixlen (addr, nm_ip6_address_get_prefix (config_addr));
if (!success) {
rtnl_addr_put (addr);
addr = NULL;
}
return addr;
}
static gboolean
addr_slist_compare (GSList *a, GSList *b)
{
GSList *iter_a, *iter_b;
gboolean found = FALSE;
for (iter_a = a; iter_a; iter_a = g_slist_next (iter_a)) {
NMIP6Address *addr_a = (NMIP6Address *) iter_a->data;
for (iter_b = b, found = FALSE; iter_b; iter_b = g_slist_next (iter_b)) {
NMIP6Address *addr_b = (NMIP6Address *) iter_b->data;
if (nm_ip6_address_compare (addr_a, addr_b)) {
found = TRUE;
break;
}
}
if (!found)
return FALSE;
}
return TRUE;
}
static gboolean
route_slist_compare (GSList *a, GSList *b)
{
GSList *iter_a, *iter_b;
gboolean found = FALSE;
for (iter_a = a; iter_a; iter_a = g_slist_next (iter_a)) {
NMIP6Route *route_a = (NMIP6Route *) iter_a->data;
for (iter_b = b, found = FALSE; iter_b; iter_b = g_slist_next (iter_b)) {
NMIP6Route *route_b = (NMIP6Route *) iter_b->data;
if (nm_ip6_route_compare (route_a, route_b)) {
found = TRUE;
break;
}
}
if (!found)
return FALSE;
}
return TRUE;
}
static gboolean
string_array_compare (GPtrArray *a, GPtrArray *b)
{
int i, j;
gboolean found = FALSE;
for (i = 0; i < a->len; i++) {
for (j = 0, found = FALSE; j < b->len; j++) {
const char *item_a = g_ptr_array_index (a, i);
const char *item_b = g_ptr_array_index (b, j);
if ((!item_a && !item_b) || (item_a && item_b && !strcmp (item_a, item_b))) {
found = TRUE;
break;
}
}
if (!found)
return FALSE;
}
return TRUE;
}
static gboolean
addr_array_compare (GArray *a, GArray *b)
{
struct in6_addr *addrs_a, *addrs_b;
int i, j;
gboolean found = FALSE;
addrs_a = (struct in6_addr *)a->data;
addrs_b = (struct in6_addr *)b->data;
for (i = 0; i < a->len; i++) {
for (j = 0, found = FALSE; j < b->len; j++) {
if (memcmp (&addrs_a[i], &addrs_b[j], sizeof (struct in6_addr)) == 0) {
found = TRUE;
break;
}
}
if (!found)
return FALSE;
}
return TRUE;
}
NMIP6ConfigCompareFlags
nm_ip6_config_diff (NMIP6Config *a, NMIP6Config *b)
{
NMIP6ConfigPrivate *a_priv;
NMIP6ConfigPrivate *b_priv;
NMIP6ConfigCompareFlags flags = NM_IP6_COMPARE_FLAG_NONE;
if ((a && !b) || (b && !a))
return 0xFFFFFFFF;
if (!a && !b)
return NM_IP6_COMPARE_FLAG_NONE;
a_priv = NM_IP6_CONFIG_GET_PRIVATE (a);
b_priv = NM_IP6_CONFIG_GET_PRIVATE (b);
if ( !addr_slist_compare (a_priv->addresses, b_priv->addresses)
|| !addr_slist_compare (b_priv->addresses, a_priv->addresses))
flags |= NM_IP6_COMPARE_FLAG_ADDRESSES;
if (memcmp (&a_priv->ptp_address, &b_priv->ptp_address, sizeof (struct in6_addr)) != 0)
flags |= NM_IP6_COMPARE_FLAG_PTP_ADDRESS;
if ( (a_priv->nameservers->len != b_priv->nameservers->len)
|| !addr_array_compare (a_priv->nameservers, b_priv->nameservers)
|| !addr_array_compare (b_priv->nameservers, a_priv->nameservers))
flags |= NM_IP6_COMPARE_FLAG_NAMESERVERS;
if ( !route_slist_compare (a_priv->routes, b_priv->routes)
|| !route_slist_compare (b_priv->routes, a_priv->routes))
flags |= NM_IP6_COMPARE_FLAG_ROUTES;
if ( (a_priv->domains->len != b_priv->domains->len)
|| !string_array_compare (a_priv->domains, b_priv->domains)
|| !string_array_compare (b_priv->domains, a_priv->domains))
flags |= NM_IP6_COMPARE_FLAG_DOMAINS;
if ( (a_priv->searches->len != b_priv->searches->len)
|| !string_array_compare (a_priv->searches, b_priv->searches)
|| !string_array_compare (b_priv->searches, a_priv->searches))
flags |= NM_IP6_COMPARE_FLAG_SEARCHES;
if (a_priv->mss != b_priv->mss)
flags |= NM_IP6_COMPARE_FLAG_MSS;
return flags;
}
static void
nm_ip6_config_init (NMIP6Config *config)
{
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config);
priv->nameservers = g_array_new (FALSE, TRUE, sizeof (struct in6_addr));
priv->domains = g_ptr_array_sized_new (3);
priv->searches = g_ptr_array_sized_new (3);
}
static void
finalize (GObject *object)
{
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (object);
nm_utils_slist_free (priv->addresses, (GDestroyNotify) nm_ip6_address_unref);
nm_utils_slist_free (priv->routes, (GDestroyNotify) nm_ip6_route_unref);
g_array_free (priv->nameservers, TRUE);
g_ptr_array_free (priv->domains, TRUE);
g_ptr_array_free (priv->searches, TRUE);
G_OBJECT_CLASS (nm_ip6_config_parent_class)->finalize (object);
}
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (object);
switch (prop_id) {
case PROP_ADDRESSES:
nm_utils_ip6_addresses_to_gvalue (priv->addresses, value);
break;
case PROP_NAMESERVERS:
g_value_set_boxed (value, priv->nameservers);
break;
case PROP_DOMAINS:
g_value_set_boxed (value, priv->domains);
break;
case PROP_ROUTES:
nm_utils_ip6_routes_to_gvalue (priv->routes, value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
nm_ip6_config_class_init (NMIP6ConfigClass *config_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (config_class);
g_type_class_add_private (config_class, sizeof (NMIP6ConfigPrivate));
/* virtual methods */
object_class->get_property = get_property;
object_class->finalize = finalize;
/* properties */
g_object_class_install_property
(object_class, PROP_ADDRESSES,
g_param_spec_boxed (NM_IP6_CONFIG_ADDRESSES,
"Addresses",
"IP6 addresses",
DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT,
G_PARAM_READABLE));
g_object_class_install_property
(object_class, PROP_NAMESERVERS,
g_param_spec_boxed (NM_IP6_CONFIG_NAMESERVERS,
"Nameservers",
"DNS list",
DBUS_TYPE_G_UINT_ARRAY,
G_PARAM_READABLE));
g_object_class_install_property
(object_class, PROP_DOMAINS,
g_param_spec_boxed (NM_IP6_CONFIG_DOMAINS,
"Domains",
"Domains",
DBUS_TYPE_G_ARRAY_OF_STRING,
G_PARAM_READABLE));
g_object_class_install_property
(object_class, PROP_ROUTES,
g_param_spec_boxed (NM_IP6_CONFIG_ROUTES,
"Routes",
"Routes",
DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT,
G_PARAM_READABLE));
dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (config_class),
&dbus_glib_nm_ip6_config_object_info);
}

120
src/nm-ip6-config.h Normal file
View file

@ -0,0 +1,120 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager -- Network link manager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2008 Red Hat, Inc.
*/
#ifndef NM_IP6_CONFIG_H
#define NM_IP6_CONFIG_H
#include <glib.h>
#include <glib-object.h>
#include "nm-setting-ip6-config.h"
#define NM_TYPE_IP6_CONFIG (nm_ip6_config_get_type ())
#define NM_IP6_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IP6_CONFIG, NMIP6Config))
#define NM_IP6_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_IP6_CONFIG, NMIP6ConfigClass))
#define NM_IS_IP6_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_IP6_CONFIG))
#define NM_IS_IP6_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_IP6_CONFIG))
#define NM_IP6_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_IP6_CONFIG, NMIP6ConfigClass))
typedef struct {
GObject parent;
} NMIP6Config;
typedef struct {
GObjectClass parent;
} NMIP6ConfigClass;
#define NM_IP6_CONFIG_ADDRESSES "addresses"
#define NM_IP6_CONFIG_NAMESERVERS "nameservers"
#define NM_IP6_CONFIG_DOMAINS "domains"
#define NM_IP6_CONFIG_ROUTES "routes"
GType nm_ip6_config_get_type (void);
NMIP6Config * nm_ip6_config_new (void);
void nm_ip6_config_export (NMIP6Config *config);
const char * nm_ip6_config_get_dbus_path (NMIP6Config *config);
void nm_ip6_config_take_address (NMIP6Config *config, NMIP6Address *address);
void nm_ip6_config_add_address (NMIP6Config *config, NMIP6Address *address);
void nm_ip6_config_replace_address (NMIP6Config *config, guint32 i, NMIP6Address *new_address);
NMIP6Address *nm_ip6_config_get_address (NMIP6Config *config, guint32 i);
guint32 nm_ip6_config_get_num_addresses (NMIP6Config *config);
const struct in6_addr *nm_ip6_config_get_ptp_address (NMIP6Config *config);
void nm_ip6_config_set_ptp_address (NMIP6Config *config, struct in6_addr *ptp_addr);
void nm_ip6_config_add_nameserver (NMIP6Config *config, const struct in6_addr *nameserver);
const struct in6_addr *nm_ip6_config_get_nameserver (NMIP6Config *config, guint i);
guint32 nm_ip6_config_get_num_nameservers (NMIP6Config *config);
void nm_ip6_config_reset_nameservers (NMIP6Config *config);
void nm_ip6_config_take_route (NMIP6Config *config, NMIP6Route *route);
void nm_ip6_config_add_route (NMIP6Config *config, NMIP6Route *route);
void nm_ip6_config_replace_route (NMIP6Config *config, guint32 i, NMIP6Route *new_route);
NMIP6Route * nm_ip6_config_get_route (NMIP6Config *config, guint32 i);
guint32 nm_ip6_config_get_num_routes (NMIP6Config *config);
void nm_ip6_config_reset_routes (NMIP6Config *config);
void nm_ip6_config_add_domain (NMIP6Config *config, const char *domain);
const char * nm_ip6_config_get_domain (NMIP6Config *config, guint i);
guint32 nm_ip6_config_get_num_domains (NMIP6Config *config);
void nm_ip6_config_reset_domains (NMIP6Config *config);
void nm_ip6_config_add_search (NMIP6Config *config, const char *search);
const char * nm_ip6_config_get_search (NMIP6Config *config, guint i);
guint32 nm_ip6_config_get_num_searches (NMIP6Config *config);
void nm_ip6_config_reset_searches (NMIP6Config *config);
guint32 nm_ip6_config_get_mss (NMIP6Config *config);
void nm_ip6_config_set_mss (NMIP6Config *config, guint32 mss);
gboolean nm_ip6_config_get_never_default (NMIP6Config *config);
void nm_ip6_config_set_never_default (NMIP6Config *config, gboolean never_default);
/* Flags for nm_ip6_config_to_rtnl_addr() */
#define NM_RTNL_ADDR_NONE 0x0000
#define NM_RTNL_ADDR_ADDR 0x0001
#define NM_RTNL_ADDR_PTP_ADDR 0x0002
#define NM_RTNL_ADDR_PREFIX 0x0004
#define NM_RTNL_ADDR_BROADCAST 0x0008
#define NM_RTNL_ADDR_DEFAULT (NM_RTNL_ADDR_ADDR | NM_RTNL_ADDR_PREFIX | NM_RTNL_ADDR_BROADCAST)
#define NM_RTNL_ADDR_PTP_DEFAULT (NM_RTNL_ADDR_ADDR | NM_RTNL_ADDR_PREFIX | NM_RTNL_ADDR_PTP_ADDR)
struct rtnl_addr *nm_ip6_config_to_rtnl_addr (NMIP6Config *config, guint32 i, guint32 flags);
typedef enum {
NM_IP6_COMPARE_FLAG_NONE = 0x00000000, /* match nothing, kinda pointless */
NM_IP6_COMPARE_FLAG_ADDRESSES = 0x00000001,
NM_IP6_COMPARE_FLAG_PTP_ADDRESS = 0x00000002,
NM_IP6_COMPARE_FLAG_NAMESERVERS = 0x00000004,
NM_IP6_COMPARE_FLAG_ROUTES = 0x00000008,
NM_IP6_COMPARE_FLAG_DOMAINS = 0x00000010,
NM_IP6_COMPARE_FLAG_SEARCHES = 0x00000020,
NM_IP6_COMPARE_FLAG_MSS = 0x00000080,
NM_IP6_COMPARE_FLAG_ALL = 0xFFFFFFFF /* match everything */
} NMIP6ConfigCompareFlags;
/* Returns a bitfield representing how the two IP6 configs differ */
NMIP6ConfigCompareFlags nm_ip6_config_diff (NMIP6Config *a, NMIP6Config *b);
#endif /* NM_IP6_CONFIG_H */

View file

@ -35,6 +35,7 @@
#include "nm-device-private.h"
#include "nm-device-ethernet.h"
#include "nm-device-wifi.h"
#include "nm-device-olpc-mesh.h"
#include "NetworkManagerSystem.h"
#include "nm-properties-changed-signal.h"
#include "nm-setting-bluetooth.h"
@ -115,6 +116,14 @@ static void add_device (NMManager *self, NMDevice *device);
static void hostname_provider_init (NMHostnameProvider *provider_class);
static const char *internal_activate_device (NMManager *manager,
NMDevice *device,
NMConnection *connection,
const char *specific_object,
gboolean user_requested,
gboolean assumed,
GError **error);
#define SSD_POKE_INTERVAL 120
#define ORIGDEV_TAG "originating-device"
@ -350,12 +359,24 @@ manager_device_state_changed (NMDevice *device,
/* Removes a device from a device list; returns the start of the new device list */
static GSList *
remove_one_device (NMManager *manager, GSList *list, NMDevice *device)
remove_one_device (NMManager *manager,
GSList *list,
NMDevice *device,
gboolean quitting)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
if (nm_device_get_managed (device))
nm_device_set_managed (device, FALSE, NM_DEVICE_STATE_REASON_REMOVED);
if (nm_device_get_managed (device)) {
gboolean unmanage = !quitting;
/* Don't unmanage active assume-connection-capable devices at shutdown */
if ( nm_device_interface_can_assume_connection (NM_DEVICE_INTERFACE (device))
&& nm_device_get_state (device) == NM_DEVICE_STATE_ACTIVATED)
unmanage = FALSE;
if (unmanage)
nm_device_set_managed (device, FALSE, NM_DEVICE_STATE_REASON_REMOVED);
}
g_signal_handlers_disconnect_by_func (device, manager_device_state_changed, manager);
@ -374,7 +395,7 @@ modem_removed (NMModemManager *modem_manager,
NMManager *self = NM_MANAGER (user_data);
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
priv->devices = remove_one_device (self, priv->devices, modem);
priv->devices = remove_one_device (self, priv->devices, modem, FALSE);
}
static void
@ -640,8 +661,8 @@ user_connection_get_settings_cb (DBusGProxy *proxy,
*/
g_object_set_data_full (G_OBJECT (connection),
"proxy",
info->proxy,
g_object_ref (info->proxy));
g_object_ref (info->proxy),
g_object_unref);
} else
g_object_unref (connection);
@ -1149,6 +1170,9 @@ add_device (NMManager *self, NMDevice *device)
char *path;
static guint32 devcount = 0;
const GSList *unmanaged_specs;
NMConnection *existing = NULL;
GHashTableIter iter;
gpointer value;
priv->devices = g_slist_append (priv->devices, device);
@ -1185,13 +1209,50 @@ add_device (NMManager *self, NMDevice *device)
nm_info ("(%s): exported as %s", iface, path);
g_free (path);
/* Check if we should assume the device's active connection by matching its
* config with an existing system connection.
*/
if (nm_device_interface_can_assume_connection (NM_DEVICE_INTERFACE (device))) {
GSList *connections = NULL;
g_hash_table_iter_init (&iter, priv->system_connections);
while (g_hash_table_iter_next (&iter, NULL, &value))
connections = g_slist_append (connections, value);
existing = nm_device_interface_connection_match_config (NM_DEVICE_INTERFACE (device),
(const GSList *) connections);
g_slist_free (connections);
}
/* Start the device if it's supposed to be managed */
unmanaged_specs = nm_sysconfig_settings_get_unmanaged_specs (priv->sys_settings);
if (!priv->sleeping && !nm_device_interface_spec_match_list (NM_DEVICE_INTERFACE (device), unmanaged_specs))
nm_device_set_managed (device, TRUE, NM_DEVICE_STATE_REASON_NOW_MANAGED);
if ( !priv->sleeping
&& !nm_device_interface_spec_match_list (NM_DEVICE_INTERFACE (device), unmanaged_specs)) {
nm_device_set_managed (device,
TRUE,
existing ? NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED :
NM_DEVICE_STATE_REASON_NOW_MANAGED);
}
nm_sysconfig_settings_device_added (priv->sys_settings, device);
g_signal_emit (self, signals[DEVICE_ADDED], 0, device);
/* If the device has a connection it can assume, do that now */
if (existing) {
const char *ac_path;
GError *error = NULL;
ac_path = internal_activate_device (self, device, existing, NULL, FALSE, TRUE, &error);
if (ac_path)
g_object_notify (G_OBJECT (self), NM_MANAGER_ACTIVE_CONNECTIONS);
else {
nm_warning ("Assumed connection (%d) %s failed to activate: (%d) %s",
nm_connection_get_scope (existing),
nm_connection_get_path (existing),
error ? error->code : -1,
error && error->message ? error->message : "(unknown)");
g_error_free (error);
}
}
}
static gboolean
@ -1298,7 +1359,7 @@ bluez_manager_resync_devices (NMManager *self)
priv->devices = keep;
while (g_slist_length (gone))
gone = remove_one_device (self, gone, NM_DEVICE (gone->data));
gone = remove_one_device (self, gone, NM_DEVICE (gone->data), FALSE);
} else {
g_slist_free (keep);
g_slist_free (gone);
@ -1368,7 +1429,7 @@ bluez_manager_bdaddr_removed_cb (NMBluezManager *bluez_mgr,
NMDevice *device = NM_DEVICE (iter->data);
if (!strcmp (nm_device_get_udi (device), object_path)) {
priv->devices = remove_one_device (self, priv->devices, device);
priv->devices = remove_one_device (self, priv->devices, device, FALSE);
break;
}
}
@ -1388,6 +1449,8 @@ find_device_by_ifindex (NMManager *self, guint32 ifindex)
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;
@ -1429,8 +1492,7 @@ udev_device_removed_cb (NMUdevManager *manager,
ifindex = g_udev_device_get_property_as_int (udev_device, "IFINDEX");
device = find_device_by_ifindex (self, ifindex);
if (device)
priv->devices = remove_one_device (self, priv->devices, device);
priv->devices = remove_one_device (self, priv->devices, device, FALSE);
}
static void
@ -1809,6 +1871,7 @@ internal_activate_device (NMManager *manager,
NMConnection *connection,
const char *specific_object,
gboolean user_requested,
gboolean assumed,
GError **error)
{
NMActRequest *req;
@ -1832,7 +1895,7 @@ internal_activate_device (NMManager *manager,
NM_DEVICE_STATE_REASON_NONE);
}
req = nm_act_request_new (connection, specific_object, user_requested, (gpointer) device);
req = nm_act_request_new (connection, specific_object, user_requested, assumed, (gpointer) device);
g_signal_connect (req, "manager-get-secrets", G_CALLBACK (provider_get_secrets), manager);
g_signal_connect (req, "manager-cancel-secrets", G_CALLBACK (provider_cancel_secrets), manager);
success = nm_device_interface_activate (dev_iface, req, error);
@ -1944,6 +2007,7 @@ nm_manager_activate_connection (NMManager *manager,
connection,
specific_object,
user_requested,
FALSE,
error);
}
@ -2530,7 +2594,7 @@ dispose (GObject *object)
while (g_slist_length (priv->devices)) {
NMDevice *device = NM_DEVICE (priv->devices->data);
priv->devices = remove_one_device (manager, priv->devices, device);
priv->devices = remove_one_device (manager, priv->devices, device, TRUE);
}
user_destroy_connections (manager);

View file

@ -36,6 +36,7 @@
#include "nm-utils.h"
#include "NetworkManagerUtils.h"
#include "nm-device-wifi.h"
#include "nm-device-olpc-mesh.h"
#include "nm-device-ethernet.h"
typedef struct {
@ -271,6 +272,13 @@ is_wireless (GUdevDevice *device)
return is_wifi;
}
static gboolean
is_olpc_mesh (GUdevDevice *device)
{
const gchar *prop = g_udev_device_get_property (device, "ID_NM_OLPC_MESH");
return (prop != NULL);
}
static GObject *
device_creator (NMUdevManager *manager,
GUdevDevice *udev_device,
@ -311,7 +319,9 @@ device_creator (NMUdevManager *manager,
return NULL;
}
if (is_wireless (udev_device))
if (is_olpc_mesh (udev_device)) /* must be before is_wireless */
device = (GObject *) nm_device_olpc_mesh_new (path, ifname, driver, ifindex);
else if (is_wireless (udev_device))
device = (GObject *) nm_device_wifi_new (path, ifname, driver, ifindex);
else
device = (GObject *) nm_device_ethernet_new (path, ifname, driver, ifindex);

View file

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

View file

@ -32,7 +32,8 @@ libifcfg_rh_io_la_CPPFLAGS = \
$(DBUS_CFLAGS) \
$(NSS_CFLAGS) \
-DG_DISABLE_DEPRECATED \
-DSYSCONFDIR=\"$(sysconfdir)\"
-DSYSCONFDIR=\"$(sysconfdir)\" \
-DSBINDIR=\"$(sbindir)\"
libifcfg_rh_io_la_LIBADD = $(GLIB_LIBS) $(NSS_LIBS)

View file

@ -112,7 +112,7 @@ nm_ifcfg_connection_new (const char *filename,
g_return_val_if_fail (filename != NULL, NULL);
tmp = connection_from_file (filename, NULL, NULL, &unmanaged, &keyfile, error, ignore_error);
tmp = connection_from_file (filename, NULL, NULL, NULL, &unmanaged, &keyfile, error, ignore_error);
if (!tmp)
return NULL;

View file

@ -23,6 +23,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <ctype.h>
#include <sys/inotify.h>
#include <errno.h>
@ -183,6 +184,284 @@ make_connection_setting (const char *file,
return NM_SETTING (s_con);
}
static gboolean
read_mac_address (shvarFile *ifcfg, GByteArray **array, GError **error)
{
char *value = NULL;
struct ether_addr *mac;
g_return_val_if_fail (ifcfg != NULL, FALSE);
g_return_val_if_fail (array != NULL, FALSE);
g_return_val_if_fail (*array == NULL, FALSE);
g_return_val_if_fail (error != NULL, FALSE);
g_return_val_if_fail (*error == NULL, FALSE);
value = svGetValue (ifcfg, "HWADDR", FALSE);
if (!value || !strlen (value)) {
g_free (value);
return TRUE;
}
mac = ether_aton (value);
if (!mac) {
g_free (value);
g_set_error (error, ifcfg_plugin_error_quark (), 0,
"The MAC address '%s' was invalid.", value);
return FALSE;
}
g_free (value);
*array = g_byte_array_sized_new (ETH_ALEN);
g_byte_array_append (*array, (guint8 *) mac->ether_addr_octet, ETH_ALEN);
return TRUE;
}
static void
iscsiadm_child_setup (gpointer user_data G_GNUC_UNUSED)
{
/* We are in the child process here; set a different process group to
* ensure signal isolation between child and parent.
*/
pid_t pid = getpid ();
setpgid (pid, pid);
}
static char *
match_iscsiadm_tag (const char *line, const char *tag, gboolean *skip)
{
char *p;
if (g_ascii_strncasecmp (line, tag, strlen (tag)))
return NULL;
p = strchr (line, '=');
if (!p) {
g_warning ("%s: malformed iscsiadm record: no = in '%s'.",
__func__, line);
*skip = TRUE;
return NULL;
}
p++; /* advance past = */
return g_strstrip (p);
}
#define ISCSI_HWADDR_TAG "iface.hwaddress"
#define ISCSI_BOOTPROTO_TAG "iface.bootproto"
#define ISCSI_IPADDR_TAG "iface.ipaddress"
#define ISCSI_SUBNET_TAG "iface.subnet_mask"
#define ISCSI_GATEWAY_TAG "iface.gateway"
#define ISCSI_DNS1_TAG "iface.primary_dns"
#define ISCSI_DNS2_TAG "iface.secondary_dns"
static gboolean
fill_ip4_setting_from_ibft (shvarFile *ifcfg,
NMSettingIP4Config *s_ip4,
const char *iscsiadm_path,
GError **error)
{
const char *argv[4] = { iscsiadm_path, "-m", "fw", NULL };
const char *envp[1] = { NULL };
gboolean success = FALSE, in_record = FALSE, hwaddr_matched = FALSE, skip = FALSE;
char *out = NULL, *err = NULL;
gint status = 0;
GByteArray *ifcfg_mac = NULL;
char **lines = NULL, **iter;
const char *method = NULL;
struct in_addr ipaddr;
struct in_addr gateway;
struct in_addr dns1;
struct in_addr dns2;
guint32 prefix = 0;
g_return_val_if_fail (s_ip4 != NULL, FALSE);
g_return_val_if_fail (iscsiadm_path != NULL, FALSE);
if (!g_spawn_sync ("/", (char **) argv, (char **) envp, 0,
iscsiadm_child_setup, NULL, &out, &err, &status, error))
return FALSE;
if (!WIFEXITED (status)) {
g_set_error (error, ifcfg_plugin_error_quark (), 0,
"%s exited abnormally.", iscsiadm_path);
goto done;
}
if (WEXITSTATUS (status) != 0) {
g_set_error (error, ifcfg_plugin_error_quark (), 0,
"%s exited with error %d. Message: '%s'",
iscsiadm_path, WEXITSTATUS (status), err ? err : "(none)");
goto done;
}
if (!read_mac_address (ifcfg, &ifcfg_mac, error))
goto done;
/* Ensure we got a MAC */
if (!ifcfg_mac) {
g_set_error (error, ifcfg_plugin_error_quark (), 0,
"Missing device MAC address (no HWADDR tag present).");
goto done;
}
memset (&ipaddr, 0, sizeof (ipaddr));
memset (&gateway, 0, sizeof (gateway));
memset (&dns1, 0, sizeof (dns1));
memset (&dns2, 0, sizeof (dns2));
/* Success, lets parse the output */
lines = g_strsplit_set (out, "\n\r", -1);
for (iter = lines; iter && *iter; iter++) {
char *p;
if (!g_ascii_strcasecmp (*iter, "# BEGIN RECORD")) {
if (in_record) {
g_warning ("%s: malformed iscsiadm record: already parsing record.", __func__);
skip = TRUE;
}
} else if (!g_ascii_strcasecmp (*iter, "# END RECORD")) {
if (!skip && hwaddr_matched) {
/* Record is good; fill IP4 config with its info */
if (!method) {
g_warning ("%s: malformed iscsiadm record: missing BOOTPROTO.", __func__);
return FALSE;
}
g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, method, NULL);
if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) {
NMIP4Address *addr;
if (!ipaddr.s_addr || !prefix) {
g_warning ("%s: malformed iscsiadm record: BOOTPROTO=static "
"but missing IP address or prefix.", __func__);
return FALSE;
}
addr = nm_ip4_address_new ();
nm_ip4_address_set_address (addr, ipaddr.s_addr);
nm_ip4_address_set_prefix (addr, prefix);
nm_ip4_address_set_gateway (addr, gateway.s_addr);
nm_setting_ip4_config_add_address (s_ip4, addr);
nm_ip4_address_unref (addr);
if (dns1.s_addr)
nm_setting_ip4_config_add_dns (s_ip4, dns1.s_addr);
if (dns2.s_addr)
nm_setting_ip4_config_add_dns (s_ip4, dns2.s_addr);
// FIXME: DNS search domains?
}
return TRUE;
}
skip = FALSE;
hwaddr_matched = FALSE;
memset (&ipaddr, 0, sizeof (ipaddr));
memset (&gateway, 0, sizeof (gateway));
memset (&dns1, 0, sizeof (dns1));
memset (&dns2, 0, sizeof (dns2));
prefix = 0;
method = NULL;
}
if (skip)
continue;
/* HWADDR */
if (!skip && (p = match_iscsiadm_tag (*iter, ISCSI_HWADDR_TAG, &skip))) {
struct ether_addr *ibft_mac;
ibft_mac = ether_aton (p);
if (!ibft_mac) {
g_warning ("%s: malformed iscsiadm record: invalid hwaddress.", __func__);
skip = TRUE;
continue;
}
if (memcmp (ifcfg_mac->data, (guint8 *) ibft_mac->ether_addr_octet, ETH_ALEN)) {
/* This record isn't for the current device, ignore it */
skip = TRUE;
continue;
}
/* Success, this record is for this device */
hwaddr_matched = TRUE;
}
/* BOOTPROTO */
if (!skip && (p = match_iscsiadm_tag (*iter, ISCSI_BOOTPROTO_TAG, &skip))) {
if (!g_ascii_strcasecmp (p, "dhcp"))
method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
else if (!g_ascii_strcasecmp (p, "static"))
method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL;
else {
g_warning ("%s: malformed iscsiadm record: unknown BOOTPROTO '%s'.",
__func__, p);
skip = TRUE;
continue;
}
}
if (!skip && (p = match_iscsiadm_tag (*iter, ISCSI_IPADDR_TAG, &skip))) {
if (inet_pton (AF_INET, p, &ipaddr) < 1) {
g_warning ("%s: malformed iscsiadm record: invalid IP address '%s'.",
__func__, p);
skip = TRUE;
continue;
}
}
if (!skip && (p = match_iscsiadm_tag (*iter, ISCSI_SUBNET_TAG, &skip))) {
struct in_addr mask;
if (inet_pton (AF_INET, p, &mask) < 1) {
g_warning ("%s: malformed iscsiadm record: invalid subnet mask '%s'.",
__func__, p);
skip = TRUE;
continue;
}
prefix = nm_utils_ip4_netmask_to_prefix (mask.s_addr);
}
if (!skip && (p = match_iscsiadm_tag (*iter, ISCSI_GATEWAY_TAG, &skip))) {
if (inet_pton (AF_INET, p, &gateway) < 1) {
g_warning ("%s: malformed iscsiadm record: invalid IP gateway '%s'.",
__func__, p);
skip = TRUE;
continue;
}
}
if (!skip && (p = match_iscsiadm_tag (*iter, ISCSI_DNS1_TAG, &skip))) {
if (inet_pton (AF_INET, p, &dns1) < 1) {
g_warning ("%s: malformed iscsiadm record: invalid DNS1 address '%s'.",
__func__, p);
skip = TRUE;
continue;
}
}
if (!skip && (p = match_iscsiadm_tag (*iter, ISCSI_DNS2_TAG, &skip))) {
if (inet_pton (AF_INET, p, &dns2) < 1) {
g_warning ("%s: malformed iscsiadm record: invalid DNS2 address '%s'.",
__func__, p);
skip = TRUE;
continue;
}
}
}
success = TRUE;
done:
if (ifcfg_mac)
g_byte_array_free (ifcfg_mac, TRUE);
g_strfreev (lines);
g_free (out);
g_free (err);
return success;
}
static gboolean
read_ip4_address (shvarFile *ifcfg,
const char *tag,
@ -325,7 +604,10 @@ error:
}
static NMSetting *
make_ip4_setting (shvarFile *ifcfg, const char *network_file, GError **error)
make_ip4_setting (shvarFile *ifcfg,
const char *network_file,
const char *iscsiadm_path,
GError **error)
{
NMSettingIP4Config *s_ip4 = NULL;
char *value = NULL;
@ -364,7 +646,15 @@ make_ip4_setting (shvarFile *ifcfg, const char *network_file, GError **error)
if (value) {
if (!g_ascii_strcasecmp (value, "bootp") || !g_ascii_strcasecmp (value, "dhcp"))
method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
else if (!g_ascii_strcasecmp (value, "autoip")) {
else if (!g_ascii_strcasecmp (value, "ibft")) {
/* iSCSI Boot Firmware Table: need to read values from the iSCSI
* firmware for this device and create the IP4 setting using those.
*/
if (fill_ip4_setting_from_ibft (ifcfg, s_ip4, iscsiadm_path, error))
return NM_SETTING (s_ip4);
g_object_unref (s_ip4);
return NULL;
} else if (!g_ascii_strcasecmp (value, "autoip")) {
g_free (value);
g_object_set (s_ip4,
NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL,
@ -498,38 +788,6 @@ error:
return NULL;
}
static gboolean
read_mac_address (shvarFile *ifcfg, GByteArray **array, GError **error)
{
char *value = NULL;
struct ether_addr *mac;
g_return_val_if_fail (ifcfg != NULL, FALSE);
g_return_val_if_fail (array != NULL, FALSE);
g_return_val_if_fail (*array == NULL, FALSE);
g_return_val_if_fail (error != NULL, FALSE);
g_return_val_if_fail (*error == NULL, FALSE);
value = svGetValue (ifcfg, "HWADDR", FALSE);
if (!value || !strlen (value)) {
g_free (value);
return TRUE;
}
mac = ether_aton (value);
if (!mac) {
g_free (value);
g_set_error (error, ifcfg_plugin_error_quark (), 0,
"The MAC address '%s' was invalid.", value);
return FALSE;
}
g_free (value);
*array = g_byte_array_sized_new (ETH_ALEN);
g_byte_array_append (*array, (guint8 *) mac->ether_addr_octet, ETH_ALEN);
return TRUE;
}
static gboolean
add_one_wep_key (shvarFile *ifcfg,
const char *shvar_key,
@ -1204,7 +1462,9 @@ eap_peap_reader (const char *eap_method,
if (!strlen (*iter))
continue;
if (!strcmp (*iter, "MSCHAPV2") || !strcmp (*iter, "MD5")) {
if ( !strcmp (*iter, "MSCHAPV2")
|| !strcmp (*iter, "MD5")
|| !strcmp (*iter, "GTC")) {
if (!eap_simple_reader (*iter, ifcfg, keys, s_8021x, TRUE, error))
goto done;
} else if (!strcmp (*iter, "TLS")) {
@ -1217,7 +1477,6 @@ eap_peap_reader (const char *eap_method,
goto done;
}
// FIXME: OTP & GTC too
lower = g_ascii_strdown (*iter, -1);
g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, lower, NULL);
g_free (lower);
@ -2031,8 +2290,9 @@ is_wireless_device (const char *iface)
NMConnection *
connection_from_file (const char *filename,
const char *network_file,
const char *test_type, /* for unit tests only */
const char *network_file, /* for unit tests only */
const char *test_type, /* for unit tests only */
const char *iscsiadm_path, /* for unit tests only */
char **unmanaged,
char **keyfile,
GError **error,
@ -2040,7 +2300,7 @@ connection_from_file (const char *filename,
{
NMConnection *connection = NULL;
shvarFile *parsed;
char *type, *nmc = NULL;
char *type, *nmc = NULL, *bootproto;
NMSetting *s_ip4;
char *ifcfg_name = NULL;
gboolean nm_controlled = TRUE;
@ -2055,6 +2315,9 @@ connection_from_file (const char *filename,
if (!network_file)
network_file = SYSCONFDIR "/sysconfig/network";
if (!iscsiadm_path)
iscsiadm_path = SBINDIR "/iscsiadm";
ifcfg_name = utils_get_ifcfg_name (filename);
if (!ifcfg_name) {
g_set_error (error, ifcfg_plugin_error_quark (), 0,
@ -2141,7 +2404,7 @@ connection_from_file (const char *filename,
if (!connection || *unmanaged)
goto done;
s_ip4 = make_ip4_setting (parsed, network_file, error);
s_ip4 = make_ip4_setting (parsed, network_file, iscsiadm_path, error);
if (*error) {
g_object_unref (connection);
connection = NULL;
@ -2150,6 +2413,21 @@ connection_from_file (const char *filename,
nm_connection_add_setting (connection, s_ip4);
}
/* iSCSI / ibft connections are read-only since their settings are
* stored in NVRAM and can only be changed in BIOS.
*/
bootproto = svGetValue (parsed, "BOOTPROTO", FALSE);
if ( bootproto
&& connection
&& !g_ascii_strcasecmp (bootproto, "ibft")) {
NMSettingConnection *s_con;
s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
g_assert (s_con);
g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_READ_ONLY, TRUE, NULL);
}
if (!nm_connection_verify (connection, error)) {
g_object_unref (connection);
connection = NULL;

View file

@ -27,8 +27,9 @@
#include "shvar.h"
NMConnection *connection_from_file (const char *filename,
const char *network_file,
const char *test_type,
const char *network_file, /* for unit tests only */
const char *test_type, /* for unit tests only */
const char *iscsiadm_path, /* for unit tests only */
char **unmanaged,
char **keyfile,
GError **error,

View file

@ -30,3 +30,12 @@ check-local: test-ifcfg-rh
endif
EXTRA_DIST = \
iscsiadm-test-dhcp \
iscsiadm-test-static \
iscsiadm-test-malformed \
iscsiadm-test-bad-ipaddr \
iscsiadm-test-bad-gateway \
iscsiadm-test-bad-dns1 \
iscsiadm-test-bad-dns2

View file

@ -0,0 +1,21 @@
#!/bin/bash
cat << EOF
# BEGIN RECORD
iface.initiatorname = iqn.pjones6
iface.hwaddress = 00:33:21:98:b9:f0
iface.bootproto = STATIC
iface.ipaddress = 192.168.32.72
iface.subnet_mask = 255.255.252.0
iface.gateway = 192.168.35.254
iface.primary_dns = 10000.500.250.1
iface.secondary_dns = 10.16.255.3
iface.vlan = 0
iface.net_ifacename = eth0
node.name = iqn.0.2008-11.com.blahblah:iscsi0
node.conn[0].address = 10.16.52.16
node.conn[0].port = 3260
node.boot_lun = 00000000
# END RECORD
EOF

View file

@ -0,0 +1,21 @@
#!/bin/bash
cat << EOF
# BEGIN RECORD
iface.initiatorname = iqn.pjones6
iface.hwaddress = 00:33:21:98:b9:f0
iface.bootproto = STATIC
iface.ipaddress = 192.168.32.72
iface.subnet_mask = 255.255.252.0
iface.gateway = 192.168.35.254
iface.primary_dns = 10.16.255.2
iface.secondary_dns = blah.foo.bar.baz
iface.vlan = 0
iface.net_ifacename = eth0
node.name = iqn.0.2008-11.com.blahblah:iscsi0
node.conn[0].address = 10.16.52.16
node.conn[0].port = 3260
node.boot_lun = 00000000
# END RECORD
EOF

View file

@ -0,0 +1,35 @@
#!/bin/bash
cat << EOF
# BEGIN RECORD
iface.initiatorname = iqn.pjones6
iface.hwaddress = 00:33:21:98:b9:f0
iface.bootproto = STATIC
iface.ipaddress 192.168.32.72
iface.subnet_mask = 255.255.252.0
iface.gateway = 192.168.35.254
iface.primary_dns = 10.16.255.2
iface.secondary_dns = 10.16.255.3
iface.vlan = 0
iface.net_ifacename = eth0
node.name = iqn.0.2008-11.com.blahblah:iscsi0
node.conn[0].address = 10.16.52.16
node.conn[0].port = 3260
node.boot_lun = 00000000
# END RECORD
# BEGIN RECORD
iface.initiatorname = iqn.pjones6
iface.hwaddress = 00:33:21:98:b9:f1
iface.bootproto = DHCP
iface.gateway = 10.16.52.254
iface.primary_dns = 10.16.255.2
iface.secondary_dns = 10.16.255.3
iface.vlan = 0
iface.net_ifacename = eth1
node.name = iqn.1.2008-11.com.blahblah:iscsi1
node.conn[0].address = 10.16.52.16
node.conn[0].port = 3260
node.boot_lun = 00000000
# END RECORD
EOF

View file

@ -0,0 +1,21 @@
#!/bin/bash
cat << EOF
# BEGIN RECORD
iface.initiatorname = iqn.pjones6
iface.hwaddress = 00:33:21:98:b9:f0
iface.bootproto = STATIC
iface.ipaddress = aa.bb.cc.dd
iface.subnet_mask = 255.255.252.0
iface.gateway = 192.168.35.254
iface.primary_dns = 10.16.255.2
iface.secondary_dns = 10.16.255.3
iface.vlan = 0
iface.net_ifacename = eth0
node.name = iqn.0.2008-11.com.blahblah:iscsi0
node.conn[0].address = 10.16.52.16
node.conn[0].port = 3260
node.boot_lun = 00000000
# END RECORD
EOF

View file

@ -0,0 +1,21 @@
#!/bin/bash
cat << EOF
# BEGIN RECORD
iface.initiatorname = iqn.pjones6
iface.hwaddress = 00:33:21:98:b9:f0
iface.bootproto = STATIC
iface.ipaddress = 192.168.32.72
iface.subnet_mask = 255.255.252.0
iface.gateway = bb.cc.dd.ee
iface.primary_dns = 10.16.255.2
iface.secondary_dns = 10.16.255.3
iface.vlan = 0
iface.net_ifacename = eth0
node.name = iqn.0.2008-11.com.blahblah:iscsi0
node.conn[0].address = 10.16.52.16
node.conn[0].port = 3260
node.boot_lun = 00000000
# END RECORD
EOF

View file

@ -0,0 +1,18 @@
#!/bin/bash
cat << EOF
# BEGIN RECORD
iface.initiatorname = iqn.pjones6
iface.hwaddress = 00:33:21:98:b9:f0
iface.bootproto = DHCP
iface.gateway = 10.16.52.254
iface.primary_dns = 10.16.255.2
iface.secondary_dns = 10.16.255.3
iface.vlan = 0
iface.net_ifacename = eth0
node.name = iqn.0.2008-11.com.blahblah:iscsi0
node.conn[0].address = 10.16.52.16
node.conn[0].port = 3260
node.boot_lun = 00000000
EOF

View file

@ -0,0 +1,33 @@
#!/bin/bash
cat << EOF
# BEGIN RECORD
iface.initiatorname = iqn.pjones6
iface.hwaddress = 00:33:21:98:b9:f0
iface.bootproto = DHCP
iface.gateway = 10.16.52.254
iface.primary_dns = 10.16.255.2
iface.secondary_dns = 10.16.255.3
iface.vlan = 0
iface.net_ifacename = eth0
node.name = iqn.0.2008-11.com.blahblah:iscsi0
node.conn[0].address = 10.16.52.16
node.conn[0].port = 3260
node.boot_lun = 00000000
# END RECORD
# BEGIN RECORD
iface.initiatorname = iqn.pjones6
iface.hwaddress = 00:33:21:98:b9:f1
iface.bootproto = DHCP
iface.gateway = 10.16.52.254
iface.primary_dns = 10.16.255.2
iface.secondary_dns = 10.16.255.3
iface.vlan = 0
iface.net_ifacename = eth1
node.name = iqn.1.2008-11.com.blahblah:iscsi1
node.conn[0].address = 10.16.52.16
node.conn[0].port = 3260
node.boot_lun = 00000000
# END RECORD
EOF

View file

@ -0,0 +1,35 @@
#!/bin/bash
cat << EOF
# BEGIN RECORD
iface.initiatorname = iqn.pjones6
iface.hwaddress = 00:33:21:98:b9:f0
iface.bootproto = STATIC
iface.ipaddress = 192.168.32.72
iface.subnet_mask = 255.255.252.0
iface.gateway = 192.168.35.254
iface.primary_dns = 10.16.255.2
iface.secondary_dns = 10.16.255.3
iface.vlan = 0
iface.net_ifacename = eth0
node.name = iqn.0.2008-11.com.blahblah:iscsi0
node.conn[0].address = 10.16.52.16
node.conn[0].port = 3260
node.boot_lun = 00000000
# END RECORD
# BEGIN RECORD
iface.initiatorname = iqn.pjones6
iface.hwaddress = 00:33:21:98:b9:f1
iface.bootproto = DHCP
iface.gateway = 10.16.52.254
iface.primary_dns = 10.16.255.2
iface.secondary_dns = 10.16.255.3
iface.vlan = 0
iface.net_ifacename = eth1
node.name = iqn.1.2008-11.com.blahblah:iscsi1
node.conn[0].address = 10.16.52.16
node.conn[0].port = 3260
node.boot_lun = 00000000
# END RECORD
EOF

View file

@ -35,7 +35,9 @@ EXTRA_DIST = \
ifcfg-test-wifi-wpa-eap-ttls-tls \
keys-test-wifi-wpa-eap-ttls-tls \
test_ca_cert.pem \
test1_key_and_cert.pem
test1_key_and_cert.pem \
ifcfg-test-ibft-dhcp \
ifcfg-test-ibft-static
check-local:
@for f in $(EXTRA_DIST); do \

View file

@ -0,0 +1,4 @@
# Intel Corporation 82540EP Gigabit Ethernet Controller (Mobile)
DEVICE=eth0
HWADDR=00:33:21:98:b9:f1
BOOTPROTO=ibft

View file

@ -0,0 +1,4 @@
# Intel Corporation 82540EP Gigabit Ethernet Controller (Mobile)
DEVICE=eth0
HWADDR=00:33:21:98:b9:f0
BOOTPROTO=ibft

View file

@ -176,6 +176,7 @@ test_read_minimal (void)
connection = connection_from_file (TEST_IFCFG_MINIMAL,
NULL,
TYPE_ETHERNET,
NULL,
&unmanaged,
&keyfile,
&error,
@ -299,6 +300,7 @@ test_read_unmanaged (void)
connection = connection_from_file (TEST_IFCFG_UNMANAGED,
NULL,
TYPE_ETHERNET,
NULL,
&unmanaged,
&keyfile,
&error,
@ -417,6 +419,7 @@ test_read_wired_static (void)
connection = connection_from_file (TEST_IFCFG_WIRED_STATIC,
NULL,
TYPE_ETHERNET,
NULL,
&unmanaged,
&keyfile,
&error,
@ -557,7 +560,7 @@ test_read_wired_static (void)
NM_SETTING_IP4_CONFIG_ADDRESSES);
ASSERT (nm_ip4_address_get_prefix (ip4_addr) == 24,
"wired-static-verify-ip4", "failed to verify %s: unexpected IP4 address #1 gateway",
"wired-static-verify-ip4", "failed to verify %s: unexpected IP4 address #1 prefix",
TEST_IFCFG_WIRED_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_ADDRESSES);
@ -612,6 +615,7 @@ test_read_wired_dhcp (void)
connection = connection_from_file (TEST_IFCFG_WIRED_DHCP,
NULL,
TYPE_ETHERNET,
NULL,
&unmanaged,
&keyfile,
&error,
@ -777,6 +781,7 @@ test_read_wired_global_gateway (void)
connection = connection_from_file (TEST_IFCFG_WIRED_GLOBAL_GATEWAY,
TEST_NETWORK_WIRED_GLOBAL_GATEWAY,
TYPE_ETHERNET,
NULL,
&unmanaged,
&keyfile,
&error,
@ -844,7 +849,7 @@ test_read_wired_global_gateway (void)
NM_SETTING_IP4_CONFIG_ADDRESSES);
ASSERT (nm_ip4_address_get_prefix (ip4_addr) == 24,
"wired-global-gateway-verify-ip4", "failed to verify %s: unexpected IP4 address #1 gateway",
"wired-global-gateway-verify-ip4", "failed to verify %s: unexpected IP4 address #1 prefix",
TEST_IFCFG_WIRED_GLOBAL_GATEWAY,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_ADDRESSES);
@ -894,6 +899,7 @@ test_read_wired_never_default (void)
connection = connection_from_file (TEST_IFCFG_WIRED_NEVER_DEFAULT,
TEST_NETWORK_WIRED_NEVER_DEFAULT,
TYPE_ETHERNET,
NULL,
&unmanaged,
&keyfile,
&error,
@ -983,6 +989,7 @@ test_read_onboot_no (void)
connection = connection_from_file (TEST_IFCFG_ONBOOT_NO,
NULL,
TYPE_ETHERNET,
NULL,
&unmanaged,
&keyfile,
&error,
@ -1039,6 +1046,7 @@ test_read_wired_8021x_peap_mschapv2 (void)
connection = connection_from_file (TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
NULL,
TYPE_ETHERNET,
NULL,
&unmanaged,
&keyfile,
&error,
@ -1226,6 +1234,7 @@ test_read_wifi_open (void)
connection = connection_from_file (TEST_IFCFG_WIFI_OPEN,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -1394,6 +1403,7 @@ test_read_wifi_open_ssid_hex (void)
connection = connection_from_file (TEST_IFCFG_WIFI_OPEN_SSID_HEX,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -1463,7 +1473,14 @@ test_read_wifi_open_ssid_bad (const char *file, const char *test)
gboolean ignore_error = FALSE;
GError *error = NULL;
connection = connection_from_file (file, NULL, TYPE_WIRELESS, &unmanaged, &keyfile, &error, &ignore_error);
connection = connection_from_file (file,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
&ignore_error);
ASSERT (connection == NULL, test, "unexpected success reading %s", file);
g_clear_error (&error);
}
@ -1488,6 +1505,7 @@ test_read_wifi_open_ssid_quoted (void)
connection = connection_from_file (TEST_IFCFG_WIFI_OPEN_SSID_QUOTED,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -1575,6 +1593,7 @@ test_read_wifi_wep (void)
connection = connection_from_file (TEST_IFCFG_WIFI_WEP,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -1835,6 +1854,7 @@ test_read_wifi_wep_adhoc (void)
connection = connection_from_file (TEST_IFCFG_WIFI_WEP_ADHOC,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -2088,6 +2108,7 @@ test_read_wifi_leap (void)
connection = connection_from_file (TEST_IFCFG_WIFI_LEAP,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -2235,6 +2256,7 @@ test_read_wifi_wpa_psk (void)
connection = connection_from_file (TEST_IFCFG_WIFI_WPA_PSK,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -2533,6 +2555,7 @@ test_read_wifi_wpa_psk_adhoc (void)
connection = connection_from_file (TEST_IFCFG_WIFI_WPA_PSK_ADHOC,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -2715,6 +2738,7 @@ test_read_wifi_wpa_psk_hex (void)
connection = connection_from_file (TEST_IFCFG_WIFI_WPA_PSK_HEX,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -2861,6 +2885,7 @@ test_read_wifi_wpa_eap_tls (void)
connection = connection_from_file (TEST_IFCFG_WIFI_WPA_EAP_TLS,
NULL,
TYPE_ETHERNET,
NULL,
&unmanaged,
&keyfile,
&error,
@ -2995,6 +3020,7 @@ test_read_wifi_wpa_eap_ttls_tls (void)
connection = connection_from_file (TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -3152,6 +3178,7 @@ test_read_wifi_wep_eap_ttls_chap (void)
connection = connection_from_file (TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -3402,6 +3429,7 @@ test_write_wired_static (void)
reread = connection_from_file (testfile,
NULL,
TYPE_ETHERNET,
NULL,
&unmanaged,
&keyfile,
&error,
@ -3500,6 +3528,7 @@ test_write_wired_dhcp (void)
reread = connection_from_file (testfile,
NULL,
TYPE_ETHERNET,
NULL,
&unmanaged,
&keyfile,
&error,
@ -3618,6 +3647,7 @@ test_write_wired_dhcp_8021x_peap_mschapv2 (void)
reread = connection_from_file (testfile,
NULL,
TYPE_ETHERNET,
NULL,
&unmanaged,
&keyfile,
&error,
@ -3742,6 +3772,7 @@ test_write_wifi_open (void)
reread = connection_from_file (testfile,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -3846,6 +3877,7 @@ test_write_wifi_open_hex_ssid (void)
reread = connection_from_file (testfile,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -3970,6 +4002,7 @@ test_write_wifi_wep (void)
reread = connection_from_file (testfile,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -4114,6 +4147,7 @@ test_write_wifi_wep_adhoc (void)
reread = connection_from_file (testfile,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -4263,6 +4297,7 @@ test_write_wifi_wpa_psk (const char *name,
reread = connection_from_file (testfile,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -4407,6 +4442,7 @@ test_write_wifi_wpa_psk_adhoc (void)
reread = connection_from_file (testfile,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -4566,6 +4602,7 @@ test_write_wifi_wpa_eap_tls (void)
reread = connection_from_file (testfile,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -4742,6 +4779,7 @@ test_write_wifi_wpa_eap_ttls_tls (void)
reread = connection_from_file (testfile,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -4893,6 +4931,7 @@ test_write_wifi_wpa_eap_ttls_mschapv2 (void)
reread = connection_from_file (testfile,
NULL,
TYPE_WIRELESS,
NULL,
&unmanaged,
&keyfile,
&error,
@ -4917,6 +4956,366 @@ test_write_wifi_wpa_eap_ttls_mschapv2 (void)
g_object_unref (reread);
}
#define TEST_IFCFG_IBFT_DHCP TEST_IFCFG_DIR"/network-scripts/ifcfg-test-ibft-dhcp"
static void
test_read_ibft_dhcp (void)
{
NMConnection *connection;
NMSettingConnection *s_con;
NMSettingWired *s_wired;
NMSettingIP4Config *s_ip4;
char *unmanaged = NULL;
char *keyfile = NULL;
gboolean ignore_error = FALSE;
GError *error = NULL;
const char *tmp;
const GByteArray *array;
char expected_mac_address[ETH_ALEN] = { 0x00, 0x33, 0x21, 0x98, 0xb9, 0xf1 };
const char *expected_id = "System test-ibft-dhcp";
guint64 expected_timestamp = 0;
connection = connection_from_file (TEST_IFCFG_IBFT_DHCP,
NULL,
TYPE_ETHERNET,
TEST_IFCFG_DIR "/iscsiadm-test-dhcp",
&unmanaged,
&keyfile,
&error,
&ignore_error);
ASSERT (connection != NULL,
"ibft-dhcp-read", "failed to read %s: %s", TEST_IFCFG_IBFT_DHCP, error->message);
ASSERT (nm_connection_verify (connection, &error),
"ibft-dhcp-verify", "failed to verify %s: %s", TEST_IFCFG_IBFT_DHCP, error->message);
/* ===== CONNECTION SETTING ===== */
s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
ASSERT (s_con != NULL,
"ibft-dhcp-verify-connection", "failed to verify %s: missing %s setting",
TEST_IFCFG_IBFT_DHCP,
NM_SETTING_CONNECTION_SETTING_NAME);
/* ID */
tmp = nm_setting_connection_get_id (s_con);
ASSERT (tmp != NULL,
"ibft-dhcp-verify-connection", "failed to verify %s: missing %s / %s key",
TEST_IFCFG_IBFT_DHCP,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_ID);
ASSERT (strcmp (tmp, expected_id) == 0,
"ibft-dhcp-verify-connection", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_IBFT_DHCP,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_ID);
/* UUID can't be tested if the ifcfg does not contain the UUID key, because
* the UUID is generated on the full path of the ifcfg file, which can change
* depending on where the tests are run.
*/
/* Timestamp */
ASSERT (nm_setting_connection_get_timestamp (s_con) == expected_timestamp,
"ibft-dhcp-verify-connection", "failed to verify %s: unexpected %s /%s key value",
TEST_IFCFG_IBFT_DHCP,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_TIMESTAMP);
/* Autoconnect */
ASSERT (nm_setting_connection_get_autoconnect (s_con) == TRUE,
"ibft-dhcp-verify-connection", "failed to verify %s: unexpected %s /%s key value",
TEST_IFCFG_IBFT_DHCP,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_AUTOCONNECT);
/* Read-only */
ASSERT (nm_setting_connection_get_read_only (s_con) == TRUE,
"ibft-dhcp-verify-connection", "failed to verify %s: unexpected %s /%s key value",
TEST_IFCFG_IBFT_DHCP,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_READ_ONLY);
/* ===== WIRED SETTING ===== */
s_wired = NM_SETTING_WIRED (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED));
ASSERT (s_wired != NULL,
"ibft-dhcp-verify-wired", "failed to verify %s: missing %s setting",
TEST_IFCFG_IBFT_DHCP,
NM_SETTING_WIRED_SETTING_NAME);
/* MAC address */
array = nm_setting_wired_get_mac_address (s_wired);
ASSERT (array != NULL,
"ibft-dhcp-verify-wired", "failed to verify %s: missing %s / %s key",
TEST_IFCFG_IBFT_DHCP,
NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_WIRED_MAC_ADDRESS);
ASSERT (array->len == ETH_ALEN,
"ibft-dhcp-verify-wired", "failed to verify %s: unexpected %s / %s key value length",
TEST_IFCFG_IBFT_DHCP,
NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_WIRED_MAC_ADDRESS);
ASSERT (memcmp (array->data, &expected_mac_address[0], sizeof (expected_mac_address)) == 0,
"ibft-dhcp-verify-wired", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_IBFT_DHCP,
NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_WIRED_MAC_ADDRESS);
ASSERT (nm_setting_wired_get_mtu (s_wired) == 0,
"ibft-dhcp-verify-wired", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_IBFT_DHCP,
NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_WIRED_MTU);
/* ===== IPv4 SETTING ===== */
s_ip4 = NM_SETTING_IP4_CONFIG (nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG));
ASSERT (s_ip4 != NULL,
"ibft-dhcp-verify-ip4", "failed to verify %s: missing %s setting",
TEST_IFCFG_IBFT_DHCP,
NM_SETTING_IP4_CONFIG_SETTING_NAME);
/* Method */
tmp = nm_setting_ip4_config_get_method (s_ip4);
ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0,
"ibft-dhcp-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_IBFT_DHCP,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_METHOD);
g_object_unref (connection);
}
#define TEST_IFCFG_IBFT_STATIC TEST_IFCFG_DIR"/network-scripts/ifcfg-test-ibft-static"
static void
test_read_ibft_static (void)
{
NMConnection *connection;
NMSettingConnection *s_con;
NMSettingWired *s_wired;
NMSettingIP4Config *s_ip4;
char *unmanaged = NULL;
char *keyfile = NULL;
gboolean ignore_error = FALSE;
GError *error = NULL;
const char *tmp;
const GByteArray *array;
char expected_mac_address[ETH_ALEN] = { 0x00, 0x33, 0x21, 0x98, 0xb9, 0xf0 };
const char *expected_id = "System test-ibft-static";
guint64 expected_timestamp = 0;
const char *expected_dns1 = "10.16.255.2";
const char *expected_dns2 = "10.16.255.3";
struct in_addr addr;
const char *expected_address1 = "192.168.32.72";
const char *expected_address1_gw = "192.168.35.254";
NMIP4Address *ip4_addr;
connection = connection_from_file (TEST_IFCFG_IBFT_STATIC,
NULL,
TYPE_ETHERNET,
TEST_IFCFG_DIR "/iscsiadm-test-static",
&unmanaged,
&keyfile,
&error,
&ignore_error);
ASSERT (connection != NULL,
"ibft-static-read", "failed to read %s: %s", TEST_IFCFG_IBFT_STATIC, error->message);
ASSERT (nm_connection_verify (connection, &error),
"ibft-static-verify", "failed to verify %s: %s", TEST_IFCFG_IBFT_STATIC, error->message);
/* ===== CONNECTION SETTING ===== */
s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
ASSERT (s_con != NULL,
"ibft-static-verify-connection", "failed to verify %s: missing %s setting",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_CONNECTION_SETTING_NAME);
/* ID */
tmp = nm_setting_connection_get_id (s_con);
ASSERT (tmp != NULL,
"ibft-static-verify-connection", "failed to verify %s: missing %s / %s key",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_ID);
ASSERT (strcmp (tmp, expected_id) == 0,
"ibft-static-verify-connection", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_ID);
/* UUID can't be tested if the ifcfg does not contain the UUID key, because
* the UUID is generated on the full path of the ifcfg file, which can change
* depending on where the tests are run.
*/
/* Timestamp */
ASSERT (nm_setting_connection_get_timestamp (s_con) == expected_timestamp,
"ibft-static-verify-connection", "failed to verify %s: unexpected %s /%s key value",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_TIMESTAMP);
/* Autoconnect */
ASSERT (nm_setting_connection_get_autoconnect (s_con) == TRUE,
"ibft-static-verify-connection", "failed to verify %s: unexpected %s /%s key value",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_AUTOCONNECT);
/* Read-only */
ASSERT (nm_setting_connection_get_read_only (s_con) == TRUE,
"ibft-static-verify-connection", "failed to verify %s: unexpected %s /%s key value",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_READ_ONLY);
/* ===== WIRED SETTING ===== */
s_wired = NM_SETTING_WIRED (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED));
ASSERT (s_wired != NULL,
"ibft-static-verify-wired", "failed to verify %s: missing %s setting",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_WIRED_SETTING_NAME);
/* MAC address */
array = nm_setting_wired_get_mac_address (s_wired);
ASSERT (array != NULL,
"ibft-static-verify-wired", "failed to verify %s: missing %s / %s key",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_WIRED_MAC_ADDRESS);
ASSERT (array->len == ETH_ALEN,
"ibft-static-verify-wired", "failed to verify %s: unexpected %s / %s key value length",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_WIRED_MAC_ADDRESS);
ASSERT (memcmp (array->data, &expected_mac_address[0], sizeof (expected_mac_address)) == 0,
"ibft-static-verify-wired", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_WIRED_MAC_ADDRESS);
ASSERT (nm_setting_wired_get_mtu (s_wired) == 0,
"ibft-static-verify-wired", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_WIRED_MTU);
/* ===== IPv4 SETTING ===== */
s_ip4 = NM_SETTING_IP4_CONFIG (nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG));
ASSERT (s_ip4 != NULL,
"ibft-static-verify-ip4", "failed to verify %s: missing %s setting",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME);
/* Method */
tmp = nm_setting_ip4_config_get_method (s_ip4);
ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0,
"ibft-static-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_METHOD);
/* DNS Addresses */
ASSERT (nm_setting_ip4_config_get_num_dns (s_ip4) == 2,
"ibft-static-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_DNS);
ASSERT (inet_pton (AF_INET, expected_dns1, &addr) > 0,
"ibft-static-verify-ip4", "failed to verify %s: couldn't convert DNS IP address #1",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_DNS);
ASSERT (nm_setting_ip4_config_get_dns (s_ip4, 0) == addr.s_addr,
"ibft-static-verify-ip4", "failed to verify %s: unexpected %s / %s key value #1",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_DNS);
ASSERT (inet_pton (AF_INET, expected_dns2, &addr) > 0,
"ibft-static-verify-ip4", "failed to verify %s: couldn't convert DNS IP address #2",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_DNS);
ASSERT (nm_setting_ip4_config_get_dns (s_ip4, 1) == addr.s_addr,
"ibft-static-verify-ip4", "failed to verify %s: unexpected %s / %s key value #2",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_DNS);
ASSERT (nm_setting_ip4_config_get_num_addresses (s_ip4) == 1,
"ibft-static-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_DNS);
/* Address #1 */
ip4_addr = nm_setting_ip4_config_get_address (s_ip4, 0);
ASSERT (ip4_addr,
"ibft-static-verify-ip4", "failed to verify %s: missing IP4 address #1",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_ADDRESSES);
ASSERT (nm_ip4_address_get_prefix (ip4_addr) == 22,
"ibft-static-verify-ip4", "failed to verify %s: unexpected IP4 address #1 prefix",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_ADDRESSES);
ASSERT (inet_pton (AF_INET, expected_address1, &addr) > 0,
"ibft-static-verify-ip4", "failed to verify %s: couldn't convert IP address #1",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_DNS);
ASSERT (nm_ip4_address_get_address (ip4_addr) == addr.s_addr,
"ibft-static-verify-ip4", "failed to verify %s: unexpected IP4 address #1",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_ADDRESSES);
ASSERT (inet_pton (AF_INET, expected_address1_gw, &addr) > 0,
"ibft-static-verify-ip4", "failed to verify %s: couldn't convert IP address #1 gateway",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_ADDRESSES);
ASSERT (nm_ip4_address_get_gateway (ip4_addr) == addr.s_addr,
"ibft-static-verify-ip4", "failed to verify %s: unexpected IP4 address #1 gateway",
TEST_IFCFG_IBFT_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_ADDRESSES);
g_object_unref (connection);
}
static void
test_read_ibft_malformed (const char *name, const char *iscsiadm_path)
{
NMConnection *connection;
char *unmanaged = NULL;
char *keyfile = NULL;
gboolean ignore_error = FALSE;
GError *error = NULL;
connection = connection_from_file (TEST_IFCFG_IBFT_STATIC,
NULL,
TYPE_ETHERNET,
iscsiadm_path,
&unmanaged,
&keyfile,
&error,
&ignore_error);
ASSERT (connection == NULL,
name, "unexpectedly able to read %s", TEST_IFCFG_IBFT_STATIC);
}
static void
test_write_wired_pppoe (void)
{
@ -5236,6 +5635,16 @@ int main (int argc, char **argv)
test_write_wifi_wpa_eap_ttls_tls ();
test_write_wifi_wpa_eap_ttls_mschapv2 ();
/* iSCSI / ibft */
test_read_ibft_dhcp ();
test_read_ibft_static ();
test_read_ibft_malformed ("ibft-bad-record-read", TEST_IFCFG_DIR "/iscsiadm-test-bad-record");
test_read_ibft_malformed ("ibft-bad-entry-read", TEST_IFCFG_DIR "/iscsiadm-test-bad-entry");
test_read_ibft_malformed ("ibft-bad-ipaddr-read", TEST_IFCFG_DIR "/iscsiadm-test-bad-ipaddr");
test_read_ibft_malformed ("ibft-bad-gateway-read", TEST_IFCFG_DIR "/iscsiadm-test-bad-gateway");
test_read_ibft_malformed ("ibft-bad-dns1-read", TEST_IFCFG_DIR "/iscsiadm-test-bad-dns1");
test_read_ibft_malformed ("ibft-bad-dns2-read", TEST_IFCFG_DIR "/iscsiadm-test-bad-dns2");
/* Stuff we expect to fail for now */
test_write_wired_pppoe ();
test_write_vpn ();