Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Evergreen:11.2
NetworkManager
0000-upstream.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0000-upstream.patch of Package NetworkManager
Index: autogen.sh =================================================================== --- /dev/null +++ autogen.sh @@ -0,0 +1,23 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. +REQUIRED_AUTOMAKE_VERSION=1.9 +PKG_NAME=NetworkManager + +(test -f $srcdir/configure.ac \ + && test -f $srcdir/src/NetworkManager.c) || { + echo -n "**Error**: Directory "\`$srcdir\'" does not look like the" + echo " top-level $PKG_NAME directory" + exit 1 +} + +(cd $srcdir; + gtkdocize || exit 1 + autoreconf --install --symlink && + intltoolize --force && + autoreconf && + ./configure --enable-maintainer-mode $@ +) + Index: callouts/77-nm-probe-modem-capabilities.rules =================================================================== --- callouts/77-nm-probe-modem-capabilities.rules.orig +++ callouts/77-nm-probe-modem-capabilities.rules @@ -6,7 +6,7 @@ SUBSYSTEM!="tty", GOTO="nm_modem_probe_e DRIVERS=="serial_cs|nozomi", IMPORT{program}="nm-modem-probe --delay 3000 --export $tempnode", GOTO="nm_modem_probe_end" # Only probe known mobile broadband drivers -DRIVERS=="option|sierra|hso|cdc_acm|qcserial", GOTO="probe" +DRIVERS=="option|sierra|hso|cdc_acm|qcserial|moto-modem", GOTO="probe" GOTO="nm_modem_probe_end" Index: callouts/77-nm-zte-port-types.rules =================================================================== --- /dev/null +++ callouts/77-nm-zte-port-types.rules @@ -0,0 +1,101 @@ +# do not edit this file, it will be overwritten on update + +ACTION!="add|change", GOTO="nm_zte_port_types_end" +SUBSYSTEM!="tty", GOTO="nm_zte_port_types_end" + +SUBSYSTEMS=="usb", ATTRS{idVendor}=="19d2", GOTO="nm_zte_port_types_vendorcheck" +GOTO="nm_zte_port_types_end" + +LABEL="nm_zte_port_types_vendorcheck" +SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.NM_USBIFNUM}="$attr{bInterfaceNumber}" + +ATTRS{idProduct}=="0001", ENV{.NM_USBIFNUM}=="00", ENV{ID_NM_ZTE_PORT_TYPE_MODEM}="1" +ATTRS{idProduct}=="0001", ENV{.NM_USBIFNUM}=="02", ENV{ID_NM_ZTE_PORT_TYPE_AUX}="1" +ATTRS{idProduct}=="0001", ENV{ID_NM_ZTE_PORT_TYPE_SET}="1" + +ATTRS{idProduct}=="0002", ENV{.NM_USBIFNUM}=="02", ENV{ID_NM_ZTE_PORT_TYPE_MODEM}="1" +ATTRS{idProduct}=="0002", ENV{.NM_USBIFNUM}=="04", ENV{ID_NM_ZTE_PORT_TYPE_AUX}="1" +ATTRS{idProduct}=="0002", ENV{ID_NM_ZTE_PORT_TYPE_SET}="1" + +ATTRS{idProduct}=="0012", ENV{.NM_USBIFNUM}=="02", ENV{ID_NM_ZTE_PORT_TYPE_MODEM}="1" +ATTRS{idProduct}=="0012", ENV{.NM_USBIFNUM}=="04", ENV{ID_NM_ZTE_PORT_TYPE_AUX}="1" +ATTRS{idProduct}=="0012", ENV{ID_NM_ZTE_PORT_TYPE_SET}="1" + +ATTRS{idProduct}=="0015", ENV{.NM_USBIFNUM}=="01", ENV{ID_NM_ZTE_PORT_TYPE_MODEM}="1" +ATTRS{idProduct}=="0015", ENV{.NM_USBIFNUM}=="03", ENV{ID_NM_ZTE_PORT_TYPE_AUX}="1" +ATTRS{idProduct}=="0015", ENV{ID_NM_ZTE_PORT_TYPE_SET}="1" + +ATTRS{idProduct}=="0016", ENV{.NM_USBIFNUM}=="02", ENV{ID_NM_ZTE_PORT_TYPE_MODEM}="1" +ATTRS{idProduct}=="0016", ENV{.NM_USBIFNUM}=="01", ENV{ID_NM_ZTE_PORT_TYPE_AUX}="1" +ATTRS{idProduct}=="0016", ENV{ID_NM_ZTE_PORT_TYPE_SET}="1" + +ATTRS{idProduct}=="0017", ENV{.NM_USBIFNUM}=="02", ENV{ID_NM_ZTE_PORT_TYPE_MODEM}="1" +ATTRS{idProduct}=="0017", ENV{.NM_USBIFNUM}=="01", ENV{ID_NM_ZTE_PORT_TYPE_AUX}="1" +ATTRS{idProduct}=="0017", ENV{ID_NM_ZTE_PORT_TYPE_SET}="1" + +ATTRS{idProduct}=="0021", ENV{.NM_USBIFNUM}=="03", ENV{ID_NM_ZTE_PORT_TYPE_MODEM}="1" +ATTRS{idProduct}=="0021", ENV{.NM_USBIFNUM}=="01", ENV{ID_NM_ZTE_PORT_TYPE_AUX}="1" +ATTRS{idProduct}=="0021", ENV{ID_NM_ZTE_PORT_TYPE_SET}="1" + +ATTRS{idProduct}=="0025", ENV{.NM_USBIFNUM}=="02", ENV{ID_NM_ZTE_PORT_TYPE_MODEM}="1" +ATTRS{idProduct}=="0025", ENV{.NM_USBIFNUM}=="04", ENV{ID_NM_ZTE_PORT_TYPE_AUX}="1" +ATTRS{idProduct}=="0025", ENV{ID_NM_ZTE_PORT_TYPE_SET}="1" + +ATTRS{idProduct}=="0030", ENV{.NM_USBIFNUM}=="01", ENV{ID_NM_ZTE_PORT_TYPE_MODEM}="1" +ATTRS{idProduct}=="0030", ENV{.NM_USBIFNUM}=="03", ENV{ID_NM_ZTE_PORT_TYPE_AUX}="1" +ATTRS{idProduct}=="0030", ENV{ID_NM_ZTE_PORT_TYPE_SET}="1" + +ATTRS{idProduct}=="0031", ENV{.NM_USBIFNUM}=="03", ENV{ID_NM_ZTE_PORT_TYPE_MODEM}="1" +ATTRS{idProduct}=="0031", ENV{.NM_USBIFNUM}=="01", ENV{ID_NM_ZTE_PORT_TYPE_AUX}="1" +ATTRS{idProduct}=="0031", ENV{ID_NM_ZTE_PORT_TYPE_SET}="1" + +ATTRS{idProduct}=="0033", ENV{.NM_USBIFNUM}=="04", ENV{ID_NM_ZTE_PORT_TYPE_MODEM}="1" +ATTRS{idProduct}=="0033", ENV{.NM_USBIFNUM}=="01", ENV{ID_NM_ZTE_PORT_TYPE_AUX}="1" +ATTRS{idProduct}=="0033", ENV{ID_NM_ZTE_PORT_TYPE_SET}="1" + +ATTRS{idProduct}=="0042", ENV{.NM_USBIFNUM}=="03", ENV{ID_NM_ZTE_PORT_TYPE_MODEM}="1" +ATTRS{idProduct}=="0042", ENV{.NM_USBIFNUM}=="01", ENV{ID_NM_ZTE_PORT_TYPE_AUX}="1" +ATTRS{idProduct}=="0042", ENV{ID_NM_ZTE_PORT_TYPE_SET}="1" + +ATTRS{idProduct}=="0043", ENV{.NM_USBIFNUM}=="03", ENV{ID_NM_ZTE_PORT_TYPE_MODEM}="1" +ATTRS{idProduct}=="0043", ENV{.NM_USBIFNUM}=="02", ENV{ID_NM_ZTE_PORT_TYPE_AUX}="1" +ATTRS{idProduct}=="0043", ENV{ID_NM_ZTE_PORT_TYPE_SET}="1" + +ATTRS{idProduct}=="0048", ENV{.NM_USBIFNUM}=="04", ENV{ID_NM_ZTE_PORT_TYPE_MODEM}="1" +ATTRS{idProduct}=="0048", ENV{.NM_USBIFNUM}=="02", ENV{ID_NM_ZTE_PORT_TYPE_AUX}="1" +ATTRS{idProduct}=="0048", ENV{ID_NM_ZTE_PORT_TYPE_SET}="1" + +ATTRS{idProduct}=="0049", ENV{.NM_USBIFNUM}=="04", ENV{ID_NM_ZTE_PORT_TYPE_MODEM}="1" +ATTRS{idProduct}=="0049", ENV{.NM_USBIFNUM}=="02", ENV{ID_NM_ZTE_PORT_TYPE_AUX}="1" +ATTRS{idProduct}=="0049", ENV{ID_NM_ZTE_PORT_TYPE_SET}="1" + +ATTRS{idProduct}=="0052", ENV{.NM_USBIFNUM}=="03", ENV{ID_NM_ZTE_PORT_TYPE_MODEM}="1" +ATTRS{idProduct}=="0052", ENV{.NM_USBIFNUM}=="01", ENV{ID_NM_ZTE_PORT_TYPE_AUX}="1" +ATTRS{idProduct}=="0052", ENV{ID_NM_ZTE_PORT_TYPE_SET}="1" + +ATTRS{idProduct}=="0055", ENV{.NM_USBIFNUM}=="02", ENV{ID_NM_ZTE_PORT_TYPE_MODEM}="1" +ATTRS{idProduct}=="0055", ENV{.NM_USBIFNUM}=="04", ENV{ID_NM_ZTE_PORT_TYPE_AUX}="1" +ATTRS{idProduct}=="0055", ENV{ID_NM_ZTE_PORT_TYPE_SET}="1" + +ATTRS{idProduct}=="0061", ENV{.NM_USBIFNUM}=="03", ENV{ID_NM_ZTE_PORT_TYPE_MODEM}="1" +ATTRS{idProduct}=="0061", ENV{.NM_USBIFNUM}=="01", ENV{ID_NM_ZTE_PORT_TYPE_AUX}="1" +ATTRS{idProduct}=="0061", ENV{ID_NM_ZTE_PORT_TYPE_SET}="1" + +ATTRS{idProduct}=="0063", ENV{.NM_USBIFNUM}=="03", ENV{ID_NM_ZTE_PORT_TYPE_MODEM}="1" +ATTRS{idProduct}=="0063", ENV{.NM_USBIFNUM}=="01", ENV{ID_NM_ZTE_PORT_TYPE_AUX}="1" +ATTRS{idProduct}=="0063", ENV{ID_NM_ZTE_PORT_TYPE_SET}="1" + +ATTRS{idProduct}=="0064", ENV{.NM_USBIFNUM}=="02", ENV{ID_NM_ZTE_PORT_TYPE_MODEM}="1" +ATTRS{idProduct}=="0064", ENV{.NM_USBIFNUM}=="00", ENV{ID_NM_ZTE_PORT_TYPE_AUX}="1" +ATTRS{idProduct}=="0064", ENV{ID_NM_ZTE_PORT_TYPE_SET}="1" + +ATTRS{idProduct}=="0066", ENV{.NM_USBIFNUM}=="03", ENV{ID_NM_ZTE_PORT_TYPE_MODEM}="1" +ATTRS{idProduct}=="0066", ENV{.NM_USBIFNUM}=="01", ENV{ID_NM_ZTE_PORT_TYPE_AUX}="1" +ATTRS{idProduct}=="0066", ENV{ID_NM_ZTE_PORT_TYPE_SET}="1" + +ATTRS{idProduct}=="2002", ENV{.NM_USBIFNUM}=="03", ENV{ID_NM_ZTE_PORT_TYPE_MODEM}="1" +ATTRS{idProduct}=="2002", ENV{.NM_USBIFNUM}=="01", ENV{ID_NM_ZTE_PORT_TYPE_AUX}="1" +ATTRS{idProduct}=="2002", ENV{ID_NM_ZTE_PORT_TYPE_SET}="1" + +LABEL="nm_zte_port_types_end" + Index: callouts/Makefile.am =================================================================== --- callouts/Makefile.am.orig +++ callouts/Makefile.am @@ -15,7 +15,6 @@ nm_dhcp_client_action_SOURCES = \ nm_dhcp_client_action_CPPFLAGS = \ $(DBUS_CFLAGS) \ $(GLIB_CFLAGS) \ - -DDBUS_API_SUBJECT_TO_CHANGE \ -DG_DISABLE_DEPRECATED \ -DSYSCONFDIR=\"$(sysconfdir)\" \ -DLIBEXECDIR=\"$(libexecdir)\" @@ -31,7 +30,6 @@ nm_avahi_autoipd_action_SOURCES = \ nm_avahi_autoipd_action_CPPFLAGS = \ $(DBUS_CFLAGS) \ $(GLIB_CFLAGS) \ - -DDBUS_API_SUBJECT_TO_CHANGE \ -DG_DISABLE_DEPRECATED \ -DSYSCONFDIR=\"$(sysconfdir)\" \ -DLIBEXECDIR=\"$(libexecdir)\" @@ -51,7 +49,6 @@ nm_dispatcher_action_CPPFLAGS = \ -I${top_srcdir}/libnm-util \ $(DBUS_CFLAGS) \ $(GLIB_CFLAGS) \ - -DDBUS_API_SUBJECT_TO_CHANGE \ -DG_DISABLE_DEPRECATED \ -DSYSCONFDIR=\"$(sysconfdir)\" \ -DLIBEXECDIR=\"$(libexecdir)\" @@ -73,7 +70,9 @@ nm_modem_probe_CPPFLAGS = $(GLIB_CFLAGS) nm_modem_probe_LDADD = $(GLIB_LIBS) udevrulesdir = $(UDEV_BASE_DIR)/rules.d -udevrules_DATA = 77-nm-probe-modem-capabilities.rules +udevrules_DATA = \ + 77-nm-probe-modem-capabilities.rules \ + 77-nm-zte-port-types.rules dbusactivationdir = $(datadir)/dbus-1/system-services dbusactivation_in_files = org.freedesktop.nm_dispatcher.service.in Index: callouts/nm-avahi-autoipd-action.c =================================================================== --- callouts/nm-avahi-autoipd-action.c.orig +++ callouts/nm-avahi-autoipd-action.c @@ -18,8 +18,6 @@ * Copyright (C) 2008 Red Hat, Inc. */ -#define _GNU_SOURCE - #include <stdio.h> #include <unistd.h> #include <stdlib.h> Index: callouts/nm-dhcp-client-action.c =================================================================== --- callouts/nm-dhcp-client-action.c.orig +++ callouts/nm-dhcp-client-action.c @@ -18,8 +18,6 @@ * Copyright (C) 2007 - 2008 Red Hat, Inc. */ -#define _GNU_SOURCE - #include <stdio.h> #include <unistd.h> #include <stdlib.h> Index: callouts/nm-modem-probe.c =================================================================== --- callouts/nm-modem-probe.c.orig +++ callouts/nm-modem-probe.c @@ -14,10 +14,6 @@ * GNU General Public License for more details: */ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE 1 -#endif - #include <termios.h> #include <unistd.h> #include <fcntl.h> @@ -32,6 +28,7 @@ #define HUAWEI_VENDOR_ID 0x12D1 #define SIERRA_VENDOR_ID 0x1199 +#define ZTE_VENDOR_ID 0x19D2 #define MODEM_CAP_GSM 0x0001 /* GSM */ #define MODEM_CAP_IS707_A 0x0002 /* CDMA Circuit Switched Data */ @@ -56,10 +53,12 @@ struct modem_caps { static struct modem_caps modem_caps[] = { {"+CGSM", MODEM_CAP_GSM}, {"+CIS707-A", MODEM_CAP_IS707_A}, + {"+CIS707A", MODEM_CAP_IS707_A}, /* Cmotech */ {"+CIS707", MODEM_CAP_IS707_A}, {"CIS707", MODEM_CAP_IS707_A}, /* Qualcomm Gobi */ {"+CIS707P", MODEM_CAP_IS707_P}, {"CIS-856", MODEM_CAP_IS856}, + {"+IS-856", MODEM_CAP_IS856}, /* Cmotech */ {"CIS-856-A", MODEM_CAP_IS856_A}, {"CIS-856A", MODEM_CAP_IS856_A}, /* Kyocera KPC680 */ {"+DS", MODEM_CAP_DS}, @@ -234,15 +233,19 @@ modem_wait_reply (int fd, } #define GCAP_TAG "+GCAP:" -#define GMM_TAG "+GMM:" +#define CGMM_TAG "+CGMM:" +#define HUAWEI_EC121_TAG "+CIS707-A" static int -parse_gcap (const char *buf) +parse_gcap (const char *tag, gboolean strip_tag, const char *buf) { - const char *p = buf + strlen (GCAP_TAG); + const char *p = buf; char **caps, **iter; int ret = 0; + if (strip_tag) + p += strlen (tag); + caps = g_strsplit_set (p, " ,\t", 0); if (!caps) return 0; @@ -264,24 +267,24 @@ parse_gcap (const char *buf) } static int -parse_gmm (const char *buf) +parse_cgmm (const char *buf) { - const char *p = buf + strlen (GMM_TAG); - char **gmm, **iter; + const char *p = buf + strlen (CGMM_TAG); + char **cgmm, **iter; gboolean gsm = FALSE; - gmm = g_strsplit_set (p, " ,\t", 0); - if (!gmm) + cgmm = g_strsplit_set (p, " ,\t", 0); + if (!cgmm) return 0; - /* BUSlink SCWi275u USB GPRS modem */ - for (iter = gmm; *iter && !gsm; iter++) { + /* BUSlink SCWi275u USB GPRS modem and some Motorola phones */ + for (iter = cgmm; *iter && !gsm; iter++) { if (strstr (*iter, "GSM900") || strstr (*iter, "GSM1800") || strstr (*iter, "GSM1900") || strstr (*iter, "GSM850")) gsm = TRUE; } - g_strfreev (gmm); + g_strfreev (cgmm); return gsm ? MODEM_CAP_GSM : 0; } @@ -311,9 +314,9 @@ g_timeval_subtract (GTimeVal *result, GT return x->tv_sec < y->tv_sec; } -static int modem_probe_caps(int fd, glong timeout_ms) +static int modem_probe_caps(int fd, glong timeout_ms, unsigned int vid) { - const char *gcap_responses[] = { GCAP_TAG, NULL }; + const char *gcap_responses[] = { GCAP_TAG, HUAWEI_EC121_TAG, NULL }; const char *terminators[] = { "OK", "ERROR", "ERR", "+CME ERROR", NULL }; char *reply = NULL; int idx = -1, term_idx = -1, ret = 0; @@ -330,6 +333,17 @@ static int modem_probe_caps(int fd, glon /* Standard response timeout case */ timeout_ms += 3000; + /* ZTE devices need to be told to shut up before probing */ + if (vid == ZTE_VENDOR_ID) { + if (modem_send_command (fd, "AT+CPMS\r\n")) { + const char *null_responses[] = { NULL }; + + modem_wait_reply (fd, 2, null_responses, terminators, &term_idx, &reply); + g_free (reply); + reply = NULL; + } + } + while (timeout_ms > 0) { GTimeVal diff; gulong sleep_time = 100000; @@ -351,7 +365,12 @@ static int modem_probe_caps(int fd, glon if (0 == term_idx && 0 == idx) { /* Success */ verbose ("GCAP response: %s", reply); - ret = parse_gcap (reply); + ret = parse_gcap (gcap_responses[idx], TRUE, reply); + break; + } else if (0 == term_idx && 1 == idx) { + /* Stupid Huawei EC121 that doesn't prefix response with +GCAP: */ + verbose ("GCAP response: %s", reply); + ret = parse_gcap (gcap_responses[idx], FALSE, reply); break; } else if (0 == term_idx && -1 == idx) { /* Just returned "OK" but no GCAP (Sierra) */ @@ -374,7 +393,7 @@ static int modem_probe_caps(int fd, glon } if (!ret && try_ati) { - const char *ati_responses[] = { GCAP_TAG, NULL }; + const char *ati_responses[] = { GCAP_TAG, HUAWEI_EC121_TAG, NULL }; /* Many cards (ex Sierra 860 & 875) won't accept AT+GCAP but * accept ATI when the SIM is missing. Often the GCAP info is @@ -388,7 +407,10 @@ static int modem_probe_caps(int fd, glon idx = modem_wait_reply (fd, 3, ati_responses, terminators, &term_idx, &reply); if (0 == term_idx && 0 == idx) { verbose ("ATI response: %s", reply); - ret = parse_gcap (reply); + ret = parse_gcap (ati_responses[idx], TRUE, reply); + } else if (0 == term_idx && 1 == idx) { + verbose ("ATI response: %s", reply); + ret = parse_gcap (ati_responses[idx], FALSE, reply); } } } @@ -398,13 +420,13 @@ static int modem_probe_caps(int fd, glon /* Try an alternate method on some hardware (ex BUSlink SCWi275u) */ if ((idx != -2) && !(ret & MODEM_CAP_GSM) && !(ret & MODEM_CAP_IS707_A)) { - const char *gmm_responses[] = { GMM_TAG, NULL }; + const char *cgmm_responses[] = { CGMM_TAG, NULL }; - if (modem_send_command (fd, "AT+GMM\r\n")) { - idx = modem_wait_reply (fd, 5, gmm_responses, terminators, &term_idx, &reply); + if (modem_send_command (fd, "AT+CGMM\r\n")) { + idx = modem_wait_reply (fd, 5, cgmm_responses, terminators, &term_idx, &reply); if (0 == term_idx && 0 == idx) { - verbose ("GMM response: %s", reply); - ret |= parse_gmm (reply); + verbose ("CGMM response: %s", reply); + ret |= parse_cgmm (reply); } g_free (reply); } @@ -589,7 +611,7 @@ main(int argc, char *argv[]) attrs.c_cflag |= (B9600 | CS8 | CREAD | PARENB); tcsetattr (fd, TCSANOW, &attrs); - caps = modem_probe_caps (fd, delay_ms); + caps = modem_probe_caps (fd, delay_ms, vid); tcsetattr (fd, TCSANOW, &orig); if (caps < 0) { Index: .gitignore =================================================================== --- /dev/null +++ .gitignore @@ -0,0 +1,60 @@ +*~ +*.o +*.lo +*.la +Makefile +Makefile.in* +configure +compile +config.* +aclocal.m4 +depcomp +install-sh +libtool +ltmain.sh +missing +mkinstalldirs +POTFILES +stamp-* +.deps +.libs +autom4te.cache +intltool-* +COPYING +INSTALL +*.pc +man/*.[18] +po/*.gmo + +callouts/nm-dhcp-client.action +dispatcher-daemon/NetworkManagerDispatcher +initscript/*/NetworkManagerDispatcher +initscript/*/networkmanager-dispatcher +initscript/Slackware/rc.networkmanager +initscript/*/rc.networkmanager-dispatcher +initscript/*/[Nn]etwork[Mm]anager + +*-glue.h +*-bindings.h +nm-marshal.[ch] +libnm-glib/libnm-glib-test +src/NetworkManager +src/nm-crash-logger +system-settings/src/nm-system-settings +test/libnm_glib_test +test/nm-online +test/nm-tool +test/nmtestdevices +libnm-util/test-crypto +libnm-util/tests/test-crypto +libnm-util/tests/test-settings-defaults +src/tests/test-dhcp-options +system-settings/plugins/keyfile/tests/test-keyfile + +m4/gtk-doc.m4 +m4/intltool.m4 +m4/libtool.m4 +m4/lt*.m4 + +policy/org.freedesktop.network-manager-settings.system.policy + Index: include/nm-test-helpers.h =================================================================== --- include/nm-test-helpers.h.orig +++ include/nm-test-helpers.h @@ -28,14 +28,14 @@ static void FAIL(const char *test_name, const char *fmt, ...) { - va_list args; - char buf[500]; + va_list args; + char buf[500]; snprintf (buf, 500, "FAIL: (%s) %s\n", test_name, fmt); - va_start (args, fmt); + va_start (args, fmt); vfprintf (stderr, buf, args); - va_end (args); + va_end (args); _exit (1); } Index: libnm-glib/nm-dbus-settings-system.c =================================================================== --- libnm-glib/nm-dbus-settings-system.c.orig +++ libnm-glib/nm-dbus-settings-system.c @@ -290,22 +290,20 @@ constructor (GType type, NULL); priv->settings_proxy = dbus_g_proxy_new_for_name (dbus_connection, - NM_DBUS_SERVICE_SYSTEM_SETTINGS, - NM_DBUS_PATH_SETTINGS, - NM_DBUS_IFACE_SETTINGS_SYSTEM); + NM_DBUS_SERVICE_SYSTEM_SETTINGS, + NM_DBUS_PATH_SETTINGS, + NM_DBUS_IFACE_SETTINGS_SYSTEM); + dbus_g_proxy_add_signal (priv->settings_proxy, "PropertiesChanged", + DBUS_TYPE_G_MAP_OF_VARIANT, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->settings_proxy, "PropertiesChanged", + G_CALLBACK (proxy_properties_changed), + object, NULL); priv->props_proxy = dbus_g_proxy_new_for_name (dbus_connection, NM_DBUS_SERVICE_SYSTEM_SETTINGS, NM_DBUS_PATH_SETTINGS, "org.freedesktop.DBus.Properties"); - dbus_g_proxy_add_signal (priv->props_proxy, "PropertiesChanged", - DBUS_TYPE_G_MAP_OF_VARIANT, - G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->props_proxy, "PropertiesChanged", - G_CALLBACK (proxy_properties_changed), - object, NULL); - return object; } Index: libnm-util/libnm-util.ver =================================================================== --- libnm-util/libnm-util.ver.orig +++ libnm-util/libnm-util.ver @@ -239,6 +239,7 @@ global: nm_setting_wireless_security_get_psk; nm_setting_wireless_security_get_type; nm_setting_wireless_security_get_wep_key; + nm_setting_wireless_security_get_wep_key_type; nm_setting_wireless_security_get_wep_tx_keyidx; nm_setting_wireless_security_new; nm_setting_wireless_security_remove_group; Index: libnm-util/Makefile.am =================================================================== --- libnm-util/Makefile.am.orig +++ libnm-util/Makefile.am @@ -8,7 +8,6 @@ libnm_util_la_CPPFLAGS = \ $(GLIB_CFLAGS) \ $(DBUS_CFLAGS) \ $(UUID_CFLAGS) \ - -DDBUS_API_SUBJECT_TO_CHANGE \ -DG_DISABLE_DEPRECATED libnm_util_include_HEADERS = \ Index: libnm-util/nm-connection.c =================================================================== --- libnm-util/nm-connection.c.orig +++ libnm-util/nm-connection.c @@ -290,6 +290,11 @@ nm_connection_lookup_setting_type (const char *type_name; GType type; + g_return_val_if_fail (name != NULL, G_TYPE_NONE); + + if (!registered_settings) + register_default_settings (); + type_name = (char *) g_hash_table_lookup (registered_settings, name); if (type_name) { type = g_type_from_name (type_name); Index: libnm-util/nm-setting-8021x.c =================================================================== --- libnm-util/nm-setting-8021x.c.orig +++ libnm-util/nm-setting-8021x.c @@ -947,7 +947,7 @@ static EAPMethodsTable eap_methods_table { "peap", need_secrets_phase2, verify_ttls }, { "ttls", need_secrets_phase2, verify_ttls }, { "sim", need_secrets_sim, NULL }, - { "gtc", NULL, NULL }, // FIXME: implement + { "gtc", need_secrets_password, verify_identity }, { "otp", NULL, NULL }, // FIXME: implement { NULL, NULL, NULL } }; Index: libnm-util/nm-setting.c =================================================================== --- libnm-util/nm-setting.c.orig +++ libnm-util/nm-setting.c @@ -176,7 +176,7 @@ one_property_cb (gpointer key, gpointer param_spec = g_object_class_find_property (info->class, prop_name); if (!param_spec || !(param_spec->flags & NM_SETTING_PARAM_SERIALIZE)) { /* Oh, we're so nice and only warn, maybe it should be a fatal error? */ - nm_warning ("Ignorning invalid property '%s'", prop_name); + nm_warning ("Ignoring invalid property '%s'", prop_name); return; } Index: libnm-util/nm-setting-connection.c =================================================================== --- libnm-util/nm-setting-connection.c.orig +++ libnm-util/nm-setting-connection.c @@ -24,6 +24,7 @@ */ #include <string.h> +#include <ctype.h> #include "nm-setting-connection.h" /** @@ -219,6 +220,22 @@ find_setting_by_name (gconstpointer a, g } static gboolean +validate_uuid (const char *uuid) +{ + int i; + + if (!uuid || !strlen (uuid)) + return FALSE; + + for (i = 0; i < strlen (uuid); i++) { + if (!isxdigit (uuid[i]) && (uuid[i] != '-')) + return FALSE; + } + + return TRUE; +} + +static gboolean verify (NMSetting *setting, GSList *all_settings, GError **error) { NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting); @@ -243,7 +260,7 @@ verify (NMSetting *setting, GSList *all_ NM_SETTING_CONNECTION_ERROR_MISSING_PROPERTY, NM_SETTING_CONNECTION_UUID); return FALSE; - } else if (!strlen (priv->uuid)) { + } else if (!validate_uuid (priv->uuid)) { g_set_error (error, NM_SETTING_CONNECTION_ERROR, NM_SETTING_CONNECTION_ERROR_INVALID_PROPERTY, Index: libnm-util/nm-setting-template.c =================================================================== --- /dev/null +++ libnm-util/nm-setting-template.c @@ -0,0 +1,105 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Tambet Ingo <tambet@gmail.com> + * + * 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 Novell, Inc. + */ + +/* This file is just a template - it's not built nor included in the tarball. + It's sole purpose is to make the process of creating new settings easier. + Just replace 'template' with new setting name (preserving the case), + remove this comment, and you're almost done. +*/ + +#include "nm-setting-template.h" + +G_DEFINE_TYPE (NMSettingTemplate, nm_setting_template, NM_TYPE_SETTING) + +enum { + PROP_0, + + LAST_PROP +}; + +NMSetting * +nm_setting_template_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_TEMPLATE, NULL); +} + +static gboolean +verify (NMSetting *setting, GSList *all_settings) +{ + NMSettingTemplate *self = NM_SETTING_TEMPLATE (setting); +} + +static void +nm_setting_template_init (NMSettingTemplate *setting) +{ + g_object_set (setting, NM_SETTING_NAME, NM_SETTING_TEMPLATE_SETTING_NAME, NULL); +} + +static void +finalize (GObject *object) +{ + NMSettingTemplate *self = NM_SETTING_TEMPLATE (object); + + G_OBJECT_CLASS (nm_setting_template_parent_class)->finalize (object); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingTemplate *setting = NM_SETTING_TEMPLATE (object); + + switch (prop_id) { + 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) +{ + NMSettingTemplate *setting = NM_SETTING_TEMPLATE (object); + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_setting_template_class_init (NMSettingTemplateClass *setting_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (setting_class); + NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + + /* virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + parent_class->verify = verify; + + /* Properties */ +} Index: libnm-util/nm-setting-template.h =================================================================== --- /dev/null +++ libnm-util/nm-setting-template.h @@ -0,0 +1,60 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Tambet Ingo <tambet@gmail.com> + * + * 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 Novell, Inc. + */ + +/* This file is just a template - it's not built nor included in the tarball. + It's sole purpose is to make the process of creating new settings easier. + Just replace 'template' with new setting name (preserving the case), + remove this comment, and you're almost done. +*/ + +#ifndef NM_SETTING_TEMPLATE_H +#define NM_SETTING_TEMPLATE_H + +#include <nm-setting.h> + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_TEMPLATE (nm_setting_template_get_type ()) +#define NM_SETTING_TEMPLATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_TEMPLATE, NMSettingTemplate)) +#define NM_SETTING_TEMPLATE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_TEMPLATE, NMSettingTemplateClass)) +#define NM_IS_SETTING_TEMPLATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_TEMPLATE)) +#define NM_IS_SETTING_TEMPLATE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTING_TEMPLATE)) +#define NM_SETTING_TEMPLATE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_TEMPLATE, NMSettingTemplateClass)) + +#define NM_SETTING_TEMPLATE_SETTING_NAME "template" + +typedef struct { + NMSetting parent; +} NMSettingTemplate; + +typedef struct { + NMSettingClass parent; +} NMSettingTemplateClass; + +GType nm_setting_template_get_type (void); + +NMSetting *nm_setting_template_new (void); + +G_END_DECLS + +#endif /* NM_SETTING_TEMPLATE_H */ Index: libnm-util/nm-setting-wireless-security.c =================================================================== --- libnm-util/nm-setting-wireless-security.c.orig +++ libnm-util/nm-setting-wireless-security.c @@ -93,6 +93,7 @@ typedef struct { char *wep_key3; char *psk; char *leap_password; + NMWepKeyType wep_key_type; } NMSettingWirelessSecurityPrivate; enum { @@ -110,6 +111,7 @@ enum { PROP_WEP_KEY3, PROP_PSK, PROP_LEAP_PASSWORD, + PROP_WEP_KEY_TYPE, LAST_PROP }; @@ -425,8 +427,16 @@ nm_setting_wireless_security_get_auth_al return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->auth_alg; } +NMWepKeyType +nm_setting_wireless_security_get_wep_key_type (NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), 0); + + return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->wep_key_type; +} + static gboolean -verify_wep_key (const char *key) +verify_wep_key (const char *key, NMWepKeyType wep_type) { int keylen, i; @@ -434,11 +444,24 @@ verify_wep_key (const char *key) return FALSE; keylen = strlen (key); - if (keylen != 10 && keylen != 26) - return FALSE; + if (wep_type == NM_WEP_KEY_TYPE_KEY || NM_WEP_KEY_TYPE_UNKNOWN) { + if (keylen == 10 || keylen == 26) { + /* Hex key */ + for (i = 0; i < keylen; i++) { + if (!isxdigit (key[i])) + return FALSE; + } + } else if (keylen == 5 || keylen == 13) { + /* ASCII key */ + for (i = 0; i < keylen; i++) { + if (!isascii (key[i])) + return FALSE; + } + } else + return FALSE; - for (i = 0; i < keylen; i++) { - if (!isxdigit (key[i])) + } else if (wep_type == NM_WEP_KEY_TYPE_PASSPHRASE) { + if (!keylen || keylen > 64) return FALSE; } @@ -454,12 +477,15 @@ verify_wpa_psk (const char *psk) return FALSE; psklen = strlen (psk); - if (psklen != 64) + if (psklen < 8 || psklen > 64) return FALSE; - for (i = 0; i < psklen; i++) { - if (!isxdigit (psk[i])) - return FALSE; + if (psklen == 64) { + /* Hex PSK */ + for (i = 0; i < psklen; i++) { + if (!isxdigit (psk[i])) + return FALSE; + } } return TRUE; @@ -483,19 +509,19 @@ need_secrets (NMSetting *setting) /* Static WEP */ if (strcmp (priv->key_mgmt, "none") == 0) { - if ((priv->wep_tx_keyidx == 0) && !verify_wep_key (priv->wep_key0)) { + if ((priv->wep_tx_keyidx == 0) && !verify_wep_key (priv->wep_key0, priv->wep_key_type)) { g_ptr_array_add (secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0); return secrets; } - if ((priv->wep_tx_keyidx == 1) && !verify_wep_key (priv->wep_key1)) { + if ((priv->wep_tx_keyidx == 1) && !verify_wep_key (priv->wep_key1, priv->wep_key_type)) { g_ptr_array_add (secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY1); return secrets; } - if ((priv->wep_tx_keyidx == 2) && !verify_wep_key (priv->wep_key2)) { + if ((priv->wep_tx_keyidx == 2) && !verify_wep_key (priv->wep_key2, priv->wep_key_type)) { g_ptr_array_add (secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY2); return secrets; } - if ((priv->wep_tx_keyidx == 3) && !verify_wep_key (priv->wep_key3)) { + if ((priv->wep_tx_keyidx == 3) && !verify_wep_key (priv->wep_key3, priv->wep_key_type)) { g_ptr_array_add (secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY3); return secrets; } @@ -627,28 +653,36 @@ verify (NMSetting *setting, GSList *all_ return FALSE; } - if (priv->wep_key0 && !strlen (priv->wep_key0)) { + if (priv->wep_key_type > NM_WEP_KEY_TYPE_LAST) { + g_set_error (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE); + return FALSE; + } + + if (priv->wep_key0 && !verify_wep_key (priv->wep_key0, priv->wep_key_type)) { g_set_error (error, NM_SETTING_WIRELESS_SECURITY_ERROR, NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0); return FALSE; } - if (priv->wep_key1 && !strlen (priv->wep_key1)) { + if (priv->wep_key1 && !verify_wep_key (priv->wep_key1, priv->wep_key_type)) { g_set_error (error, NM_SETTING_WIRELESS_SECURITY_ERROR, NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, NM_SETTING_WIRELESS_SECURITY_WEP_KEY1); return FALSE; } - if (priv->wep_key2 && !strlen (priv->wep_key2)) { + if (priv->wep_key2 && !verify_wep_key (priv->wep_key2, priv->wep_key_type)) { g_set_error (error, NM_SETTING_WIRELESS_SECURITY_ERROR, NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, NM_SETTING_WIRELESS_SECURITY_WEP_KEY2); return FALSE; } - if (priv->wep_key3 && !strlen (priv->wep_key3)) { + if (priv->wep_key3 && !verify_wep_key (priv->wep_key3, priv->wep_key_type)) { g_set_error (error, NM_SETTING_WIRELESS_SECURITY_ERROR, NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, @@ -664,7 +698,7 @@ verify (NMSetting *setting, GSList *all_ return FALSE; } - if (priv->psk && !strlen (priv->psk)) { + if (priv->psk && !verify_wpa_psk (priv->psk)) { g_set_error (error, NM_SETTING_WIRELESS_SECURITY_ERROR, NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, @@ -825,6 +859,9 @@ set_property (GObject *object, guint pro g_free (priv->leap_password); priv->leap_password = g_value_dup_string (value); break; + case PROP_WEP_KEY_TYPE: + priv->wep_key_type = g_value_get_uint (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -878,6 +915,9 @@ get_property (GObject *object, guint pro case PROP_LEAP_PASSWORD: g_value_set_string (value, priv->leap_password); break; + case PROP_WEP_KEY_TYPE: + g_value_set_uint (value, priv->wep_key_type); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1004,4 +1044,14 @@ nm_setting_wireless_security_class_init "LEAP Password", NULL, G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET)); + + g_object_class_install_property + (object_class, PROP_WEP_KEY_TYPE, + g_param_spec_uint (NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, + "WEP Key Type", + "WEP Key Type", + NM_WEP_KEY_TYPE_UNKNOWN, + NM_WEP_KEY_TYPE_LAST, + NM_WEP_KEY_TYPE_UNKNOWN, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); } Index: libnm-util/nm-setting-wireless-security.h =================================================================== --- libnm-util/nm-setting-wireless-security.h.orig +++ libnm-util/nm-setting-wireless-security.h @@ -56,6 +56,14 @@ GType nm_setting_wireless_security_error #define NM_SETTING_WIRELESS_SECURITY_ERROR nm_setting_wireless_security_error_quark () GQuark nm_setting_wireless_security_error_quark (void); +typedef enum { + NM_WEP_KEY_TYPE_UNKNOWN = 0, + NM_WEP_KEY_TYPE_KEY = 1, /* Hex or ASCII */ + NM_WEP_KEY_TYPE_PASSPHRASE = 2, /* 104/128-bit Passphrase */ + + NM_WEP_KEY_TYPE_LAST = NM_WEP_KEY_TYPE_PASSPHRASE +} NMWepKeyType; + #define NM_SETTING_WIRELESS_SECURITY_KEY_MGMT "key-mgmt" #define NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX "wep-tx-keyidx" #define NM_SETTING_WIRELESS_SECURITY_AUTH_ALG "auth-alg" @@ -69,6 +77,7 @@ GQuark nm_setting_wireless_security_erro #define NM_SETTING_WIRELESS_SECURITY_WEP_KEY3 "wep-key3" #define NM_SETTING_WIRELESS_SECURITY_PSK "psk" #define NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD "leap-password" +#define NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE "wep-key-type" typedef struct { NMSetting parent; @@ -111,6 +120,7 @@ const char *nm_setting_wireless_security void nm_setting_wireless_security_set_wep_key (NMSettingWirelessSecurity *setting, guint32 idx, const char *key); guint32 nm_setting_wireless_security_get_wep_tx_keyidx (NMSettingWirelessSecurity *setting); const char *nm_setting_wireless_security_get_auth_alg (NMSettingWirelessSecurity *setting); +NMWepKeyType nm_setting_wireless_security_get_wep_key_type (NMSettingWirelessSecurity *setting); G_END_DECLS Index: libnm-util/nm-utils.c =================================================================== --- libnm-util/nm-utils.c.orig +++ libnm-util/nm-utils.c @@ -566,7 +566,7 @@ nm_utils_convert_strv_to_slist (const GV str = (char **) g_value_get_boxed (src_value); - while (str[i]) + while (str && str[i]) list = g_slist_prepend (list, g_strdup (str[i++])); g_value_take_boxed (dest_value, g_slist_reverse (list)); @@ -642,7 +642,7 @@ nm_utils_convert_ip4_addr_struct_array_t ptr_array = (GPtrArray *) g_value_get_boxed (src_value); printable = g_string_new ("["); - while (i < ptr_array->len) { + while (ptr_array && (i < ptr_array->len)) { GArray *array; char buf[INET_ADDRSTRLEN + 1]; struct in_addr addr; @@ -666,11 +666,8 @@ nm_utils_convert_ip4_addr_struct_array_t g_string_append (printable, ", "); memset (buf, 0, sizeof (buf)); - addr.s_addr = g_array_index (array, guint32, 1); - if (!inet_ntop (AF_INET, &addr, buf, INET_ADDRSTRLEN)) - nm_warning ("%s: error converting IP4 address 0x%X", - __func__, ntohl (addr.s_addr)); - g_string_append_printf (printable, "mask = %s", buf); + g_string_append_printf (printable, "px = %u", + g_array_index (array, guint32, 1)); if (array->len > 2) { g_string_append (printable, ", "); @@ -746,6 +743,34 @@ nm_utils_convert_string_hash_to_string ( g_string_free (printable, FALSE); } +static void +nm_utils_convert_byte_array_to_string (const GValue *src_value, GValue *dest_value) +{ + GArray *array; + GString *printable; + guint i = 0; + + g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_UCHAR_ARRAY)); + + array = (GArray *) g_value_get_boxed (src_value); + + printable = g_string_new ("["); + if (array) { + while (i < MIN (array->len, 35)) { + if (i > 0) + g_string_append_c (printable, ' '); + g_string_append_printf (printable, "0x%02X", + g_array_index (array, unsigned char, i++)); + } + if (i < array->len) + g_string_append (printable, " ... "); + } + g_string_append_c (printable, ']'); + + g_value_take_string (dest_value, printable->str); + g_string_free (printable, FALSE); +} + void _nm_utils_register_value_transformations (void) { @@ -770,6 +795,9 @@ _nm_utils_register_value_transformations g_value_register_transform_func (DBUS_TYPE_G_MAP_OF_STRING, G_TYPE_STRING, nm_utils_convert_string_hash_to_string); + g_value_register_transform_func (DBUS_TYPE_G_UCHAR_ARRAY, + G_TYPE_STRING, + nm_utils_convert_byte_array_to_string); registered = TRUE; } } @@ -1370,8 +1398,8 @@ nm_utils_uuid_generate_from_string (cons return NULL; } - uuid = g_malloc0 (sizeof (uuid)); - if (!crypto_md5_hash (NULL, 0, s, strlen (s), (char *) uuid, sizeof (uuid), &error)) { + uuid = g_malloc0 (sizeof (*uuid)); + if (!crypto_md5_hash (NULL, 0, s, strlen (s), (char *) uuid, sizeof (*uuid), &error)) { nm_warning ("error generating UUID: (%d) %s", error ? error->code : 0, error ? error->message : "unknown"); Index: libnm-util/tests/Makefile.am =================================================================== --- libnm-util/tests/Makefile.am.orig +++ libnm-util/tests/Makefile.am @@ -22,8 +22,7 @@ test_crypto_SOURCES = \ test-crypto.c test_crypto_CPPFLAGS = \ - $(GLIB_CFLAGS) \ - -D_GNU_SOURCE + $(GLIB_CFLAGS) test_crypto_LDADD = \ $(GLIB_LIBS) \ Index: libnm-util/tests/test-settings-defaults.c =================================================================== --- libnm-util/tests/test-settings-defaults.c.orig +++ libnm-util/tests/test-settings-defaults.c @@ -104,7 +104,7 @@ int main (int argc, char **argv) { GError *error = NULL; DBusGConnection *bus; - char *basename; + char *base; g_type_init (); bus = dbus_g_bus_get (DBUS_BUS_SESSION, NULL); @@ -127,9 +127,9 @@ int main (int argc, char **argv) test_defaults (NM_TYPE_SETTING_WIRELESS, NM_SETTING_WIRELESS_SETTING_NAME); test_defaults (NM_TYPE_SETTING_WIRELESS_SECURITY, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME); - basename = g_path_get_basename (argv[0]); - fprintf (stdout, "%s: SUCCESS\n", basename); - g_free (basename); + base = g_path_get_basename (argv[0]); + fprintf (stdout, "%s: SUCCESS\n", base); + g_free (base); return 0; } Index: m4/compiler_warnings.m4 =================================================================== --- /dev/null +++ m4/compiler_warnings.m4 @@ -0,0 +1,31 @@ +AC_DEFUN([NM_COMPILER_WARNINGS], +[AC_ARG_ENABLE(more-warnings, + AS_HELP_STRING([--enable-more-warnings], [Maximum compiler warnings]), + set_more_warnings="$enableval",set_more_warnings=yes) +AC_MSG_CHECKING(for more warnings, including -Werror) +if test "$GCC" = "yes" -a "$set_more_warnings" != "no"; then + AC_MSG_RESULT(yes) + CFLAGS="-Wall -Werror -std=gnu89 $CFLAGS" + + for option in -Wshadow -Wmissing-declarations -Wmissing-prototypes \ + -Wdeclaration-after-statement -Wstrict-prototypes \ + -Wfloat-equal -Wno-unused-parameter -Wno-sign-compare \ + -fno-strict-aliasing; do + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $option" + AC_MSG_CHECKING([whether gcc understands $option]) + AC_TRY_COMPILE([], [], + has_option=yes, + has_option=no,) + if test $has_option = no; then + CFLAGS="$SAVE_CFLAGS" + fi + AC_MSG_RESULT($has_option) + unset has_option + unset SAVE_CFLAGS + done + unset option +else + AC_MSG_RESULT(no) +fi +]) Index: MAINTAINERS =================================================================== --- /dev/null +++ MAINTAINERS @@ -0,0 +1,4 @@ +Dan Williams +E-mail: dcbw redhat com +Userid: dcbw + Index: Makefile.am =================================================================== --- Makefile.am.orig +++ Makefile.am @@ -34,3 +34,4 @@ DISTCLEANFILES = intltool-extract intlto pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = NetworkManager.pc +ACLOCAL_AMFLAGS = -I m4 Index: man/NetworkManager.8.in =================================================================== --- man/NetworkManager.8.in.orig +++ man/NetworkManager.8.in @@ -58,5 +58,18 @@ The following options are supported: .I "--no-daemon" Do not daemonize. This is useful for debugging, and directs log output to the controlling terminal in addition to syslog. +.SH DEBUGGING +The following environment variables are supported to help debugging. When used +in conjunction with the "--no-daemon" option (thus echoing PPP and DHCP helper +output to stdout) these can quickly help pinpoint the source of connection +issues. +.TP +.I "NM_SERIAL_DEBUG" +When set to anything, causes NetworkManager to log all serial communication to +and from serial devices like mobile broadband 3G modems. +.TP +.I "NM_PPP_DEBUG" +When set to anything, causes NetworkManager to turn on PPP debugging in pppd, +which logs all PPP and PPTP frames and client/server exchanges. .SH SEE ALSO .BR nm-tool (1) Index: po/POTFILES.in =================================================================== --- po/POTFILES.in.orig +++ po/POTFILES.in @@ -8,6 +8,9 @@ src/nm-netlink-monitor.c src/NetworkManager.c src/dhcp-manager/nm-dhcp-dhclient.c src/named-manager/nm-named-manager.c +system-settings/plugins/ifcfg-rh/crypto.c +system-settings/plugins/ifcfg-rh/reader.c system-settings/src/main.c system-settings/src/nm-default-wired-connection.c +policy/org.freedesktop.network-manager-settings.system.policy.in Index: policy/Makefile.am =================================================================== --- policy/Makefile.am.orig +++ policy/Makefile.am @@ -1,7 +1,11 @@ polkit_policydir = $(datadir)/PolicyKit/policy -dist_polkit_policy_DATA = \ - org.freedesktop.network-manager-settings.system.policy +dist_polkit_policy_in_files = org.freedesktop.network-manager-settings.system.policy.in +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 \ Index: policy/org.freedesktop.network-manager-settings.system.policy.in =================================================================== --- /dev/null +++ policy/org.freedesktop.network-manager-settings.system.policy.in @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE policyconfig PUBLIC + "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN" + "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd"> + +<policyconfig> + + <vendor>NetworkManager</vendor> + <vendor_url>http://www.gnome.org/projects/NetworkManager</vendor_url> + <icon_name>nm-icon</icon_name> + + <action id="org.freedesktop.network-manager-settings.system.modify"> + <_description>Modify system connections</_description> + <_message>System policy prevents modification of system settings</_message> + <defaults> + <allow_inactive>no</allow_inactive> + <allow_active>auth_admin_keep_always</allow_active> + </defaults> + </action> + +</policyconfig> Index: src/backends/Makefile.am =================================================================== --- src/backends/Makefile.am.orig +++ src/backends/Makefile.am @@ -53,7 +53,6 @@ libnmbackend_la_LIBADD += $(DBUS_LIBS) $ libnmbackend_la_CPPFLAGS = $(DBUS_CFLAGS) \ $(GLIB_CFLAGS) \ $(HAL_CFLAGS) \ - -DDBUS_API_SUBJECT_TO_CHANGE \ -DG_DISABLE_DEPRECATED \ -DBINDIR=\"$(bindir)\" \ -DDATADIR=\"$(datadir)\" \ Index: src/dhcp-manager/Makefile.am =================================================================== --- src/dhcp-manager/Makefile.am.orig +++ src/dhcp-manager/Makefile.am @@ -17,7 +17,6 @@ libdhcp_manager_la_CPPFLAGS = \ $(DBUS_CFLAGS) \ $(GLIB_CFLAGS) \ $(HAL_CFLAGS) \ - -DDBUS_API_SUBJECT_TO_CHANGE \ -DG_DISABLE_DEPRECATED \ -DBINDIR=\"$(bindir)\" \ -DDATADIR=\"$(datadir)\" \ Index: src/dhcp-manager/nm-dhcp-dhclient.c =================================================================== --- src/dhcp-manager/nm-dhcp-dhclient.c.orig +++ src/dhcp-manager/nm-dhcp-dhclient.c @@ -28,6 +28,7 @@ #include <stdio.h> #include <netinet/in.h> #include <arpa/inet.h> +#include <ctype.h> #include <config.h> @@ -61,11 +62,12 @@ get_pidfile_for_iface (const char * ifac static char * -get_leasefile_for_iface (const char * iface) +get_leasefile_for_iface (const char * iface, const char *uuid) { - return g_strdup_printf ("%s/%s-%s.%s", + return g_strdup_printf ("%s/%s-%s-%s.%s", NM_DHCP_MANAGER_LEASE_DIR, NM_DHCP_MANAGER_LEASE_FILENAME, + uuid, iface, NM_DHCP_MANAGER_LEASE_FILE_EXT); } @@ -74,6 +76,7 @@ get_leasefile_for_iface (const char * if #define DHCP_CLIENT_ID_TAG "send dhcp-client-identifier" #define DHCP_CLIENT_ID_FORMAT DHCP_CLIENT_ID_TAG " \"%s\"; # added by NetworkManager" +#define DHCP_CLIENT_ID_FORMAT_OCTETS DHCP_CLIENT_ID_TAG " %s; # added by NetworkManager" #define DHCP_HOSTNAME_TAG "send host-name" #define DHCP_HOSTNAME_FORMAT DHCP_HOSTNAME_TAG " \"%s\"; # added by NetworkManager" @@ -132,8 +135,27 @@ merge_dhclient_config (NMDHCPDevice *dev const char *tmp; tmp = nm_setting_ip4_config_get_dhcp_client_id (s_ip4); - if (tmp) - g_string_append_printf (new_contents, DHCP_CLIENT_ID_FORMAT "\n", tmp); + if (tmp) { + gboolean is_octets = TRUE; + const char *p = tmp; + + while (*p) { + if (!isxdigit (*p) && (*p != ':')) { + is_octets = FALSE; + break; + } + p++; + } + + /* If the client ID is just hex digits and : then don't use quotes, + * becuase dhclient expects either a quoted ASCII string, or a byte + * array formated as hex octets separated by : + */ + if (is_octets) + g_string_append_printf (new_contents, DHCP_CLIENT_ID_FORMAT_OCTETS "\n", tmp); + else + g_string_append_printf (new_contents, DHCP_CLIENT_ID_FORMAT "\n", tmp); + } tmp = nm_setting_ip4_config_get_dhcp_hostname (s_ip4); if (tmp) @@ -167,6 +189,8 @@ create_dhclient_config (NMDHCPDevice *de orig = g_strdup (SYSCONFDIR "/dhclient.conf"); #elif defined(TARGET_DEBIAN) orig = g_strdup (SYSCONFDIR "/dhcp3/dhclient.conf"); +#elif defined(TARGET_GENTOO) + orig = g_strdup (SYSCONFDIR "/dhcp/dhclient.conf"); #else orig = g_strdup_printf (SYSCONFDIR "/dhclient-%s.conf", device->iface); #endif @@ -216,7 +240,9 @@ dhclient_child_setup (gpointer user_data GPid -nm_dhcp_client_start (NMDHCPDevice *device, NMSettingIP4Config *s_ip4) +nm_dhcp_client_start (NMDHCPDevice *device, + const char *uuid, + NMSettingIP4Config *s_ip4) { GPtrArray *dhclient_argv = NULL; GPid pid = 0; @@ -234,7 +260,7 @@ nm_dhcp_client_start (NMDHCPDevice *devi goto out; } - device->lease_file = get_leasefile_for_iface (device->iface); + device->lease_file = get_leasefile_for_iface (device->iface, uuid); if (!device->lease_file) { nm_warning ("%s: not enough memory for dhclient options.", device->iface); goto out; Index: src/dhcp-manager/nm-dhcp-dhcpcd.c =================================================================== --- src/dhcp-manager/nm-dhcp-dhcpcd.c.orig +++ src/dhcp-manager/nm-dhcp-dhcpcd.c @@ -60,7 +60,9 @@ dhcpcd_child_setup (gpointer user_data G GPid -nm_dhcp_client_start (NMDHCPDevice *device, NMSettingIP4Config *s_ip4) +nm_dhcp_client_start (NMDHCPDevice *device, + const char *uuid, + NMSettingIP4Config *s_ip4) { GPtrArray *argv = NULL; GPid pid = 0; Index: src/dhcp-manager/nm-dhcp-manager.c =================================================================== --- src/dhcp-manager/nm-dhcp-manager.c.orig +++ src/dhcp-manager/nm-dhcp-manager.c @@ -577,6 +577,7 @@ static void dhcp_watch_cb (GPid pid, gin gboolean nm_dhcp_manager_begin_transaction (NMDHCPManager *manager, const char *iface, + const char *uuid, NMSettingIP4Config *s_ip4, guint32 timeout) { @@ -599,7 +600,7 @@ nm_dhcp_manager_begin_transaction (NMDHC nm_info ("Activation (%s) Beginning DHCP transaction.", iface); - device->pid = nm_dhcp_client_start (device, s_ip4); + device->pid = nm_dhcp_client_start (device, uuid, s_ip4); if (device->pid == 0) return FALSE; @@ -681,9 +682,8 @@ nm_dhcp_manager_cancel_transaction_real device->pid_file = NULL; } - /* Clean up the leasefile if it got left around */ + /* Free leasefile (but don't delete) */ if (device->lease_file) { - remove (device->lease_file); g_free (device->lease_file); device->lease_file = NULL; } Index: src/dhcp-manager/nm-dhcp-manager.h =================================================================== --- src/dhcp-manager/nm-dhcp-manager.h.orig +++ src/dhcp-manager/nm-dhcp-manager.h @@ -89,6 +89,7 @@ GType nm_dhcp_manager_get_type (void); NMDHCPManager *nm_dhcp_manager_get (void); gboolean nm_dhcp_manager_begin_transaction (NMDHCPManager *manager, const char *iface, + const char *uuid, NMSettingIP4Config *s_ip4, guint32 timeout); void nm_dhcp_manager_cancel_transaction (NMDHCPManager *manager, @@ -102,7 +103,9 @@ gboolean nm_dhcp_manager_foreach_d gpointer user_data); /* The following are implemented by the DHCP client backends */ -GPid nm_dhcp_client_start (NMDHCPDevice *device, NMSettingIP4Config *s_ip4); +GPid nm_dhcp_client_start (NMDHCPDevice *device, + const char *uuid, + NMSettingIP4Config *s_ip4); void nm_dhcp_client_stop (NMDHCPDevice *device, pid_t pid); gboolean nm_dhcp_client_process_classless_routes (GHashTable *options, Index: src/Makefile.am =================================================================== --- src/Makefile.am.orig +++ src/Makefile.am @@ -155,7 +155,6 @@ NetworkManager_CPPFLAGS = \ $(OPENSSL_CFLAGS) \ $(LIBNL_CFLAGS) \ $(LIBUDEV_CFLAGS) \ - -DDBUS_API_SUBJECT_TO_CHANGE \ -DG_DISABLE_DEPRECATED \ -DBINDIR=\"$(bindir)\" \ -DSBINDIR=\"$(sbindir)\" \ Index: src/named-manager/Makefile.am =================================================================== --- src/named-manager/Makefile.am.orig +++ src/named-manager/Makefile.am @@ -8,7 +8,6 @@ libnamed_manager_la_CPPFLAGS = \ $(DBUS_CFLAGS) \ $(GLIB_CFLAGS) \ -DNM_PKGDATADIR=\"$(pkgdatadir)\" \ - -DNM_LOCALSTATEDIR=\"$(localstatedir)\" \ - -DDBUS_API_SUBJECT_TO_CHANGE + -DNM_LOCALSTATEDIR=\"$(localstatedir)\" libnamed_manager_la_LIBADD = $(DBUS_LIBS) $(GLIB_LIBS) Index: src/named-manager/nm-named-manager.c =================================================================== --- src/named-manager/nm-named-manager.c.orig +++ src/named-manager/nm-named-manager.c @@ -30,6 +30,7 @@ #include <errno.h> #include <arpa/inet.h> #include <sys/types.h> +#include <sys/wait.h> #include <unistd.h> #include <glib.h> @@ -107,16 +108,15 @@ merge_one_ip4_config (NMIP4Config *dst, nm_ip4_config_add_domain (dst, nm_ip4_config_get_domain (src, i)); num = nm_ip4_config_get_num_searches (src); - if (num > 0) { - for (i = 0; i < num; i++) - nm_ip4_config_add_search (dst, nm_ip4_config_get_search (src, i)); - } else { - /* If no search domains were specified, add the 'domain' list to - * search domains. - */ - for (i = 0; i < num_domains; i++) - nm_ip4_config_add_search (dst, nm_ip4_config_get_domain (src, i)); - } + for (i = 0; i < num; i++) + nm_ip4_config_add_search (dst, 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)); } @@ -131,12 +131,12 @@ netconfig_child_setup (gpointer user_dat setpgid (pid, pid); } -static gint -run_netconfig (GError **error) +static GPid +run_netconfig (GError **error, gint *stdin_fd) { char *argv[5]; char *tmp; - gint stdin_fd; + GPid pid = -1; argv[0] = "/sbin/netconfig"; argv[1] = "modify"; @@ -149,10 +149,10 @@ run_netconfig (GError **error) g_free (tmp); if (!g_spawn_async_with_pipes (NULL, argv, NULL, 0, netconfig_child_setup, - NULL, NULL, &stdin_fd, NULL, NULL, error)) + NULL, &pid, stdin_fd, NULL, NULL, error)) return -1; - return stdin_fd; + return pid; } static void @@ -169,16 +169,18 @@ write_to_netconfig (gint fd, const char static gboolean dispatch_netconfig (const char *domain, - char **searches, - char **nameservers, - const char *iface, - GError **error) + char **searches, + char **nameservers, + const char *iface, + GError **error) { - gint fd; char *str; + GPid pid; + gint fd; + int ret; - fd = run_netconfig (error); - if (fd < 0) + pid = run_netconfig (error, &fd); + if (pid < 0) return FALSE; write_to_netconfig (fd, "INTERFACE", iface); @@ -206,16 +208,24 @@ dispatch_netconfig (const char *domain, close (fd); - return TRUE; + /* Wait until the process exits */ + + again: + + ret = waitpid (pid, NULL, 0); + if (ret < 0 && errno == EINTR) + goto again; + + return ret > 0; } #endif static gboolean write_resolv_conf (FILE *f, const char *domain, - char **searches, - char **nameservers, - GError **error) + char **searches, + char **nameservers, + GError **error) { char *domain_str = NULL; char *searches_str = NULL; @@ -283,10 +293,10 @@ write_resolv_conf (FILE *f, const char * #ifdef RESOLVCONF_PATH static gboolean dispatch_resolvconf (const char *domain, - char **searches, - char **nameservers, - const char *iface, - GError **error) + char **searches, + char **nameservers, + const char *iface, + GError **error) { char *cmd; FILE *f; @@ -324,26 +334,35 @@ dispatch_resolvconf (const char *domain, static gboolean update_resolv_conf (const char *domain, - char **searches, - char **nameservers, - const char *iface, - GError **error) + char **searches, + char **nameservers, + const char *iface, + GError **error) { const char *tmp_resolv_conf = RESOLV_CONF ".tmp"; char tmp_resolv_conf_realpath [PATH_MAX]; FILE *f; + int do_rename = 1; + int old_errno = 0; - if (!realpath(tmp_resolv_conf, tmp_resolv_conf_realpath)) - strcpy(tmp_resolv_conf_realpath, tmp_resolv_conf); + if (!realpath (tmp_resolv_conf, tmp_resolv_conf_realpath)) + strcpy (tmp_resolv_conf_realpath, tmp_resolv_conf); if ((f = fopen (tmp_resolv_conf_realpath, "w")) == NULL) { - g_set_error (error, - NM_NAMED_MANAGER_ERROR, - NM_NAMED_MANAGER_ERROR_SYSTEM, - "Could not open %s: %s\n", - tmp_resolv_conf_realpath, - g_strerror (errno)); - return FALSE; + do_rename = 0; + old_errno = errno; + if ((f = fopen (RESOLV_CONF, "w")) == NULL) { + g_set_error (error, + NM_NAMED_MANAGER_ERROR, + NM_NAMED_MANAGER_ERROR_SYSTEM, + "Could not open %s: %s\nCould not open %s: %s\n", + tmp_resolv_conf_realpath, + g_strerror (old_errno), + RESOLV_CONF, + g_strerror (errno)); + return FALSE; + } + strcpy (tmp_resolv_conf_realpath, RESOLV_CONF); } write_resolv_conf (f, domain, searches, nameservers, error); @@ -359,7 +378,7 @@ update_resolv_conf (const char *domain, } } - if (*error == NULL) { + if (*error == NULL && do_rename) { if (rename (tmp_resolv_conf, RESOLV_CONF) < 0) { g_set_error (error, NM_NAMED_MANAGER_ERROR, @@ -372,6 +391,35 @@ 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) @@ -424,21 +472,10 @@ rewrite_resolv_conf (NMNamedManager *mgr domain = nm_ip4_config_get_domain (composite, 0); /* Searches */ - if (num_searches > 0) { - array = g_ptr_array_sized_new (num_searches + 1); - for (i = 0; i < num_searches; i++) - g_ptr_array_add (array, g_strdup (nm_ip4_config_get_search (composite, i))); - - g_ptr_array_add (array, NULL); - searches = (char **) g_ptr_array_free (array, FALSE); - } else if (num_domains > 0) { - array = g_ptr_array_sized_new (num_domains + 1); - for (i = 0; i < num_domains; i++) - g_ptr_array_add (array, g_strdup (nm_ip4_config_get_domain (composite, i))); - - g_ptr_array_add (array, NULL); - searches = (char **) g_ptr_array_free (array, FALSE); - } + 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); @@ -464,6 +501,8 @@ rewrite_resolv_conf (NMNamedManager *mgr nameservers = (char **) g_ptr_array_free (array, FALSE); } + g_object_unref (composite); + #ifdef RESOLVCONF_PATH success = dispatch_resolvconf (domain, searches, nameservers, iface, error); #endif Index: src/NetworkManagerAP.c =================================================================== --- src/NetworkManagerAP.c.orig +++ src/NetworkManagerAP.c @@ -53,7 +53,6 @@ typedef struct guint32 rsn_flags; /* RSN (WPA2) -related flags */ /* Non-scanned attributes */ - gboolean invalid; gboolean fake; /* Whether or not the AP is from a scan */ gboolean broadcast; /* Whether or not the AP is broadcasting (hidden) */ gboolean user_created; /* Whether or not the AP was created @@ -702,8 +701,7 @@ nm_ap_print_self (NMAccessPoint *ap, priv = NM_AP_GET_PRIVATE (ap); nm_info ("%s'%s' (%p) stamp=%ld flags=0x%X wpa-flags=0x%X rsn-flags=0x%x " - "bssid=" MAC_FMT " strength=%d freq=%d rate=%d inval=%d " - "mode=%d seen=%ld", + "bssid=" MAC_FMT " strength=%d freq=%d rate=%d mode=%d seen=%ld", prefix, priv->ssid ? nm_utils_escape_ssid (priv->ssid->data, priv->ssid->len) : "(none)", ap, @@ -715,7 +713,6 @@ nm_ap_print_self (NMAccessPoint *ap, priv->strength, priv->freq, priv->max_bitrate, - priv->invalid, priv->mode, priv->last_seen); } @@ -1040,28 +1037,6 @@ nm_ap_set_max_bitrate (NMAccessPoint *ap } } - -/* - * Get/set functions for "invalid" access points, ie ones - * for which a user explicitly does not wish to connect to - * (by cancelling requests for WEP key, for example) - * - */ -gboolean nm_ap_get_invalid (const NMAccessPoint *ap) -{ - g_return_val_if_fail (NM_IS_AP (ap), TRUE); - - return NM_AP_GET_PRIVATE (ap)->invalid; -} - -void nm_ap_set_invalid (NMAccessPoint *ap, gboolean invalid) -{ - g_return_if_fail (NM_IS_AP (ap)); - - NM_AP_GET_PRIVATE (ap)->invalid = invalid; -} - - /* * Get/Set functions to indicate that an access point is 'fake', ie whether * or not it was created from scan results Index: src/NetworkManagerAP.h =================================================================== --- src/NetworkManagerAP.h.orig +++ src/NetworkManagerAP.h @@ -95,9 +95,6 @@ void nm_ap_set_freq (NMAccessPoint guint32 nm_ap_get_max_bitrate (NMAccessPoint *ap); void nm_ap_set_max_bitrate (NMAccessPoint *ap, guint32 bitrate); -gboolean nm_ap_get_invalid (const NMAccessPoint *ap); -void nm_ap_set_invalid (NMAccessPoint *ap, gboolean invalid); - gboolean nm_ap_get_fake (const NMAccessPoint *ap); void nm_ap_set_fake (NMAccessPoint *ap, gboolean fake); Index: src/NetworkManager.conf =================================================================== --- src/NetworkManager.conf.orig +++ src/NetworkManager.conf @@ -12,15 +12,51 @@ <policy at_console="true"> <allow send_destination="org.freedesktop.NetworkManager"/> - <deny send_destination="org.freedesktop.NetworkManager" - send_interface="org.freedesktop.NetworkManager.PPP"/> + <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.NetworkManager"/> + + <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.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.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.Wireless"/> + + <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.IP4Config"/> + + <allow send_destination="org.freedesktop.NetworkManager" + send_interface="org.freedesktop.NetworkManager.VPN.Connection"/> </policy> <policy context="default"> <deny own="org.freedesktop.NetworkManager"/> <deny send_destination="org.freedesktop.NetworkManager"/> - - <deny send_destination="org.freedesktop.NetworkManager" - send_interface="org.freedesktop.NetworkManager.PPP"/> </policy> <limit name="max_replies_per_connection">512</limit> Index: src/NetworkManagerUtils.c =================================================================== --- src/NetworkManagerUtils.c.orig +++ src/NetworkManagerUtils.c @@ -182,61 +182,6 @@ nm_utils_ip4_prefix_to_netmask (guint32 return (guint32) htonl (netmask); } - -/* From hostap, Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi> */ - -static int hex2num (char c) -{ - if (c >= '0' && c <= '9') - return c - '0'; - if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - if (c >= 'A' && c <= 'F') - return c - 'A' + 10; - return -1; -} - -static int hex2byte (const char *hex) -{ - int a, b; - a = hex2num(*hex++); - if (a < 0) - return -1; - b = hex2num(*hex++); - if (b < 0) - return -1; - return (a << 4) | b; -} - -char * -nm_utils_hexstr2bin (const char *hex, - size_t len) -{ - size_t i; - int a; - const char * ipos = hex; - char * buf = NULL; - char * opos; - - /* Length must be a multiple of 2 */ - if ((len % 2) != 0) - return NULL; - - opos = buf = g_malloc0 ((len / 2) + 1); - for (i = 0; i < len; i += 2) { - a = hex2byte (ipos); - if (a < 0) { - g_free (buf); - return NULL; - } - *opos++ = a; - ipos += 2; - } - return buf; -} - -/* End from hostap */ - char * nm_ether_ntop (const struct ether_addr *mac) { @@ -259,6 +204,7 @@ nm_utils_merge_ip4_config (NMIP4Config * if (nm_setting_ip4_config_get_ignore_auto_dns (setting)) { nm_ip4_config_reset_nameservers (ip4_config); + nm_ip4_config_reset_domains (ip4_config); nm_ip4_config_reset_searches (ip4_config); } Index: src/NetworkManagerUtils.h =================================================================== --- src/NetworkManagerUtils.h.orig +++ src/NetworkManagerUtils.h @@ -37,8 +37,6 @@ int nm_spawn_process (const char *args); void nm_print_device_capabilities (NMDevice *dev); -char *nm_utils_hexstr2bin (const char *hex, size_t len); - char *nm_ether_ntop (const struct ether_addr *mac); void nm_utils_merge_ip4_config (NMIP4Config *ip4_config, NMSettingIP4Config *setting); Index: src/nm-cdma-device.c =================================================================== --- src/nm-cdma-device.c.orig +++ src/nm-cdma-device.c @@ -170,7 +170,7 @@ power_up_response (NMSerialDevice *devic static void power_up (NMSerialDevice *device) { - const char *responses[] = { "OK", "ERROR", "ERR", NULL }; + const char *responses[] = { "OK", "ERROR", "ERR", "COMMAND NOT SUPPORT", NULL }; guint id = 0; /* Only works on Sierra cards */ Index: src/nm-dbus-manager.c =================================================================== --- src/nm-dbus-manager.c.orig +++ src/nm-dbus-manager.c @@ -161,12 +161,14 @@ nm_dbus_manager_reconnect (gpointer user nm_info ("reconnected to the system bus."); g_signal_emit (self, signals[DBUS_CONNECTION_CHANGED], 0, priv->connection); - return TRUE; + priv->reconnect_id = 0; + return FALSE; } } + /* Try again */ nm_dbus_manager_cleanup (self, FALSE); - return FALSE; + return TRUE; } static void Index: src/nm-device.c =================================================================== --- src/nm-device.c.orig +++ src/nm-device.c @@ -862,10 +862,12 @@ aipd_exec (NMDevice *self, GError **erro static NMActStageReturn real_act_stage3_ip_config_start (NMDevice *self, NMDeviceStateReason *reason) { + NMConnection *connection; + NMSettingConnection *s_con; NMSettingIP4Config *s_ip4; NMActRequest *req; NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; - const char *ip_iface, *method = NULL; + const char *ip_iface, *method = NULL, *uuid; g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); @@ -873,8 +875,12 @@ real_act_stage3_ip_config_start (NMDevic ip_iface = nm_device_get_ip_iface (self); req = nm_device_get_act_request (self); - s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (nm_act_request_get_connection (req), - NM_TYPE_SETTING_IP4_CONFIG); + connection = nm_act_request_get_connection (req); + s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION); + g_assert (s_con); + uuid = nm_setting_connection_get_uuid (s_con); + + s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG); /* If we did not receive IP4 configuration information, default to DHCP */ if (s_ip4) @@ -890,7 +896,7 @@ real_act_stage3_ip_config_start (NMDevic /* DHCP manager will cancel any transaction already in progress and we do not want to cancel this activation if we get "down" state from that. */ g_signal_handler_block (priv->dhcp_manager, priv->dhcp_state_sigid); - success = nm_dhcp_manager_begin_transaction (priv->dhcp_manager, ip_iface, s_ip4, 45); + success = nm_dhcp_manager_begin_transaction (priv->dhcp_manager, ip_iface, uuid, s_ip4, 45); g_signal_handler_unblock (priv->dhcp_manager, priv->dhcp_state_sigid); if (success) { @@ -2398,7 +2404,9 @@ nm_device_state_changed (NMDevice *devic old_state = priv->state; priv->state = state; -nm_info ("(%s): device state change: %d -> %d", nm_device_get_iface (device), old_state, state); + + nm_info ("(%s): device state change: %d -> %d (reason %d)", + nm_device_get_iface (device), old_state, state, reason); if (priv->failed_to_disconnected_id) { g_source_remove (priv->failed_to_disconnected_id); @@ -2432,7 +2440,7 @@ nm_info ("(%s): device state change: %d } g_object_notify (G_OBJECT (device), NM_DEVICE_INTERFACE_STATE); - g_signal_emit_by_name (device, "state-changed", state, old_state, 0); + g_signal_emit_by_name (device, "state-changed", state, old_state, reason); /* Post-process the event after internal notification */ Index: src/nm-device-wifi.c =================================================================== --- src/nm-device-wifi.c.orig +++ src/nm-device-wifi.c @@ -96,8 +96,7 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; -typedef enum -{ +typedef enum { NM_WIFI_ERROR_CONNECTION_NOT_WIRELESS = 0, NM_WIFI_ERROR_CONNECTION_INVALID, NM_WIFI_ERROR_CONNECTION_INCOMPATIBLE, @@ -115,15 +114,16 @@ typedef struct SupplicantStateTask { } SupplicantStateTask; typedef struct Supplicant { - NMSupplicantManager * mgr; - NMSupplicantInterface * iface; + NMSupplicantManager *mgr; + NMSupplicantInterface *iface; /* signal handler ids */ guint mgr_state_id; guint iface_error_id; guint iface_state_id; guint iface_scanned_ap_id; - guint iface_scan_result_id; + guint iface_scan_request_result_id; + guint iface_scan_results_id; guint iface_con_state_id; /* Timeouts and idles */ @@ -134,68 +134,60 @@ typedef struct Supplicant { GSList *iface_tasks; } Supplicant; -struct _NMDeviceWifiPrivate -{ - gboolean dispose_has_run; - - struct ether_addr hw_addr; - - GByteArray * ssid; - gint8 invalid_strength_counter; - iwqual max_qual; - iwqual avg_qual; +struct _NMDeviceWifiPrivate { + gboolean dispose_has_run; - gint8 num_freqs; - guint32 freqs[IW_MAX_FREQUENCIES]; + struct ether_addr hw_addr; - GSList * ap_list; - NMAccessPoint * current_ap; - guint32 rate; - gboolean enabled; /* rfkilled or not */ - guint state_to_disconnected_id; + GByteArray * ssid; + gint8 invalid_strength_counter; + iwqual max_qual; + + gint8 num_freqs; + guint32 freqs[IW_MAX_FREQUENCIES]; + + GSList * ap_list; + NMAccessPoint * current_ap; + guint32 rate; + gboolean enabled; /* rfkilled or not */ + guint state_to_disconnected_id; - gboolean scanning; - glong scheduled_scan_time; - guint8 scan_interval; /* seconds */ - guint pending_scan_id; - - Supplicant supplicant; - - guint32 failed_link_count; - guint periodic_source_id; - guint link_timeout_id; + glong scheduled_scan_time; + guint8 scan_interval; /* seconds */ + guint pending_scan_id; + + Supplicant supplicant; + + guint32 failed_link_count; + guint periodic_source_id; + guint link_timeout_id; /* Static options from driver */ - guint8 we_version; - guint32 capabilities; - gboolean has_scan_capa_ssid; + guint8 we_version; + guint32 capabilities; + gboolean has_scan_capa_ssid; }; static guint32 nm_device_wifi_get_frequency (NMDeviceWifi *self); -static void nm_device_wifi_set_ssid (NMDeviceWifi *self, const GByteArray * ssid); - #if DEBUG static void nm_device_wifi_ap_list_print (NMDeviceWifi *self); #endif static gboolean request_wireless_scan (gpointer user_data); -static void schedule_scan (NMDeviceWifi *self, gboolean backoff); +static void schedule_scan (NMDeviceWifi *self, gboolean backoff); -static void cancel_pending_scan (NMDeviceWifi *self); +static void cancel_pending_scan (NMDeviceWifi *self); static int wireless_qual_to_percent (const struct iw_quality *qual, - const struct iw_quality *max_qual, - const struct iw_quality *avg_qual); + const struct iw_quality *max_qual); static void cleanup_association_attempt (NMDeviceWifi * self, gboolean disconnect); static void remove_supplicant_timeouts (NMDeviceWifi *self); -static void nm_device_wifi_disable_encryption (NMDeviceWifi *self); - static void supplicant_iface_state_cb (NMSupplicantInterface * iface, guint32 new_state, guint32 old_state, @@ -210,9 +202,13 @@ static void supplicant_iface_scanned_ap_ GHashTable *properties, NMDeviceWifi * self); -static void supplicant_iface_scan_result_cb (NMSupplicantInterface * iface, - gboolean result, - NMDeviceWifi * self); +static void supplicant_iface_scan_request_result_cb (NMSupplicantInterface * iface, + gboolean success, + NMDeviceWifi * self); + +static void supplicant_iface_scan_results_cb (NMSupplicantInterface * iface, + guint32 num_bssids, + NMDeviceWifi * self); static void supplicant_mgr_state_cb (NMSupplicantInterface * iface, guint32 new_state, @@ -221,6 +217,7 @@ static void supplicant_mgr_state_cb (NMS static guint32 nm_device_wifi_get_bitrate (NMDeviceWifi *self); +static void cull_scan_list (NMDeviceWifi *self); static GQuark nm_wifi_error_quark (void) @@ -284,13 +281,11 @@ nm_device_wifi_update_signal_strength (N wrq.u.data.pointer = &stats; wrq.u.data.length = sizeof (stats); - wrq.u.data.flags = 1; /* Clear updated flag */ + wrq.u.data.flags = 1; /* Clear updated flag */ strncpy (wrq.ifr_name, iface, IFNAMSIZ); - if (ioctl (fd, SIOCGIWSTATS, &wrq) == 0) { - percent = wireless_qual_to_percent (&stats.qual, (const iwqual *)(&priv->max_qual), - (const iwqual *)(&priv->avg_qual)); - } + if (ioctl (fd, SIOCGIWSTATS, &wrq) == 0) + percent = wireless_qual_to_percent (&stats.qual, &priv->max_qual); close (fd); } @@ -407,8 +402,8 @@ get_wireless_capabilities (NMDeviceWifi iwrange * range, guint32 data_len) { - guint32 minlen; - guint32 caps = NM_WIFI_DEVICE_CAP_NONE; + guint32 minlen; + guint32 caps = NM_WIFI_DEVICE_CAP_NONE; const char * iface; g_return_val_if_fail (self != NULL, NM_WIFI_DEVICE_CAP_NONE); @@ -461,7 +456,6 @@ nm_device_wifi_init (NMDeviceWifi * self NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); priv->dispose_has_run = FALSE; - priv->scanning = FALSE; priv->ap_list = NULL; priv->we_version = 0; @@ -490,26 +484,26 @@ static guint32 iw_freq_to_uint32 (struct * 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 +#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; + guint32 throughput; + guint32 min_nwid; + guint32 max_nwid; + guint16 old_num_channels; + guint8 old_num_frequency; - guint8 scan_capa; + guint8 scan_capa; /* don't need the rest... */ }; static GObject* constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) + guint n_construct_params, + GObjectConstructParam *construct_params) { GObject *object; GObjectClass *klass; @@ -539,11 +533,6 @@ constructor (GType type, priv->max_qual.noise = range.max_qual.noise; priv->max_qual.updated = range.max_qual.updated; - priv->avg_qual.qual = range.avg_qual.qual; - priv->avg_qual.level = range.avg_qual.level; - priv->avg_qual.noise = range.avg_qual.noise; - priv->avg_qual.updated = range.avg_qual.updated; - 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]); @@ -619,10 +608,16 @@ supplicant_interface_acquire (NMDeviceWi priv->supplicant.iface_scanned_ap_id = id; id = g_signal_connect (priv->supplicant.iface, - "scan-result", - G_CALLBACK (supplicant_iface_scan_result_cb), + "scan-req-result", + G_CALLBACK (supplicant_iface_scan_request_result_cb), self); - priv->supplicant.iface_scan_result_id = id; + priv->supplicant.iface_scan_request_result_id = id; + + id = g_signal_connect (priv->supplicant.iface, + "scan-results", + G_CALLBACK (supplicant_iface_scan_results_cb), + self); + priv->supplicant.iface_scan_results_id = id; id = g_signal_connect (priv->supplicant.iface, "connection-state", @@ -706,9 +701,14 @@ supplicant_interface_release (NMDeviceWi priv->supplicant.iface_scanned_ap_id = 0; } - if (priv->supplicant.iface_scan_result_id > 0) { - g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_scan_result_id); - priv->supplicant.iface_scan_result_id = 0; + if (priv->supplicant.iface_scan_request_result_id > 0) { + g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_scan_request_result_id); + priv->supplicant.iface_scan_request_result_id = 0; + } + + if (priv->supplicant.iface_scan_results_id > 0) { + g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_scan_results_id); + priv->supplicant.iface_scan_results_id = 0; } if (priv->supplicant.iface_con_state_id > 0) { @@ -960,7 +960,7 @@ nm_device_wifi_periodic_update (gpointer if (state != NM_DEVICE_STATE_ACTIVATED) goto out; - if (priv->scanning) + if (nm_supplicant_interface_get_scanning (priv->supplicant.iface)) goto out; periodic_update (self); @@ -976,9 +976,12 @@ real_hw_is_up (NMDevice *device) } static gboolean -real_hw_bring_up (NMDevice *dev, gboolean *no_firmware) +real_hw_bring_up (NMDevice *device, gboolean *no_firmware) { - return nm_system_device_set_up_down (dev, TRUE, no_firmware); + if (!NM_DEVICE_WIFI_GET_PRIVATE (device)->enabled) + return FALSE; + + return nm_system_device_set_up_down (device, TRUE, no_firmware); } static void @@ -1064,16 +1067,12 @@ real_deactivate_quickly (NMDevice *dev) priv->ap_list = g_slist_remove (priv->ap_list, orig_ap); g_object_unref (orig_ap); } - - /* Clean up stuff, don't leave the card associated */ - nm_device_wifi_set_ssid (self, NULL); - nm_device_wifi_disable_encryption (self); } static void real_deactivate (NMDevice *dev) { - NMDeviceWifi * self = NM_DEVICE_WIFI (dev); + NMDeviceWifi *self = NM_DEVICE_WIFI (dev); nm_device_wifi_set_mode (self, NM_802_11_MODE_INFRA); /* FIXME: Should we reset the scan interval here? */ @@ -1398,15 +1397,13 @@ nm_device_wifi_get_frequency (NMDeviceWi */ static int wireless_qual_to_percent (const struct iw_quality *qual, - const struct iw_quality *max_qual, - const struct iw_quality *avg_qual) + const struct iw_quality *max_qual) { - int percent = -1; - int level_percent = -1; + int percent = -1; + int level_percent = -1; g_return_val_if_fail (qual != NULL, -1); g_return_val_if_fail (max_qual != NULL, -1); - g_return_val_if_fail (avg_qual != NULL, -1); #ifdef IW_QUAL_DEBUG nm_debug ("QL: qual %d/%u/0x%X, level %d/%u/0x%X, noise %d/%u/0x%X, updated: 0x%X ** MAX: qual %d/%u/0x%X, level %d/%u/0x%X, noise %d/%u/0x%X, updated: 0x%X", @@ -1439,20 +1436,20 @@ max_qual->updated); * If drivers don't conform to it, they are wrong and need to be fixed. */ - if ( (max_qual->level == 0) && !(max_qual->updated & IW_QUAL_LEVEL_INVALID) /* Valid max_qual->level == 0 */ - && !(qual->updated & IW_QUAL_LEVEL_INVALID) /* Must have valid qual->level */ - && ( ((max_qual->noise > 0) && !(max_qual->updated & IW_QUAL_NOISE_INVALID)) /* Must have valid max_qual->noise */ - || ((qual->noise > 0) && !(qual->updated & IW_QUAL_NOISE_INVALID))) /* OR valid qual->noise */ + if ( (max_qual->level == 0) && !(max_qual->updated & IW_QUAL_LEVEL_INVALID) /* Valid max_qual->level == 0 */ + && !(qual->updated & IW_QUAL_LEVEL_INVALID) /* Must have valid qual->level */ + && ( ((max_qual->noise > 0) && !(max_qual->updated & IW_QUAL_NOISE_INVALID)) /* Must have valid max_qual->noise */ + || ((qual->noise > 0) && !(qual->updated & IW_QUAL_NOISE_INVALID))) /* OR valid qual->noise */ ) { /* Absolute power values (dBm) */ /* Reasonable fallbacks for dumb drivers that don't specify either level. */ - #define FALLBACK_NOISE_FLOOR_DBM -90 - #define FALLBACK_SIGNAL_MAX_DBM -20 - int max_level = FALLBACK_SIGNAL_MAX_DBM; - int noise = FALLBACK_NOISE_FLOOR_DBM; - int level = qual->level - 0x100; + #define FALLBACK_NOISE_FLOOR_DBM -90 + #define FALLBACK_SIGNAL_MAX_DBM -20 + int max_level = FALLBACK_SIGNAL_MAX_DBM; + int noise = FALLBACK_NOISE_FLOOR_DBM; + int level = qual->level - 0x100; level = CLAMP (level, FALLBACK_NOISE_FLOOR_DBM, FALLBACK_SIGNAL_MAX_DBM); @@ -1464,18 +1461,17 @@ max_qual->updated); /* A sort of signal-to-noise ratio calculation */ level_percent = (int)(100 - 70 *( - ((double)max_level - (double)level) / - ((double)max_level - (double)noise))); + ((double)max_level - (double)level) / + ((double)max_level - (double)noise))); #ifdef IW_QUAL_DEBUG nm_debug ("QL1: level_percent is %d. max_level %d, level %d, noise_floor %d.", level_percent, max_level, level, noise); #endif - } - else if ((max_qual->level != 0) && !(max_qual->updated & IW_QUAL_LEVEL_INVALID) /* Valid max_qual->level as upper bound */ - && !(qual->updated & IW_QUAL_LEVEL_INVALID)) - { + } else if ( (max_qual->level != 0) + && !(max_qual->updated & IW_QUAL_LEVEL_INVALID) /* Valid max_qual->level as upper bound */ + && !(qual->updated & IW_QUAL_LEVEL_INVALID)) { /* Relative power values (RSSI) */ - int level = qual->level; + int level = qual->level; /* Signal level is relavtive (0 -> max_qual->level) */ level = CLAMP (level, 0, max_qual->level); @@ -1512,12 +1508,12 @@ const GByteArray * nm_device_wifi_get_ssid (NMDeviceWifi *self) { NMDeviceWifiPrivate *priv; - int sk; + int sk; struct iwreq wrq; char ssid[IW_ESSID_MAX_SIZE + 2]; guint32 len; - g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (self != NULL, NULL); priv = NM_DEVICE_WIFI_GET_PRIVATE (self); sk = socket (AF_INET, SOCK_DGRAM, 0); @@ -1562,77 +1558,6 @@ out: /* - * nm_device_wifi_set_ssid - * - */ -static void -nm_device_wifi_set_ssid (NMDeviceWifi *self, - const GByteArray * ssid) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - int sk; - struct iwreq wrq; - const char * iface; - const char * driver; - 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)); - } - } - - /* Orinoco cards seem to need extra time here to not screw - * up the firmware, which reboots when you set the SSID. - * Unfortunately, there's no way to know when the card is back up - * again. Sigh... - */ - driver = nm_device_get_driver (NM_DEVICE (self)); - if (!driver || !strcmp (driver, "orinoco")) - sleep (2); - - close (sk); -} - - -/* * nm_device_wifi_get_bitrate * * For wireless devices, get the bitrate to broadcast/receive at. @@ -1667,7 +1592,7 @@ nm_device_wifi_get_bitrate (NMDeviceWifi */ void nm_device_wifi_get_bssid (NMDeviceWifi *self, - struct ether_addr *bssid) + struct ether_addr *bssid) { int fd; struct iwreq wrq; @@ -1692,44 +1617,6 @@ nm_device_wifi_get_bssid (NMDeviceWifi * } -/* - * nm_device_wifi_disable_encryption - * - * Clear any encryption keys the device may have set. - * - */ -static void -nm_device_wifi_disable_encryption (NMDeviceWifi *self) -{ - int fd; - const char *iface; - struct iwreq wrq = { - .u.data.pointer = (caddr_t) NULL, - .u.data.length = 0, - .u.data.flags = IW_ENCODE_DISABLED - }; - - g_return_if_fail (self != NULL); - - fd = socket (PF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - nm_warning ("could not open control socket."); - return; - } - - iface = nm_device_get_iface (NM_DEVICE (self)); - strncpy (wrq.ifr_name, iface, IFNAMSIZ); - - if (ioctl (fd, SIOCSIWENCODE, &wrq) < 0) { - if (errno != ENODEV) { - nm_warning ("error setting key for device %s: %s", - iface, strerror (errno)); - } - } - - close (fd); -} - static gboolean can_scan (NMDeviceWifi *self) { @@ -1858,14 +1745,27 @@ cancel_pending_scan (NMDeviceWifi *self) static void -supplicant_iface_scan_result_cb (NMSupplicantInterface * iface, - gboolean result, - NMDeviceWifi * self) +supplicant_iface_scan_request_result_cb (NMSupplicantInterface *iface, + gboolean success, + NMDeviceWifi *self) { if (can_scan (self)) schedule_scan (self, TRUE); } +static void +supplicant_iface_scan_results_cb (NMSupplicantInterface *iface, + guint32 num_results, + NMDeviceWifi *self) +{ + if (num_results == 0) { + /* ensure that old APs get culled, which otherwise only + * happens when there are actual scan results to process. + */ + cull_scan_list (self); + } +} + static gboolean is_encrypted (guint32 flags, guint32 wpa_flags, guint32 rsn_flags) { @@ -1960,7 +1860,7 @@ out: */ static void merge_scanned_ap (NMDeviceWifi *self, - NMAccessPoint *merge_ap) + NMAccessPoint *merge_ap) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); NMAccessPoint *found_ap = NULL; @@ -2071,13 +1971,14 @@ cull_scan_list (NMDeviceWifi *self) static void set_ap_strength_from_properties (NMDeviceWifi *self, - NMAccessPoint *ap, - GHashTable *properties) + NMAccessPoint *ap, + GHashTable *properties) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); int qual, level, noise; struct iw_quality quality; GValue *value; + gint8 strength; value = (GValue *) g_hash_table_lookup (properties, "quality"); qual = value ? g_value_get_int (value) : -1; @@ -2094,15 +1995,13 @@ set_ap_strength_from_properties (NMDevic SET_QUALITY_MEMBER (quality, level, LEVEL); SET_QUALITY_MEMBER (quality, noise, NOISE); - nm_ap_set_strength (ap, wireless_qual_to_percent - (&quality, - (const iwqual *)(&priv->max_qual), - (const iwqual *)(&priv->avg_qual))); + strength = wireless_qual_to_percent (&quality, &priv->max_qual); + nm_ap_set_strength (ap, strength); } static void supplicant_iface_scanned_ap_cb (NMSupplicantInterface *iface, - GHashTable *properties, + GHashTable *properties, NMDeviceWifi *self) { NMDeviceState state; @@ -2344,6 +2243,7 @@ supplicant_iface_connection_state_cb_han NMDeviceWifi *self = task->self; NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); NMDevice *dev = NM_DEVICE (self); + gboolean scanning; if (!nm_device_get_act_request (dev)) { /* The device is not activating or already activated; do nothing. */ @@ -2355,7 +2255,7 @@ supplicant_iface_connection_state_cb_han nm_supplicant_interface_connection_state_to_string (task->old_state), nm_supplicant_interface_connection_state_to_string (task->new_state)); - priv->scanning = (task->new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_SCANNING); + scanning = nm_supplicant_interface_get_scanning (priv->supplicant.iface); if (task->new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_COMPLETED) { remove_supplicant_interface_error_handler (self); @@ -2381,7 +2281,7 @@ supplicant_iface_connection_state_cb_han * while to scan. */ if (!priv->link_timeout_id) { - priv->link_timeout_id = g_timeout_add_seconds (priv->scanning ? 30 : 15, + priv->link_timeout_id = g_timeout_add_seconds (scanning ? 30 : 15, link_timeout_cb, self); } } @@ -2581,11 +2481,8 @@ handle_auth_or_fail (NMDeviceWifi *self, g_assert (ap); tries = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES)); - if (tries > 3) { - /* Make the user try again explicitly */ - nm_ap_set_invalid (ap, TRUE); + if (tries > 3) return NM_ACT_STAGE_RETURN_FAILURE; - } nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); @@ -2772,8 +2669,7 @@ build_supplicant_config (NMDeviceWifi *s goto error; } - s_wireless_sec = (NMSettingWirelessSecurity *) nm_connection_get_setting (connection, - NM_TYPE_SETTING_WIRELESS_SECURITY); + s_wireless_sec = (NMSettingWirelessSecurity *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS_SECURITY); if (s_wireless_sec) { DBusGProxy *proxy = g_object_get_data (G_OBJECT (connection), NM_MANAGER_CONNECTION_PROXY_TAG); const char *con_path = dbus_g_proxy_get_path (proxy); @@ -2781,18 +2677,16 @@ build_supplicant_config (NMDeviceWifi *s s_8021x = (NMSetting8021x *) nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X); if (!nm_supplicant_config_add_setting_wireless_security (config, - s_wireless_sec, - s_8021x, - con_path)) { + s_wireless_sec, + s_8021x, + con_path)) { nm_warning ("Couldn't add 802-11-wireless-security setting to " "supplicant config."); goto error; } } else { - /* Unencrypted, wpa_supplicant needs key_mgmt=NONE here */ - if (!nm_supplicant_config_add_option (config, "key_mgmt", "NONE", -1, FALSE)) { - nm_warning ("Couldn't add 802-11-wireless (no security) setting to" - " supplicant config."); + if (!nm_supplicant_config_add_no_security (config)) { + nm_warning ("Couldn't add unsecured option to supplicant config."); goto error; } } @@ -2940,18 +2834,18 @@ real_connection_secrets_updated (NMDevic static NMActStageReturn real_act_stage2_config (NMDevice *dev, NMDeviceStateReason *reason) { - NMDeviceWifi * self = NM_DEVICE_WIFI (dev); + NMDeviceWifi *self = NM_DEVICE_WIFI (dev); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; - const char * iface = nm_device_get_iface (dev); - NMSupplicantConfig * config = NULL; - gulong id = 0; - NMActRequest * req; - NMAccessPoint * ap; - NMConnection * connection; - NMSettingConnection * s_connection; - const char * setting_name; - NMSettingWireless * s_wireless; + NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; + const char *iface = nm_device_get_iface (dev); + NMSupplicantConfig *config = NULL; + gulong id = 0; + NMActRequest *req; + NMAccessPoint *ap; + NMConnection *connection; + NMSettingConnection *s_connection; + const char *setting_name; + NMSettingWireless *s_wireless; g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); @@ -3079,13 +2973,13 @@ real_act_stage4_ip_config_timeout (NMDev NMIP4Config **config, NMDeviceStateReason *reason) { - NMDeviceWifi * self = NM_DEVICE_WIFI (dev); - NMAccessPoint * ap = nm_device_wifi_get_activation_ap (self); - NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; - NMIP4Config * real_config = NULL; - NMActRequest * req = nm_device_get_act_request (dev); - NMConnection * connection; - gboolean auth_enforced = FALSE, encrypted = FALSE; + NMDeviceWifi *self = NM_DEVICE_WIFI (dev); + NMAccessPoint *ap = nm_device_wifi_get_activation_ap (self); + NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; + NMIP4Config *real_config = NULL; + NMActRequest *req = nm_device_get_act_request (dev); + NMConnection *connection; + gboolean auth_enforced = FALSE, encrypted = FALSE; g_return_val_if_fail (config != NULL, NM_ACT_STAGE_RETURN_FAILURE); g_return_val_if_fail (*config == NULL, NM_ACT_STAGE_RETURN_FAILURE); @@ -3117,7 +3011,7 @@ real_act_stage4_ip_config_timeout (NMDev *reason = NM_DEVICE_STATE_REASON_NO_SECRETS; } } else if (nm_ap_get_mode (ap) == NM_802_11_MODE_ADHOC) { - NMDeviceWifiClass * klass; + NMDeviceWifiClass *klass; NMDeviceClass * parent_class; /* For Ad-Hoc networks, chain up to parent to get a Zeroconf IP */ @@ -3211,7 +3105,7 @@ activation_failure_handler (NMDevice *de { NMDeviceWifi *self = NM_DEVICE_WIFI (dev); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - NMAccessPoint * ap; + NMAccessPoint *ap; const GByteArray * ssid; NMActRequest *req; NMConnection *connection; @@ -3236,9 +3130,6 @@ activation_failure_handler (NMDevice *de access_point_removed (self, ap); priv->ap_list = g_slist_remove (priv->ap_list, ap); g_object_unref (ap); - } else { - /* Add the AP to the invalid list */ - nm_ap_set_invalid (ap, TRUE); } } @@ -3320,7 +3211,7 @@ nm_device_wifi_dispose (GObject *object) static void get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) + GValue *value, GParamSpec *pspec) { NMDeviceWifi *device = NM_DEVICE_WIFI (object); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device); @@ -3387,79 +3278,79 @@ nm_device_wifi_class_init (NMDeviceWifiC parent_class->can_interrupt_activation = real_can_interrupt_activation; /* Properties */ - g_object_class_install_property - (object_class, PROP_HW_ADDRESS, - g_param_spec_string (NM_DEVICE_WIFI_HW_ADDRESS, - "MAC Address", - "Hardware MAC address", - NULL, - G_PARAM_READABLE)); - g_object_class_install_property - (object_class, PROP_MODE, - g_param_spec_uint (NM_DEVICE_WIFI_MODE, - "Mode", - "Mode", - NM_802_11_MODE_UNKNOWN, NM_802_11_MODE_INFRA, NM_802_11_MODE_INFRA, - G_PARAM_READABLE)); - g_object_class_install_property - (object_class, PROP_BITRATE, - g_param_spec_uint (NM_DEVICE_WIFI_BITRATE, - "Bitrate", - "Bitrate", - 0, G_MAXUINT32, 0, - G_PARAM_READABLE)); - g_object_class_install_property - (object_class, PROP_ACTIVE_ACCESS_POINT, - g_param_spec_boxed (NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT, - "Active access point", - "Currently active access point", - DBUS_TYPE_G_OBJECT_PATH, - G_PARAM_READABLE)); - g_object_class_install_property - (object_class, PROP_CAPABILITIES, - g_param_spec_uint (NM_DEVICE_WIFI_CAPABILITIES, - "Wireless Capabilities", - "Wireless Capabilities", - 0, G_MAXUINT32, NM_WIFI_DEVICE_CAP_NONE, - G_PARAM_READABLE)); + g_object_class_install_property (object_class, PROP_HW_ADDRESS, + g_param_spec_string (NM_DEVICE_WIFI_HW_ADDRESS, + "MAC Address", + "Hardware MAC address", + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, PROP_MODE, + g_param_spec_uint (NM_DEVICE_WIFI_MODE, + "Mode", + "Mode", + NM_802_11_MODE_UNKNOWN, + NM_802_11_MODE_INFRA, + NM_802_11_MODE_INFRA, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, PROP_BITRATE, + g_param_spec_uint (NM_DEVICE_WIFI_BITRATE, + "Bitrate", + "Bitrate", + 0, G_MAXUINT32, 0, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, PROP_ACTIVE_ACCESS_POINT, + g_param_spec_boxed (NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT, + "Active access point", + "Currently active access point", + DBUS_TYPE_G_OBJECT_PATH, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, PROP_CAPABILITIES, + g_param_spec_uint (NM_DEVICE_WIFI_CAPABILITIES, + "Wireless Capabilities", + "Wireless Capabilities", + 0, G_MAXUINT32, NM_WIFI_DEVICE_CAP_NONE, + G_PARAM_READABLE)); /* Signals */ signals[ACCESS_POINT_ADDED] = g_signal_new ("access-point-added", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMDeviceWifiClass, access_point_added), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - G_TYPE_OBJECT); + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMDeviceWifiClass, access_point_added), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); signals[ACCESS_POINT_REMOVED] = g_signal_new ("access-point-removed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMDeviceWifiClass, access_point_removed), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - G_TYPE_OBJECT); + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMDeviceWifiClass, access_point_removed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); signals[HIDDEN_AP_FOUND] = g_signal_new ("hidden-ap-found", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMDeviceWifiClass, hidden_ap_found), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - G_TYPE_OBJECT); + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMDeviceWifiClass, hidden_ap_found), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); signals[PROPERTIES_CHANGED] = nm_properties_changed_signal_new (object_class, - G_STRUCT_OFFSET (NMDeviceWifiClass, properties_changed)); + G_STRUCT_OFFSET (NMDeviceWifiClass, properties_changed)); - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_wifi_object_info); + dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), &dbus_glib_nm_device_wifi_object_info); dbus_g_error_domain_register (NM_WIFI_ERROR, NULL, NM_TYPE_WIFI_ERROR); } @@ -3542,9 +3433,9 @@ device_state_changed (NMDevice *device, NMDeviceWifi * nm_device_wifi_new (const char *udi, - const char *iface, - const char *driver, - gboolean managed) + const char *iface, + const char *driver, + gboolean managed) { GObject *obj; @@ -3553,17 +3444,15 @@ nm_device_wifi_new (const char *udi, g_return_val_if_fail (driver != NULL, NULL); obj = g_object_new (NM_TYPE_DEVICE_WIFI, - NM_DEVICE_INTERFACE_UDI, udi, - NM_DEVICE_INTERFACE_IFACE, iface, - NM_DEVICE_INTERFACE_DRIVER, driver, - NM_DEVICE_INTERFACE_MANAGED, managed, - NULL); + NM_DEVICE_INTERFACE_UDI, udi, + NM_DEVICE_INTERFACE_IFACE, iface, + NM_DEVICE_INTERFACE_DRIVER, driver, + NM_DEVICE_INTERFACE_MANAGED, managed, + NULL); if (obj == NULL) return NULL; - g_signal_connect (obj, "state-changed", - G_CALLBACK (device_state_changed), - NULL); + g_signal_connect (obj, "state-changed", G_CALLBACK (device_state_changed), NULL); return NM_DEVICE_WIFI (obj); } Index: src/nm-gsm-device.c =================================================================== --- src/nm-gsm-device.c.orig +++ src/nm-gsm-device.c @@ -664,6 +664,13 @@ enter_pin (NMGsmDevice *device, NMGsmSec g_free (command); } else { nm_info ("(%s): GSM %s secret required", nm_device_get_iface (NM_DEVICE (device)), secret_name); + + /* Close the serial device as we don't know how long it will take for + * secrets to return, and the port gets re-opened by stage1 when they + * do. + */ + nm_serial_device_close (NM_SERIAL_DEVICE (device)); + nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); Index: src/nm-hal-manager.c =================================================================== --- src/nm-hal-manager.c.orig +++ src/nm-hal-manager.c @@ -124,44 +124,117 @@ get_creator (NMHalManager *self, const c /* Common helpers for built-in device creators */ static char * +hal_get_subsystem (LibHalContext *ctx, const char *udi) +{ + char *subsys; + + subsys = libhal_device_get_property_string (ctx, udi, "info.subsystem", NULL); + if (!subsys) { + /* info.bus is deprecated */ + subsys = libhal_device_get_property_string (ctx, udi, "info.bus", NULL); + } + return subsys; +} + +static char * nm_get_device_driver_name (LibHalContext *ctx, const char *origdev_udi) { - char *driver_name = NULL; + char *driver_name = NULL, *subsystem, *drv, *od_parent = NULL; - if (origdev_udi && libhal_device_property_exists (ctx, origdev_udi, "info.linux.driver", NULL)) { - char *drv; + if (!origdev_udi) + return NULL; - drv = libhal_device_get_property_string (ctx, origdev_udi, "info.linux.driver", NULL); - if (drv) { - driver_name = g_strdup (drv); - libhal_free_string (drv); - } + /* s390 driver name is on the grandparent of the net device */ + subsystem = hal_get_subsystem (ctx, origdev_udi); + if (subsystem && !strcmp (subsystem, "ibmebus")) { + od_parent = libhal_device_get_property_string (ctx, origdev_udi, "info.parent", NULL); + origdev_udi = (const char *) od_parent; } + + drv = libhal_device_get_property_string (ctx, origdev_udi, "info.linux.driver", NULL); + if (drv) + driver_name = g_strdup (drv); + + libhal_free_string (drv); + libhal_free_string (od_parent); + libhal_free_string (subsystem); return driver_name; } -/* Returns the parent if the device is a Sony Ericsson 'mbm'-style device */ -static char * -is_mbm (LibHalContext *ctx, const char *udi) +static gboolean +get_vid_pid (LibHalContext *ctx, + const char *udi, + guint16 *out_vid, + guint16 *out_pid, + char **out_parent) { - guint32 vendor_id = 0, product_id = 0; + int tmp; char *parent; + DBusError error; + gboolean success = FALSE; + + g_return_val_if_fail (ctx != NULL, FALSE); + g_return_val_if_fail (udi != NULL, FALSE); parent = libhal_device_get_property_string (ctx, udi, "info.parent", NULL); if (!parent) - return NULL; + return FALSE; + + dbus_error_init (&error); + tmp = libhal_device_get_property_int (ctx, parent, "usb.vendor_id", &error); + if (dbus_error_is_set (&error)) { + dbus_error_free (&error); + goto out; + } + if (tmp < 0 || tmp > G_MAXUINT16) + goto out; + if (out_vid) + *out_vid = (guint16) tmp; - vendor_id = libhal_device_get_property_int (ctx, parent, "usb.vendor_id", NULL); - product_id = libhal_device_get_property_int (ctx, parent, "usb.product_id", NULL); + dbus_error_init (&error); + tmp = libhal_device_get_property_int (ctx, parent, "usb.product_id", &error); + if (dbus_error_is_set (&error)) { + dbus_error_free (&error); + goto out; + } + if (tmp < 0 || tmp > G_MAXUINT16) + goto out; + if (out_pid) + *out_pid = (guint16) tmp; - if ( (vendor_id == 0x0bdb && product_id == 0x1900) /* SE F3507g */ - || (vendor_id == 0x0bdb && product_id == 0x1902) /* SE F3507g */ - || (vendor_id == 0x0fce && product_id == 0xd0cf) /* SE MD300 */ - || (vendor_id == 0x413c && product_id == 0x8147)) /* Dell 5530 HSDPA */ - return parent; + if (out_parent) + *out_parent = g_strdup (parent); + success = TRUE; +out: libhal_free_string (parent); - return NULL; + return success; +} + +/* Returns the parent if the device is a Sony Ericsson 'mbm'-style device */ +static gboolean +is_mbm (LibHalContext *ctx, const char *udi, char **out_parent) +{ + guint16 vendor_id = 0, product_id = 0; + char *parent = NULL; + + if (!get_vid_pid (ctx, udi, &vendor_id, &product_id, &parent)) + return FALSE; + + if ( (vendor_id == 0x0bdb && product_id == 0x1900) /* SE F3507g */ + || (vendor_id == 0x0bdb && product_id == 0x1902) /* SE F3507g */ + || (vendor_id == 0x0bdb && product_id == 0x1904) /* SE F3607gw */ + || (vendor_id == 0x0bdb && product_id == 0x1906) /* SE F3307 */ + || (vendor_id == 0x0fce && product_id == 0xd0cf) /* SE MD300 */ + || (vendor_id == 0x413c && product_id == 0x8147) /* Dell 5530 HSDPA */ + || (vendor_id == 0x0930 && product_id == 0x130b)) { /* Toshiba */ + if (out_parent) + *out_parent = parent; + return TRUE; + } + + g_free (parent); + return FALSE; } /* Wired device creator */ @@ -194,7 +267,7 @@ wired_device_creator (NMHalManager *self { NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self); GObject *device = NULL; - char *iface, *driver, *parent; + char *iface, *driver; gboolean mbm = FALSE; iface = libhal_device_get_property_string (priv->hal_ctx, udi, "net.interface", NULL); @@ -208,11 +281,8 @@ wired_device_creator (NMHalManager *self /* Special handling of Ericsson F3507g 'mbm' devices; ignore the * cdc-ether device that it provides since we don't use it yet. */ - if (driver && !strcmp (driver, "cdc_ether")) { - parent = is_mbm (priv->hal_ctx, udi); - mbm = !!parent; - libhal_free_string (parent); - } + if (driver && !strcmp (driver, "cdc_ether")) + mbm = is_mbm (priv->hal_ctx, udi, NULL); if (!mbm) device = (GObject *) nm_device_ethernet_new (udi, iface, driver, managed); @@ -292,18 +362,34 @@ is_modem_device (NMHalManager *self, con } static char * +hal_get_originating_device (LibHalContext *ctx, const char *udi, const char *prefix) +{ + char *od_key = g_strdup_printf ("%s.originating_device", prefix); + char *pd_key = g_strdup_printf ("%s.physical_device", prefix); + char *od; + + od = libhal_device_get_property_string (ctx, udi, od_key, NULL); + if (!od) { + /* physical_device is deprecated */ + od = libhal_device_get_property_string (ctx, udi, pd_key, NULL); + } + + g_free (od_key); + g_free (pd_key); + return od; +} + +static char * get_hso_netdev (LibHalContext *ctx, const char *udi) { - char *serial_od = NULL, *serial_od_parent = NULL, *netdev = NULL, *bus; + char *serial_od = NULL, *serial_od_parent = NULL, *netdev = NULL, *subsys; char **netdevs = NULL; int num, i; /* Get the serial interface's originating device UDI, used to find the * originating device's netdev. */ - serial_od = libhal_device_get_property_string (ctx, udi, "serial.originating_device", NULL); - if (!serial_od) - serial_od = libhal_device_get_property_string (ctx, udi, "serial.physical_device", NULL); + serial_od = hal_get_originating_device (ctx, udi, "serial"); if (!serial_od) goto out; @@ -312,21 +398,19 @@ get_hso_netdev (LibHalContext *ctx, cons goto out; /* Check to ensure we've got the actual "USB Device" */ - bus = libhal_device_get_property_string (ctx, serial_od_parent, "info.bus", NULL); - if (!bus || strcmp (bus, "usb_device")) { - libhal_free_string (bus); + subsys = hal_get_subsystem (ctx, serial_od_parent); + if (!subsys || strcmp (subsys, "usb_device")) { + libhal_free_string (subsys); goto out; } - libhal_free_string (bus); + libhal_free_string (subsys); /* Look for the originating device's netdev */ netdevs = libhal_find_device_by_capability (ctx, "net", &num, NULL); for (i = 0; netdevs && !netdev && (i < num); i++) { char *net_od = NULL, *net_od_parent = NULL, *tmp; - net_od = libhal_device_get_property_string (ctx, netdevs[i], "net.originating_device", NULL); - if (!net_od) - net_od = libhal_device_get_property_string (ctx, netdevs[i], "net.physical_device", NULL); + net_od = hal_get_originating_device (ctx, netdevs[i], "net"); if (!net_od) goto next; @@ -335,12 +419,12 @@ get_hso_netdev (LibHalContext *ctx, cons goto next; /* Check to ensure we've got the actual "USB Device" */ - bus = libhal_device_get_property_string (ctx, net_od_parent, "info.bus", NULL); - if (!bus || strcmp (bus, "usb_device")) { - libhal_free_string (bus); + subsys = hal_get_subsystem (ctx, net_od_parent); + if (!subsys || strcmp (subsys, "usb_device")) { + libhal_free_string (subsys); goto next; } - libhal_free_string (bus); + libhal_free_string (subsys); if (!strcmp (net_od_parent, serial_od_parent)) { /* We found it */ @@ -363,16 +447,20 @@ out: return netdev; } -#define PROP_GSM "ID_NM_MODEM_GSM" -#define PROP_CDMA "ID_NM_MODEM_IS707_A" -#define PROP_EVDO1 "ID_NM_MODEM_IS856" -#define PROP_EVDOA "ID_NM_MODEM_IS856_A" +#define PROP_GSM "ID_NM_MODEM_GSM" +#define PROP_CDMA "ID_NM_MODEM_IS707_A" +#define PROP_EVDO1 "ID_NM_MODEM_IS856" +#define PROP_EVDOA "ID_NM_MODEM_IS856_A" +#define PROP_ZTE_MAIN "ID_NM_ZTE_PORT_TYPE_MODEM" +#define PROP_ZTE_SET "ID_NM_ZTE_PORT_TYPE_SET" #if HAVE_LIBUDEV typedef struct { gboolean gsm; gboolean cdma; + gboolean zte_main; + gboolean zte_set; } UdevIterData; #if UDEV_VERSION >= 129 @@ -405,6 +493,13 @@ static int udev_device_prop_iter(struct if (!strcmp (key, PROP_EVDOA) && !strcmp (value, "1")) types->cdma = TRUE; + if (types->cdma || types->gsm) { + if (!strcmp (key, PROP_ZTE_MAIN) && !strcmp (value, "1")) + types->zte_main = TRUE; + if (!strcmp (key, PROP_ZTE_SET) && !strcmp (value, "1")) + types->zte_set = TRUE; + } + /* Return 0 to continue looking */ return types->gsm && types->cdma; } @@ -413,7 +508,9 @@ static int udev_device_prop_iter(struct static gboolean libudev_get_modem_capabilities (const char *sysfs_path, gboolean *gsm, - gboolean *cdma) + gboolean *cdma, + gboolean *zte_main, + gboolean *zte_set) { struct udev *udev; struct udev_device *device; @@ -423,6 +520,10 @@ libudev_get_modem_capabilities (const ch g_return_val_if_fail (*gsm == FALSE, FALSE); g_return_val_if_fail (cdma != NULL, FALSE); g_return_val_if_fail (*cdma == FALSE, FALSE); + g_return_val_if_fail (zte_main != NULL, FALSE); + g_return_val_if_fail (*zte_main == FALSE, FALSE); + g_return_val_if_fail (zte_set != NULL, FALSE); + g_return_val_if_fail (*zte_set == FALSE, FALSE); udev = udev_new (); if (!udev) @@ -450,6 +551,8 @@ libudev_get_modem_capabilities (const ch const char *cdma_val = get_udev_property (device, PROP_CDMA); const char *evdo1_val = get_udev_property (device, PROP_EVDO1); const char *evdoa_val = get_udev_property (device, PROP_EVDOA); + const char *zte_main_val = get_udev_property (device, PROP_ZTE_MAIN); + const char *zte_set_val = get_udev_property (device, PROP_ZTE_SET); if (gsm_val && !strcmp (gsm_val, "1")) *gsm = TRUE; @@ -459,6 +562,13 @@ libudev_get_modem_capabilities (const ch *cdma = TRUE; if (evdoa_val && !strcmp (evdoa_val, "1")) *cdma = TRUE; + + if (*gsm || *cdma) { + if (zte_main_val && !strcmp (zte_main_val, "1")) + *zte_main = TRUE; + if (zte_set_val && !strcmp (zte_set_val, "1")) + *zte_set = TRUE; + } } #else { @@ -467,6 +577,10 @@ libudev_get_modem_capabilities (const ch udev_device_get_properties (device, udev_device_prop_iter, &iterdata); *gsm = iterdata.gsm; *cdma = iterdata.cdma; + if (*gsm || *cdma) { + *zte_main = iterdata.zte_main; + *zte_set = iterdata.zte_set; + } } #endif @@ -478,7 +592,9 @@ libudev_get_modem_capabilities (const ch static gboolean udevadm_get_modem_capabilities (const char *sysfs_path, gboolean *gsm, - gboolean *cdma) + gboolean *cdma, + gboolean *zte_main, + gboolean *zte_set) { char *udevadm_argv[] = { "/sbin/udevadm", "info", "--query=env", NULL, NULL }; char *syspath_arg = NULL; @@ -486,13 +602,17 @@ udevadm_get_modem_capabilities (const ch int exitcode; GError *error = NULL; char **lines = NULL, **iter; - gboolean success = FALSE; + gboolean success = FALSE, is_zte_main = FALSE, is_zte_set = FALSE; g_return_val_if_fail (sysfs_path != NULL, FALSE); g_return_val_if_fail (gsm != NULL, FALSE); g_return_val_if_fail (*gsm == FALSE, FALSE); g_return_val_if_fail (cdma != NULL, FALSE); g_return_val_if_fail (*cdma == FALSE, FALSE); + g_return_val_if_fail (zte_main != NULL, FALSE); + g_return_val_if_fail (*zte_main == FALSE, FALSE); + g_return_val_if_fail (zte_set != NULL, FALSE); + g_return_val_if_fail (*zte_set == FALSE, FALSE); udevadm_argv[3] = syspath_arg = g_strdup_printf ("--path=%s", sysfs_path); if (g_spawn_sync ("/", udevadm_argv, NULL, 0, NULL, NULL, @@ -517,14 +637,21 @@ udevadm_get_modem_capabilities (const ch for (iter = lines; *iter; iter++) { if (!strcmp (*iter, PROP_GSM "=1")) { *gsm = TRUE; - break; } else if ( !strcmp (*iter, PROP_CDMA "=1") || !strcmp (*iter, PROP_EVDO1 "=1") || !strcmp (*iter, PROP_EVDOA "=1")) { *cdma = TRUE; - break; - } + } else if (!strcmp (*iter, PROP_ZTE_MAIN "=1")) + is_zte_main = TRUE; + else if (!strcmp (*iter, PROP_ZTE_SET "=1")) + is_zte_set = TRUE; + } + + if (*gsm || *cdma) { + *zte_main = is_zte_main; + *zte_set = is_zte_set; } + success = TRUE; error: @@ -823,13 +950,12 @@ new_modem_device (const char *udi, * ModemManager more correctly in HEAD. */ if (gsm && !strcmp (driver, "cdc_acm")) { - char *parent; + char *parent = NULL; guint32 usb_interface; - parent = is_mbm (ctx, udi); - if (parent) { + if (is_mbm (ctx, udi, &parent)) { usb_interface = libhal_device_get_property_int (ctx, parent, "usb.interface.number", NULL); - libhal_free_string (parent); + g_free (parent); if (usb_interface != 1) return NULL; } @@ -851,22 +977,16 @@ new_modem_device (const char *udi, static char * nm_get_modem_device_driver_name (LibHalContext *ctx, const char *udi) { - char *driver_name = NULL; - char *origdev_udi; + char *driver_name = NULL, *origdev_udi, *driver; - origdev_udi = libhal_device_get_property_string (ctx, udi, "serial.originating_device", NULL); - /* Older HAL uses "physical_device" */ + origdev_udi = hal_get_originating_device (ctx, udi, "serial"); if (!origdev_udi) - origdev_udi = libhal_device_get_property_string (ctx, udi, "serial.physical_device", NULL); - - if (origdev_udi && libhal_device_property_exists (ctx, origdev_udi, "info.linux.driver", NULL)) { - char *drv; + return NULL; - drv = libhal_device_get_property_string (ctx, origdev_udi, "info.linux.driver", NULL); - if (drv) { - driver_name = g_strdup (drv); - libhal_free_string (drv); - } + driver = libhal_device_get_property_string (ctx, origdev_udi, "info.linux.driver", NULL); + if (driver) { + driver_name = g_strdup (driver); + libhal_free_string (driver); } libhal_free_string (origdev_udi); return driver_name; @@ -890,7 +1010,10 @@ modem_device_creator (NMHalManager *self gboolean hal_cdma = FALSE; gboolean later = FALSE; gboolean udev_success = FALSE; + gboolean zte_main = FALSE; + gboolean zte_set = FALSE; DeferredModem *deferred = NULL; + guint16 vid = 0; serial_device = libhal_device_get_property_string (priv->hal_ctx, udi, "serial.device", NULL); /* For serial devices, 'origdev_udi' will be the actual USB or platform device, @@ -921,9 +1044,9 @@ modem_device_creator (NMHalManager *self } #if HAVE_LIBUDEV - udev_success = libudev_get_modem_capabilities (sysfs_path, &udev_gsm, &udev_cdma); + udev_success = libudev_get_modem_capabilities (sysfs_path, &udev_gsm, &udev_cdma, &zte_main, &zte_set); #else - udev_success = udevadm_get_modem_capabilities (sysfs_path, &udev_gsm, &udev_cdma); + udev_success = udevadm_get_modem_capabilities (sysfs_path, &udev_gsm, &udev_cdma, &zte_main, &zte_set); #endif libhal_free_string (sysfs_path); @@ -937,6 +1060,17 @@ modem_device_creator (NMHalManager *self udev_cdma = hal_cdma; } + /* ZTE modem ports get tagged by udev rules, so if the modem was known to + * the rules (in which case ID_NM_ZTE_PORT_TYPE_SET will be set), and the + * port isn't a "main" port, we should ignore it. + */ + if (get_vid_pid (priv->hal_ctx, udi, &vid, NULL, NULL) && (vid == 0x19d2)) { + if (zte_set && !zte_main) { + udev_gsm = FALSE; + udev_cdma = FALSE; + } + } + /* If it's not known to either udev or HAL as a modem, nothing to do */ if (!udev_gsm && !udev_cdma && !hal_gsm && !hal_cdma) { nm_info ("(%s): ignoring due to lack of mobile broadband capabilties", ttyname); @@ -1039,7 +1173,7 @@ static void emit_udi_added (NMHalManager *self, const char *udi, DeviceCreator *creator) { NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self); - char *od = NULL, *tmp, *parent, *bus = NULL; + char *od = NULL, *tmp, *parent, *subsys = NULL; g_return_if_fail (self != NULL); g_return_if_fail (udi != NULL); @@ -1056,8 +1190,8 @@ emit_udi_added (NMHalManager *self, cons */ parent = libhal_device_get_property_string (priv->hal_ctx, udi, "info.parent", NULL); if (parent) - bus = libhal_device_get_property_string (priv->hal_ctx, parent, "info.bus", NULL); - if (bus && !strcmp (bus, "usb")) { + subsys = hal_get_subsystem (priv->hal_ctx, parent); + if (subsys && !strcmp (subsys, "usb")) { char *usb_intf_udi; usb_intf_udi = libhal_device_get_property_string (priv->hal_ctx, udi, "info.parent", NULL); @@ -1066,7 +1200,7 @@ emit_udi_added (NMHalManager *self, cons /* Ensure the grandparent really is the "USB Device" */ if (od) { - tmp = libhal_device_get_property_string (priv->hal_ctx, od, "info.bus", NULL); + tmp = hal_get_subsystem (priv->hal_ctx, od); if (!tmp || strcmp (tmp, "usb_device")) { libhal_free_string (od); od = NULL; @@ -1077,24 +1211,14 @@ emit_udi_added (NMHalManager *self, cons libhal_free_string (usb_intf_udi); } } - libhal_free_string (bus); + libhal_free_string (subsys); libhal_free_string (parent); /* For non-USB devices, and ss a fallback, just use the originating device * of the tty; though this might result in more than one modem being detected by NM. */ - if (!od) { - tmp = g_strdup_printf ("%s.originating_device", creator->category); - od = libhal_device_get_property_string (priv->hal_ctx, udi, tmp, NULL); - g_free (tmp); - } - - if (!od) { - /* Older HAL uses 'physical_device' */ - tmp = g_strdup_printf ("%s.physical_device", creator->category); - od = libhal_device_get_property_string (priv->hal_ctx, udi, tmp, NULL); - g_free (tmp); - } + if (!od) + od = hal_get_originating_device (priv->hal_ctx, udi, creator->category); g_signal_emit (self, signals[UDI_ADDED], 0, udi, Index: src/nm-hso-gsm-device.c =================================================================== --- src/nm-hso-gsm-device.c +++ /dev/null @@ -1,611 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2008 Red Hat, Inc. - */ - -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <stdlib.h> -#include <arpa/inet.h> -#include <dbus/dbus-glib.h> - -#include "nm-device.h" -#include "nm-hso-gsm-device.h" -#include "nm-gsm-device.h" -#include "nm-device-interface.h" -#include "nm-device-private.h" -#include "nm-setting-gsm.h" -#include "nm-utils.h" -#include "nm-properties-changed-signal.h" -#include "nm-setting-connection.h" -#include "NetworkManagerSystem.h" - -G_DEFINE_TYPE (NMHsoGsmDevice, nm_hso_gsm_device, NM_TYPE_GSM_DEVICE) - -#define NM_HSO_GSM_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_HSO_GSM_DEVICE, NMHsoGsmDevicePrivate)) - -extern const DBusGObjectInfo dbus_glib_nm_gsm_device_object_info; - -#define GSM_CID "gsm-cid" -#define HSO_CALL_STARTED "call-started" -#define HSO_SECRETS_TRIES "gsm-secrets-tries" - -typedef struct { - char *netdev_iface; - NMIP4Config *pending_ip4_config; -} NMHsoGsmDevicePrivate; - -enum { - PROP_0, - PROP_NETDEV_IFACE, - - LAST_PROP -}; - -NMHsoGsmDevice * -nm_hso_gsm_device_new (const char *udi, - const char *data_iface, - const char *monitor_iface, - const char *netdev_iface, - const char *driver, - gboolean managed) -{ - g_return_val_if_fail (udi != NULL, NULL); - g_return_val_if_fail (data_iface != NULL, NULL); - g_return_val_if_fail (driver != NULL, NULL); - g_return_val_if_fail (netdev_iface != NULL, NULL); - - return (NMHsoGsmDevice *) g_object_new (NM_TYPE_HSO_GSM_DEVICE, - NM_DEVICE_INTERFACE_UDI, udi, - NM_DEVICE_INTERFACE_IFACE, data_iface, - NM_DEVICE_INTERFACE_DRIVER, driver, - NM_GSM_DEVICE_MONITOR_IFACE, monitor_iface, - NM_HSO_GSM_DEVICE_NETDEV_IFACE, netdev_iface, - NM_DEVICE_INTERFACE_MANAGED, managed, - NULL); -} - -static void -modem_wait_for_reply (NMGsmDevice *self, - const char *command, - guint timeout, - const char **responses, - const char **terminators, - NMSerialWaitForReplyFn callback, - gpointer user_data) -{ - NMSerialDevice *serial = NM_SERIAL_DEVICE (self); - guint id = 0; - - if (nm_serial_device_send_command_string (serial, command)) - id = nm_serial_device_wait_for_reply (serial, timeout, responses, terminators, callback, user_data); - - if (id == 0) - nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_UNKNOWN); -} - -static NMSetting * -gsm_device_get_setting (NMGsmDevice *device, GType setting_type) -{ - NMActRequest *req; - NMSetting *setting = NULL; - - req = nm_device_get_act_request (NM_DEVICE (device)); - if (req) { - NMConnection *connection; - - connection = nm_act_request_get_connection (req); - if (connection) - setting = nm_connection_get_setting (connection, setting_type); - } - - return setting; -} - -static void -hso_call_done (NMSerialDevice *device, - int reply_index, - const char *reply, - gpointer user_data) -{ - NMActRequest *req; - gboolean success = FALSE; - - switch (reply_index) { - case 0: - nm_info ("Connected, Woo!"); - success = TRUE; - - req = nm_device_get_act_request (NM_DEVICE (device)); - g_assert (req); - g_object_set_data (G_OBJECT (req), HSO_CALL_STARTED, GUINT_TO_POINTER (TRUE)); - break; - default: - nm_warning ("Connect request failed"); - break; - } - - if (success) - nm_device_activate_schedule_stage3_ip_config_start (NM_DEVICE (device)); - else - nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED); -} - -static void -hso_clear_done (NMSerialDevice *device, - int reply_index, - const char *reply, - gpointer user_data) -{ - const char *responses[] = { "_OWANCALL: ", "ERROR", NULL }; - guint cid = GPOINTER_TO_UINT (user_data); - char *command; - - /* Try to connect */ - command = g_strdup_printf ("AT_OWANCALL=%d,1,1", cid); - modem_wait_for_reply (NM_GSM_DEVICE (device), command, 10, responses, responses, hso_call_done, NULL); - g_free (command); -} - -static void -hso_auth_done (NMSerialDevice *device, - int reply_index, - const char *reply, - gpointer user_data) -{ - gboolean success = FALSE; - const char *responses[] = { "_OWANCALL: ", "ERROR", "NO CARRIER", NULL }; - guint cid = GPOINTER_TO_UINT (user_data); - char *command; - - switch (reply_index) { - case 0: - nm_info ("Authentication successful!"); - success = TRUE; - break; - default: - nm_warning ("Authentication failed"); - break; - } - - if (!success) { - nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED); - return; - } - - /* Kill any existing connection */ - command = g_strdup_printf ("AT_OWANCALL=%d,0,1", cid); - modem_wait_for_reply (NM_GSM_DEVICE (device), command, 5, responses, responses, hso_clear_done, GUINT_TO_POINTER (cid)); - g_free (command); -} - -static void -do_hso_auth (NMHsoGsmDevice *device) -{ - NMSettingGsm *s_gsm; - NMActRequest *req; - const char *responses[] = { "OK", "ERROR", "ERR", NULL }; - char *command; - const char *gsm_username; - const char *gsm_password; - guint cid; - - req = nm_device_get_act_request (NM_DEVICE (device)); - g_assert (req); - - cid = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (req), GSM_CID)); - - s_gsm = NM_SETTING_GSM (gsm_device_get_setting (NM_GSM_DEVICE (device), NM_TYPE_SETTING_GSM)); - - gsm_username = nm_setting_gsm_get_username (s_gsm); - gsm_password = nm_setting_gsm_get_password (s_gsm); - - command = g_strdup_printf ("AT$QCPDPP=%d,1,\"%s\",\"%s\"", - cid, - gsm_password ? gsm_password : "", - gsm_username ? gsm_username : ""); - modem_wait_for_reply (NM_GSM_DEVICE (device), command, 5, responses, responses, hso_auth_done, GUINT_TO_POINTER (cid)); - g_free (command); -} - -static NMActStageReturn -real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) -{ - NMActRequest *req; - NMConnection *connection; - const char *setting_name; - GPtrArray *hints = NULL; - const char *hint1 = NULL, *hint2 = NULL; - guint32 tries; - - req = nm_device_get_act_request (device); - g_assert (req); - connection = nm_act_request_get_connection (req); - g_assert (connection); - - setting_name = nm_connection_need_secrets (connection, &hints); - if (!setting_name) { - do_hso_auth (NM_HSO_GSM_DEVICE (device)); - return NM_ACT_STAGE_RETURN_POSTPONE; - } - - if (hints) { - if (hints->len > 0) - hint1 = g_ptr_array_index (hints, 0); - if (hints->len > 1) - hint2 = g_ptr_array_index (hints, 1); - } - - nm_device_state_changed (device, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); - - tries = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (connection), HSO_SECRETS_TRIES)); - nm_act_request_request_connection_secrets (req, - setting_name, - tries ? TRUE : FALSE, - SECRETS_CALLER_HSO_GSM, - hint1, - hint2); - g_object_set_data (G_OBJECT (connection), HSO_SECRETS_TRIES, GUINT_TO_POINTER (++tries)); - - if (hints) - g_ptr_array_free (hints, TRUE); - - return NM_ACT_STAGE_RETURN_POSTPONE; -} - -static void -real_do_dial (NMGsmDevice *device, guint cid) -{ - NMActRequest *req; - - req = nm_device_get_act_request (NM_DEVICE (device)); - g_assert (req); - g_object_set_data (G_OBJECT (req), GSM_CID, GUINT_TO_POINTER (cid)); - - nm_device_activate_schedule_stage2_device_config (NM_DEVICE (device)); -} - -#define OWANDATA_TAG "_OWANDATA: " - -static void -hso_ip4_config_response (NMSerialDevice *device, - int reply_index, - const char *response, - gpointer user_data) -{ - NMHsoGsmDevicePrivate *priv = NM_HSO_GSM_DEVICE_GET_PRIVATE (device); - NMActRequest *req; - char **items, **iter; - guint cid, i; - guint32 dns1 = 0, dns2 = 0, ip4_address = 0; - - if ( (reply_index < 0) - || !response - || strncmp (response, OWANDATA_TAG, strlen (OWANDATA_TAG))) { - nm_device_activate_schedule_stage4_ip_config_timeout (NM_DEVICE (device)); - return; - } - - req = nm_device_get_act_request (NM_DEVICE (device)); - g_assert (req); - cid = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (req), GSM_CID)); - - items = g_strsplit (response + strlen (OWANDATA_TAG), ", ", 0); - for (iter = items, i = 0; *iter; iter++, i++) { - if (i == 0) { /* CID */ - long int tmp; - - errno = 0; - tmp = strtol (*iter, NULL, 10); - if (errno != 0 || tmp < 0 || (guint) tmp != cid) { - nm_warning ("%s: unknown CID in OWANDATA response (got %d, expected %d)", - nm_device_get_iface (NM_DEVICE (device)), - (guint) tmp, cid); - goto out; - } - } else if (i == 1) { /* IP address */ - if (inet_pton (AF_INET, *iter, &ip4_address) <= 0) - ip4_address = 0; - } else if (i == 3) { /* DNS 1 */ - if (inet_pton (AF_INET, *iter, &dns1) <= 0) - dns1 = 0; - } else if (i == 4) { /* DNS 2 */ - if (inet_pton (AF_INET, *iter, &dns2) <= 0) - dns2 = 0; - } - } - -out: - g_strfreev (items); - - if (ip4_address) { - NMIP4Address *addr; - - priv->pending_ip4_config = nm_ip4_config_new (); - - addr = nm_ip4_address_new (); - nm_ip4_address_set_address (addr, ip4_address); - nm_ip4_address_set_prefix (addr, 32); - - nm_ip4_config_take_address (priv->pending_ip4_config, addr); - - if (dns1) - nm_ip4_config_add_nameserver (priv->pending_ip4_config, dns1); - if (dns2) - nm_ip4_config_add_nameserver (priv->pending_ip4_config, dns2); - - nm_device_activate_schedule_stage4_ip_config_get (NM_DEVICE (device)); - } else { - nm_device_state_changed (NM_DEVICE (device), - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } -} - -static NMActStageReturn -real_act_stage3_ip_config_start (NMDevice *device, NMDeviceStateReason *reason) -{ - NMActRequest *req; - NMConnection *connection; - char *command; - gint cid; - const char *responses[] = { "_OWANDATA: ", NULL }; - const char *terminators[] = { "OK", "ERROR", "ERR", NULL }; - - req = nm_device_get_act_request (device); - g_assert (req); - - connection = nm_act_request_get_connection (req); - g_assert (connection); - g_object_set_data (G_OBJECT (connection), HSO_SECRETS_TRIES, NULL); - - cid = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (req), GSM_CID)); - command = g_strdup_printf ("AT_OWANDATA=%d", cid); - modem_wait_for_reply (NM_GSM_DEVICE (device), command, 5, responses, terminators, hso_ip4_config_response, NULL); - g_free (command); - - return NM_ACT_STAGE_RETURN_POSTPONE; -} - -static NMActStageReturn -real_act_stage4_get_ip4_config (NMDevice *device, - NMIP4Config **config, - NMDeviceStateReason *reason) -{ - NMHsoGsmDevice *self = NM_HSO_GSM_DEVICE (device); - NMHsoGsmDevicePrivate *priv = NM_HSO_GSM_DEVICE_GET_PRIVATE (self); - gboolean no_firmware = FALSE; - - g_return_val_if_fail (config != NULL, NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (*config == NULL, NM_ACT_STAGE_RETURN_FAILURE); - - nm_device_set_ip_iface (device, priv->netdev_iface); - if (!nm_device_hw_bring_up (device, TRUE, &no_firmware)) { - if (no_firmware) - *reason = NM_DEVICE_STATE_REASON_FIRMWARE_MISSING; - else - *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; - return NM_ACT_STAGE_RETURN_FAILURE; - } - - *config = priv->pending_ip4_config; - priv->pending_ip4_config = NULL; - return NM_ACT_STAGE_RETURN_SUCCESS; -} - -static void -real_connection_secrets_updated (NMDevice *device, - NMConnection *connection, - GSList *updated_settings, - RequestSecretsCaller caller) -{ - g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH); - - if (caller == SECRETS_CALLER_HSO_GSM) { /* HSO PPP auth */ - nm_device_activate_schedule_stage2_device_config (device); - return; - } - - /* Let parent handle other auth like PIN/PUK */ - NM_DEVICE_CLASS (nm_hso_gsm_device_parent_class)->connection_secrets_updated (device, connection, updated_settings, caller); -} - -static void -real_deactivate_quickly (NMDevice *device) -{ - NMHsoGsmDevicePrivate *priv = NM_HSO_GSM_DEVICE_GET_PRIVATE (device); - NMActRequest *req; - NMConnection *connection; - guint cid, call_started; - char *command; - - if (priv->pending_ip4_config) { - g_object_unref (priv->pending_ip4_config); - priv->pending_ip4_config = NULL; - } - - /* Don't leave the modem connected */ - req = nm_device_get_act_request (device); - if (req) { - cid = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (req), GSM_CID)); - call_started = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (req), HSO_CALL_STARTED)); - if (cid && call_started) { - const char *responses[] = { "OK", "ERROR", "ERR", NULL }; - int reply; - - /* Disconnect and disable asynchonous notification to keep serial - * buffer empty after the OK. - */ - command = g_strdup_printf ("AT_OWANCALL=%d,0,0", cid); - nm_serial_device_send_command_string (NM_SERIAL_DEVICE (device), command); - reply = nm_serial_device_wait_reply_blocking (NM_SERIAL_DEVICE (device), 5, responses, responses); - g_free (command); - } - - /* Clear the secrets attempts counter */ - connection = nm_act_request_get_connection (req); - g_assert (connection); - g_object_set_data (G_OBJECT (connection), HSO_SECRETS_TRIES, NULL); - } - - if (NM_DEVICE_CLASS (nm_hso_gsm_device_parent_class)->deactivate_quickly) - NM_DEVICE_CLASS (nm_hso_gsm_device_parent_class)->deactivate_quickly (device); -} - -static void -real_deactivate (NMDevice *device) -{ - NMHsoGsmDevicePrivate *priv = NM_HSO_GSM_DEVICE_GET_PRIVATE (device); - - if (priv->netdev_iface) { - nm_system_device_flush_ip4_routes_with_iface (priv->netdev_iface); - nm_system_device_flush_ip4_addresses_with_iface (priv->netdev_iface); - nm_system_device_set_up_down_with_iface (priv->netdev_iface, FALSE, NULL); - } - nm_device_set_ip_iface (device, NULL); - - if (NM_DEVICE_CLASS (nm_hso_gsm_device_parent_class)->deactivate) - NM_DEVICE_CLASS (nm_hso_gsm_device_parent_class)->deactivate (device); -} - -static gboolean -real_hw_is_up (NMDevice *device) -{ - NMHsoGsmDevicePrivate *priv = NM_HSO_GSM_DEVICE_GET_PRIVATE (device); - NMDeviceState state; - - state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device)); - - if ( priv->pending_ip4_config - || (state == NM_DEVICE_STATE_IP_CONFIG) - || (state == NM_DEVICE_STATE_ACTIVATED)) - return nm_system_device_is_up_with_iface (priv->netdev_iface); - - return TRUE; -} - -static gboolean -real_hw_bring_up (NMDevice *device, gboolean *no_firmware) -{ - NMHsoGsmDevicePrivate *priv = NM_HSO_GSM_DEVICE_GET_PRIVATE (device); - NMDeviceState state; - - state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device)); - - if ( priv->pending_ip4_config - || (state == NM_DEVICE_STATE_IP_CONFIG) - || (state == NM_DEVICE_STATE_ACTIVATED)) - return nm_system_device_set_up_down_with_iface (priv->netdev_iface, TRUE, no_firmware); - - return TRUE; -} - -static void -nm_hso_gsm_device_init (NMHsoGsmDevice *self) -{ -} - -static GObject* -constructor (GType type, - guint n_params, - GObjectConstructParam *params) -{ - return G_OBJECT_CLASS (nm_hso_gsm_device_parent_class)->constructor (type, n_params, params); -} - -static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - NMHsoGsmDevicePrivate *priv = NM_HSO_GSM_DEVICE_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_NETDEV_IFACE: - /* Construct only */ - priv->netdev_iface = g_value_dup_string (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) -{ - NMHsoGsmDevicePrivate *priv = NM_HSO_GSM_DEVICE_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_NETDEV_IFACE: - g_value_set_string (value, priv->netdev_iface); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -finalize (GObject *object) -{ - NMHsoGsmDevicePrivate *priv = NM_HSO_GSM_DEVICE_GET_PRIVATE (object); - - g_free (priv->netdev_iface); - - G_OBJECT_CLASS (nm_hso_gsm_device_parent_class)->finalize (object); -} - -static void -nm_hso_gsm_device_class_init (NMHsoGsmDeviceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); - NMGsmDeviceClass *gsm_class = NM_GSM_DEVICE_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMHsoGsmDevicePrivate)); - - object_class->constructor = constructor; - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - 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_stage4_get_ip4_config = real_act_stage4_get_ip4_config; - device_class->connection_secrets_updated = real_connection_secrets_updated; - device_class->deactivate_quickly = real_deactivate_quickly; - device_class->deactivate = real_deactivate; - device_class->hw_is_up = real_hw_is_up; - device_class->hw_bring_up = real_hw_bring_up; - - gsm_class->do_dial = real_do_dial; - - /* Properties */ - g_object_class_install_property - (object_class, PROP_NETDEV_IFACE, - g_param_spec_string (NM_HSO_GSM_DEVICE_NETDEV_IFACE, - "Network interface", - "Network interface", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT)); - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_gsm_device_object_info); -} Index: src/nm-ip4-config.c =================================================================== --- src/nm-ip4-config.c.orig +++ src/nm-ip4-config.c @@ -352,14 +352,21 @@ void nm_ip4_config_reset_routes (NMIP4Co void nm_ip4_config_add_domain (NMIP4Config *config, const char *domain) { + NMIP4ConfigPrivate *priv; + int i; + g_return_if_fail (NM_IS_IP4_CONFIG (config)); g_return_if_fail (domain != NULL); g_return_if_fail (strlen (domain) > 0); - if (!strlen (domain)) - return; + priv = NM_IP4_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 (NM_IP4_CONFIG_GET_PRIVATE (config)->domains, g_strdup (domain)); + g_ptr_array_add (priv->domains, g_strdup (domain)); } const char *nm_ip4_config_get_domain (NMIP4Config *config, guint i) @@ -376,13 +383,37 @@ guint32 nm_ip4_config_get_num_domains (N return NM_IP4_CONFIG_GET_PRIVATE (config)->domains->len; } +void nm_ip4_config_reset_domains (NMIP4Config *config) +{ + NMIP4ConfigPrivate *priv; + int i; + + g_return_if_fail (NM_IS_IP4_CONFIG (config)); + + priv = NM_IP4_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_ip4_config_add_search (NMIP4Config *config, const char *search) { + NMIP4ConfigPrivate *priv; + int i; + g_return_if_fail (config != NULL); g_return_if_fail (search != NULL); g_return_if_fail (strlen (search) > 0); - g_ptr_array_add (NM_IP4_CONFIG_GET_PRIVATE (config)->searches, g_strdup (search)); + priv = NM_IP4_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_ip4_config_get_search (NMIP4Config *config, guint i) @@ -402,12 +433,15 @@ guint32 nm_ip4_config_get_num_searches ( void nm_ip4_config_reset_searches (NMIP4Config *config) { NMIP4ConfigPrivate *priv; + int i; g_return_if_fail (NM_IS_IP4_CONFIG (config)); priv = NM_IP4_CONFIG_GET_PRIVATE (config); - if (priv->searches->len) - g_ptr_array_remove_range (priv->searches, 0, priv->searches->len); + 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_ip4_config_get_mtu (NMIP4Config *config) @@ -696,8 +730,8 @@ nm_ip4_config_init (NMIP4Config *config) priv->nameservers = g_array_new (FALSE, TRUE, sizeof (guint32)); priv->wins = g_array_new (FALSE, TRUE, sizeof (guint32)); - priv->domains = g_ptr_array_new (); - priv->searches = g_ptr_array_new (); + priv->domains = g_ptr_array_sized_new (3); + priv->searches = g_ptr_array_sized_new (3); } static void Index: src/nm-ip4-config.h =================================================================== --- src/nm-ip4-config.h.orig +++ src/nm-ip4-config.h @@ -83,6 +83,7 @@ void nm_ip4_config_reset_routes void nm_ip4_config_add_domain (NMIP4Config *config, const char *domain); const char * nm_ip4_config_get_domain (NMIP4Config *config, guint i); guint32 nm_ip4_config_get_num_domains (NMIP4Config *config); +void nm_ip4_config_reset_domains (NMIP4Config *config); void nm_ip4_config_add_search (NMIP4Config *config, const char *search); const char * nm_ip4_config_get_search (NMIP4Config *config, guint i); Index: src/nm-netlink-monitor.c =================================================================== --- src/nm-netlink-monitor.c.orig +++ src/nm-netlink-monitor.c @@ -399,8 +399,18 @@ deferred_emit_carrier_state (gpointer us priv->request_status_id = 0; - /* Emit each device's new state */ - nl_cache_foreach_filter (priv->nlh_link_cache, NULL, netlink_object_message_handler, monitor); + /* Update the link cache with latest state, and if there are no errors + * emit the link states for all the interfaces in the cache. + */ + if (nl_cache_refill (priv->nlh, priv->nlh_link_cache)) + nm_warning ("error updating link cache: %s", nl_geterror ()); + else { + nl_cache_foreach_filter (priv->nlh_link_cache, + NULL, + netlink_object_message_handler, + monitor); + } + return FALSE; } @@ -415,15 +425,6 @@ nm_netlink_monitor_request_status (NMNet priv = NM_NETLINK_MONITOR_GET_PRIVATE (monitor); g_return_val_if_fail (priv->event_id > 0, FALSE); - /* Update the link cache with latest state */ - if (nl_cache_refill (priv->nlh, priv->nlh_link_cache)) { - g_set_error (error, NM_NETLINK_MONITOR_ERROR, - NM_NETLINK_MONITOR_ERROR_LINK_CACHE_UPDATE, - _("error updating link cache: %s"), - nl_geterror ()); - return FALSE; - } - /* Schedule the carrier state emission */ if (!priv->request_status_id) priv->request_status_id = g_idle_add (deferred_emit_carrier_state, monitor); Index: src/nm-serial-device.c =================================================================== --- src/nm-serial-device.c +++ /dev/null @@ -1,1180 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2007 - 2008 Novell, Inc. - * Copyright (C) 2007 - 2008 Red Hat, Inc. - */ - -#define _GNU_SOURCE /* for strcasestr() */ - -#include <termio.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/ioctl.h> -#include <string.h> -#include <stdlib.h> -#include <glib.h> - -#include "nm-glib-compat.h" -#include "nm-serial-device.h" -#include "nm-device-interface.h" -#include "nm-device-private.h" -#include "ppp-manager/nm-ppp-manager.h" -#include "nm-setting-ppp.h" -#include "nm-marshal.h" -#include "nm-utils.h" -#include "nm-serial-device-glue.h" -#include "NetworkManagerUtils.h" - -static gboolean serial_debug = FALSE; - -#define SERIAL_BUF_SIZE 2048 - -G_DEFINE_TYPE (NMSerialDevice, nm_serial_device, NM_TYPE_DEVICE) - -#define NM_SERIAL_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SERIAL_DEVICE, NMSerialDevicePrivate)) - -typedef struct { - int fd; - GIOChannel *channel; - NMPPPManager *ppp_manager; - NMIP4Config *pending_ip4_config; - struct termios old_t; - - guint pending_id; - guint timeout_id; - - /* PPP stats */ - guint32 in_bytes; - guint32 out_bytes; -} NMSerialDevicePrivate; - -enum { - PPP_STATS, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -static int -parse_baudrate (guint i) -{ - int speed; - - switch (i) { - case 0: - speed = B0; - break; - case 50: - speed = B50; - break; - case 75: - speed = B75; - break; - case 110: - speed = B110; - break; - case 150: - speed = B150; - break; - case 300: - speed = B300; - break; - case 600: - speed = B600; - break; - case 1200: - speed = B1200; - break; - case 2400: - speed = B2400; - break; - case 4800: - speed = B4800; - break; - case 9600: - speed = B9600; - break; - case 19200: - speed = B19200; - break; - case 38400: - speed = B38400; - break; - case 57600: - speed = B57600; - break; - case 115200: - speed = B115200; - break; - case 460800: - speed = B460800; - break; - default: - g_warning ("Invalid baudrate '%d'", i); - speed = B9600; - } - - return speed; -} - -static int -parse_bits (guint i) -{ - int bits; - - switch (i) { - case 5: - bits = CS5; - break; - case 6: - bits = CS6; - break; - case 7: - bits = CS7; - break; - case 8: - bits = CS8; - break; - default: - g_warning ("Invalid bits (%d). Valid values are 5, 6, 7, 8.", i); - bits = CS8; - } - - return bits; -} - -static int -parse_parity (char c) -{ - int parity; - - switch (c) { - case 'n': - case 'N': - parity = 0; - break; - case 'e': - case 'E': - parity = PARENB; - break; - case 'o': - case 'O': - parity = PARENB | PARODD; - break; - default: - g_warning ("Invalid parity (%c). Valid values are n, e, o", c); - parity = 0; - } - - return parity; -} - -static int -parse_stopbits (guint i) -{ - int stopbits; - - switch (i) { - case 1: - stopbits = 0; - break; - case 2: - stopbits = CSTOPB; - break; - default: - g_warning ("Invalid stop bits (%d). Valid values are 1 and 2)", i); - stopbits = 0; - } - - return stopbits; -} - -static inline void -nm_serial_debug (const char *prefix, const char *data, int len) -{ - GString *str; - int i; - - if (!serial_debug) - return; - - str = g_string_sized_new (len); - for (i = 0; i < len; i++) { - if (data[i] == '\0') - g_string_append_c (str, ' '); - else if (data[i] == '\r') - g_string_append_c (str, '\n'); - else - g_string_append_c (str, data[i]); - } - - nm_debug ("%s '%s'", prefix, str->str); - g_string_free (str, TRUE); -} - -static NMSetting * -serial_device_get_setting (NMSerialDevice *device, GType setting_type) -{ - NMActRequest *req; - NMSetting *setting = NULL; - - req = nm_device_get_act_request (NM_DEVICE (device)); - if (req) { - NMConnection *connection; - - connection = nm_act_request_get_connection (req); - if (connection) - setting = nm_connection_get_setting (connection, setting_type); - } - - return setting; -} - -/* Timeout handling */ - -static void -nm_serial_device_timeout_removed (gpointer data) -{ - NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (data); - - priv->timeout_id = 0; -} - -static gboolean -nm_serial_device_timed_out (gpointer data) -{ - NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (data); - - /* Cancel data reading */ - if (priv->pending_id) - g_source_remove (priv->pending_id); - else - nm_warning ("Timeout reached, but there's nothing to time out"); - - return FALSE; -} - -static void -nm_serial_device_add_timeout (NMSerialDevice *self, guint timeout) -{ - NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (self); - - if (priv->pending_id == 0) - nm_warning ("Adding a time out while not waiting for any data"); - - if (priv->timeout_id) { - nm_warning ("Trying to add a new time out while the old one still exists"); - g_source_remove (priv->timeout_id); - } - - priv->timeout_id = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, - timeout, - nm_serial_device_timed_out, - self, - nm_serial_device_timeout_removed); - if (G_UNLIKELY (priv->timeout_id == 0)) - nm_warning ("Registering serial device time out failed."); -} - -static void -nm_serial_device_remove_timeout (NMSerialDevice *self) -{ - NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (self); - - if (priv->timeout_id) - g_source_remove (priv->timeout_id); -} - -/* Pending data reading */ - -static guint -nm_serial_device_set_pending (NMSerialDevice *device, - guint timeout, - GIOFunc callback, - gpointer user_data, - GDestroyNotify notify) -{ - NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (device); - - if (G_UNLIKELY (priv->pending_id)) { - /* FIXME: Probably should queue up pending calls instead? */ - /* Multiple pending calls on the same GIOChannel doesn't work, so let's cancel the previous one. */ - nm_warning ("Adding new pending call while previous one isn't finished."); - nm_warning ("Cancelling the previous pending call."); - g_source_remove (priv->pending_id); - } - - priv->pending_id = g_io_add_watch_full (priv->channel, - G_PRIORITY_DEFAULT, - G_IO_IN | G_IO_ERR | G_IO_HUP, - callback, user_data, notify); - - nm_serial_device_add_timeout (device, timeout); - - return priv->pending_id; -} - -static void -nm_serial_device_pending_done (NMSerialDevice *self) -{ - NM_SERIAL_DEVICE_GET_PRIVATE (self)->pending_id = 0; - nm_serial_device_remove_timeout (self); -} - -/****/ - -static gboolean -config_fd (NMSerialDevice *device, NMSettingSerial *setting) -{ - NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (device); - struct termio stbuf; - int speed; - int bits; - int parity; - int stopbits; - - speed = parse_baudrate (nm_setting_serial_get_baud (setting)); - bits = parse_bits (nm_setting_serial_get_bits (setting)); - parity = parse_parity (nm_setting_serial_get_parity (setting)); - stopbits = parse_stopbits (nm_setting_serial_get_stopbits (setting)); - - ioctl (priv->fd, TCGETA, &stbuf); - - stbuf.c_iflag &= ~(IGNCR | ICRNL | IUCLC | INPCK | IXON | IXANY | IGNPAR ); - stbuf.c_oflag &= ~(OPOST | OLCUC | OCRNL | ONLCR | ONLRET); - stbuf.c_lflag &= ~(ICANON | XCASE | ECHO | ECHOE | ECHONL); - stbuf.c_lflag &= ~(ECHO | ECHOE); - stbuf.c_cc[VMIN] = 1; - stbuf.c_cc[VTIME] = 0; - stbuf.c_cc[VEOF] = 1; - - stbuf.c_cflag &= ~(CBAUD | CSIZE | CSTOPB | CLOCAL | PARENB); - stbuf.c_cflag |= (speed | bits | CREAD | 0 | parity | stopbits); - - if (ioctl (priv->fd, TCSETA, &stbuf) < 0) { - nm_warning ("(%s) cannot control device (errno %d)", - nm_device_get_iface (NM_DEVICE (device)), errno); - return FALSE; - } - - return TRUE; -} - -gboolean -nm_serial_device_open (NMSerialDevice *device, - NMSettingSerial *setting) -{ - NMSerialDevicePrivate *priv; - const char *iface; - char *path; - - g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), FALSE); - g_return_val_if_fail (NM_IS_SETTING_SERIAL (setting), FALSE); - - priv = NM_SERIAL_DEVICE_GET_PRIVATE (device); - iface = nm_device_get_iface (NM_DEVICE (device)); - - nm_debug ("(%s) opening device...", iface); - - path = g_build_filename ("/dev", iface, NULL); - priv->fd = open (path, O_RDWR | O_EXCL | O_NONBLOCK | O_NOCTTY); - g_free (path); - - if (priv->fd < 0) { - nm_warning ("(%s) cannot open device (errno %d)", iface, errno); - return FALSE; - } - - if (ioctl (priv->fd, TCGETA, &priv->old_t) < 0) { - nm_warning ("(%s) cannot control device (errno %d)", iface, errno); - close (priv->fd); - return FALSE; - } - - if (!config_fd (device, setting)) { - close (priv->fd); - return FALSE; - } - - priv->channel = g_io_channel_unix_new (priv->fd); - g_io_channel_set_encoding (priv->channel, NULL, NULL); - - return TRUE; -} - -void -nm_serial_device_close (NMSerialDevice *device) -{ - NMSerialDevicePrivate *priv; - - g_return_if_fail (NM_IS_SERIAL_DEVICE (device)); - - priv = NM_SERIAL_DEVICE_GET_PRIVATE (device); - - if (priv->pending_id) - g_source_remove (priv->pending_id); - - if (priv->ppp_manager) { - nm_ppp_manager_stop (priv->ppp_manager); - g_object_unref (priv->ppp_manager); - priv->ppp_manager = NULL; - } - - if (priv->fd) { - nm_debug ("Closing device '%s'", nm_device_get_iface (NM_DEVICE (device))); - - if (priv->channel) { - g_io_channel_unref (priv->channel); - priv->channel = NULL; - } - - ioctl (priv->fd, TCSETA, &priv->old_t); - close (priv->fd); - priv->fd = 0; - } -} - -gboolean -nm_serial_device_send_command (NMSerialDevice *device, GByteArray *command) -{ - int fd; - NMSettingSerial *setting; - int i, eagain_count = 1000; - ssize_t written; - guint32 send_delay = 0; - - g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), FALSE); - g_return_val_if_fail (command != NULL, FALSE); - - fd = NM_SERIAL_DEVICE_GET_PRIVATE (device)->fd; - setting = NM_SETTING_SERIAL (serial_device_get_setting (device, NM_TYPE_SETTING_SERIAL)); - if (setting) - send_delay = nm_setting_serial_get_send_delay (setting); - if (send_delay == 0) - send_delay = G_USEC_PER_SEC / 500; - - nm_serial_debug ("Sending:", (char *) command->data, command->len); - - for (i = 0; i < command->len && eagain_count > 0;) { - written = write (fd, command->data + i, 1); - - if (written > 0) - i += written; - else { - /* Treat written == 0 as EAGAIN to ensure we break out of the - * for() loop eventually. - */ - if ((written < 0) && (errno != EAGAIN)) { - g_warning ("Error in writing (errno %d)", errno); - return FALSE; - } - eagain_count--; - } - g_usleep (send_delay); - } - - if (eagain_count <= 0) - nm_serial_debug ("Error: too many retries sending:", (char *) command->data, command->len); - - return TRUE; -} - -gboolean -nm_serial_device_send_command_string (NMSerialDevice *device, const char *str) -{ - GByteArray *command; - gboolean ret; - - g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), FALSE); - g_return_val_if_fail (str != NULL, FALSE); - - command = g_byte_array_new (); - g_byte_array_append (command, (guint8 *) str, strlen (str)); - g_byte_array_append (command, (guint8 *) "\r", 1); - - ret = nm_serial_device_send_command (device, command); - g_byte_array_free (command, TRUE); - - return ret; -} - -static gboolean -find_terminator (const char *line, const char **terminators) -{ - int i; - - for (i = 0; terminators[i]; i++) { - if (!strncasecmp (line, terminators[i], strlen (terminators[i]))) - return TRUE; - } - return FALSE; -} - -static const char * -find_response (const char *line, const char **responses, gint *idx) -{ - int i; - - /* Don't look for a result again if we got one previously */ - for (i = 0; responses[i]; i++) { - if (strcasestr (line, responses[i])) { - *idx = i; - return line; - } - } - return NULL; -} - -#define RESPONSE_LINE_MAX 128 - -int -nm_serial_device_wait_reply_blocking (NMSerialDevice *device, - guint32 timeout_secs, - const char **needles, - const char **terminators) -{ - char buf[SERIAL_BUF_SIZE + 1]; - int fd, reply_index = -1, bytes_read; - GString *result = NULL; - time_t end; - const char *response = NULL; - gboolean done = FALSE; - - g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), -1); - g_return_val_if_fail (timeout_secs <= 60, -1); - g_return_val_if_fail (needles != NULL, -1); - - fd = NM_SERIAL_DEVICE_GET_PRIVATE (device)->fd; - if (fd < 0) - return -1; - - end = time (NULL) + timeout_secs; - result = g_string_sized_new (20); - do { - bytes_read = read (fd, buf, SERIAL_BUF_SIZE); - if (bytes_read < 0 && errno != EAGAIN) { - nm_warning ("%s: read error: %d (%s)", - nm_device_get_iface (NM_DEVICE (device)), - errno, - strerror (errno)); - return -1; - } - - if (bytes_read == 0) - break; /* EOF */ - else if (bytes_read > 0) { - buf[bytes_read] = 0; - g_string_append (result, buf); - - nm_serial_debug ("Got:", result->str, result->len); - } - - /* Look for needles and terminators */ - if ((bytes_read > 0) && result->str) { - char *p = result->str; - - /* Break the response up into lines and process each one */ - while ((p < result->str + strlen (result->str)) && !done) { - char line[RESPONSE_LINE_MAX] = { '\0', }; - char *tmp; - int i; - gboolean got_something = FALSE; - - for (i = 0; *p && (i < RESPONSE_LINE_MAX - 1); p++) { - /* Ignore front CR/LF */ - if ((*p == '\n') || (*p == '\r')) { - if (got_something) - break; - } else { - line[i++] = *p; - got_something = TRUE; - } - } - line[i] = '\0'; - - tmp = g_strstrip (line); - if (tmp && strlen (tmp)) { - done = find_terminator (tmp, terminators); - if (reply_index == -1) - response = find_response (tmp, needles, &reply_index); - } - } - } - - /* Limit the size of the buffer */ - if (result->len > SERIAL_BUF_SIZE) { - g_warning ("%s (%s): response buffer filled before repsonse received", - __func__, nm_device_get_iface (NM_DEVICE (device))); - break; - } - - if (!done) - g_usleep (100); - } while (!done && (time (NULL) < end)); - - return reply_index; -} - -typedef struct { - NMSerialDevice *device; - char **str_needles; - char **terminators; - GString *result; - NMSerialWaitForReplyFn callback; - gpointer user_data; - int reply_index; - char *reply_line; - time_t end; -} WaitForReplyInfo; - -static void -wait_for_reply_done (gpointer data) -{ - WaitForReplyInfo *info = (WaitForReplyInfo *) data; - - nm_serial_device_pending_done (info->device); - - /* Call the callback */ - info->callback (info->device, info->reply_index, info->reply_line, info->user_data); - - /* Free info */ - if (info->result) - g_string_free (info->result, TRUE); - - g_free (info->reply_line); - - g_strfreev (info->str_needles); - g_strfreev (info->terminators); - g_slice_free (WaitForReplyInfo, info); -} - -static gboolean -wait_for_reply_got_data (GIOChannel *source, - GIOCondition condition, - gpointer data) -{ - WaitForReplyInfo *info = (WaitForReplyInfo *) data; - gchar buf[SERIAL_BUF_SIZE + 1]; - gsize bytes_read; - GIOStatus status; - gboolean done = FALSE; - - if (condition & G_IO_HUP || condition & G_IO_ERR) - return FALSE; - - do { - GError *err = NULL; - - status = g_io_channel_read_chars (source, buf, SERIAL_BUF_SIZE, &bytes_read, &err); - if (status == G_IO_STATUS_ERROR) { - g_warning ("%s", err->message); - g_error_free (err); - err = NULL; - } - - if (bytes_read > 0) { - buf[bytes_read] = 0; - g_string_append (info->result, buf); - - nm_serial_debug ("Got:", info->result->str, info->result->len); - } - - /* Look for needles and terminators */ - if ((bytes_read > 0) && info->result->str) { - char *p = info->result->str; - - /* Break the response up into lines and process each one */ - while ((p < info->result->str + strlen (info->result->str)) && !done) { - char line[RESPONSE_LINE_MAX] = { '\0', }; - char *tmp; - int i; - gboolean got_something = FALSE; - - for (i = 0; *p && (i < RESPONSE_LINE_MAX - 1); p++) { - /* Ignore front CR/LF */ - if ((*p == '\n') || (*p == '\r')) { - if (got_something) - break; - } else { - line[i++] = *p; - got_something = TRUE; - } - } - line[i] = '\0'; - - tmp = g_strstrip (line); - if (tmp && strlen (tmp)) { - done = find_terminator (tmp, (const char **) info->terminators); - if (info->reply_index == -1) { - if (find_response (tmp, (const char **) info->str_needles, &(info->reply_index))) - info->reply_line = g_strdup (tmp); - } - } - } - } - - /* Limit the size of the buffer */ - if (info->result->len > SERIAL_BUF_SIZE) { - nm_warning ("(%s): response buffer filled before repsonse received", - nm_device_get_iface (NM_DEVICE (info->device))); - done = TRUE; - break; - } - - /* Make sure we don't go over the timeout, in addition to the timeout - * handler that's been scheduled. If for some reason this loop doesn't - * terminate (terminator not found, whatever) then this should make - * sure that NM doesn't spin the CPU forever. - */ - if (time (NULL) > info->end) { - done = TRUE; - break; - } else if (!done) - g_usleep (50); - } while (!done || bytes_read == SERIAL_BUF_SIZE || status == G_IO_STATUS_AGAIN); - - return !done; -} - -guint -nm_serial_device_wait_for_reply (NMSerialDevice *device, - guint timeout, - const char **responses, - const char **terminators, - NMSerialWaitForReplyFn callback, - gpointer user_data) -{ - WaitForReplyInfo *info; - - g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), 0); - g_return_val_if_fail (responses != NULL, 0); - g_return_val_if_fail (callback != NULL, 0); - - info = g_slice_new0 (WaitForReplyInfo); - info->device = device; - info->str_needles = g_strdupv ((char **) responses); - info->terminators = g_strdupv ((char **) terminators); - info->result = g_string_new (NULL); - info->callback = callback; - info->user_data = user_data; - info->reply_index = -1; - info->end = time (NULL) + timeout; - - return nm_serial_device_set_pending (device, timeout, wait_for_reply_got_data, info, wait_for_reply_done); -} - -#if 0 -typedef struct { - NMSerialDevice *device; - gboolean timed_out; - NMSerialWaitQuietFn callback; - gpointer user_data; -} WaitQuietInfo; - -static void -wait_quiet_done (gpointer data) -{ - WaitQuietInfo *info = (WaitQuietInfo *) data; - - nm_serial_device_pending_done (info->device); - - /* Call the callback */ - info->callback (info->device, info->timed_out, info->user_data); - - /* Free info */ - g_slice_free (WaitQuietInfo, info); -} - -static gboolean -wait_quiet_quiettime (gpointer data) -{ - WaitQuietInfo *info = (WaitQuietInfo *) data; - - info->timed_out = FALSE; - g_source_remove (NM_SERIAL_DEVICE_GET_PRIVATE (info->device)->pending); - - return FALSE; -} - -static gboolean -wait_quiet_got_data (GIOChannel *source, - GIOCondition condition, - gpointer data) -{ - WaitQuietInfo *info = (WaitQuietInfo *) data; - gsize bytes_read; - char buf[4096]; - GIOStatus status; - - if (condition & G_IO_HUP || condition & G_IO_ERR) - return FALSE; - - if (condition & G_IO_IN) { - do { - status = g_io_channel_read_chars (source, buf, 4096, &bytes_read, NULL); - - if (bytes_read) { - /* Reset the quiet time timeout */ - g_source_remove (info->quiet_id); - info->quiet_id = g_timeout_add (info->quiet_time, wait_quiet_quiettime, info); - } - } while (bytes_read == 4096 || status == G_IO_STATUS_AGAIN); - } - - return TRUE; -} - -void -nm_serial_device_wait_quiet (NMSerialDevice *device, - guint timeout, - guint quiet_time, - NMSerialWaitQuietFn callback, - gpointer user_data) -{ - WaitQuietInfo *info; - - g_return_if_fail (NM_IS_SERIAL_DEVICE (device)); - g_return_if_fail (callback != NULL); - - info = g_slice_new0 (WaitQuietInfo); - info->device = device; - info->timed_out = TRUE; - info->callback = callback; - info->user_data = user_data; - info->quiet_id = g_timeout_add (quiet_time, - wait_quiet_timeout, - info); - - return nm_serial_device_set_pending (device, timeout, wait_quiet_got_data, info, wait_quiet_done); -} - -#endif - -typedef struct { - NMSerialDevice *device; - speed_t current_speed; - NMSerialFlashFn callback; - gpointer user_data; -} FlashInfo; - -static speed_t -get_speed (NMSerialDevice *device) -{ - struct termios options; - - tcgetattr (NM_SERIAL_DEVICE_GET_PRIVATE (device)->fd, &options); - - return cfgetospeed (&options); -} - -static void -set_speed (NMSerialDevice *device, speed_t speed) -{ - struct termios options; - int fd; - - fd = NM_SERIAL_DEVICE_GET_PRIVATE (device)->fd; - tcgetattr (fd, &options); - - cfsetispeed (&options, speed); - cfsetospeed (&options, speed); - - options.c_cflag |= (CLOCAL | CREAD); - tcsetattr (fd, TCSANOW, &options); -} - -static void -flash_done (gpointer data) -{ - FlashInfo *info = (FlashInfo *) data; - - NM_SERIAL_DEVICE_GET_PRIVATE (info->device)->pending_id = 0; - - info->callback (info->device, info->user_data); - - g_slice_free (FlashInfo, info); -} - -static gboolean -flash_do (gpointer data) -{ - FlashInfo *info = (FlashInfo *) data; - - set_speed (info->device, info->current_speed); - - return FALSE; -} - -guint -nm_serial_device_flash (NMSerialDevice *device, - guint32 flash_time, - NMSerialFlashFn callback, - gpointer user_data) -{ - FlashInfo *info; - guint id; - - g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), 0); - g_return_val_if_fail (callback != NULL, 0); - - info = g_slice_new0 (FlashInfo); - info->device = device; - info->current_speed = get_speed (device); - info->callback = callback; - info->user_data = user_data; - - set_speed (device, B0); - - id = g_timeout_add_full (G_PRIORITY_DEFAULT, - flash_time, - flash_do, - info, - flash_done); - - NM_SERIAL_DEVICE_GET_PRIVATE (device)->pending_id = id; - - return id; -} - -GIOChannel * -nm_serial_device_get_io_channel (NMSerialDevice *device) -{ - NMSerialDevicePrivate *priv; - - g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), 0); - - priv = NM_SERIAL_DEVICE_GET_PRIVATE (device); - if (priv->channel) - return g_io_channel_ref (priv->channel); - - return NULL; -} - -NMPPPManager * -nm_serial_device_get_ppp_manager (NMSerialDevice *device) -{ - g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), NULL); - - return NM_SERIAL_DEVICE_GET_PRIVATE (device)->ppp_manager; -} - -static void -ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data) -{ - NMDevice *device = NM_DEVICE (user_data); - - switch (status) { - case NM_PPP_STATUS_NETWORK: - nm_device_state_changed (device, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_NONE); - break; - case NM_PPP_STATUS_DISCONNECT: - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_DISCONNECT); - break; - case NM_PPP_STATUS_DEAD: - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_FAILED); - break; - case NM_PPP_STATUS_AUTHENTICATE: - nm_device_state_changed (device, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); - break; - default: - break; - } -} - -static void -ppp_ip4_config (NMPPPManager *ppp_manager, - const char *iface, - NMIP4Config *config, - gpointer user_data) -{ - NMDevice *device = NM_DEVICE (user_data); - - nm_device_set_ip_iface (device, iface); - NM_SERIAL_DEVICE_GET_PRIVATE (device)->pending_ip4_config = g_object_ref (config); - nm_device_activate_schedule_stage4_ip_config_get (device); -} - -static void -ppp_stats (NMPPPManager *ppp_manager, - guint32 in_bytes, - guint32 out_bytes, - gpointer user_data) -{ - NMSerialDevice *device = NM_SERIAL_DEVICE (user_data); - NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (device); - - if (priv->in_bytes != in_bytes || priv->out_bytes != out_bytes) { - priv->in_bytes = in_bytes; - priv->out_bytes = out_bytes; - - g_signal_emit (device, signals[PPP_STATS], 0, in_bytes, out_bytes); - } -} - -static NMActStageReturn -real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) -{ - NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (device); - NMSerialDeviceClass *serial_class = NM_SERIAL_DEVICE_GET_CLASS (device); - NMActRequest *req; - GError *err = NULL; - NMActStageReturn ret; - const char *ppp_name = NULL; - - req = nm_device_get_act_request (device); - g_assert (req); - - if (serial_class->get_ppp_name) - ppp_name = serial_class->get_ppp_name (NM_SERIAL_DEVICE (device), req); - - priv->ppp_manager = nm_ppp_manager_new (nm_device_get_iface (device)); - if (nm_ppp_manager_start (priv->ppp_manager, req, ppp_name, &err)) { - g_signal_connect (priv->ppp_manager, "state-changed", - G_CALLBACK (ppp_state_changed), - device); - g_signal_connect (priv->ppp_manager, "ip4-config", - G_CALLBACK (ppp_ip4_config), - device); - g_signal_connect (priv->ppp_manager, "stats", - G_CALLBACK (ppp_stats), - device); - - ret = NM_ACT_STAGE_RETURN_POSTPONE; - } else { - nm_warning ("%s", err->message); - g_error_free (err); - - g_object_unref (priv->ppp_manager); - priv->ppp_manager = NULL; - - *reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED; - ret = NM_ACT_STAGE_RETURN_FAILURE; - } - - return ret; -} - -static NMActStageReturn -real_act_stage4_get_ip4_config (NMDevice *device, - NMIP4Config **config, - NMDeviceStateReason *reason) -{ - NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (device); - NMConnection *connection; - NMSettingIP4Config *s_ip4; - - g_return_val_if_fail (config != NULL, NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (*config == NULL, NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - connection = nm_act_request_get_connection (nm_device_get_act_request (device)); - g_assert (connection); - - s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG); - - *config = priv->pending_ip4_config; - priv->pending_ip4_config = NULL; - nm_utils_merge_ip4_config (*config, s_ip4); - - return NM_ACT_STAGE_RETURN_SUCCESS; -} - -static void -cleanup_device (NMSerialDevice *device) -{ - NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (device); - - nm_device_set_ip_iface (NM_DEVICE (device), NULL); - - if (priv->pending_ip4_config) { - g_object_unref (priv->pending_ip4_config); - priv->pending_ip4_config = NULL; - } - - priv->in_bytes = priv->out_bytes = 0; -} - -static void -real_deactivate_quickly (NMDevice *device) -{ - NMSerialDevice *self = NM_SERIAL_DEVICE (device); - - cleanup_device (self); - nm_serial_device_close (self); -} - -static guint32 -real_get_generic_capabilities (NMDevice *dev) -{ - return NM_DEVICE_CAP_NM_SUPPORTED; -} - -/*****************************************************************************/ - -static void -nm_serial_device_init (NMSerialDevice *self) -{ - if (getenv ("NM_SERIAL_DEBUG")) - serial_debug = TRUE; -} - -static void -finalize (GObject *object) -{ - NMSerialDevice *self = NM_SERIAL_DEVICE (object); - - cleanup_device (self); - nm_serial_device_close (self); - - G_OBJECT_CLASS (nm_serial_device_parent_class)->finalize (object); -} - -static void -nm_serial_device_class_init (NMSerialDeviceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMSerialDevicePrivate)); - - /* Virtual methods */ - object_class->finalize = finalize; - - parent_class->get_generic_capabilities = real_get_generic_capabilities; - parent_class->act_stage2_config = real_act_stage2_config; - parent_class->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config; - parent_class->deactivate_quickly = real_deactivate_quickly; - - /* Signals */ - signals[PPP_STATS] = - g_signal_new ("ppp-stats", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMSerialDeviceClass, ppp_stats), - NULL, NULL, - _nm_marshal_VOID__UINT_UINT, - G_TYPE_NONE, 2, - G_TYPE_UINT, G_TYPE_UINT); - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_serial_device_object_info); -} Index: src/ppp-manager/nm-pppd-plugin.xml =================================================================== --- /dev/null +++ src/ppp-manager/nm-pppd-plugin.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<node name="/"> + <interface name="org.freedesktop.NetworkManager.PPP"> + <signal name="StateChanged"> + <arg name="state" type="u"/> + </signal> + + <signal name="Ip4Config"> + <arg name="ip4config" type="a{sv}"/> + </signal> + + </interface> +</node> Index: src/ppp-manager/nm-ppp-manager.c =================================================================== --- src/ppp-manager/nm-ppp-manager.c.orig +++ src/ppp-manager/nm-ppp-manager.c @@ -66,7 +66,7 @@ static gboolean impl_ppp_manager_set_ip4 #include "nm-ppp-manager-glue.h" #define NM_PPPD_PLUGIN PLUGINDIR "/nm-pppd-plugin.so" -#define NM_PPP_WAIT_PPPD 15 /* 15 seconds */ +#define NM_PPP_WAIT_PPPD 20 /* seconds */ #define PPP_MANAGER_SECRET_TRIES "ppp-manager-secret-tries" typedef struct { Index: src/supplicant-manager/gnome-keyring-md5.c =================================================================== --- /dev/null +++ src/supplicant-manager/gnome-keyring-md5.c @@ -0,0 +1,291 @@ +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * GnomeKeyringMD5Context structure, pass it to gnome_keyring_md5_init, call + * gnome_keyring_md5_update as needed on buffers full of bytes, and then call + * gnome_keyring_md5_final, which will fill a supplied 32-byte array with the + * digest in ascii form. + * + */ + +#include "gnome-keyring-md5.h" +#include <string.h> + +static void gnome_keyring_md5_transform (guint32 buf[4], + guint32 const in[16]); + +void +gnome_keyring_md5_string (const char *string, unsigned char digest[16]) +{ + struct GnomeKeyringMD5Context md5_context; + + gnome_keyring_md5_init (&md5_context); + gnome_keyring_md5_update (&md5_context, (const unsigned char *)string, strlen (string)); + gnome_keyring_md5_final (digest, &md5_context); +} + +#if G_BYTE_ORDER == G_LITTLE_ENDIAN +#define byteReverse(buf, len) /* Nothing */ +#else + +/* + * Note: this code is harmless on little-endian machines. + */ +static void +byteReverse(unsigned char *buf, unsigned longs) +{ + guint32 t; + do { + t = (guint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(guint32 *) buf = t; + buf += 4; + } while (--longs); +} + +#endif + +char * +gnome_keyring_md5_digest_to_ascii (unsigned char digest[16]) +{ + static char hex_digits[] = "0123456789abcdef"; + char *res; + int i; + + res = g_malloc (33); + + for (i = 0; i < 16; i++) { + res[2*i] = hex_digits[digest[i] >> 4]; + res[2*i+1] = hex_digits[digest[i] & 0xf]; + } + + res[32] = 0; + + return res; +} + + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void +gnome_keyring_md5_init (struct GnomeKeyringMD5Context *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +void +gnome_keyring_md5_update (struct GnomeKeyringMD5Context *ctx, + unsigned char const *buf, + unsigned len) +{ + guint32 t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((guint32) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + memcpy (p, buf, len); + return; + } + memcpy (p, buf, t); + byteReverse (ctx->in, 16); + gnome_keyring_md5_transform (ctx->buf, (guint32 *) ctx->in); + buf += t; + len -= t; + } + + /* Process data in 64-byte chunks */ + + while (len >= 64) { + memcpy (ctx->in, buf, 64); + byteReverse (ctx->in, 16); + gnome_keyring_md5_transform (ctx->buf, (guint32 *) ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + memcpy(ctx->in, buf, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void +gnome_keyring_md5_final (unsigned char digest[16], struct GnomeKeyringMD5Context *ctx) +{ + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset (p, 0, count); + byteReverse (ctx->in, 16); + gnome_keyring_md5_transform (ctx->buf, (guint32 *) ctx->in); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } else { + /* Pad block to 56 bytes */ + memset(p, 0, count - 8); + } + byteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + ((guint32 *) ctx->in)[14] = ctx->bits[0]; + ((guint32 *) ctx->in)[15] = ctx->bits[1]; + + gnome_keyring_md5_transform (ctx->buf, (guint32 *) ctx->in); + byteReverse ((unsigned char *) ctx->buf, 4); + memcpy (digest, ctx->buf, 16); + memset (ctx, 0, sizeof(ctx)); /* In case it's sensitive */ +} + + +/* The four core functions - F1 is optimized somewhat */ + +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1 (z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define gnome_keyring_md5_step(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. GnomeKeyringMD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +static void +gnome_keyring_md5_transform (guint32 buf[4], guint32 const in[16]) +{ + register guint32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + gnome_keyring_md5_step(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + gnome_keyring_md5_step(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + gnome_keyring_md5_step(F1, c, d, a, b, in[2] + 0x242070db, 17); + gnome_keyring_md5_step(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + gnome_keyring_md5_step(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + gnome_keyring_md5_step(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + gnome_keyring_md5_step(F1, c, d, a, b, in[6] + 0xa8304613, 17); + gnome_keyring_md5_step(F1, b, c, d, a, in[7] + 0xfd469501, 22); + gnome_keyring_md5_step(F1, a, b, c, d, in[8] + 0x698098d8, 7); + gnome_keyring_md5_step(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + gnome_keyring_md5_step(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + gnome_keyring_md5_step(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + gnome_keyring_md5_step(F1, a, b, c, d, in[12] + 0x6b901122, 7); + gnome_keyring_md5_step(F1, d, a, b, c, in[13] + 0xfd987193, 12); + gnome_keyring_md5_step(F1, c, d, a, b, in[14] + 0xa679438e, 17); + gnome_keyring_md5_step(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + gnome_keyring_md5_step(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + gnome_keyring_md5_step(F2, d, a, b, c, in[6] + 0xc040b340, 9); + gnome_keyring_md5_step(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + gnome_keyring_md5_step(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + gnome_keyring_md5_step(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + gnome_keyring_md5_step(F2, d, a, b, c, in[10] + 0x02441453, 9); + gnome_keyring_md5_step(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + gnome_keyring_md5_step(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + gnome_keyring_md5_step(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + gnome_keyring_md5_step(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + gnome_keyring_md5_step(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + gnome_keyring_md5_step(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + gnome_keyring_md5_step(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + gnome_keyring_md5_step(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + gnome_keyring_md5_step(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + gnome_keyring_md5_step(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + gnome_keyring_md5_step(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + gnome_keyring_md5_step(F3, d, a, b, c, in[8] + 0x8771f681, 11); + gnome_keyring_md5_step(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + gnome_keyring_md5_step(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + gnome_keyring_md5_step(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + gnome_keyring_md5_step(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + gnome_keyring_md5_step(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + gnome_keyring_md5_step(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + gnome_keyring_md5_step(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + gnome_keyring_md5_step(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + gnome_keyring_md5_step(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + gnome_keyring_md5_step(F3, b, c, d, a, in[6] + 0x04881d05, 23); + gnome_keyring_md5_step(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + gnome_keyring_md5_step(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + gnome_keyring_md5_step(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + gnome_keyring_md5_step(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + gnome_keyring_md5_step(F4, a, b, c, d, in[0] + 0xf4292244, 6); + gnome_keyring_md5_step(F4, d, a, b, c, in[7] + 0x432aff97, 10); + gnome_keyring_md5_step(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + gnome_keyring_md5_step(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + gnome_keyring_md5_step(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + gnome_keyring_md5_step(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + gnome_keyring_md5_step(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + gnome_keyring_md5_step(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + gnome_keyring_md5_step(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + gnome_keyring_md5_step(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + gnome_keyring_md5_step(F4, c, d, a, b, in[6] + 0xa3014314, 15); + gnome_keyring_md5_step(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + gnome_keyring_md5_step(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + gnome_keyring_md5_step(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + gnome_keyring_md5_step(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + gnome_keyring_md5_step(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + Index: src/supplicant-manager/gnome-keyring-md5.h =================================================================== --- /dev/null +++ src/supplicant-manager/gnome-keyring-md5.h @@ -0,0 +1,41 @@ +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * GnomeKeyringMD5Context structure, pass it to gnome_keyring_md5_init, call + * gnome_keyring_md5_update as needed on buffers full of bytes, and then call + * gnome_keyring_md5_final, which will fill a supplied 32-byte array with the + * digest in ascii form. + * + */ + +#ifndef GNOME_KEYRING_MD5_H +#define GNOME_KEYRING_MD5_H + +#include <glib.h> + +struct GnomeKeyringMD5Context { + guint32 buf[4]; + guint32 bits[2]; + unsigned char in[64]; +}; + +char *gnome_keyring_md5_digest_to_ascii (unsigned char digest[16]); +void gnome_keyring_md5_string (const char *string, + unsigned char digest[16]); +void gnome_keyring_md5_init (struct GnomeKeyringMD5Context *ctx); +void gnome_keyring_md5_update (struct GnomeKeyringMD5Context *ctx, + unsigned char const *buf, + unsigned len); +void gnome_keyring_md5_final (unsigned char digest[16], + struct GnomeKeyringMD5Context *ctx); + +#endif /* GNOME_KEYRING_MD5_H */ Index: src/supplicant-manager/Makefile.am =================================================================== --- src/supplicant-manager/Makefile.am.orig +++ src/supplicant-manager/Makefile.am @@ -1,3 +1,5 @@ +SUBDIRS=. tests + INCLUDES = \ -I${top_srcdir}/src \ -I${top_srcdir}/include \ @@ -16,15 +18,16 @@ libsupplicant_manager_la_SOURCES = \ nm-supplicant-interface.c \ nm-supplicant-interface.h \ nm-supplicant-settings-verify.h \ - nm-supplicant-settings-verify.c + nm-supplicant-settings-verify.c \ + gnome-keyring-md5.h \ + gnome-keyring-md5.c libsupplicant_manager_la_CPPFLAGS = \ $(DBUS_CFLAGS) \ $(GLIB_CFLAGS) \ $(HAL_CFLAGS) \ -DNM_PKGDATADIR=\"$(pkgdatadir)\" \ - -DNM_LOCALSTATEDIR=\"$(localstatedir)\" \ - -DDBUS_API_SUBJECT_TO_CHANGE + -DNM_LOCALSTATEDIR=\"$(localstatedir)\" libsupplicant_manager_la_LIBADD = \ $(DBUS_LIBS) \ Index: src/supplicant-manager/nm-supplicant-config.c =================================================================== --- src/supplicant-manager/nm-supplicant-config.c.orig +++ src/supplicant-manager/nm-supplicant-config.c @@ -35,6 +35,10 @@ #include "nm-setting.h" #include "NetworkManagerUtils.h" +#include "gnome-keyring-md5.h" + +static char *hexstr2bin (const char *hex, size_t len); + #define NM_SUPPLICANT_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ NM_TYPE_SUPPLICANT_CONFIG, \ NMSupplicantConfigPrivate)) @@ -44,7 +48,7 @@ G_DEFINE_TYPE (NMSupplicantConfig, nm_su typedef struct { char *value; guint32 len; - enum OptType type; + OptType type; } ConfigOption; typedef struct @@ -80,8 +84,8 @@ nm_supplicant_config_init (NMSupplicantC NMSupplicantConfigPrivate *priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE (self); priv->config = g_hash_table_new_full (g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) config_option_free); + (GDestroyNotify) g_free, + (GDestroyNotify) config_option_free); priv->blobs = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, @@ -91,12 +95,13 @@ nm_supplicant_config_init (NMSupplicantC priv->dispose_has_run = FALSE; } -gboolean -nm_supplicant_config_add_option (NMSupplicantConfig *self, - const char * key, - const char * value, - gint32 len, - gboolean secret) +static gboolean +nm_supplicant_config_add_option_with_type (NMSupplicantConfig *self, + const char *key, + const char *value, + gint32 len, + OptType opt_type, + gboolean secret) { NMSupplicantConfigPrivate *priv; ConfigOption *old_opt; @@ -112,13 +117,17 @@ nm_supplicant_config_add_option (NMSuppl if (len < 0) len = strlen (value); - type = nm_supplicant_settings_verify_setting (key, value, len); - if (type == TYPE_INVALID) { - char buf[255]; - memset (&buf[0], 0, sizeof (buf)); - memcpy (&buf[0], value, len > 254 ? 254 : len); - nm_debug ("Key '%s' and/or value '%s' invalid.", key, buf); - return FALSE; + if (opt_type != TYPE_INVALID) + type = opt_type; + else { + type = nm_supplicant_settings_verify_setting (key, value, len); + if (type == TYPE_INVALID) { + char buf[255]; + memset (&buf[0], 0, sizeof (buf)); + memcpy (&buf[0], value, len > 254 ? 254 : len); + nm_debug ("Key '%s' and/or value '%s' invalid.", key, buf); + return FALSE; + } } old_opt = (ConfigOption *) g_hash_table_lookup (priv->config, key); @@ -155,6 +164,15 @@ nm_info ("Config: added '%s' value '%s'" return TRUE; } +static gboolean +nm_supplicant_config_add_option (NMSupplicantConfig *self, + const char *key, + const char *value, + gint32 len, + gboolean secret) +{ + return nm_supplicant_config_add_option_with_type (self, key, value, len, TYPE_INVALID, secret); +} static gboolean nm_supplicant_config_add_blob (NMSupplicantConfig *self, @@ -283,6 +301,7 @@ get_hash_cb (gpointer key, gpointer valu g_byte_array_free (array, TRUE); break; case TYPE_KEYWORD: + case TYPE_STRING: g_value_init (variant, G_TYPE_STRING); g_value_set_string (variant, opt->value); break; @@ -306,17 +325,17 @@ destroy_hash_value (gpointer data) GHashTable * nm_supplicant_config_get_hash (NMSupplicantConfig * self) { + NMSupplicantConfigPrivate *priv; GHashTable *hash; g_return_val_if_fail (NM_IS_SUPPLICANT_CONFIG (self), NULL); hash = g_hash_table_new_full (g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - destroy_hash_value); - - g_hash_table_foreach (NM_SUPPLICANT_CONFIG_GET_PRIVATE (self)->config, - get_hash_cb, hash); + (GDestroyNotify) g_free, + destroy_hash_value); + priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE (self); + g_hash_table_foreach (priv->config, get_hash_cb, hash); return hash; } @@ -412,23 +431,26 @@ nm_supplicant_config_add_setting_wireles return TRUE; } -#define ADD_STRING_VAL(field, name, ucase, unhexify, secret) \ - if (field) { \ - int len = -1; \ - if (ucase) \ - value = g_ascii_strup (field, -1); \ - else if (unhexify) { \ - value = nm_utils_hexstr2bin (field, strlen (field)); \ - len = strlen (field) / 2; \ - } else \ - value = g_strdup (field); \ - success = nm_supplicant_config_add_option (self, name, value, len, secret); \ - g_free (value); \ - if (!success) { \ - nm_warning ("Error adding %s to supplicant config.", name); \ - return FALSE; \ - } \ - } +static gboolean +add_string_val (NMSupplicantConfig *self, + const char *field, + const char *name, + gboolean ucase, + gboolean secret) +{ + gboolean success; + char *value; + + if (!field) + return TRUE; + + value = ucase ? g_ascii_strup (field, -1) : g_strdup (field); + success = nm_supplicant_config_add_option (self, name, value, strlen (field), secret); + if (!success) + nm_warning ("Error adding %s to supplicant config.", name); + g_free (value); + return success; +} #define ADD_STRING_LIST_VAL(setting, setting_name, field, field_plural, name, ucase, secret) \ if (nm_setting_##setting_name##_get_num_##field_plural (setting)) { \ @@ -444,7 +466,7 @@ nm_supplicant_config_add_setting_wireles } \ } \ if (ucase) \ - g_string_ascii_up (str); \ + g_string_ascii_up (str); \ if (str->len) \ success = nm_supplicant_config_add_option (self, name, str->str, -1, secret); \ else \ @@ -479,6 +501,75 @@ get_blob_id (const char *name, const cha } \ } + +static unsigned char * +wep128_passphrase_hash (const char *input, size_t input_len, size_t *out_len) +{ + char md5_data[65]; + unsigned char *digest; + int i; + + *out_len = 16; + digest = g_malloc0 (*out_len); + + /* Get at least 64 bytes */ + for (i = 0; i < 64; i++) + md5_data[i] = input[i % input_len]; + + /* Null terminate md5 seed data and hash it */ + md5_data[64] = 0; + gnome_keyring_md5_string (md5_data, digest); + return digest; +} + +static gboolean +add_wep_key (NMSupplicantConfig *self, + const char *key, + const char *name, + NMWepKeyType wep_type) +{ + char *value; + gboolean success; + size_t key_len = key ? strlen (key) : 0; + + if (!key || !key_len) + return TRUE; + + if ( (wep_type == NM_WEP_KEY_TYPE_UNKNOWN) + || (wep_type == NM_WEP_KEY_TYPE_KEY)) { + if ((key_len == 10) || (key_len == 26)) { + value = hexstr2bin (key, strlen (key)); + success = nm_supplicant_config_add_option (self, name, value, key_len / 2, TRUE); + g_free (value); + if (!success) { + nm_warning ("Error adding %s to supplicant config.", name); + return FALSE; + } + } else if ((key_len == 5) || (key_len == 13)) { + if (!nm_supplicant_config_add_option (self, name, key, key_len, TRUE)) { + nm_warning ("Error adding %s to supplicant config.", name); + return FALSE; + } + } else { + nm_warning ("Invalid WEP key '%s'", name); + return FALSE; + } + } else if (wep_type == NM_WEP_KEY_TYPE_PASSPHRASE) { + char *digest; + size_t digest_len; + + digest = (char *) wep128_passphrase_hash (key, key_len, &digest_len); + success = nm_supplicant_config_add_option (self, name, digest, 13, TRUE); + g_free (digest); + if (!success) { + nm_warning ("Error adding %s to supplicant config.", name); + return FALSE; + } + } + + return TRUE; +} + gboolean nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self, NMSettingWirelessSecurity *setting, @@ -489,6 +580,7 @@ nm_supplicant_config_add_setting_wireles char *value; gboolean success; const char *key_mgmt, *auth_alg; + const char *psk; g_return_val_if_fail (NM_IS_SUPPLICANT_CONFIG (self), FALSE); g_return_val_if_fail (setting != NULL, FALSE); @@ -497,12 +589,42 @@ nm_supplicant_config_add_setting_wireles priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE (self); key_mgmt = nm_setting_wireless_security_get_key_mgmt (setting); - ADD_STRING_VAL (key_mgmt, "key_mgmt", TRUE, FALSE, FALSE); + if (!add_string_val (self, key_mgmt, "key_mgmt", TRUE, FALSE)) + return FALSE; auth_alg = nm_setting_wireless_security_get_auth_alg (setting); - ADD_STRING_VAL (auth_alg, "auth_alg", TRUE, FALSE, FALSE); + if (!add_string_val (self, auth_alg, "auth_alg", TRUE, FALSE)) + return FALSE; - ADD_STRING_VAL (nm_setting_wireless_security_get_psk (setting), "psk", FALSE, TRUE, TRUE); + psk = nm_setting_wireless_security_get_psk (setting); + if (psk) { + size_t psk_len = strlen (psk); + + if (psk_len == 64) { + /* Hex PSK */ + value = hexstr2bin (psk, psk_len); + success = nm_supplicant_config_add_option (self, "psk", value, psk_len / 2, TRUE); + g_free (value); + if (!success) { + nm_warning ("Error adding 'psk' to supplicant config."); + return FALSE; + } + } else if (psk_len >= 8 && psk_len <= 63) { + /* Use TYPE_STRING here so that it gets pushed to the + * supplicant as a string, and therefore gets quoted, + * and therefore the supplicant will interpret it as a + * passphrase and not a hex key. + */ + if (!nm_supplicant_config_add_option_with_type (self, "psk", psk, -1, TYPE_STRING, TRUE)) { + nm_warning ("Error adding 'psk' to supplicant config."); + return FALSE; + } + } else { + /* Invalid PSK */ + nm_warning ("Invalid PSK length %u: not between 8 and 63 characters inclusive.", (guint32) psk_len); + return FALSE; + } + } /* Only WPA-specific things when using WPA */ if ( !strcmp (key_mgmt, "wpa-none") @@ -515,15 +637,20 @@ nm_supplicant_config_add_setting_wireles /* WEP keys if required */ if (!strcmp (key_mgmt, "none")) { + NMWepKeyType wep_type = nm_setting_wireless_security_get_wep_key_type (setting); const char *wep0 = nm_setting_wireless_security_get_wep_key (setting, 0); const char *wep1 = nm_setting_wireless_security_get_wep_key (setting, 1); const char *wep2 = nm_setting_wireless_security_get_wep_key (setting, 2); const char *wep3 = nm_setting_wireless_security_get_wep_key (setting, 3); - ADD_STRING_VAL (wep0, "wep_key0", FALSE, TRUE, TRUE); - ADD_STRING_VAL (wep1, "wep_key1", FALSE, TRUE, TRUE); - ADD_STRING_VAL (wep2, "wep_key2", FALSE, TRUE, TRUE); - ADD_STRING_VAL (wep3, "wep_key3", FALSE, TRUE, TRUE); + if (!add_wep_key (self, wep0, "wep_key0", wep_type)) + return FALSE; + if (!add_wep_key (self, wep1, "wep_key1", wep_type)) + return FALSE; + if (!add_wep_key (self, wep2, "wep_key2", wep_type)) + return FALSE; + if (!add_wep_key (self, wep3, "wep_key3", wep_type)) + return FALSE; if (wep0 || wep1 || wep2 || wep3) { value = g_strdup_printf ("%d", nm_setting_wireless_security_get_wep_tx_keyidx (setting)); @@ -539,9 +666,18 @@ nm_supplicant_config_add_setting_wireles if (auth_alg && !strcmp (auth_alg, "leap")) { /* LEAP */ if (!strcmp (key_mgmt, "ieee8021x")) { - ADD_STRING_VAL (nm_setting_wireless_security_get_leap_username (setting), "identity", FALSE, FALSE, FALSE); - ADD_STRING_VAL (nm_setting_wireless_security_get_leap_password (setting), "password", FALSE, FALSE, TRUE); - ADD_STRING_VAL ("leap", "eap", TRUE, FALSE, FALSE); + const char *tmp; + + tmp = nm_setting_wireless_security_get_leap_username (setting); + if (!add_string_val (self, tmp, "identity", FALSE, FALSE)) + return FALSE; + + tmp = nm_setting_wireless_security_get_leap_password (setting); + if (!add_string_val (self, tmp, "password", FALSE, TRUE)) + return FALSE; + + if (!add_string_val (self, "leap", "eap", TRUE, FALSE)) + return FALSE; } else { return FALSE; } @@ -565,8 +701,8 @@ nm_supplicant_config_add_setting_8021x ( gboolean wired) { NMSupplicantConfigPrivate *priv; - char *value, *tmp; - const char *peapver; + char *tmp; + const char *peapver, *value; gboolean success; GString *phase1, *phase2; const GByteArray *array; @@ -577,13 +713,19 @@ nm_supplicant_config_add_setting_8021x ( priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE (self); - ADD_STRING_VAL (nm_setting_802_1x_get_password (setting), "password", FALSE, FALSE, TRUE); - ADD_STRING_VAL (nm_setting_802_1x_get_pin (setting), "pin", FALSE, FALSE, TRUE); + value = nm_setting_802_1x_get_password (setting); + if (!add_string_val (self, value, "password", FALSE, TRUE)) + return FALSE; + value = nm_setting_802_1x_get_pin (setting); + if (!add_string_val (self, value, "pin", FALSE, TRUE)) + return FALSE; if (wired) { - ADD_STRING_VAL ("IEEE8021X", "key_mgmt", TRUE, FALSE, FALSE); + if (!add_string_val (self, "IEEE8021X", "key_mgmt", FALSE, FALSE)) + return FALSE; /* Wired 802.1x must always use eapol_flags=0 */ - ADD_STRING_VAL ("0", "eapol_flags", FALSE, FALSE, FALSE); + if (!add_string_val (self, "0", "eapol_flags", FALSE, FALSE)) + return FALSE; } ADD_STRING_LIST_VAL (setting, 802_1x, eap_method, eap_methods, "eap", TRUE, FALSE); @@ -607,8 +749,12 @@ nm_supplicant_config_add_setting_8021x ( g_string_append_printf (phase1, "peaplabel=%s", nm_setting_802_1x_get_phase1_peaplabel (setting)); } - if (phase1->len) - ADD_STRING_VAL (phase1->str, "phase1", FALSE, FALSE, FALSE); + if (phase1->len) { + if (!add_string_val (self, phase1->str, "phase1", FALSE, FALSE)) { + g_string_free (phase1, TRUE); + return FALSE; + } + } g_string_free (phase1, TRUE); phase2 = g_string_new (NULL); @@ -626,12 +772,17 @@ nm_supplicant_config_add_setting_8021x ( g_free (tmp); } - if (phase2->len) - ADD_STRING_VAL (phase2->str, "phase2", FALSE, FALSE, FALSE); + if (phase2->len) { + if (!add_string_val (self, phase2->str, "phase2", FALSE, FALSE)) { + g_string_free (phase2, TRUE); + return FALSE; + } + } g_string_free (phase2, TRUE); if (nm_setting_802_1x_get_system_ca_certs (setting)) { - ADD_STRING_VAL (SYSTEM_CA_PATH, "ca_path", FALSE, FALSE, FALSE); + if (!add_string_val (self, SYSTEM_CA_PATH, "ca_path", FALSE, FALSE)) + return FALSE; } else { ADD_BLOB_VAL (nm_setting_802_1x_get_ca_cert (setting), "ca_cert", connection_uid); } @@ -643,7 +794,9 @@ nm_supplicant_config_add_setting_8021x ( switch (nm_setting_802_1x_get_private_key_type (setting)) { case NM_SETTING_802_1X_CK_TYPE_PKCS12: /* Only add the private key password for PKCS#12 keys */ - ADD_STRING_VAL (nm_setting_802_1x_get_private_key_password (setting), "private_key_passwd", FALSE, FALSE, TRUE); + value = nm_setting_802_1x_get_private_key_password (setting); + if (!add_string_val (self, value, "private_key_passwd", FALSE, TRUE)) + return FALSE; break; default: /* Only add the client cert if the private key is not PKCS#12 */ @@ -653,7 +806,8 @@ nm_supplicant_config_add_setting_8021x ( } if (nm_setting_802_1x_get_system_ca_certs (setting)) { - ADD_STRING_VAL (SYSTEM_CA_PATH, "ca_path2", FALSE, FALSE, FALSE); + if (!add_string_val (self, SYSTEM_CA_PATH, "ca_path2", FALSE, FALSE)) + return FALSE; } else { ADD_BLOB_VAL (nm_setting_802_1x_get_phase2_ca_cert (setting), "ca_cert2", connection_uid); } @@ -665,7 +819,9 @@ nm_supplicant_config_add_setting_8021x ( switch (nm_setting_802_1x_get_phase2_private_key_type (setting)) { case NM_SETTING_802_1X_CK_TYPE_PKCS12: /* Only add the private key password for PKCS#12 keys */ - ADD_STRING_VAL (nm_setting_802_1x_get_phase2_private_key_password (setting), "private_key2_passwd", FALSE, FALSE, TRUE); + value = nm_setting_802_1x_get_phase2_private_key_password (setting); + if (!add_string_val (self, value, "private_key2_passwd", FALSE, TRUE)) + return FALSE; break; default: /* Only add the client cert if the private key is not PKCS#12 */ @@ -674,9 +830,72 @@ nm_supplicant_config_add_setting_8021x ( } } - ADD_STRING_VAL (nm_setting_802_1x_get_identity (setting), "identity", FALSE, FALSE, FALSE); - ADD_STRING_VAL (nm_setting_802_1x_get_anonymous_identity (setting), "anonymous_identity", FALSE, FALSE, FALSE); + value = nm_setting_802_1x_get_identity (setting); + if (!add_string_val (self, value, "identity", FALSE, FALSE)) + return FALSE; + value = nm_setting_802_1x_get_anonymous_identity (setting); + if (!add_string_val (self, value, "anonymous_identity", FALSE, FALSE)) + return FALSE; return TRUE; } +gboolean +nm_supplicant_config_add_no_security (NMSupplicantConfig *self) +{ + return nm_supplicant_config_add_option (self, "key_mgmt", "NONE", -1, FALSE); +} + +/* From hostap, Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi> */ + +static int hex2num (char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return -1; +} + +static int hex2byte (const char *hex) +{ + int a, b; + a = hex2num(*hex++); + if (a < 0) + return -1; + b = hex2num(*hex++); + if (b < 0) + return -1; + return (a << 4) | b; +} + +static char * +hexstr2bin (const char *hex, size_t len) +{ + size_t i; + int a; + const char * ipos = hex; + char * buf = NULL; + char * opos; + + /* Length must be a multiple of 2 */ + if ((len % 2) != 0) + return NULL; + + opos = buf = g_malloc0 ((len / 2) + 1); + for (i = 0; i < len; i += 2) { + a = hex2byte (ipos); + if (a < 0) { + g_free (buf); + return NULL; + } + *opos++ = a; + ipos += 2; + } + return buf; +} + +/* End from hostap */ + Index: src/supplicant-manager/nm-supplicant-config.h =================================================================== --- src/supplicant-manager/nm-supplicant-config.h.orig +++ src/supplicant-manager/nm-supplicant-config.h @@ -50,25 +50,19 @@ typedef struct GType nm_supplicant_config_get_type (void); -NMSupplicantConfig * nm_supplicant_config_new (void); +NMSupplicantConfig *nm_supplicant_config_new (void); -guint32 nm_supplicant_config_get_ap_scan (NMSupplicantConfig * self); +guint32 nm_supplicant_config_get_ap_scan (NMSupplicantConfig *self); -void nm_supplicant_config_set_ap_scan (NMSupplicantConfig * self, +void nm_supplicant_config_set_ap_scan (NMSupplicantConfig *self, guint32 ap_scan); -gboolean nm_supplicant_config_add_option (NMSupplicantConfig *self, - const char * key, - const char * value, - gint32 len, - gboolean secret); +GHashTable *nm_supplicant_config_get_hash (NMSupplicantConfig *self); -GHashTable *nm_supplicant_config_get_hash (NMSupplicantConfig * self); +GHashTable *nm_supplicant_config_get_blobs (NMSupplicantConfig *self); -GHashTable *nm_supplicant_config_get_blobs (NMSupplicantConfig * self); - -gboolean nm_supplicant_config_add_setting_wireless (NMSupplicantConfig * self, - NMSettingWireless * setting, +gboolean nm_supplicant_config_add_setting_wireless (NMSupplicantConfig *self, + NMSettingWireless *setting, gboolean is_broadcast, guint32 adhoc_freq, gboolean has_scan_capa_ssid); @@ -78,6 +72,8 @@ gboolean nm_supplicant_config_add_settin NMSetting8021x *setting_8021x, const char *connection_uid); +gboolean nm_supplicant_config_add_no_security (NMSupplicantConfig *self); + gboolean nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self, NMSetting8021x *setting, const char *connection_uid, Index: src/supplicant-manager/nm-supplicant-interface.c =================================================================== --- src/supplicant-manager/nm-supplicant-interface.c.orig +++ src/supplicant-manager/nm-supplicant-interface.c @@ -57,17 +57,17 @@ static void nm_supplicant_interface_get_ GValue * value, GParamSpec * pspec); -static void nm_supplicant_interface_start (NMSupplicantInterface * self); +static void nm_supplicant_interface_start (NMSupplicantInterface *self); -static void nm_supplicant_interface_add_to_supplicant (NMSupplicantInterface * self, +static void nm_supplicant_interface_add_to_supplicant (NMSupplicantInterface *self, gboolean get_only); -static void nm_supplicant_interface_smgr_state_changed (NMSupplicantManager * smgr, +static void nm_supplicant_interface_smgr_state_changed (NMSupplicantManager *smgr, guint32 new_state, guint32 old_state, gpointer user_data); -static void nm_supplicant_interface_set_state (NMSupplicantInterface * self, +static void nm_supplicant_interface_set_state (NMSupplicantInterface *self, guint32 new_state); @@ -76,7 +76,8 @@ enum { STATE, /* change in the interface's state */ REMOVED, /* interface was removed by the supplicant */ SCANNED_AP, /* interface saw a new access point from a scan */ - SCAN_RESULT, /* result of a wireless scan request */ + SCAN_REQ_RESULT, /* result of a wireless scan request */ + SCAN_RESULTS, /* scan results returned from supplicant */ CONNECTION_STATE, /* link state of the device's connection */ CONNECTION_ERROR, /* an error occurred during a connection request */ LAST_SIGNAL @@ -91,6 +92,7 @@ enum { PROP_DEVICE, PROP_STATE, PROP_CONNECTION_STATE, + PROP_SCANNING, LAST_PROP }; @@ -109,6 +111,7 @@ typedef struct NMCallStore * other_pcalls; guint32 con_state; + gboolean scanning; DBusGProxy * iface_proxy; DBusGProxy * net_proxy; @@ -145,8 +148,8 @@ typedef struct { static NMSupplicantInfo * nm_supplicant_info_new (NMSupplicantInterface *interface, - DBusGProxy *proxy, - NMCallStore *store) + DBusGProxy *proxy, + NMCallStore *store) { NMSupplicantInfo *info; @@ -242,12 +245,6 @@ nm_supplicant_interface_set_property (GO /* Construct-only */ priv->dev = g_strdup (g_value_get_string (value)); break; - case PROP_STATE: - /* warn on setting read-only property */ - break; - case PROP_CONNECTION_STATE: - /* warn on setting read-only property */ - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -275,6 +272,9 @@ nm_supplicant_interface_get_property (GO case PROP_CONNECTION_STATE: g_value_set_uint (value, priv->con_state); break; + case PROP_SCANNING: + g_value_set_boolean (value, priv->scanning); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -282,21 +282,24 @@ nm_supplicant_interface_get_property (GO } static void -try_remove_iface (DBusGConnection * g_connection, - const char * path) +try_remove_iface (DBusGConnection *g_connection, + const char *path) { - DBusGProxy * proxy; + DBusGProxy *proxy; + + g_return_if_fail (g_connection != NULL); + g_return_if_fail (path != NULL); proxy = dbus_g_proxy_new_for_name (g_connection, - WPAS_DBUS_SERVICE, - WPAS_DBUS_PATH, - WPAS_DBUS_INTERFACE); + WPAS_DBUS_SERVICE, + WPAS_DBUS_PATH, + WPAS_DBUS_INTERFACE); if (!proxy) return; dbus_g_proxy_call_no_reply (proxy, "removeInterface", - DBUS_TYPE_G_OBJECT_PATH, path, - G_TYPE_INVALID); + DBUS_TYPE_G_OBJECT_PATH, path, + G_TYPE_INVALID); g_object_unref (proxy); } @@ -316,8 +319,10 @@ nm_supplicant_interface_dispose (GObject /* Ask wpa_supplicant to remove this interface */ sm_state = nm_supplicant_manager_get_state (priv->smgr); if (sm_state == NM_SUPPLICANT_MANAGER_STATE_IDLE) { - try_remove_iface (nm_dbus_manager_get_connection (priv->dbus_mgr), - priv->object_path); + if (priv->object_path) { + try_remove_iface (nm_dbus_manager_get_connection (priv->dbus_mgr), + priv->object_path); + } } if (priv->iface_proxy) @@ -394,6 +399,14 @@ nm_supplicant_interface_class_init (NMSu NM_SUPPLICANT_INTERFACE_STATE_INIT, G_PARAM_READABLE)); + g_object_class_install_property (object_class, + PROP_SCANNING, + g_param_spec_boolean ("scanning", + "Scanning", + "Scanning", + FALSE, + G_PARAM_READABLE)); + /* Signals */ nm_supplicant_interface_signals[STATE] = g_signal_new ("state", @@ -422,15 +435,24 @@ nm_supplicant_interface_class_init (NMSu g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); - nm_supplicant_interface_signals[SCAN_RESULT] = - g_signal_new ("scan-result", + nm_supplicant_interface_signals[SCAN_REQ_RESULT] = + g_signal_new ("scan-req-result", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSupplicantInterfaceClass, scan_result), + G_STRUCT_OFFSET (NMSupplicantInterfaceClass, scan_req_result), NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + nm_supplicant_interface_signals[SCAN_RESULTS] = + g_signal_new ("scan-results", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMSupplicantInterfaceClass, scan_results), + NULL, NULL, + g_cclosure_marshal_VOID__UINT, + G_TYPE_NONE, 1, G_TYPE_UINT); + nm_supplicant_interface_signals[CONNECTION_STATE] = g_signal_new ("connection-state", G_OBJECT_CLASS_TYPE (object_class), @@ -474,16 +496,16 @@ bssid_properties_cb (DBusGProxy *proxy, GHashTable *hash = NULL; if (!dbus_g_proxy_end_call (proxy, call_id, &err, - DBUS_TYPE_G_MAP_OF_VARIANT, &hash, - G_TYPE_INVALID)) { + DBUS_TYPE_G_MAP_OF_VARIANT, &hash, + G_TYPE_INVALID)) { if (!strstr (err->message, "The BSSID requested was invalid")) nm_warning ("Couldn't retrieve BSSID properties: %s.", err->message); g_error_free (err); } else { g_signal_emit (info->interface, - nm_supplicant_interface_signals[SCANNED_AP], - 0, - hash); + nm_supplicant_interface_signals[SCANNED_AP], + 0, + hash); g_hash_table_destroy (hash); } @@ -499,15 +521,15 @@ request_bssid_properties (NMSupplicantIn DBusGProxyCall *call; proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr), - WPAS_DBUS_SERVICE, - op, - WPAS_DBUS_IFACE_BSSID); + WPAS_DBUS_SERVICE, + op, + WPAS_DBUS_IFACE_BSSID); info = nm_supplicant_info_new (self, proxy, priv->other_pcalls); call = dbus_g_proxy_begin_call (proxy, "properties", - bssid_properties_cb, - info, - nm_supplicant_info_destroy, - G_TYPE_INVALID); + bssid_properties_cb, + info, + nm_supplicant_info_destroy, + G_TYPE_INVALID); nm_supplicant_info_set_call (info, call); g_object_unref (proxy); } @@ -519,8 +541,8 @@ scan_results_cb (DBusGProxy *proxy, DBus GPtrArray *array = NULL; if (!dbus_g_proxy_end_call (proxy, call_id, &err, - DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, &array, - G_TYPE_INVALID)) { + DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, &array, + G_TYPE_INVALID)) { nm_warning ("could not get scan results: %s.", err->message); g_error_free (err); } else { @@ -529,9 +551,9 @@ scan_results_cb (DBusGProxy *proxy, DBus /* Notify listeners of the result of the scan */ g_signal_emit (info->interface, - nm_supplicant_interface_signals[SCAN_RESULT], - 0, - TRUE); + nm_supplicant_interface_signals[SCAN_RESULTS], + 0, + array->len); /* Fire off a "properties" call for each returned BSSID */ for (i = 0; i < array->len; i++) { @@ -559,10 +581,11 @@ request_scan_results (gpointer user_data g_return_val_if_fail (priv->iface_proxy != NULL, FALSE); info = nm_supplicant_info_new (self, priv->iface_proxy, priv->other_pcalls); - call = dbus_g_proxy_begin_call (priv->iface_proxy, "scanResults", scan_results_cb, - info, - nm_supplicant_info_destroy, - G_TYPE_INVALID); + call = dbus_g_proxy_begin_call (priv->iface_proxy, "scanResults", + scan_results_cb, + info, + nm_supplicant_info_destroy, + G_TYPE_INVALID); nm_supplicant_info_set_call (info, call); g_get_current_time (&cur_time); @@ -574,15 +597,23 @@ static void wpas_iface_query_scan_results (DBusGProxy *proxy, gpointer user_data) { NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (user_data); + GTimeVal cur_time; /* Only query scan results if a query is not queued */ if (priv->scan_results_timeout) return; + g_get_current_time (&cur_time); + /* Only fetch scan results every 4s max, but initially do it right away */ - priv->scan_results_timeout = g_timeout_add_seconds (priv->last_scan ? 4 : 0, - request_scan_results, - user_data); + if (priv->last_scan + 4 < cur_time.tv_sec) { + priv->scan_results_timeout = g_idle_add (request_scan_results, + user_data); + } else { + priv->scan_results_timeout = + g_timeout_add_seconds ((4 - (cur_time.tv_sec - priv->last_scan)), + request_scan_results, user_data); + } } static guint32 @@ -590,32 +621,31 @@ wpas_state_string_to_enum (const char * { guint32 enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED; - if (!strcmp (str_state, "DISCONNECTED")) { + if (!strcmp (str_state, "DISCONNECTED")) enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED; - } else if (!strcmp (str_state, "INACTIVE")) { + else if (!strcmp (str_state, "INACTIVE")) enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_INACTIVE; - } else if (!strcmp (str_state, "SCANNING")) { + else if (!strcmp (str_state, "SCANNING")) enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_SCANNING; - } else if (!strcmp (str_state, "ASSOCIATING")) { + else if (!strcmp (str_state, "ASSOCIATING")) enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_ASSOCIATING; - } else if (!strcmp (str_state, "ASSOCIATED")) { + else if (!strcmp (str_state, "ASSOCIATED")) enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_ASSOCIATED; - } else if (!strcmp (str_state, "4WAY_HANDSHAKE")) { + else if (!strcmp (str_state, "4WAY_HANDSHAKE")) enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_4WAY_HANDSHAKE; - } else if (!strcmp (str_state, "GROUP_HANDSHAKE")) { + else if (!strcmp (str_state, "GROUP_HANDSHAKE")) enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_GROUP_HANDSHAKE; - } else if (!strcmp (str_state, "COMPLETED")) { + else if (!strcmp (str_state, "COMPLETED")) enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_COMPLETED; - } return enum_state; } static void wpas_iface_handle_state_change (DBusGProxy *proxy, - const char *str_new_state, - const char *str_old_state, - gpointer user_data) + const char *str_new_state, + const char *str_old_state, + gpointer user_data) { NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (user_data); guint32 old_state, enum_new_state; @@ -640,17 +670,17 @@ iface_state_cb (DBusGProxy *proxy, DBusG char *state_str = NULL; if (!dbus_g_proxy_end_call (proxy, call_id, &err, - G_TYPE_STRING, &state_str, - G_TYPE_INVALID)) { + G_TYPE_STRING, &state_str, + G_TYPE_INVALID)) { nm_warning ("could not get interface state: %s.", err->message); g_error_free (err); } else { NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface); - NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface)->con_state = wpas_state_string_to_enum (state_str); + priv->con_state = wpas_state_string_to_enum (state_str); g_free (state_str); - nm_supplicant_interface_set_state (info->interface, - NM_SUPPLICANT_INTERFACE_STATE_READY); + nm_supplicant_interface_set_state (info->interface, NM_SUPPLICANT_INTERFACE_STATE_READY); } } @@ -662,15 +692,77 @@ wpas_iface_get_state (NMSupplicantInterf DBusGProxyCall *call; info = nm_supplicant_info_new (self, priv->iface_proxy, priv->other_pcalls); - call = dbus_g_proxy_begin_call (priv->iface_proxy, - "state", iface_state_cb, - info, - nm_supplicant_info_destroy, - G_TYPE_INVALID); + call = dbus_g_proxy_begin_call (priv->iface_proxy, "state", + iface_state_cb, + info, + nm_supplicant_info_destroy, + G_TYPE_INVALID); + nm_supplicant_info_set_call (info, call); +} + +static void +iface_scanning_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +{ + NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface); + gboolean scanning = FALSE; + + if (dbus_g_proxy_end_call (proxy, call_id, NULL, + G_TYPE_BOOLEAN, &scanning, + G_TYPE_INVALID)) { + if (scanning != priv->scanning) { + priv->scanning = scanning; + g_object_notify (G_OBJECT (info->interface), "scanning"); + } + } +} + +static void +wpas_iface_get_scanning (NMSupplicantInterface *self) +{ + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + NMSupplicantInfo *info; + DBusGProxyCall *call; + + info = nm_supplicant_info_new (self, priv->iface_proxy, priv->other_pcalls); + call = dbus_g_proxy_begin_call (priv->iface_proxy, "scanning", + iface_scanning_cb, + info, + nm_supplicant_info_destroy, + G_TYPE_INVALID); nm_supplicant_info_set_call (info, call); } static void +wpas_iface_handle_scanning (DBusGProxy *proxy, + gboolean scanning, + gpointer user_data) +{ + NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + + if (scanning != priv->scanning) { + priv->scanning = scanning; + g_object_notify (G_OBJECT (self), "scanning"); + } +} + +gboolean +nm_supplicant_interface_get_scanning (NMSupplicantInterface *self) +{ + NMSupplicantInterfacePrivate *priv; + + g_return_val_if_fail (self != NULL, FALSE); + + priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + if (priv->scanning) + return TRUE; + if (priv->con_state == NM_SUPPLICANT_INTERFACE_CON_STATE_SCANNING) + return TRUE; + return FALSE; +} + +static void nm_supplicant_interface_add_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; @@ -678,8 +770,8 @@ nm_supplicant_interface_add_cb (DBusGPro char *path = NULL; if (!dbus_g_proxy_end_call (proxy, call_id, &err, - DBUS_TYPE_G_OBJECT_PATH, &path, - G_TYPE_INVALID)) { + DBUS_TYPE_G_OBJECT_PATH, &path, + G_TYPE_INVALID)) { if (dbus_g_error_has_name (err, WPAS_ERROR_INVALID_IFACE)) { /* Interface not added, try to add it */ @@ -698,31 +790,39 @@ nm_supplicant_interface_add_cb (DBusGPro priv->object_path = path; priv->iface_proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr), - WPAS_DBUS_SERVICE, - path, - WPAS_DBUS_IFACE_INTERFACE); + WPAS_DBUS_SERVICE, + path, + WPAS_DBUS_IFACE_INTERFACE); dbus_g_proxy_add_signal (priv->iface_proxy, "ScanResultsAvailable", G_TYPE_INVALID); dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_STRING, - G_TYPE_NONE, - G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_INVALID); + G_TYPE_NONE, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_INVALID); dbus_g_proxy_add_signal (priv->iface_proxy, "StateChange", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal (priv->iface_proxy, "ScanResultsAvailable", - G_CALLBACK (wpas_iface_query_scan_results), - info->interface, - NULL); + G_CALLBACK (wpas_iface_query_scan_results), + info->interface, + NULL); dbus_g_proxy_connect_signal (priv->iface_proxy, "StateChange", - G_CALLBACK (wpas_iface_handle_state_change), - info->interface, - NULL); + G_CALLBACK (wpas_iface_handle_state_change), + info->interface, + NULL); + + dbus_g_proxy_add_signal (priv->iface_proxy, "Scanning", G_TYPE_BOOLEAN, G_TYPE_INVALID); + + dbus_g_proxy_connect_signal (priv->iface_proxy, "Scanning", + G_CALLBACK (wpas_iface_handle_scanning), + info->interface, + NULL); /* Interface added to the supplicant; get its initial state. */ wpas_iface_get_state (info->interface); + wpas_iface_get_scanning (info->interface); } } @@ -736,19 +836,18 @@ nm_supplicant_interface_add_to_supplican DBusGProxyCall *call; proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr), - WPAS_DBUS_SERVICE, - WPAS_DBUS_PATH, - WPAS_DBUS_INTERFACE); + WPAS_DBUS_SERVICE, + WPAS_DBUS_PATH, + WPAS_DBUS_INTERFACE); info = nm_supplicant_info_new (self, proxy, priv->other_pcalls); if (get_only) { - call = dbus_g_proxy_begin_call (proxy, - "getInterface", - nm_supplicant_interface_add_cb, - info, - nm_supplicant_info_destroy, - G_TYPE_STRING, priv->dev, - G_TYPE_INVALID); + call = dbus_g_proxy_begin_call (proxy, "getInterface", + nm_supplicant_interface_add_cb, + info, + nm_supplicant_info_destroy, + G_TYPE_STRING, priv->dev, + G_TYPE_INVALID); } else { GHashTable *hash = g_hash_table_new (g_str_hash, g_str_equal); GValue *driver; @@ -758,14 +857,13 @@ nm_supplicant_interface_add_to_supplican g_value_set_string (driver, priv->is_wireless ? "wext" : "wired"); g_hash_table_insert (hash, "driver", driver); - call = dbus_g_proxy_begin_call (proxy, - "addInterface", - nm_supplicant_interface_add_cb, - info, - nm_supplicant_info_destroy, - G_TYPE_STRING, priv->dev, - DBUS_TYPE_G_MAP_OF_VARIANT, hash, - G_TYPE_INVALID); + call = dbus_g_proxy_begin_call (proxy, "addInterface", + nm_supplicant_interface_add_cb, + info, + nm_supplicant_info_destroy, + G_TYPE_STRING, priv->dev, + DBUS_TYPE_G_MAP_OF_VARIANT, hash, + G_TYPE_INVALID); g_value_unset (driver); g_free (driver); @@ -794,9 +892,8 @@ nm_supplicant_interface_start (NMSupplic /* Don't do anything; wait for signal from supplicant manager * that its state has changed. */ - } else { - nm_warning ("Unknown supplicant manager state!"); - } + } else + nm_warning ("Unknown supplicant manager state!"); } static void @@ -936,17 +1033,20 @@ nm_supplicant_interface_disconnect (NMSu /* Remove any network that was added by NetworkManager */ if (priv->net_proxy) { - dbus_g_proxy_begin_call (priv->iface_proxy, "removeNetwork", remove_network_cb, - NULL, NULL, - DBUS_TYPE_G_OBJECT_PATH, dbus_g_proxy_get_path (priv->net_proxy), - G_TYPE_INVALID); + dbus_g_proxy_begin_call (priv->iface_proxy, "removeNetwork", + remove_network_cb, + NULL, NULL, + DBUS_TYPE_G_OBJECT_PATH, dbus_g_proxy_get_path (priv->net_proxy), + G_TYPE_INVALID); g_object_unref (priv->net_proxy); priv->net_proxy = NULL; } - dbus_g_proxy_begin_call (priv->iface_proxy, "disconnect", disconnect_cb, - NULL, NULL, G_TYPE_INVALID); + dbus_g_proxy_begin_call (priv->iface_proxy, "disconnect", + disconnect_cb, + NULL, NULL, + G_TYPE_INVALID); } static void @@ -967,6 +1067,7 @@ static void set_network_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface); GError *err = NULL; guint tmp; @@ -975,16 +1076,15 @@ set_network_cb (DBusGProxy *proxy, DBusG emit_error_helper (info->interface, err); g_error_free (err); } else { - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface); DBusGProxyCall *call; - info = nm_supplicant_info_new (info->interface, priv->iface_proxy, - NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface)->assoc_pcalls); - call = dbus_g_proxy_begin_call (priv->iface_proxy, "selectNetwork", select_network_cb, - info, - nm_supplicant_info_destroy, - DBUS_TYPE_G_OBJECT_PATH, dbus_g_proxy_get_path (proxy), - G_TYPE_INVALID); + info = nm_supplicant_info_new (info->interface, priv->iface_proxy, priv->assoc_pcalls); + call = dbus_g_proxy_begin_call (priv->iface_proxy, "selectNetwork", + select_network_cb, + info, + nm_supplicant_info_destroy, + DBUS_TYPE_G_OBJECT_PATH, dbus_g_proxy_get_path (proxy), + G_TYPE_INVALID); nm_supplicant_info_set_call (info, call); } } @@ -997,11 +1097,12 @@ call_set_network (NMSupplicantInfo *info DBusGProxyCall *call; config_hash = nm_supplicant_config_get_hash (priv->cfg); - call = dbus_g_proxy_begin_call (priv->net_proxy, "set", set_network_cb, - info, - nm_supplicant_info_destroy, - DBUS_TYPE_G_MAP_OF_VARIANT, config_hash, - G_TYPE_INVALID); + call = dbus_g_proxy_begin_call (priv->net_proxy, "set", + set_network_cb, + info, + nm_supplicant_info_destroy, + DBUS_TYPE_G_MAP_OF_VARIANT, config_hash, + G_TYPE_INVALID); nm_supplicant_info_set_call (info, call); g_hash_table_destroy (config_hash); } @@ -1010,6 +1111,7 @@ static void set_blobs_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface); GError *err = NULL; guint tmp; @@ -1018,10 +1120,7 @@ set_blobs_cb (DBusGProxy *proxy, DBusGPr emit_error_helper (info->interface, err); g_error_free (err); } else { - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface); - - info = nm_supplicant_info_new (info->interface, priv->iface_proxy, - NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface)->assoc_pcalls); + info = nm_supplicant_info_new (info->interface, priv->iface_proxy, priv->assoc_pcalls); call_set_network (info); } } @@ -1075,11 +1174,12 @@ call_set_blobs (NMSupplicantInfo *info, g_hash_table_foreach (orig_blobs, (GHFunc) convert_blob, blobs); - call = dbus_g_proxy_begin_call (priv->iface_proxy, "setBlobs", set_blobs_cb, - info, - nm_supplicant_info_destroy, - DBUS_TYPE_G_MAP_OF_VARIANT, blobs, - G_TYPE_INVALID); + call = dbus_g_proxy_begin_call (priv->iface_proxy, "setBlobs", + set_blobs_cb, + info, + nm_supplicant_info_destroy, + DBUS_TYPE_G_MAP_OF_VARIANT, blobs, + G_TYPE_INVALID); nm_supplicant_info_set_call (info, call); g_hash_table_destroy (blobs); } @@ -1092,8 +1192,8 @@ add_network_cb (DBusGProxy *proxy, DBusG char *path = NULL; if (!dbus_g_proxy_end_call (proxy, call_id, &err, - DBUS_TYPE_G_OBJECT_PATH, &path, - G_TYPE_INVALID)) { + DBUS_TYPE_G_OBJECT_PATH, &path, + G_TYPE_INVALID)) { nm_warning ("Couldn't add a network to the supplicant interface: %s.", err->message); emit_error_helper (info->interface, err); g_error_free (err); @@ -1102,9 +1202,9 @@ add_network_cb (DBusGProxy *proxy, DBusG GHashTable *blobs; priv->net_proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr), - WPAS_DBUS_SERVICE, - path, - WPAS_DBUS_IFACE_NETWORK); + WPAS_DBUS_SERVICE, + path, + WPAS_DBUS_IFACE_NETWORK); g_free (path); info = nm_supplicant_info_new (info->interface, @@ -1143,10 +1243,11 @@ nm_info ("Config: set interface ap_scan } info = nm_supplicant_info_new (info->interface, proxy, info->store); - call = dbus_g_proxy_begin_call (proxy, "addNetwork", add_network_cb, - info, - nm_supplicant_info_destroy, - G_TYPE_INVALID); + call = dbus_g_proxy_begin_call (proxy, "addNetwork", + add_network_cb, + info, + nm_supplicant_info_destroy, + G_TYPE_INVALID); nm_supplicant_info_set_call (info, call); } @@ -1176,11 +1277,12 @@ nm_supplicant_interface_set_config (NMSu info = nm_supplicant_info_new (self, priv->iface_proxy, priv->other_pcalls); ap_scan = nm_supplicant_config_get_ap_scan (priv->cfg); - call = dbus_g_proxy_begin_call (priv->iface_proxy, "setAPScan", set_ap_scan_cb, - info, - nm_supplicant_info_destroy, - G_TYPE_UINT, ap_scan, - G_TYPE_INVALID); + call = dbus_g_proxy_begin_call (priv->iface_proxy, "setAPScan", + set_ap_scan_cb, + info, + nm_supplicant_info_destroy, + G_TYPE_UINT, ap_scan, + G_TYPE_INVALID); nm_supplicant_info_set_call (info, call); return call != NULL; @@ -1202,17 +1304,17 @@ scan_request_cb (DBusGProxy *proxy, DBus guint32 success = 0; if (!dbus_g_proxy_end_call (proxy, call_id, &err, - G_TYPE_UINT, &success, - G_TYPE_INVALID)) { + G_TYPE_UINT, &success, + G_TYPE_INVALID)) { nm_warning ("Could not get scan request result: %s", err->message); g_error_free (err); } /* Notify listeners of the result of the scan */ g_signal_emit (info->interface, - nm_supplicant_interface_signals[SCAN_RESULT], + nm_supplicant_interface_signals[SCAN_REQ_RESULT], 0, - success ? TRUE : FALSE); + success ? TRUE : FALSE); } gboolean @@ -1227,10 +1329,11 @@ nm_supplicant_interface_request_scan (NM priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); info = nm_supplicant_info_new (self, priv->iface_proxy, priv->other_pcalls); - call = dbus_g_proxy_begin_call (priv->iface_proxy, "scan", scan_request_cb, - info, - nm_supplicant_info_destroy, - G_TYPE_INVALID); + call = dbus_g_proxy_begin_call (priv->iface_proxy, "scan", + scan_request_cb, + info, + nm_supplicant_info_destroy, + G_TYPE_INVALID); nm_supplicant_info_set_call (info, call); return call != NULL; Index: src/supplicant-manager/nm-supplicant-interface.h =================================================================== --- src/supplicant-manager/nm-supplicant-interface.h.orig +++ src/supplicant-manager/nm-supplicant-interface.h @@ -74,42 +74,52 @@ enum { #define NM_IS_SUPPLICANT_INTERFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SUPPLICANT_INTERFACE)) #define NM_SUPPLICANT_INTERFACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SUPPLICANT_INTERFACE, NMSupplicantInterfaceClass)) -struct _NMSupplicantInterface -{ +struct _NMSupplicantInterface { GObject parent; }; -typedef struct -{ +typedef struct { GObjectClass parent; - /* class members */ - void (* state) (NMSupplicantInterface * iface, - guint32 new_state, - guint32 old_state); + /* Signals */ - void (* removed) (NMSupplicantInterface * iface); - - void (* scanned_ap) (NMSupplicantInterface * iface, - DBusMessage * message); - - void (* scan_result) (NMSupplicantInterface * iface, gboolean result); - - void (* connection_state) (NMSupplicantInterface * iface, - guint32 new_state, - guint32 old_state); - - void (* connection_error) (NMSupplicantInterface * iface, - const char * name, - const char * message); + /* change in the interface's state */ + void (*state) (NMSupplicantInterface * iface, + guint32 new_state, + guint32 old_state); + + /* interface was removed by the supplicant */ + void (*removed) (NMSupplicantInterface * iface); + + /* interface saw a new access point from a scan */ + void (*scanned_ap) (NMSupplicantInterface * iface, + DBusMessage * message); + + /* result of a wireless scan request */ + void (*scan_req_result) (NMSupplicantInterface * iface, + gboolean success); + + /* scan results returned from supplicant */ + void (*scan_results) (NMSupplicantInterface * iface, + guint num_bssids); + + /* link state of the device's connection */ + void (*connection_state) (NMSupplicantInterface * iface, + guint32 new_state, + guint32 old_state); + + /* an error occurred during a connection request */ + void (*connection_error) (NMSupplicantInterface * iface, + const char * name, + const char * message); } NMSupplicantInterfaceClass; GType nm_supplicant_interface_get_type (void); NMSupplicantInterface * nm_supplicant_interface_new (NMSupplicantManager * smgr, - const char *ifname, - gboolean is_wireless); + const char *ifname, + gboolean is_wireless); gboolean nm_supplicant_interface_set_config (NMSupplicantInterface * iface, NMSupplicantConfig * cfg); @@ -128,6 +138,8 @@ const char *nm_supplicant_interface_stat const char *nm_supplicant_interface_connection_state_to_string (guint32 state); +gboolean nm_supplicant_interface_get_scanning (NMSupplicantInterface *self); + G_END_DECLS #endif /* NM_SUPPLICANT_INTERFACE_H */ Index: src/supplicant-manager/nm-supplicant-settings-verify.h =================================================================== --- src/supplicant-manager/nm-supplicant-settings-verify.h.orig +++ src/supplicant-manager/nm-supplicant-settings-verify.h @@ -25,7 +25,8 @@ typedef enum OptType { TYPE_INVALID = 0, TYPE_INT, TYPE_BYTES, - TYPE_KEYWORD + TYPE_KEYWORD, + TYPE_STRING } OptType; OptType nm_supplicant_settings_verify_setting (const char * key, Index: src/supplicant-manager/tests/Makefile.am =================================================================== --- /dev/null +++ src/supplicant-manager/tests/Makefile.am @@ -0,0 +1,27 @@ +INCLUDES = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/libnm-util \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/supplicant-manager + +noinst_PROGRAMS = test-supplicant-config + +test_supplicant_config_SOURCES = \ + test-supplicant-config.c + +test_supplicant_config_CPPFLAGS = \ + $(GLIB_CFLAGS) \ + $(DBUS_CFLAGS) + +test_supplicant_config_LDADD = \ + $(DBUS_LIBS) \ + $(top_builddir)/libnm-util/libnm-util.la \ + $(top_builddir)/src/supplicant-manager/libsupplicant-manager.la + +if WITH_TESTS + +check-local: test-supplicant-config + $(abs_builddir)/test-supplicant-config + +endif + Index: src/supplicant-manager/tests/test-supplicant-config.c =================================================================== --- /dev/null +++ src/supplicant-manager/tests/test-supplicant-config.c @@ -0,0 +1,518 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager + * + * 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 - 2009 Red Hat, Inc. + */ + +#include <stdio.h> +#include <stdarg.h> +#include <unistd.h> +#include <string.h> +#include <netinet/ether.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include <dbus/dbus-glib.h> + +#include <nm-utils.h> +#include <nm-setting-connection.h> +#include <nm-setting-wired.h> +#include <nm-setting-wireless.h> +#include <nm-setting-wireless-security.h> +#include <nm-setting-ip4-config.h> +#include <nm-setting-8021x.h> + +#include "nm-test-helpers.h" + +#include "nm-supplicant-config.h" +#include "nm-supplicant-settings-verify.h" + +static gboolean +validate_opt (const char *detail, + GHashTable *hash, + const char *key, + OptType val_type, + gconstpointer expected, + size_t expected_len) +{ + GValue *value; + gint int_val; + GByteArray *array; + const char *s; + const unsigned char *expected_array = expected; + int result; + + ASSERT (hash != NULL, detail, "hash was NULL"); + + value = g_hash_table_lookup (hash, key); + ASSERT (value != NULL, + detail, "option '%s' expected but not found in config hash."); + + switch (val_type) { + case TYPE_INT: + ASSERT (G_VALUE_HOLDS_INT (value), + detail, "config hash item '%s' was not TYPE_INT.", key); + int_val = g_value_get_int (value); + ASSERT (int_val == GPOINTER_TO_INT (expected), + detail, "unexpected config hash item '%s' value %d (expected %d)", + key, int_val, GPOINTER_TO_INT (expected)); + break; + case TYPE_BYTES: + ASSERT (G_VALUE_HOLDS (value, DBUS_TYPE_G_UCHAR_ARRAY), + detail, "config hash item '%s' was not TYPE_BYTES.", key); + array = g_value_get_boxed (value); + ASSERT (array->len == expected_len, + detail, "unexpected config hash item '%s' length %d (expected %d)", + key, array->len, expected_len); + result = memcmp (array->data, expected_array, expected_len); + ASSERT (result == 0, detail, "unexpected config hash item '%s' value", key); + break; + case TYPE_KEYWORD: + case TYPE_STRING: + ASSERT (G_VALUE_HOLDS_STRING (value), + detail, "config hash item '%s' was not TYPE_STRING or TYPE_KEYWORD.", key); + if (expected_len == -1) + expected_len = strlen ((const char *) expected); + s = g_value_get_string (value); + ASSERT (s != NULL, detail, "unexpected NULL config hash string item '%s'.", key); + ASSERT (strlen (s) == expected_len, + detail, "unexpected config hash string item '%s' length %d (expected %d)", + key, strlen (s), expected_len); + result = strcmp (s, (const char *) expected); + ASSERT (result == 0, + detail, "unexpected config hash string item '%s' value '%s' (expected '%s')", + key, s, (const char *) expected); + break; + default: + g_warning ("unknown supplicant config hash item '%s' option type %d", + key, val_type); + return FALSE; + } + + return TRUE; +} + +static void +test_wifi_open (void) +{ + NMConnection *connection; + NMSettingConnection *s_con; + NMSettingWireless *s_wifi; + NMSettingIP4Config *s_ip4; + NMSupplicantConfig *config; + GHashTable *hash; + char *uuid; + gboolean success; + GError *error = NULL; + GByteArray *ssid; + const unsigned char ssid_data[] = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44 }; + GByteArray *bssid; + const unsigned char bssid_data[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 }; + const char *bssid_str = "11:22:33:44:55:66"; + + connection = nm_connection_new (); + ASSERT (connection != NULL, + "wifi-open", "failed to allocate new connection"); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + ASSERT (s_con != NULL, + "wifi-open", "failed to allocate new %s setting", + NM_SETTING_CONNECTION_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + uuid = nm_utils_uuid_generate (); + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, "Test Wifi Open", + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, + NULL); + g_free (uuid); + + /* Wifi setting */ + s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); + ASSERT (s_wifi != NULL, + "wifi-open", "failed to allocate new %s setting", + NM_SETTING_WIRELESS_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wifi)); + + ssid = g_byte_array_sized_new (sizeof (ssid_data)); + g_byte_array_append (ssid, ssid_data, sizeof (ssid_data)); + bssid = g_byte_array_sized_new (sizeof (bssid_data)); + g_byte_array_append (bssid, bssid_data, sizeof (bssid_data)); + + g_object_set (s_wifi, + NM_SETTING_WIRELESS_SSID, ssid, + NM_SETTING_WIRELESS_BSSID, bssid, + NM_SETTING_WIRELESS_MODE, "infrastructure", + NM_SETTING_WIRELESS_BAND, "bg", + NULL); + + g_byte_array_free (ssid, TRUE); + g_byte_array_free (bssid, TRUE); + + /* IP4 setting */ + s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); + ASSERT (s_ip4 != NULL, + "wifi-open", "failed to allocate new %s setting", + NM_SETTING_IP4_CONFIG_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + + g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); + + ASSERT (nm_connection_verify (connection, &error) == TRUE, + "wifi-open", "failed to verify connection: %s", + (error && error->message) ? error->message : "(unknown)"); + + config = nm_supplicant_config_new (); + ASSERT (config != NULL, + "wifi-open", "failed to create new supplicant config"); + + success = nm_supplicant_config_add_setting_wireless (config, s_wifi, TRUE, 0, TRUE); + ASSERT (success == TRUE, + "wifi-open", "failed to add wireless setting to supplicant config."); + + success = nm_supplicant_config_add_no_security (config); + ASSERT (success == TRUE, + "wifi-open", "failed to add wireless security to supplicant config."); + + hash = nm_supplicant_config_get_hash (config); + ASSERT (hash != NULL, + "wifi-open", "failed to hash supplicant config options."); + + validate_opt ("wifi-open", hash, "scan_ssid", TYPE_INT, GINT_TO_POINTER (1), -1); + validate_opt ("wifi-open", hash, "ssid", TYPE_BYTES, ssid_data, sizeof (ssid_data)); + validate_opt ("wifi-open", hash, "bssid", TYPE_KEYWORD, bssid_str, -1); + validate_opt ("wifi-open", hash, "key_mgmt", TYPE_KEYWORD, "NONE", -1); + + g_object_unref (connection); +} + +static void +test_wifi_wep_key (const char *detail, + NMWepKeyType wep_type, + const char *key_data, + const unsigned char *expected, + size_t expected_size) +{ + NMConnection *connection; + NMSettingConnection *s_con; + NMSettingWireless *s_wifi; + NMSettingWirelessSecurity *s_wsec; + NMSettingIP4Config *s_ip4; + NMSupplicantConfig *config; + GHashTable *hash; + char *uuid; + gboolean success; + GError *error = NULL; + GByteArray *ssid; + const unsigned char ssid_data[] = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44 }; + GByteArray *bssid; + const unsigned char bssid_data[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 }; + const char *bssid_str = "11:22:33:44:55:66"; + + connection = nm_connection_new (); + ASSERT (connection != NULL, + detail, "failed to allocate new connection"); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + ASSERT (s_con != NULL, + detail, "failed to allocate new %s setting", + NM_SETTING_CONNECTION_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + uuid = nm_utils_uuid_generate (); + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, "Test Wifi WEP Key", + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, + NULL); + g_free (uuid); + + /* Wifi setting */ + s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); + ASSERT (s_wifi != NULL, + detail, "failed to allocate new %s setting", + NM_SETTING_WIRELESS_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wifi)); + + ssid = g_byte_array_sized_new (sizeof (ssid_data)); + g_byte_array_append (ssid, ssid_data, sizeof (ssid_data)); + bssid = g_byte_array_sized_new (sizeof (bssid_data)); + g_byte_array_append (bssid, bssid_data, sizeof (bssid_data)); + + g_object_set (s_wifi, + NM_SETTING_WIRELESS_SSID, ssid, + NM_SETTING_WIRELESS_BSSID, bssid, + NM_SETTING_WIRELESS_MODE, "infrastructure", + NM_SETTING_WIRELESS_BAND, "bg", + NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NULL); + + g_byte_array_free (ssid, TRUE); + g_byte_array_free (bssid, TRUE); + + /* Wifi Security setting */ + s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new (); + ASSERT (s_wsec != NULL, + detail, "failed to allocate new %s setting", + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wsec)); + + g_object_set (s_wsec, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none", + NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, wep_type, + NULL); + nm_setting_wireless_security_set_wep_key (s_wsec, 0, key_data); + + /* IP4 setting */ + s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); + ASSERT (s_ip4 != NULL, + detail, "failed to allocate new %s setting", + NM_SETTING_IP4_CONFIG_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + + g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); + + ASSERT (nm_connection_verify (connection, &error) == TRUE, + detail, "failed to verify connection: %s", + (error && error->message) ? error->message : "(unknown)"); + + config = nm_supplicant_config_new (); + ASSERT (config != NULL, + detail, "failed to create new supplicant config"); + + success = nm_supplicant_config_add_setting_wireless (config, s_wifi, TRUE, 0, TRUE); + ASSERT (success == TRUE, + detail, "failed to add wireless setting to supplicant config."); + + success = nm_supplicant_config_add_setting_wireless_security (config, + s_wsec, + NULL, + "376aced7-b28c-46be-9a62-fcdf072571da"); + ASSERT (success == TRUE, + detail, "failed to add wireless security to supplicant config."); + + hash = nm_supplicant_config_get_hash (config); + ASSERT (hash != NULL, + detail, "failed to hash supplicant config options."); + + validate_opt (detail, hash, "scan_ssid", TYPE_INT, GINT_TO_POINTER (1), -1); + validate_opt (detail, hash, "ssid", TYPE_BYTES, ssid_data, sizeof (ssid_data)); + validate_opt (detail, hash, "bssid", TYPE_KEYWORD, bssid_str, -1); + validate_opt (detail, hash, "key_mgmt", TYPE_KEYWORD, "NONE", -1); + validate_opt (detail, hash, "wep_tx_keyidx", TYPE_INT, GINT_TO_POINTER (0), -1); + validate_opt (detail, hash, "wep_key0", TYPE_BYTES, expected, expected_size); + + g_object_unref (connection); +} + +static void +test_wifi_wep (void) +{ + const char *key1 = "12345"; + const unsigned char key1_expected[] = { 0x31, 0x32, 0x33, 0x34, 0x35 }; + const char *key2 = "ascii test$$$"; + const unsigned char key2_expected[] = { 0x61, 0x73, 0x63, 0x69, 0x69, 0x20, 0x74, 0x65, 0x73, 0x74, 0x24, 0x24, 0x24 }; + const char *key3 = "abcdef1234"; + const unsigned char key3_expected[] = { 0xab, 0xcd, 0xef, 0x12, 0x34 }; + const char *key4 = "96aec785c6392675f87f592972"; + const unsigned char key4_expected[] = { 0x96, 0xae, 0xc7, 0x85, 0xc6, 0x39, 0x26, 0x75, 0xf8, 0x7f, 0x59, 0x29, 0x72 }; + const char *key5 = "r34lly l33t w3p p4ssphr4s3 for t3st1ng"; + const unsigned char key5_expected[] = { 0xce, 0x68, 0x8b, 0x35, 0xf6, 0x0a, 0x2b, 0xbf, 0xc9, 0x8f, 0xed, 0x10, 0xda }; + + test_wifi_wep_key ("wifi-wep-ascii-40", NM_WEP_KEY_TYPE_KEY, key1, key1_expected, sizeof (key1_expected)); + test_wifi_wep_key ("wifi-wep-ascii-104", NM_WEP_KEY_TYPE_KEY, key2, key2_expected, sizeof (key2_expected)); + test_wifi_wep_key ("wifi-wep-hex-40", NM_WEP_KEY_TYPE_KEY, key3, key3_expected, sizeof (key3_expected)); + test_wifi_wep_key ("wifi-wep-hex-104", NM_WEP_KEY_TYPE_KEY, key4, key4_expected, sizeof (key4_expected)); + test_wifi_wep_key ("wifi-wep-passphrase-104", NM_WEP_KEY_TYPE_PASSPHRASE, key5, key5_expected, sizeof (key5_expected)); + + test_wifi_wep_key ("wifi-wep-old-hex-104", NM_WEP_KEY_TYPE_UNKNOWN, key4, key4_expected, sizeof (key4_expected)); +} + +static void +test_wifi_wpa_psk (const char *detail, + OptType key_type, + const char *key_data, + const unsigned char *expected, + size_t expected_size) +{ + NMConnection *connection; + NMSettingConnection *s_con; + NMSettingWireless *s_wifi; + NMSettingWirelessSecurity *s_wsec; + NMSettingIP4Config *s_ip4; + NMSupplicantConfig *config; + GHashTable *hash; + char *uuid; + gboolean success; + GError *error = NULL; + GByteArray *ssid; + const unsigned char ssid_data[] = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44 }; + GByteArray *bssid; + const unsigned char bssid_data[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 }; + const char *bssid_str = "11:22:33:44:55:66"; + + connection = nm_connection_new (); + ASSERT (connection != NULL, + detail, "failed to allocate new connection"); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + ASSERT (s_con != NULL, + detail, "failed to allocate new %s setting", + NM_SETTING_CONNECTION_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + uuid = nm_utils_uuid_generate (); + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, "Test Wifi WEP Key", + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, + NULL); + g_free (uuid); + + /* Wifi setting */ + s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); + ASSERT (s_wifi != NULL, + detail, "failed to allocate new %s setting", + NM_SETTING_WIRELESS_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wifi)); + + ssid = g_byte_array_sized_new (sizeof (ssid_data)); + g_byte_array_append (ssid, ssid_data, sizeof (ssid_data)); + bssid = g_byte_array_sized_new (sizeof (bssid_data)); + g_byte_array_append (bssid, bssid_data, sizeof (bssid_data)); + + g_object_set (s_wifi, + NM_SETTING_WIRELESS_SSID, ssid, + NM_SETTING_WIRELESS_BSSID, bssid, + NM_SETTING_WIRELESS_MODE, "infrastructure", + NM_SETTING_WIRELESS_BAND, "bg", + NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NULL); + + g_byte_array_free (ssid, TRUE); + g_byte_array_free (bssid, TRUE); + + /* Wifi Security setting */ + s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new (); + ASSERT (s_wsec != NULL, + detail, "failed to allocate new %s setting", + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wsec)); + + g_object_set (s_wsec, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", + NM_SETTING_WIRELESS_SECURITY_PSK, key_data, + NULL); + + nm_setting_wireless_security_add_proto (s_wsec, "wpa"); + nm_setting_wireless_security_add_proto (s_wsec, "rsn"); + nm_setting_wireless_security_add_pairwise (s_wsec, "tkip"); + nm_setting_wireless_security_add_pairwise (s_wsec, "ccmp"); + nm_setting_wireless_security_add_group (s_wsec, "tkip"); + nm_setting_wireless_security_add_group (s_wsec, "ccmp"); + + /* IP4 setting */ + s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); + ASSERT (s_ip4 != NULL, + detail, "failed to allocate new %s setting", + NM_SETTING_IP4_CONFIG_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + + g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); + + ASSERT (nm_connection_verify (connection, &error) == TRUE, + detail, "failed to verify connection: %s", + (error && error->message) ? error->message : "(unknown)"); + + config = nm_supplicant_config_new (); + ASSERT (config != NULL, + detail, "failed to create new supplicant config"); + + success = nm_supplicant_config_add_setting_wireless (config, s_wifi, TRUE, 0, TRUE); + ASSERT (success == TRUE, + detail, "failed to add wireless setting to supplicant config."); + + success = nm_supplicant_config_add_setting_wireless_security (config, + s_wsec, + NULL, + "376aced7-b28c-46be-9a62-fcdf072571da"); + ASSERT (success == TRUE, + detail, "failed to add wireless security to supplicant config."); + + hash = nm_supplicant_config_get_hash (config); + ASSERT (hash != NULL, + detail, "failed to hash supplicant config options."); + + validate_opt (detail, hash, "scan_ssid", TYPE_INT, GINT_TO_POINTER (1), -1); + validate_opt (detail, hash, "ssid", TYPE_BYTES, ssid_data, sizeof (ssid_data)); + validate_opt (detail, hash, "bssid", TYPE_KEYWORD, bssid_str, -1); + validate_opt (detail, hash, "key_mgmt", TYPE_KEYWORD, "WPA-PSK", -1); + validate_opt (detail, hash, "proto", TYPE_KEYWORD, "WPA RSN", -1); + validate_opt (detail, hash, "pairwise", TYPE_KEYWORD, "TKIP CCMP", -1); + validate_opt (detail, hash, "group", TYPE_KEYWORD, "TKIP CCMP", -1); + validate_opt (detail, hash, "psk", key_type, expected, expected_size); + + g_object_unref (connection); +} + +static void +test_wifi_wpa_psk_types (void) +{ + const char *key1 = "d4721e911461d3cdef9793858e977fcda091779243abb7316c2f11605a160893"; + const unsigned char key1_expected[] = { 0xd4, 0x72, 0x1e, 0x91, 0x14, 0x61, 0xd3, 0xcd, + 0xef, 0x97, 0x93, 0x85, 0x8e, 0x97, 0x7f, 0xcd, + 0xa0, 0x91, 0x77, 0x92, 0x43, 0xab, 0xb7, 0x31, + 0x6c, 0x2f, 0x11, 0x60, 0x5a, 0x16, 0x08, 0x93 }; + const char *key2 = "r34lly l33t wp4 p4ssphr4s3 for t3st1ng"; + + test_wifi_wpa_psk ("wifi-wpa-psk-hex", TYPE_BYTES, key1, key1_expected, sizeof (key1_expected)); + test_wifi_wpa_psk ("wifi-wep-psk-passphrase", TYPE_STRING, key2, (gconstpointer) key2, strlen (key2)); +} + +int main (int argc, char **argv) +{ + GError *error = NULL; + DBusGConnection *bus; + char *base; + + g_type_init (); + bus = dbus_g_bus_get (DBUS_BUS_SESSION, NULL); + + if (!nm_utils_init (&error)) + FAIL ("nm-utils-init", "failed to initialize libnm-util: %s", error->message); + + /* The tests */ + test_wifi_open (); + test_wifi_wep (); + test_wifi_wpa_psk_types (); + + base = g_path_get_basename (argv[0]); + fprintf (stdout, "%s: SUCCESS\n", base); + g_free (base); + return 0; +} + Index: src/tests/test-dhcp-options.c =================================================================== --- src/tests/test-dhcp-options.c.orig +++ src/tests/test-dhcp-options.c @@ -583,7 +583,7 @@ int main (int argc, char **argv) { GError *error = NULL; DBusGConnection *bus; - char *basename; + char *base; g_type_init (); bus = dbus_g_bus_get (DBUS_BUS_SESSION, NULL); @@ -602,9 +602,9 @@ int main (int argc, char **argv) test_escaped_domain_searches (); test_invalid_escaped_domain_searches (); - basename = g_path_get_basename (argv[0]); - fprintf (stdout, "%s: SUCCESS\n", basename); - g_free (basename); + base = g_path_get_basename (argv[0]); + fprintf (stdout, "%s: SUCCESS\n", base); + g_free (base); return 0; } Index: system-settings/plugins/ifcfg-rh/common.h =================================================================== --- system-settings/plugins/ifcfg-rh/common.h.orig +++ system-settings/plugins/ifcfg-rh/common.h @@ -21,6 +21,8 @@ #ifndef __COMMON_H__ #define __COMMON_H__ +#include <glib.h> + #define IFCFG_TAG "ifcfg-" #define KEYS_TAG "keys-" #define BAK_TAG ".bak" @@ -28,10 +30,31 @@ #define ORIG_TAG ".orig" #define REJ_TAG ".rej" +#define IFCFG_DIR SYSCONFDIR"/sysconfig/network-scripts" + #define IFCFG_PLUGIN_NAME "ifcfg-rh" #define IFCFG_PLUGIN_INFO "(c) 2007 - 2008 Red Hat, Inc. To report bugs please use the NetworkManager mailing list." -#include <glib.h> +#define TYPE_ETHERNET "Ethernet" +#define TYPE_WIRELESS "Wireless" + +#define TAG_CA_CERT_PATH "ca-cert-path" +#define TAG_CA_CERT_HASH "ca-cert-hash" + +#define TAG_CLIENT_CERT_PATH "client-cert-path" +#define TAG_CLIENT_CERT_HASH "client-cert-hash" + +#define TAG_PRIVATE_KEY_PATH "private-key-path" +#define TAG_PRIVATE_KEY_HASH "private-key-hash" + +#define TAG_PHASE2_CA_CERT_PATH "phase2-ca-cert-path" +#define TAG_PHASE2_CA_CERT_HASH "phase2-ca-cert-hash" + +#define TAG_PHASE2_CLIENT_CERT_PATH "phase2-client-cert-path" +#define TAG_PHASE2_CLIENT_CERT_HASH "phase2-client-cert-hash" + +#define TAG_PHASE2_PRIVATE_KEY_PATH "phase2-private-key-path" +#define TAG_PHASE2_PRIVATE_KEY_HASH "phase2-private-key-hash" GQuark ifcfg_plugin_error_quark (void); Index: system-settings/plugins/ifcfg-rh/crypto.c =================================================================== --- /dev/null +++ system-settings/plugins/ifcfg-rh/crypto.c @@ -0,0 +1,391 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager system settings service - keyfile plugin + * + * 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) 2009 Red Hat, Inc. + */ + +#include "config.h" + +#include <glib.h> +#include <glib/gi18n.h> + +#include <prinit.h> +#include <nss.h> +#include <pk11pub.h> +#include <pkcs11t.h> +#include <cert.h> +#include <prerror.h> + +#include "common.h" +#include "crypto.h" +#include "utils.h" + +static gboolean initialized = FALSE; + +static gboolean +crypto_init (GError **error) +{ + SECStatus ret; + + if (initialized) + return TRUE; + + PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 1); + ret = NSS_NoDB_Init (NULL); + if (ret != SECSuccess) { + PR_Cleanup (); + g_set_error (error, ifcfg_plugin_error_quark (), 0, + _("Failed to initialize the crypto engine: %d."), + PR_GetError ()); + return FALSE; + } + + initialized = TRUE; + return TRUE; +} + +static gboolean +nss_md5_hash (const unsigned char *salt, + const gsize salt_len, + const char *password, + gsize password_len, + unsigned char *buffer, + gsize buflen, + GError **error) +{ + PK11Context *ctx; + int nkey = buflen; + unsigned int digest_len; + int count = 0; + char digest[20]; /* MD5 hash length */ + unsigned char *p = buffer; + + if (salt) + g_return_val_if_fail (salt_len >= 8, FALSE); + + g_return_val_if_fail (password != NULL, FALSE); + g_return_val_if_fail (password_len > 0, FALSE); + g_return_val_if_fail (buffer != NULL, FALSE); + g_return_val_if_fail (buflen > 0, FALSE); + + ctx = PK11_CreateDigestContext (SEC_OID_MD5); + if (!ctx) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Failed to initialize the MD5 context: %d.", + PORT_GetError ()); + return FALSE; + } + + while (nkey > 0) { + int i = 0; + + PK11_DigestBegin (ctx); + if (count++) + PK11_DigestOp (ctx, (const unsigned char *) digest, digest_len); + PK11_DigestOp (ctx, (const unsigned char *) password, password_len); + if (salt) + PK11_DigestOp (ctx, salt, 8); /* Only use 8 bytes of salt */ + PK11_DigestFinal (ctx, (unsigned char *) digest, &digest_len, sizeof (digest)); + + while (nkey && (i < digest_len)) { + *(p++) = digest[i++]; + nkey--; + } + } + + memset (digest, 0, sizeof (digest)); + PK11_DestroyContext (ctx, PR_TRUE); + return TRUE; +} + +static unsigned char * +make_key (const unsigned char *salt, + gsize salt_len, + const char *password, + gsize *out_len, + GError **error) +{ + unsigned char *key; + guint32 digest_len = 24; /* DES-EDE3-CBC */ + + g_return_val_if_fail (salt != NULL, NULL); + g_return_val_if_fail (salt_len >= 8, NULL); + g_return_val_if_fail (password != NULL, NULL); + g_return_val_if_fail (out_len != NULL, NULL); + + key = g_malloc0 (digest_len + 1); + if (!key) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Not enough memory to decrypt private key."); + return NULL; + } + + if (!nss_md5_hash (salt, salt_len, password, strlen (password), key, digest_len, error)) { + *out_len = 0; + memset (key, 0, digest_len); + g_free (key); + key = NULL; + } else + *out_len = digest_len; + + return key; +} + +static unsigned char * +nss_des3_encrypt (const unsigned char *key, + gsize key_len, + const unsigned char *iv, + gsize iv_len, + const unsigned char *data, + gsize data_len, + gsize *out_len, + GError **error) +{ + SECStatus ret; + CK_MECHANISM_TYPE cipher_mech = CKM_DES3_CBC_PAD; + PK11SlotInfo *slot = NULL; + SECItem key_item = { .data = (unsigned char *) key, .len = key_len }; + SECItem iv_item = { .data = (unsigned char *) iv, .len = iv_len }; + PK11SymKey *sym_key = NULL; + SECItem *sec_param = NULL; + PK11Context *ctx = NULL; + unsigned char *buf; + gsize buflen = data_len + 64; + int tmp1_len = 0; + unsigned int tmp2_len = 0, len; + gboolean success = FALSE; + + buf = g_malloc0 (buflen); + if (!buf) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Could not allocate memory encrypting private key."); + return NULL; + } + + slot = PK11_GetBestSlot (cipher_mech, NULL); + if (!slot) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Failed to initialize the encryption cipher slot."); + goto out; + } + + sym_key = PK11_ImportSymKey (slot, cipher_mech, PK11_OriginUnwrap, CKA_ENCRYPT, &key_item, NULL); + if (!sym_key) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Failed to set symmetric key for encryption."); + goto out; + } + + sec_param = PK11_ParamFromIV (cipher_mech, &iv_item); + if (!sec_param) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Failed to set IV for encryption."); + goto out; + } + + ctx = PK11_CreateContextBySymKey (cipher_mech, CKA_ENCRYPT, sym_key, sec_param); + if (!ctx) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Failed to initialize the encryption context."); + goto out; + } + + ret = PK11_CipherOp (ctx, buf, &tmp1_len, buflen, (unsigned char *) data, data_len); + if (ret != SECSuccess) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Failed to encrypt the private key: %d.", + PORT_GetError ()); + goto out; + } + + ret = PK11_DigestFinal (ctx, + (unsigned char *) (buf + tmp1_len), + &tmp2_len, + buflen - tmp1_len); + if (ret != SECSuccess) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Failed to finalize encryption of the private key: %d.", + PORT_GetError ()); + goto out; + } + len = tmp1_len + tmp2_len; + if (len > buflen) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Error encrypting private key; too much data."); + goto out; + } + + *out_len = len; + buf[*out_len] = '\0'; + success = TRUE; + +out: + if (ctx) + PK11_DestroyContext (ctx, PR_TRUE); + if (sym_key) + PK11_FreeSymKey (sym_key); + if (sec_param) + SECITEM_FreeItem (sec_param, PR_TRUE); + if (slot) + PK11_FreeSlot (slot); + + if (!success) { + memset (buf, 0, buflen); + g_free (buf); + buf = NULL; + } + return buf; +} + +#define PEM_RSA_KEY_BEGIN "-----BEGIN RSA PRIVATE KEY-----"; +#define PEM_RSA_KEY_END "-----END RSA PRIVATE KEY-----"; + +GByteArray * +crypto_key_to_pem (const GByteArray *data, + const char *password, + GError **error) +{ + SECStatus s; + unsigned char salt[32]; + unsigned char *key = NULL, *enc = NULL; + gsize key_len = 0, enc_len = 0; + GString *pem = NULL; + char *tmp; + gboolean success = FALSE; + int left; + const char *p; + GByteArray *ret = NULL; + + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->len > 0, NULL); + g_return_val_if_fail (password != NULL, NULL); + + if (!crypto_init (error)) + return NULL; + + s = PK11_GenerateRandom (salt, sizeof (salt)); + if (s != SECSuccess) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Could not generate random IV for encrypting private key."); + return NULL; + } + + key = make_key (&salt[0], sizeof (salt), password, &key_len, error); + if (!key) + return NULL; + + enc = nss_des3_encrypt (key, key_len, salt, sizeof (salt), data->data, data->len, &enc_len, error); + if (!enc) + goto out; + + pem = g_string_sized_new (enc_len * 2 + 100); + if (!pem) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Could not allocate memory for PEM file creation."); + goto out; + } + + g_string_append (pem, "-----BEGIN RSA PRIVATE KEY-----\n"); + g_string_append (pem, "Proc-Type: 4,ENCRYPTED\n"); + + /* Convert the salt to a hex string */ + tmp = utils_bin2hexstr ((const char *) salt, sizeof (salt), 16); + if (!tmp) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Could not allocate memory for writing IV to PEM file."); + goto out; + } + + g_string_append_printf (pem, "DEK-Info: DES-EDE3-CBC,%s\n\n", tmp); + g_free (tmp); + + /* Convert the encrypted key to a base64 string */ + p = tmp = g_base64_encode (enc, enc_len); + if (!tmp) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Could not allocate memory for writing encrypted key to PEM file."); + goto out; + } + + left = strlen (tmp); + while (left > 0) { + g_string_append_len (pem, p, (left < 64) ? left : 64); + g_string_append_c (pem, '\n'); + left -= 64; + p += 64; + } + g_free (tmp); + + g_string_append (pem, "-----END RSA PRIVATE KEY-----\n"); + + ret = g_byte_array_sized_new (pem->len); + if (!ret) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Could not allocate memory for PEM file data."); + goto out; + } + g_byte_array_append (ret, (const unsigned char *) pem->str, pem->len); + success = TRUE; + +out: + if (key) { + memset (key, 0, key_len); + g_free (key); + } + if (!enc) { + memset (enc, 0, enc_len); + g_free (enc); + } + if (pem) + g_string_free (pem, TRUE); + + return ret; +} + +GByteArray * +crypto_random (gsize len, GError **error) +{ + SECStatus s; + GByteArray *array; + unsigned char *buf; + + if (!crypto_init (error)) + return NULL; + + buf = g_malloc (len); + if (!buf) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Could not allocate memory for random data."); + return NULL; + } + + s = PK11_GenerateRandom (buf, len); + if (s != SECSuccess) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Could not generate random IV for encrypting private key."); + g_free (buf); + return NULL; + } + + array = g_byte_array_sized_new (len); + g_byte_array_append (array, buf, len); + memset (buf, 0, len); + g_free (buf); + + return array; +} + Index: system-settings/plugins/ifcfg-rh/crypto.h =================================================================== --- /dev/null +++ system-settings/plugins/ifcfg-rh/crypto.h @@ -0,0 +1,34 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager system settings service - keyfile plugin + * + * 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) 2009 Red Hat, Inc. + */ + +#ifndef _CRYPTO_H_ +#define _CRYPTO_H_ + +#include <glib.h> + +GByteArray * +crypto_key_to_pem (const GByteArray *data, + const char *password, + GError **error); + +GByteArray *crypto_random (gsize len, GError **error); + +#endif /* _CRYPTO_H_ */ + Index: system-settings/plugins/ifcfg-rh/Makefile.am =================================================================== --- system-settings/plugins/ifcfg-rh/Makefile.am.orig +++ system-settings/plugins/ifcfg-rh/Makefile.am @@ -9,20 +9,27 @@ libifcfg_rh_io_la_SOURCES = \ shvar.h \ reader.c \ reader.h \ + writer.c \ + writer.h \ sha1.c \ sha1.h \ errors.c \ - common.h + common.h \ + utils.c \ + utils.h \ + crypto.c \ + crypto.h libifcfg_rh_io_la_CPPFLAGS = \ $(GLIB_CFLAGS) \ $(DBUS_CFLAGS) \ + $(NSS_CFLAGS) \ -DG_DISABLE_DEPRECATED \ -I$(top_srcdir)/include \ -I$(top_srcdir)/libnm-util \ -DSYSCONFDIR=\"$(sysconfdir)\" -libifcfg_rh_io_la_LIBADD = $(GLIB_LIBS) +libifcfg_rh_io_la_LIBADD = $(GLIB_LIBS) $(NSS_LIBS) libnm_settings_plugin_ifcfg_rh_la_SOURCES = \ plugin.c \ Index: system-settings/plugins/ifcfg-rh/nm-ifcfg-connection.c =================================================================== --- system-settings/plugins/ifcfg-rh/nm-ifcfg-connection.c.orig +++ system-settings/plugins/ifcfg-rh/nm-ifcfg-connection.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2008 Red Hat, Inc. + * Copyright (C) 2008 - 2009 Red Hat, Inc. */ #include <string.h> @@ -38,6 +38,7 @@ #include "nm-ifcfg-connection.h" #include "nm-system-config-hal-manager.h" #include "reader.h" +#include "writer.h" #include "nm-inotify-helper.h" G_DEFINE_TYPE (NMIfcfgConnection, nm_ifcfg_connection, NM_TYPE_SYSCONFIG_CONNECTION) @@ -316,11 +317,27 @@ nm_ifcfg_connection_get_unmanaged (NMIfc return NM_IFCFG_CONNECTION_GET_PRIVATE (self)->unmanaged; } +gboolean +nm_ifcfg_connection_update (NMIfcfgConnection *self, GHashTable *new_settings, GError **error) +{ + NMExportedConnection *exported = NM_EXPORTED_CONNECTION (self); + NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (exported); + NMConnection *connection; + + connection = nm_exported_connection_get_connection (exported); + if (!nm_connection_replace_settings (connection, new_settings, error)) + return FALSE; + + return writer_update_connection (connection, IFCFG_DIR, priv->filename, priv->keyfile, error); +} + static gboolean update (NMExportedConnection *exported, GHashTable *new_settings, GError **error) { -// write_connection (NM_IFCFG_CONNECTION (exported)); - return TRUE; + if (!NM_EXPORTED_CONNECTION_CLASS (nm_ifcfg_connection_parent_class)->update (exported, new_settings, error)) + return FALSE; + + return nm_ifcfg_connection_update (NM_IFCFG_CONNECTION (exported), new_settings, error); } static gboolean Index: system-settings/plugins/ifcfg-rh/nm-ifcfg-connection.h =================================================================== --- system-settings/plugins/ifcfg-rh/nm-ifcfg-connection.h.orig +++ system-settings/plugins/ifcfg-rh/nm-ifcfg-connection.h @@ -60,6 +60,10 @@ const char *nm_ifcfg_connection_get_udi gboolean nm_ifcfg_connection_get_unmanaged (NMIfcfgConnection *self); +gboolean nm_ifcfg_connection_update (NMIfcfgConnection *self, + GHashTable *new_settings, + GError **error); + G_END_DECLS #endif /* NM_IFCFG_CONNECTION_H */ Index: system-settings/plugins/ifcfg-rh/plugin.c =================================================================== --- system-settings/plugins/ifcfg-rh/plugin.c.orig +++ system-settings/plugins/ifcfg-rh/plugin.c @@ -48,8 +48,7 @@ #include "nm-ifcfg-connection.h" #include "nm-inotify-helper.h" #include "shvar.h" - -#define IFCFG_DIR SYSCONFDIR"/sysconfig/network-scripts/" +#include "writer.h" static void system_config_interface_init (NMSystemConfigInterface *system_config_interface_class); @@ -199,16 +198,16 @@ read_one_connection (SCPluginIfcfg *plug } static gboolean -check_suffix (const char *basename, const char *tag) +check_suffix (const char *base, const char *tag) { int len, tag_len; - g_return_val_if_fail (basename != NULL, TRUE); + g_return_val_if_fail (base != NULL, TRUE); g_return_val_if_fail (tag != NULL, TRUE); - len = strlen (basename); + len = strlen (base); tag_len = strlen (tag); - if ((len > tag_len) && !strcasecmp (basename + len - tag_len, tag)) + if ((len > tag_len) && !strcasecmp (base + len - tag_len, tag)) return TRUE; return FALSE; } @@ -216,22 +215,22 @@ check_suffix (const char *basename, cons static gboolean should_ignore_file (const char *filename) { - char *basename; + char *base; gboolean ignore = TRUE; g_return_val_if_fail (filename != NULL, TRUE); - basename = g_path_get_basename (filename); - g_return_val_if_fail (basename != NULL, TRUE); + base = g_path_get_basename (filename); + g_return_val_if_fail (base != NULL, TRUE); - if ( !strncmp (basename, IFCFG_TAG, strlen (IFCFG_TAG)) - && !check_suffix (basename, BAK_TAG) - && !check_suffix (basename, TILDE_TAG) - && !check_suffix (basename, ORIG_TAG) - && !check_suffix (basename, REJ_TAG)) + if ( !strncmp (base, IFCFG_TAG, strlen (IFCFG_TAG)) + && !check_suffix (base, BAK_TAG) + && !check_suffix (base, TILDE_TAG) + && !check_suffix (base, ORIG_TAG) + && !check_suffix (base, REJ_TAG)) ignore = FALSE; - g_free (basename); + g_free (base); return ignore; } @@ -294,9 +293,9 @@ connection_changed_handler (SCPluginIfcf /* errors reading connection; remove it */ if (!ignore_error) { PLUGIN_WARN (IFCFG_PLUGIN_NAME, " error: %s", - error->message ? error->message : "(unknown)"); + (error && error->message) ? error->message : "(unknown)"); } - g_error_free (error); + g_clear_error (&error); PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "removed %s.", path); *do_remove = TRUE; @@ -337,7 +336,11 @@ connection_changed_handler (SCPluginIfcf /* Only update if different */ if (!nm_connection_compare (new_wrapped, old_wrapped, NM_SETTING_COMPARE_FLAG_EXACT)) { settings = nm_connection_to_hash (new_wrapped); - nm_exported_connection_update (NM_EXPORTED_CONNECTION (connection), settings, NULL); + if (!nm_ifcfg_connection_update (connection, settings, &error)) { + PLUGIN_WARN (IFCFG_PLUGIN_NAME, " error updating: %s", + (error && error->message) ? error->message : "(unknown)"); + g_clear_error (&error); + } g_hash_table_destroy (settings); } @@ -435,7 +438,7 @@ setup_ifcfg_monitoring (SCPluginIfcfg *p priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref); - file = g_file_new_for_path (IFCFG_DIR); + file = g_file_new_for_path (IFCFG_DIR "/"); monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL); g_object_unref (file); @@ -472,6 +475,14 @@ get_connections (NMSystemConfigInterface return list; } +static gboolean +add_connection (NMSystemConfigInterface *config, + NMConnection *connection, + GError **error) +{ + return writer_new_connection (connection, IFCFG_DIR, NULL, error); +} + #define SC_NETWORK_FILE SYSCONFDIR"/sysconfig/network" static char * @@ -515,7 +526,7 @@ plugin_set_hostname (SCPluginIfcfg *plug return FALSE; } - svSetValue (network, "HOSTNAME", hostname); + svSetValue (network, "HOSTNAME", hostname, FALSE); svWriteFile (network, 0644); svCloseFile (network); @@ -633,7 +644,7 @@ get_property (GObject *object, guint pro g_value_set_string (value, IFCFG_PLUGIN_INFO); break; case NM_SYSTEM_CONFIG_INTERFACE_PROP_CAPABILITIES: - g_value_set_uint (value, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME); + g_value_set_uint (value, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS | NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME); break; case NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME: g_value_set_string (value, priv->hostname); @@ -697,6 +708,7 @@ system_config_interface_init (NMSystemCo { /* interface implementation */ system_config_interface_class->get_connections = get_connections; + system_config_interface_class->add_connection = add_connection; system_config_interface_class->get_unmanaged_devices = get_unmanaged_devices; system_config_interface_class->init = init; } Index: system-settings/plugins/ifcfg-rh/reader.c =================================================================== --- system-settings/plugins/ifcfg-rh/reader.c.orig +++ system-settings/plugins/ifcfg-rh/reader.c @@ -39,6 +39,7 @@ #undef __user #include <glib.h> +#include <glib/gi18n.h> #include <nm-connection.h> #include <NetworkManager.h> #include <nm-setting-connection.h> @@ -51,6 +52,7 @@ #include "common.h" #include "shvar.h" #include "sha1.h" +#include "utils.h" #include "reader.h" @@ -60,28 +62,43 @@ #define PLUGIN_WARN(pname, fmt, args...) \ { g_warning (" " pname ": " fmt, ##args); } -static char * -get_ifcfg_name (const char *file) -{ - char *ifcfg_name; - char *basename; +static gboolean eap_simple_reader (const char *eap_method, + shvarFile *ifcfg, + shvarFile *keys, + NMSetting8021x *s_8021x, + gboolean phase2, + GError **error); - basename = g_path_get_basename (file); - if (!basename) - return NULL; +static gboolean eap_tls_reader (const char *eap_method, + shvarFile *ifcfg, + shvarFile *keys, + NMSetting8021x *s_8021x, + gboolean phase2, + GError **error); + +static gboolean eap_peap_reader (const char *eap_method, + shvarFile *ifcfg, + shvarFile *keys, + NMSetting8021x *s_8021x, + gboolean phase2, + GError **error); + +static gboolean eap_ttls_reader (const char *eap_method, + shvarFile *ifcfg, + shvarFile *keys, + NMSetting8021x *s_8021x, + gboolean phase2, + GError **error); - ifcfg_name = g_strdup (basename + strlen (IFCFG_TAG)); - g_free (basename); - return ifcfg_name; -} static gboolean get_int (const char *str, int *value) { char *e; + errno = 0; *value = strtol (str, &e, 0); - if (*e != '\0') + if (errno || *e != '\0') return FALSE; return TRUE; @@ -96,29 +113,40 @@ make_connection_setting (const char *fil NMSettingConnection *s_con; char *ifcfg_name = NULL; char *new_id = NULL, *uuid = NULL, *value; + char *ifcfg_id; - ifcfg_name = get_ifcfg_name (file); + ifcfg_name = utils_get_ifcfg_name (file); if (!ifcfg_name) return NULL; s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ()); - if (suggested) { - /* For cosmetic reasons, if the suggested name is the same as - * the ifcfg files name, don't use it. - */ - if (strcmp (ifcfg_name, suggested)) { - new_id = g_strdup_printf ("System %s (%s)", suggested, ifcfg_name); - g_object_set (s_con, NM_SETTING_CONNECTION_ID, new_id, NULL); - } - } + /* Try the ifcfg file's internally defined name if available */ + ifcfg_id = svGetValue (ifcfg, "NAME", FALSE); + if (ifcfg_id && strlen (ifcfg_id)) + g_object_set (s_con, NM_SETTING_CONNECTION_ID, ifcfg_id, NULL); if (!nm_setting_connection_get_id (s_con)) { - new_id = g_strdup_printf ("System %s", ifcfg_name); - g_object_set (s_con, NM_SETTING_CONNECTION_ID, new_id, NULL); + if (suggested) { + /* For cosmetic reasons, if the suggested name is the same as + * the ifcfg files name, don't use it. Mainly for wifi so that + * the SSID is shown in the connection ID instead of just "wlan0". + */ + if (strcmp (ifcfg_name, suggested)) { + new_id = g_strdup_printf ("%s %s (%s)", reader_get_prefix (), suggested, ifcfg_name); + g_object_set (s_con, NM_SETTING_CONNECTION_ID, new_id, NULL); + } + } + + /* Use the ifcfg file's name as a last resort */ + if (!nm_setting_connection_get_id (s_con)) { + new_id = g_strdup_printf ("%s %s", reader_get_prefix (), ifcfg_name); + g_object_set (s_con, NM_SETTING_CONNECTION_ID, new_id, NULL); + } } g_free (new_id); + g_free (ifcfg_id); /* Try for a UUID key before falling back to hashing the file name */ uuid = svGetValue (ifcfg, "UUID", FALSE); @@ -140,12 +168,14 @@ make_connection_setting (const char *fil value = svGetValue (ifcfg, "LAST_CONNECT", FALSE); if (value) { unsigned long int tmp; + guint64 timestamp; errno = 0; tmp = strtoul (value, NULL, 10); - if (errno == 0) - g_object_set (s_con, NM_SETTING_CONNECTION_TIMESTAMP, tmp, NULL); - else + if (errno == 0) { + timestamp = (guint64) tmp; + g_object_set (s_con, NM_SETTING_CONNECTION_TIMESTAMP, timestamp, NULL); + } else PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: invalid LAST_CONNECT time"); g_free (value); } @@ -154,58 +184,163 @@ make_connection_setting (const char *fil return NM_SETTING (s_con); } -static void -get_one_ip4_addr (shvarFile *ifcfg, +static gboolean +read_ip4_address (shvarFile *ifcfg, const char *tag, guint32 *out_addr, GError **error) { char *value = NULL; struct in_addr ip4_addr; + gboolean success = FALSE; + + g_return_val_if_fail (ifcfg != NULL, FALSE); + g_return_val_if_fail (tag != NULL, FALSE); + g_return_val_if_fail (out_addr != NULL, FALSE); + g_return_val_if_fail (error != NULL, FALSE); + g_return_val_if_fail (*error == NULL, FALSE); - g_return_if_fail (ifcfg != NULL); - g_return_if_fail (tag != NULL); - g_return_if_fail (out_addr != NULL); - g_return_if_fail (*out_addr == 0); - g_return_if_fail (error != NULL); - g_return_if_fail (*error == NULL); + *out_addr = 0; value = svGetValue (ifcfg, tag, FALSE); if (!value) - return; + return TRUE; - if (inet_pton (AF_INET, value, &ip4_addr) > 0) + if (inet_pton (AF_INET, value, &ip4_addr) > 0) { *out_addr = ip4_addr.s_addr; - else { + success = TRUE; + } else { g_set_error (error, ifcfg_plugin_error_quark (), 0, "Invalid %s IP4 address '%s'", tag, value); } g_free (value); + return success; } -#define GET_ONE_DNS(tag) \ - { \ - guint32 dns = 0; \ - get_one_ip4_addr (ifcfg, tag, &dns, error); \ - if (*error) \ - goto error; \ - if (dns) { \ - if (!nm_setting_ip4_config_add_dns (s_ip4, dns)) \ - PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: duplicate DNS server %s", tag); \ - } \ +static NMIP4Address * +read_full_ip4_address (shvarFile *ifcfg, + const char *network_file, + guint32 which, + GError **error) +{ + NMIP4Address *addr; + char *ip_tag, *prefix_tag, *netmask_tag, *gw_tag; + guint32 tmp; + gboolean success = FALSE; + shvarFile *network_ifcfg; + char *value; + + g_return_val_if_fail (which > 0, NULL); + g_return_val_if_fail (ifcfg != NULL, NULL); + g_return_val_if_fail (network_file != NULL, NULL); + + addr = nm_ip4_address_new (); + if (which == 1) { + ip_tag = g_strdup ("IPADDR"); + prefix_tag = g_strdup ("PREFIX"); + netmask_tag = g_strdup ("NETMASK"); + gw_tag = g_strdup ("GATEWAY"); + } else { + ip_tag = g_strdup_printf ("IPADDR%u", which); + prefix_tag = g_strdup_printf ("PREFIX%u", which); + netmask_tag = g_strdup_printf ("NETMASK%u", which); + gw_tag = g_strdup_printf ("GATEWAY%u", which); + } + + /* IP address */ + if (!read_ip4_address (ifcfg, ip_tag, &tmp, error)) + goto error; + if (!tmp) { + nm_ip4_address_unref (addr); + addr = NULL; + success = TRUE; /* done */ + goto error; + } + nm_ip4_address_set_address (addr, tmp); + + /* Gateway */ + if (!read_ip4_address (ifcfg, gw_tag, &tmp, error)) + goto error; + if (tmp) + nm_ip4_address_set_gateway (addr, tmp); + else { + gboolean read_success; + + /* If no gateway in the ifcfg, try /etc/sysconfig/network instead */ + network_ifcfg = svNewFile (network_file); + if (network_ifcfg) { + read_success = read_ip4_address (network_ifcfg, "GATEWAY", &tmp, error); + svCloseFile (network_ifcfg); + if (!read_success) + goto error; + nm_ip4_address_set_gateway (addr, tmp); + } + } + + /* Prefix */ + value = svGetValue (ifcfg, prefix_tag, FALSE); + if (value) { + long int prefix; + + errno = 0; + prefix = strtol (value, NULL, 10); + if (errno || prefix <= 0 || prefix > 32) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Invalid IP4 prefix '%s'", value); + g_free (value); + goto error; + } + nm_ip4_address_set_prefix (addr, (guint32) prefix); + g_free (value); + } + + /* Fall back to NETMASK if no PREFIX was specified */ + if (!nm_ip4_address_get_prefix (addr)) { + if (!read_ip4_address (ifcfg, netmask_tag, &tmp, error)) + goto error; + nm_ip4_address_set_prefix (addr, nm_utils_ip4_netmask_to_prefix (tmp)); } - + + /* Validate the prefix */ + if ( !nm_ip4_address_get_prefix (addr) + || nm_ip4_address_get_prefix (addr) > 32) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Missing or invalid IP4 prefix '%d'", + nm_ip4_address_get_prefix (addr)); + goto error; + } + + success = TRUE; + +error: + if (!success) { + nm_ip4_address_unref (addr); + addr = NULL; + } + + g_free (ip_tag); + g_free (prefix_tag); + g_free (netmask_tag); + g_free (gw_tag); + return addr; +} static NMSetting * make_ip4_setting (shvarFile *ifcfg, const char *network_file, GError **error) { NMSettingIP4Config *s_ip4 = NULL; char *value = NULL; - NMIP4Address *addr = NULL; char *method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL; - guint32 netmask = 0, tmp = 0; + guint32 i; shvarFile *network_ifcfg; - gboolean never_default = FALSE; + gboolean never_default = FALSE, tmp_success; + + s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); + if (!s_ip4) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Could not allocate IP4 setting"); + return NULL; + } network_ifcfg = svNewFile (network_file); if (network_ifcfg) { @@ -232,12 +367,18 @@ make_ip4_setting (shvarFile *ifcfg, cons method = NM_SETTING_IP4_CONFIG_METHOD_AUTO; else if (!g_ascii_strcasecmp (value, "autoip")) { g_free (value); - s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL, NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, never_default, NULL); return NM_SETTING (s_ip4); + } else if (!g_ascii_strcasecmp (value, "shared")) { + g_free (value); + g_object_set (s_ip4, + NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_SHARED, + NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, never_default, + NULL); + return NM_SETTING (s_ip4); } g_free (value); } else { @@ -260,94 +401,56 @@ make_ip4_setting (shvarFile *ifcfg, cons g_free (tmp_netmask); } + g_object_set (s_ip4, + NM_SETTING_IP4_CONFIG_METHOD, method, + NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS, !svTrueValue (ifcfg, "PEERDNS", TRUE), + NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES, !svTrueValue (ifcfg, "PEERROUTES", TRUE), + NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, never_default, + NULL); + /* Handle manual settings */ if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) { - addr = nm_ip4_address_new (); - - tmp = 0; - get_one_ip4_addr (ifcfg, "IPADDR", &tmp, error); - if (*error) - goto error; - nm_ip4_address_set_address (addr, tmp); - - tmp = 0; - get_one_ip4_addr (ifcfg, "GATEWAY", &tmp, error); - if (*error) - goto error; - nm_ip4_address_set_gateway (addr, tmp); + NMIP4Address *addr; - /* If no gateway in the ifcfg, try /etc/sysconfig/network instead */ - if (!nm_ip4_address_get_gateway (addr)) { - network_ifcfg = svNewFile (network_file); - if (network_ifcfg) { - tmp = 0; - get_one_ip4_addr (network_ifcfg, "GATEWAY", &tmp, error); - svCloseFile (network_ifcfg); - if (*error) - goto error; - nm_ip4_address_set_gateway (addr, tmp); - } - } - - value = svGetValue (ifcfg, "PREFIX", FALSE); - if (value) { - long int prefix; - - errno = 0; - prefix = strtol (value, NULL, 10); - if (errno || prefix <= 0 || prefix > 32) { - g_set_error (error, ifcfg_plugin_error_quark (), 0, - "Invalid IP4 prefix '%s'", value); - g_free (value); + for (i = 1; i < 256; i++) { + addr = read_full_ip4_address (ifcfg, network_file, i, error); + if (error && *error) goto error; - } - nm_ip4_address_set_prefix (addr, (guint32) prefix); - g_free (value); - } + if (!addr) + break; - /* Fall back to NETMASK if no PREFIX was specified */ - if (!nm_ip4_address_get_prefix (addr)) { - netmask = 0; - get_one_ip4_addr (ifcfg, "NETMASK", &netmask, error); - if (*error) - goto error; - nm_ip4_address_set_prefix (addr, nm_utils_ip4_netmask_to_prefix (netmask)); - } - - /* Validate the prefix */ - if ( !nm_ip4_address_get_prefix (addr) - || nm_ip4_address_get_prefix (addr) > 32) { - g_set_error (error, ifcfg_plugin_error_quark (), 0, - "Missing or invalid IP4 prefix '%d'", - nm_ip4_address_get_prefix (addr)); - goto error; + if (!nm_setting_ip4_config_add_address (s_ip4, addr)) + PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: duplicate IP4 address"); + nm_ip4_address_unref (addr); } - } - - /* Yay, let's make an IP4 config */ - s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); - g_object_set (s_ip4, - NM_SETTING_IP4_CONFIG_METHOD, method, - NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS, !svTrueValue (ifcfg, "PEERDNS", 1), - NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, never_default, - NULL); - - /* DHCP hostname for 'send host-name' option */ - if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) { + } else if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) { value = svGetValue (ifcfg, "DHCP_HOSTNAME", FALSE); if (value && strlen (value)) g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME, value, NULL); g_free (value); - } - if (addr) { - if (!nm_setting_ip4_config_add_address (s_ip4, addr)) - PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: duplicate IP4 address"); + value = svGetValue (ifcfg, "DHCP_CLIENT_ID", FALSE); + if (value && strlen (value)) + g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, value, NULL); + g_free (value); } - GET_ONE_DNS("DNS1"); - GET_ONE_DNS("DNS2"); - GET_ONE_DNS("DNS3"); + /* DNS servers */ + for (i = 1, tmp_success = TRUE; i <= 10 && tmp_success; i++) { + char *tag; + guint32 dns; + + tag = g_strdup_printf ("DNS%u", i); + tmp_success = read_ip4_address (ifcfg, tag, &dns, error); + if (!tmp_success) { + g_free (tag); + goto error; + } + + if (dns && !nm_setting_ip4_config_add_dns (s_ip4, dns)) + PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: duplicate DNS server %s", tag); + g_free (tag); + } /* DNS searches */ value = svGetValue (ifcfg, "DOMAIN", FALSE); @@ -389,52 +492,13 @@ make_ip4_setting (shvarFile *ifcfg, cons } } - if (addr) - nm_ip4_address_unref (addr); - return NM_SETTING (s_ip4); error: - if (addr) - nm_ip4_address_unref (addr); - if (s_ip4) - g_object_unref (s_ip4); + g_object_unref (s_ip4); return NULL; } -/* - * utils_bin2hexstr - * - * Convert a byte-array into a hexadecimal string. - * - * Code originally by Alex Larsson <alexl@redhat.com> and - * copyright Red Hat, Inc. under terms of the LGPL. - * - */ -static char * -utils_bin2hexstr (const char *bytes, int len, int final_len) -{ - static char hex_digits[] = "0123456789abcdef"; - char * result; - int i; - - g_return_val_if_fail (bytes != NULL, NULL); - g_return_val_if_fail (len > 0, NULL); - g_return_val_if_fail (len < 256, NULL); /* Arbitrary limit */ - - result = g_malloc0 (len * 2 + 1); - for (i = 0; i < len; i++) - { - result[2*i] = hex_digits[(bytes[i] >> 4) & 0xf]; - result[2*i+1] = hex_digits[bytes[i] & 0xf]; - } - /* Cut converted key off at the correct length for this cipher type */ - if (final_len > -1) - result[final_len] = '\0'; - - return result; -} - static gboolean read_mac_address (shvarFile *ifcfg, GByteArray **array, GError **error) { @@ -532,44 +596,6 @@ out: return success; } -static char * -get_keys_file_path (const char *parent) -{ - char *ifcfg_name; - char *keys_file = NULL; - char *tmp = NULL; - - ifcfg_name = get_ifcfg_name (parent); - if (!ifcfg_name) - return NULL; - - tmp = g_path_get_dirname (parent); - if (!tmp) - goto out; - - keys_file = g_strdup_printf ("%s/" KEYS_TAG "%s", tmp, ifcfg_name); - -out: - g_free (tmp); - g_free (ifcfg_name); - return keys_file; -} - -static shvarFile * -get_keys_ifcfg (const char *parent) -{ - shvarFile *ifcfg = NULL; - char *keys_file; - - keys_file = get_keys_file_path (parent); - if (!keys_file) - return NULL; - - ifcfg = svNewFile (keys_file); - g_free (keys_file); - return ifcfg; -} - static gboolean read_wep_keys (shvarFile *ifcfg, guint8 def_idx, @@ -625,7 +651,7 @@ make_wep_setting (shvarFile *ifcfg, goto error; /* Try to get keys from the "shadow" key file */ - keys_ifcfg = get_keys_ifcfg (file); + keys_ifcfg = utils_get_keys_ifcfg (file, FALSE); if (keys_ifcfg) { if (!read_wep_keys (keys_ifcfg, default_key_idx, s_wireless_sec, error)) { svCloseFile (keys_ifcfg); @@ -662,7 +688,7 @@ make_wep_setting (shvarFile *ifcfg, g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "shared", NULL); } else { g_set_error (error, ifcfg_plugin_error_quark (), 0, - "Invalid WEP authentication algoritm '%s'", + "Invalid WEP authentication algorithm '%s'", lcase); g_free (lcase); goto error; @@ -781,7 +807,7 @@ parse_wpa_psk (shvarFile *ifcfg, */ /* Try to get keys from the "shadow" key file */ - keys_ifcfg = get_keys_ifcfg (file); + keys_ifcfg = utils_get_keys_ifcfg (file, FALSE); if (keys_ifcfg) { psk = svGetValue (keys_ifcfg, "WPA_PSK", TRUE); svCloseFile (keys_ifcfg); @@ -839,16 +865,567 @@ out: return hashed; } -#if 0 +typedef struct { + const char *method; + gboolean (*reader)(const char *eap_method, + shvarFile *ifcfg, + shvarFile *keys, + NMSetting8021x *s_8021x, + gboolean phase2, + GError **error); + gboolean wifi_phase2_only; +} EAPReader; + +static EAPReader eap_readers[] = { + { "md5", eap_simple_reader, TRUE }, + { "pap", eap_simple_reader, TRUE }, + { "chap", eap_simple_reader, TRUE }, + { "mschap", eap_simple_reader, TRUE }, + { "mschapv2", eap_simple_reader, TRUE }, + { "leap", eap_simple_reader, TRUE }, + { "tls", eap_tls_reader, FALSE }, + { "peap", eap_peap_reader, FALSE }, + { "ttls", eap_ttls_reader, FALSE }, + { NULL, NULL } +}; + +static gboolean +eap_simple_reader (const char *eap_method, + shvarFile *ifcfg, + shvarFile *keys, + NMSetting8021x *s_8021x, + gboolean phase2, + GError **error) +{ + char *value; + + value = svGetValue (ifcfg, "IEEE_8021X_IDENTITY", FALSE); + if (!value) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Missing IEEE_8021X_IDENTITY for EAP method '%s'.", + eap_method); + return FALSE; + } + g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, value, NULL); + g_free (value); + + value = svGetValue (ifcfg, "IEEE_8021X_PASSWORD", FALSE); + if (!value && keys) { + /* Try the lookaside keys file */ + value = svGetValue (keys, "IEEE_8021X_PASSWORD", FALSE); + } + + if (!value) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Missing IEEE_8021X_PASSWORD for EAP method '%s'.", + eap_method); + return FALSE; + } + + g_object_set (s_8021x, NM_SETTING_802_1X_PASSWORD, value, NULL); + g_free (value); + + return TRUE; +} + +static char * +get_cert_file (const char *ifcfg_path, const char *cert_path) +{ + const char *base = cert_path; + char *p, *ret, *dirname; + + g_return_val_if_fail (ifcfg_path != NULL, NULL); + g_return_val_if_fail (cert_path != NULL, NULL); + + if (cert_path[0] == '/') + return g_strdup (cert_path); + + p = strrchr (cert_path, '/'); + if (p) + base = p + 1; + + dirname = g_path_get_dirname (ifcfg_path); + ret = g_build_path ("/", dirname, base, NULL); + g_free (dirname); + return ret; +} + +static void +set_file_path (NMSetting8021x *s_8021x, + const char *path_tag, + const char *hash_tag, + const char *path, + const char *setting_key) +{ + GByteArray *data = NULL; + + g_object_set_data_full (G_OBJECT (s_8021x), path_tag, g_strdup (path), g_free); + g_object_get (G_OBJECT (s_8021x), setting_key, &data, NULL); + if (data) + g_object_set_data_full (G_OBJECT (s_8021x), hash_tag, utils_hash_byte_array (data), g_free); +} + +static gboolean +eap_tls_reader (const char *eap_method, + shvarFile *ifcfg, + shvarFile *keys, + NMSetting8021x *s_8021x, + gboolean phase2, + GError **error) +{ + char *value; + char *ca_cert = NULL; + char *real_path = NULL; + char *client_cert = NULL; + char *privkey = NULL; + char *privkey_password = NULL; + gboolean success = FALSE; + NMSetting8021xCKType privkey_type = NM_SETTING_802_1X_CK_TYPE_UNKNOWN; + + value = svGetValue (ifcfg, "IEEE_8021X_IDENTITY", FALSE); + if (!value) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Missing IEEE_8021X_IDENTITY for EAP method '%s'.", + eap_method); + return FALSE; + } + g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, value, NULL); + g_free (value); + + ca_cert = svGetValue (ifcfg, + phase2 ? "IEEE_8021X_INNER_CA_CERT" : "IEEE_8021X_CA_CERT", + FALSE); + if (ca_cert) { + real_path = get_cert_file (ifcfg->fileName, ca_cert); + if (phase2) { + if (!nm_setting_802_1x_set_phase2_ca_cert_from_file (s_8021x, real_path, NULL, error)) + goto done; + set_file_path (s_8021x, + TAG_PHASE2_CA_CERT_PATH, + TAG_PHASE2_CA_CERT_HASH, + real_path, + NM_SETTING_802_1X_PHASE2_CA_CERT); + } else { + if (!nm_setting_802_1x_set_ca_cert_from_file (s_8021x, real_path, NULL, error)) + goto done; + set_file_path (s_8021x, + TAG_CA_CERT_PATH, + TAG_CA_CERT_HASH, + real_path, + NM_SETTING_802_1X_CA_CERT); + } + } else { + PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: missing %s for EAP" + " method '%s'; this is insecure!", + phase2 ? "IEEE_8021X_INNER_CA_CERT" : "IEEE_8021X_CA_CERT", + eap_method); + } + + /* Private key password */ + privkey_password = svGetValue (ifcfg, + phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD": "IEEE_8021X_PRIVATE_KEY_PASSWORD", + FALSE); + if (!privkey_password && keys) { + /* Try the lookaside keys file */ + privkey_password = svGetValue (keys, + phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD": "IEEE_8021X_PRIVATE_KEY_PASSWORD", + FALSE); + } + + if (!privkey_password) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Missing %s for EAP method '%s'.", + phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD" : "IEEE_8021X_PRIVATE_KEY_PASSWORD", + eap_method); + goto done; + } + + /* The private key itself */ + privkey = svGetValue (ifcfg, + phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY" : "IEEE_8021X_PRIVATE_KEY", + FALSE); + if (!privkey) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Missing %s for EAP method '%s'.", + phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY" : "IEEE_8021X_PRIVATE_KEY", + eap_method); + goto done; + } + + g_free (real_path); + real_path = get_cert_file (ifcfg->fileName, privkey); + if (phase2) { + if (!nm_setting_802_1x_set_phase2_private_key_from_file (s_8021x, real_path, privkey_password, &privkey_type, error)) + goto done; + set_file_path (s_8021x, + TAG_PHASE2_PRIVATE_KEY_PATH, + TAG_PHASE2_PRIVATE_KEY_HASH, + real_path, + NM_SETTING_802_1X_PHASE2_PRIVATE_KEY); + } else { + if (!nm_setting_802_1x_set_private_key_from_file (s_8021x, real_path, privkey_password, &privkey_type, error)) + goto done; + set_file_path (s_8021x, + TAG_PRIVATE_KEY_PATH, + TAG_PRIVATE_KEY_HASH, + real_path, + NM_SETTING_802_1X_PRIVATE_KEY); + } + + /* Per NM requirements, if the private key is pkcs12, set the client cert to the + * same data as the private key, since pkcs12 files contain both. + */ + if (privkey_type == NM_SETTING_802_1X_CK_TYPE_PKCS12) { + /* Set the private key password if PKCS#12, because PKCS#12 doesn't get + * decrypted when being stored in the Setting. + */ + if (phase2) + g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD, privkey_password, NULL); + else + g_object_set (s_8021x, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD, privkey_password, NULL); + + if (phase2) { + if (!nm_setting_802_1x_set_phase2_client_cert_from_file (s_8021x, real_path, NULL, error)) + goto done; + set_file_path (s_8021x, + TAG_PHASE2_CLIENT_CERT_PATH, + TAG_PHASE2_CLIENT_CERT_HASH, + real_path, + NM_SETTING_802_1X_PHASE2_CLIENT_CERT); + } else { + if (!nm_setting_802_1x_set_client_cert_from_file (s_8021x, real_path, NULL, error)) + goto done; + set_file_path (s_8021x, + TAG_CLIENT_CERT_PATH, + TAG_CLIENT_CERT_HASH, + real_path, + NM_SETTING_802_1X_CLIENT_CERT); + } + } else { + /* Otherwise, private key is "traditional" OpenSSL format, so + * client certificate will be a separate file. + */ + client_cert = svGetValue (ifcfg, + phase2 ? "IEEE_8021X_INNER_CLIENT_CERT" : "IEEE_8021X_CLIENT_CERT", + FALSE); + if (!client_cert) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Missing %s for EAP method '%s'.", + phase2 ? "IEEE_8021X_INNER_CLIENT_CERT" : "IEEE_8021X_CLIENT_CERT", + eap_method); + goto done; + } + + g_free (real_path); + real_path = get_cert_file (ifcfg->fileName, client_cert); + if (phase2) { + if (!nm_setting_802_1x_set_phase2_client_cert_from_file (s_8021x, real_path, NULL, error)) + goto done; + set_file_path (s_8021x, + TAG_PHASE2_CLIENT_CERT_PATH, + TAG_PHASE2_CLIENT_CERT_HASH, + real_path, + NM_SETTING_802_1X_PHASE2_CLIENT_CERT); + } else { + if (!nm_setting_802_1x_set_client_cert_from_file (s_8021x, real_path, NULL, error)) + goto done; + set_file_path (s_8021x, + TAG_CLIENT_CERT_PATH, + TAG_CLIENT_CERT_HASH, + real_path, + NM_SETTING_802_1X_CLIENT_CERT); + } + } + + success = TRUE; + +done: + g_free (real_path); + g_free (ca_cert); + g_free (client_cert); + g_free (privkey); + g_free (privkey_password); + return success; +} + +static gboolean +eap_peap_reader (const char *eap_method, + shvarFile *ifcfg, + shvarFile *keys, + NMSetting8021x *s_8021x, + gboolean phase2, + GError **error) +{ + char *ca_cert = NULL; + char *real_cert_path = NULL; + char *inner_auth = NULL; + char *peapver = NULL; + char *lower; + char **list = NULL, **iter; + gboolean success = FALSE; + + ca_cert = svGetValue (ifcfg, "IEEE_8021X_CA_CERT", FALSE); + if (ca_cert) { + real_cert_path = get_cert_file (ifcfg->fileName, ca_cert); + if (!nm_setting_802_1x_set_ca_cert_from_file (s_8021x, real_cert_path, NULL, error)) + goto done; + set_file_path (s_8021x, + TAG_CA_CERT_PATH, + TAG_CA_CERT_HASH, + real_cert_path, + NM_SETTING_802_1X_CA_CERT); + } else { + PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: missing " + "IEEE_8021X_CA_CERT for EAP method '%s'; this is" + " insecure!", + eap_method); + } + + peapver = svGetValue (ifcfg, "IEEE_8021X_PEAP_VERSION", FALSE); + if (peapver) { + if (!strcmp (peapver, "0")) + g_object_set (s_8021x, NM_SETTING_802_1X_PHASE1_PEAPVER, "0", NULL); + else if (!strcmp (peapver, "1")) + g_object_set (s_8021x, NM_SETTING_802_1X_PHASE1_PEAPVER, "1", NULL); + else { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Unknown IEEE_8021X_PEAP_VERSION value '%s'", + peapver); + goto done; + } + } + + if (svTrueValue (ifcfg, "IEEE_8021X_PEAP_FORCE_NEW_LABEL", FALSE)) + g_object_set (s_8021x, NM_SETTING_802_1X_PHASE1_PEAPLABEL, "1", NULL); + + inner_auth = svGetValue (ifcfg, "IEEE_8021X_INNER_AUTH_METHODS", FALSE); + if (!inner_auth) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Missing IEEE_8021X_INNER_AUTH_METHODS."); + goto done; + } + + /* Handle options for the inner auth method */ + list = g_strsplit (inner_auth, " ", 0); + for (iter = list; iter && *iter; iter++) { + if (!strlen (*iter)) + continue; + + 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")) { + if (!eap_tls_reader (*iter, ifcfg, keys, s_8021x, TRUE, error)) + goto done; + } else { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Unknown IEEE_8021X_INNER_AUTH_METHOD '%s'.", + *iter); + goto done; + } + + lower = g_ascii_strdown (*iter, -1); + g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, lower, NULL); + g_free (lower); + break; + } + + if (!nm_setting_802_1x_get_phase2_auth (s_8021x)) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "No valid IEEE_8021X_INNER_AUTH_METHODS found."); + goto done; + } + + success = TRUE; + +done: + if (list) + g_strfreev (list); + g_free (inner_auth); + g_free (peapver); + g_free (real_cert_path); + g_free (ca_cert); + return success; +} + +static gboolean +eap_ttls_reader (const char *eap_method, + shvarFile *ifcfg, + shvarFile *keys, + NMSetting8021x *s_8021x, + gboolean phase2, + GError **error) +{ + gboolean success = FALSE; + char *anon_ident = NULL; + char *ca_cert = NULL; + char *real_cert_path = NULL; + char *inner_auth = NULL; + char *tmp; + char **list = NULL, **iter; + + ca_cert = svGetValue (ifcfg, "IEEE_8021X_CA_CERT", FALSE); + if (ca_cert) { + real_cert_path = get_cert_file (ifcfg->fileName, ca_cert); + if (!nm_setting_802_1x_set_ca_cert_from_file (s_8021x, real_cert_path, NULL, error)) + goto done; + set_file_path (s_8021x, + TAG_CA_CERT_PATH, + TAG_CA_CERT_HASH, + real_cert_path, + NM_SETTING_802_1X_CA_CERT); + } else { + PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: missing " + "IEEE_8021X_CA_CERT for EAP method '%s'; this is" + " insecure!", + eap_method); + } + + anon_ident = svGetValue (ifcfg, "IEEE_8021X_ANON_IDENTITY", FALSE); + if (anon_ident && strlen (anon_ident)) + g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, anon_ident, NULL); + + tmp = svGetValue (ifcfg, "IEEE_8021X_INNER_AUTH_METHODS", FALSE); + if (!tmp) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Missing IEEE_8021X_INNER_AUTH_METHODS."); + goto done; + } + + inner_auth = g_ascii_strdown (tmp, -1); + g_free (tmp); + + /* Handle options for the inner auth method */ + list = g_strsplit (inner_auth, " ", 0); + for (iter = list; iter && *iter; iter++) { + if (!strlen (*iter)) + continue; + + if ( !strcmp (*iter, "mschapv2") + || !strcmp (*iter, "mschap") + || !strcmp (*iter, "pap") + || !strcmp (*iter, "chap")) { + if (!eap_simple_reader (*iter, ifcfg, keys, s_8021x, TRUE, error)) + goto done; + g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, *iter, NULL); + } else if (!strcmp (*iter, "eap-tls")) { + if (!eap_tls_reader (*iter, ifcfg, keys, s_8021x, TRUE, error)) + goto done; + g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTHEAP, "tls", NULL); + } else if (!strcmp (*iter, "eap-mschapv2") || !strcmp (*iter, "eap-md5")) { + if (!eap_simple_reader (*iter, ifcfg, keys, s_8021x, TRUE, error)) + goto done; + g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTHEAP, (*iter + strlen ("eap-")), NULL); + } else { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Unknown IEEE_8021X_INNER_AUTH_METHOD '%s'.", + *iter); + goto done; + } + break; + } + + success = TRUE; + +done: + if (list) + g_strfreev (list); + g_free (inner_auth); + g_free (real_cert_path); + g_free (ca_cert); + g_free (anon_ident); + return success; +} + static NMSetting8021x * fill_8021x (shvarFile *ifcfg, const char *file, const char *key_mgmt, + gboolean wifi, GError **error) { + NMSetting8021x *s_8021x; + shvarFile *keys = NULL; + char *value; + char **list, **iter; + + value = svGetValue (ifcfg, "IEEE_8021X_EAP_METHODS", FALSE); + if (!value) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Missing IEEE_8021X_EAP_METHODS for key management '%s'", + key_mgmt); + return NULL; + } + + list = g_strsplit (value, " ", 0); + g_free (value); + + s_8021x = (NMSetting8021x *) nm_setting_802_1x_new (); + + /* Read in the lookaside keys file, if present */ + keys = utils_get_keys_ifcfg (file, FALSE); + + /* Validate and handle each EAP method */ + for (iter = list; iter && *iter; iter++) { + EAPReader *eap = &eap_readers[0]; + gboolean found = FALSE; + char *lower = NULL; + + lower = g_ascii_strdown (*iter, -1); + while (*eap->method && !found) { + if (strcmp (eap->method, lower)) + goto next; + + /* Some EAP methods don't provide keying material, thus they + * cannot be used with WiFi unless they are an inner method + * used with TTLS or PEAP or whatever. + */ + if (wifi && eap->wifi_phase2_only) { + PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: ignored invalid " + "IEEE_8021X_EAP_METHOD '%s'; not allowed for wifi.", + lower); + goto next; + } + + /* Parse EAP method specific options */ + if (!(*eap->reader)(lower, ifcfg, keys, s_8021x, FALSE, error)) { + g_free (lower); + goto error; + } + nm_setting_802_1x_add_eap_method (s_8021x, lower); + found = TRUE; + + next: + eap++; + } + + if (!found) { + PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: ignored unknown" + "IEEE_8021X_EAP_METHOD '%s'.", + lower); + } + g_free (lower); + } + g_strfreev (list); + + if (nm_setting_802_1x_get_num_eap_methods (s_8021x) == 0) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "No valid EAP methods found in IEEE_8021X_EAP_METHODS."); + goto error; + } + + if (keys) + svCloseFile (keys); + return s_8021x; + +error: + if (keys) + svCloseFile (keys); + g_object_unref (s_8021x); return NULL; } -#endif static NMSetting * make_wpa_setting (shvarFile *ifcfg, @@ -859,7 +1436,7 @@ make_wpa_setting (shvarFile *ifcfg, GError **error) { NMSettingWirelessSecurity *wsec; - char *value, *psk; + char *value, *psk, *lower; wsec = NM_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_new ()); @@ -876,10 +1453,26 @@ make_wpa_setting (shvarFile *ifcfg, /* Ad-Hoc mode only supports WPA proto for now */ nm_setting_wireless_security_add_proto (wsec, "wpa"); } else { - if (svTrueValue (ifcfg, "WPA_ALLOW_WPA", TRUE)) + char *allow_wpa, *allow_rsn; + + allow_wpa = svGetValue (ifcfg, "WPA_ALLOW_WPA", FALSE); + allow_rsn = svGetValue (ifcfg, "WPA_ALLOW_WPA2", FALSE); + + if (allow_wpa && svTrueValue (ifcfg, "WPA_ALLOW_WPA", TRUE)) nm_setting_wireless_security_add_proto (wsec, "wpa"); - if (svTrueValue (ifcfg, "WPA_ALLOW_WPA2", TRUE)) + if (allow_rsn && svTrueValue (ifcfg, "WPA_ALLOW_WPA2", TRUE)) nm_setting_wireless_security_add_proto (wsec, "rsn"); + + /* If neither WPA_ALLOW_WPA or WPA_ALLOW_WPA2 were present, default + * to both WPA and RSN allowed. + */ + if (!allow_wpa && !allow_rsn) { + nm_setting_wireless_security_add_proto (wsec, "wpa"); + nm_setting_wireless_security_add_proto (wsec, "rsn"); + } + + g_free (allow_wpa); + g_free (allow_rsn); } if (!strcmp (value, "WPA-PSK")) { @@ -893,7 +1486,6 @@ make_wpa_setting (shvarFile *ifcfg, g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-none", NULL); else g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", NULL); -#if 0 } else if (!strcmp (value, "WPA-EAP") || !strcmp (value, "IEEE8021X")) { /* Adhoc mode is mutually exclusive with any 802.1x-based authentication */ if (adhoc) { @@ -902,10 +1494,13 @@ make_wpa_setting (shvarFile *ifcfg, goto error; } - *s_8021x = fill_8021x (ifcfg, file, value, error); + *s_8021x = fill_8021x (ifcfg, file, value, TRUE, error); if (!*s_8021x) goto error; -#endif + + lower = g_ascii_strdown (value, -1); + g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, lower, NULL); + g_free (lower); } else { g_set_error (error, ifcfg_plugin_error_quark (), 0, "Unknown wireless KEY_MGMT type '%s'", value); @@ -923,6 +1518,64 @@ error: } static NMSetting * +make_leap_setting (shvarFile *ifcfg, + const char *file, + GError **error) +{ + NMSettingWirelessSecurity *wsec; + shvarFile *keys_ifcfg; + char *value; + + wsec = NM_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_new ()); + + value = svGetValue (ifcfg, "KEY_MGMT", FALSE); + if (!value || strcmp (value, "IEEE8021X")) + goto error; /* Not LEAP */ + + g_free (value); + value = svGetValue (ifcfg, "SECURITYMODE", FALSE); + if (!value || strcasecmp (value, "leap")) + goto error; /* Not LEAP */ + + g_free (value); + + value = svGetValue (ifcfg, "IEEE_8021X_PASSWORD", FALSE); + if (!value) { + /* Try to get keys from the "shadow" key file */ + keys_ifcfg = utils_get_keys_ifcfg (file, FALSE); + if (keys_ifcfg) { + value = svGetValue (keys_ifcfg, "IEEE_8021X_PASSWORD", FALSE); + svCloseFile (keys_ifcfg); + } + } + if (value && strlen (value)) + g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD, value, NULL); + g_free (value); + + value = svGetValue (ifcfg, "IEEE_8021X_IDENTITY", FALSE); + if (!value || !strlen (value)) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Missing LEAP identity"); + goto error; + } + g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, value, NULL); + g_free (value); + + g_object_set (wsec, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", + NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "leap", + NULL); + + return (NMSetting *) wsec; + +error: + g_free (value); + if (wsec) + g_object_unref (wsec); + return NULL; +} + +static NMSetting * make_wireless_security_setting (shvarFile *ifcfg, const char *file, const GByteArray *ssid, @@ -932,6 +1585,14 @@ make_wireless_security_setting (shvarFil { NMSetting *wsec; + if (!adhoc) { + wsec = make_leap_setting (ifcfg, file, error); + if (wsec) + return wsec; + else if (*error) + return NULL; + } + wsec = make_wpa_setting (ifcfg, file, ssid, adhoc, s_8021x, error); if (wsec) return wsec; @@ -959,30 +1620,73 @@ make_wireless_setting (shvarFile *ifcfg, s_wireless = NM_SETTING_WIRELESS (nm_setting_wireless_new ()); if (read_mac_address (ifcfg, &array, error)) { - g_object_set (s_wireless, NM_SETTING_WIRELESS_MAC_ADDRESS, array, NULL); - g_byte_array_free (array, TRUE); + if (array) { + g_object_set (s_wireless, NM_SETTING_WIRELESS_MAC_ADDRESS, array, NULL); + g_byte_array_free (array, TRUE); + } } else { g_object_unref (s_wireless); return NULL; } - value = svGetValue (ifcfg, "ESSID", FALSE); + value = svGetValue (ifcfg, "ESSID", TRUE); if (value) { - gsize len = strlen (value); + gsize ssid_len = 0, value_len = strlen (value); + char *p = value, *tmp; + gboolean quoted = FALSE; + char buf[33]; + + ssid_len = value_len; + if ( (value_len >= 2) + && (value[0] == '"') + && (value[value_len - 1] == '"')) { + /* Strip the quotes and unescape */ + p = value + 1; + value[value_len - 1] = '\0'; + svUnescape (p); + ssid_len = strlen (p); + quoted = TRUE; + } else if ((value_len > 2) && (strncmp (value, "0x", 2) == 0)) { + /* Hex representation */ + if (value_len % 2) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Invalid SSID '%s' size (looks like hex but length not multiple of 2)", + value); + g_free (value); + goto error; + } + + p = value + 2; + while (*p) { + if (!isxdigit (*p)) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Invalid SSID '%s' character (looks like hex SSID but '%c' isn't a hex digit)", + value, *p); + g_free (value); + goto error; + } + p++; + } + + tmp = utils_hexstr2bin (value + 2, value_len - 2); + ssid_len = (value_len - 2) / 2; + memcpy (buf, tmp, ssid_len); + p = &buf[0]; + } - if (len > 32 || len == 0) { + if (ssid_len > 32 || ssid_len == 0) { g_set_error (error, ifcfg_plugin_error_quark (), 0, "Invalid SSID '%s' (size %zu not between 1 and 32 inclusive)", - value, len); + value, ssid_len); g_free (value); goto error; } - array = g_byte_array_sized_new (strlen (value)); - g_byte_array_append (array, (const guint8 *) value, len); - g_free (value); + array = g_byte_array_sized_new (ssid_len); + g_byte_array_append (array, (const guint8 *) p, ssid_len); g_object_set (s_wireless, NM_SETTING_WIRELESS_SSID, array, NULL); g_byte_array_free (array, TRUE); + g_free (value); } else { /* Only fail on lack of SSID if device is managed */ if (!unmanaged) { @@ -991,33 +1695,86 @@ make_wireless_setting (shvarFile *ifcfg, } } - if (!unmanaged) { - value = svGetValue (ifcfg, "MODE", FALSE); - if (value) { - char *lcase; - const char *mode = NULL; + if (unmanaged) + goto done; - lcase = g_ascii_strdown (value, -1); - g_free (value); + value = svGetValue (ifcfg, "MODE", FALSE); + if (value) { + char *lcase; + const char *mode = NULL; - if (!strcmp (lcase, "ad-hoc")) { - mode = "adhoc"; - } else if (!strcmp (lcase, "managed")) { - mode = "infrastructure"; - } else { - g_set_error (error, ifcfg_plugin_error_quark (), 0, - "Invalid mode '%s' (not 'Ad-Hoc' or 'Managed')", - lcase); - g_free (lcase); - goto error; - } + lcase = g_ascii_strdown (value, -1); + g_free (value); + + if (!strcmp (lcase, "ad-hoc")) { + mode = "adhoc"; + } else if (!strcmp (lcase, "managed")) { + mode = "infrastructure"; + } else { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Invalid mode '%s' (not 'Ad-Hoc' or 'Managed')", + lcase); g_free (lcase); + goto error; + } + g_free (lcase); + + g_object_set (s_wireless, NM_SETTING_WIRELESS_MODE, mode, NULL); + } + + value = svGetValue (ifcfg, "BSSID", FALSE); + if (value) { + struct ether_addr *eth; + GByteArray *bssid; + + eth = ether_aton (value); + if (!eth) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Invalid BSSID '%s'", value); + goto error; + } + + bssid = g_byte_array_sized_new (ETH_ALEN); + g_byte_array_append (bssid, eth->ether_addr_octet, ETH_ALEN); + g_object_set (s_wireless, NM_SETTING_WIRELESS_BSSID, bssid, NULL); + g_byte_array_free (bssid, TRUE); + } + + value = svGetValue (ifcfg, "CHANNEL", FALSE); + if (value) { + long int chan; + + errno = 0; + chan = strtol (value, NULL, 10); + if (errno || chan <= 0 || chan > 196) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Invalid wireless channel '%s'", value); + g_free (value); + goto error; + } + g_object_set (s_wireless, NM_SETTING_WIRELESS_CHANNEL, (guint32) chan, NULL); + if (chan > 14) + g_object_set (s_wireless, NM_SETTING_WIRELESS_BAND, "a", NULL); + else + g_object_set (s_wireless, NM_SETTING_WIRELESS_BAND, "bg", NULL); + } + + value = svGetValue (ifcfg, "MTU", FALSE); + if (value) { + long int mtu; - g_object_set (s_wireless, NM_SETTING_WIRELESS_MODE, mode, NULL); + errno = 0; + mtu = strtol (value, NULL, 10); + if (errno || mtu < 0 || mtu > 50000) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Invalid wireless MTU '%s'", value); + g_free (value); + goto error; } - // FIXME: channel/freq, other L2 parameters like RTS + g_object_set (s_wireless, NM_SETTING_WIRELESS_MTU, (guint32) mtu, NULL); } +done: return NM_SETTING (s_wireless); error: @@ -1114,10 +1871,14 @@ wireless_connection_from_ifcfg (const ch } static NMSetting * -make_wired_setting (shvarFile *ifcfg, gboolean unmanaged, GError **error) +make_wired_setting (shvarFile *ifcfg, + const char *file, + gboolean unmanaged, + NMSetting8021x **s_8021x, + GError **error) { NMSettingWired *s_wired; - char *value; + char *value = NULL; int mtu; GByteArray *mac = NULL; @@ -1136,14 +1897,35 @@ make_wired_setting (shvarFile *ifcfg, gb } if (read_mac_address (ifcfg, &mac, error)) { - g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, mac, NULL); - g_byte_array_free (mac, TRUE); + if (mac) { + g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, mac, NULL); + g_byte_array_free (mac, TRUE); + } } else { g_object_unref (s_wired); s_wired = NULL; } + value = svGetValue (ifcfg, "KEY_MGMT", FALSE); + if (value) { + if (!strcmp (value, "IEEE8021X")) { + *s_8021x = fill_8021x (ifcfg, file, value, FALSE, error); + if (!*s_8021x) + goto error; + } else { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Unknown wired KEY_MGMT type '%s'", value); + goto error; + } + g_free (value); + } + return (NMSetting *) s_wired; + +error: + g_free (value); + g_object_unref (s_wired); + return NULL; } static NMConnection * @@ -1155,6 +1937,7 @@ wired_connection_from_ifcfg (const char NMConnection *connection = NULL; NMSetting *con_setting = NULL; NMSetting *wired_setting = NULL; + NMSetting8021x *s_8021x = NULL; g_return_val_if_fail (file != NULL, NULL); g_return_val_if_fail (ifcfg != NULL, NULL); @@ -1175,13 +1958,16 @@ wired_connection_from_ifcfg (const char } nm_connection_add_setting (connection, con_setting); - wired_setting = make_wired_setting (ifcfg, unmanaged, error); + wired_setting = make_wired_setting (ifcfg, file, unmanaged, &s_8021x, error); if (!wired_setting) { g_object_unref (connection); return NULL; } nm_connection_add_setting (connection, wired_setting); + if (s_8021x) + nm_connection_add_setting (connection, NM_SETTING (s_8021x)); + if (!nm_connection_verify (connection, error)) { g_object_unref (connection); return NULL; @@ -1241,7 +2027,6 @@ connection_from_file (const char *filena gboolean *ignore_error) { NMConnection *connection = NULL; - NMSettingConnection *s_con; shvarFile *parsed; char *type; char *nmc = NULL; @@ -1257,7 +2042,7 @@ connection_from_file (const char *filena if (!network_file) network_file = SYSCONFDIR "/sysconfig/network"; - ifcfg_name = get_ifcfg_name (filename); + ifcfg_name = utils_get_ifcfg_name (filename); if (!ifcfg_name) { g_set_error (error, ifcfg_plugin_error_quark (), 0, "Ignoring connection '%s' because it's not an ifcfg file.", filename); @@ -1334,13 +2119,6 @@ connection_from_file (const char *filena g_free (type); - /* We don't write connections yet */ - if (connection) { - s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION); - if (s_con) - g_object_set (s_con, NM_SETTING_CONNECTION_READ_ONLY, TRUE, NULL); - } - /* Don't bother reading the connection fully if it's unmanaged */ if (!connection || *ignored) goto done; @@ -1359,11 +2137,16 @@ connection_from_file (const char *filena connection = NULL; } - *keyfile = get_keys_file_path (filename); + *keyfile = utils_get_keys_path (filename); done: svCloseFile (parsed); return connection; } +const char * +reader_get_prefix (void) +{ + return _("System"); +} Index: system-settings/plugins/ifcfg-rh/reader.h =================================================================== --- system-settings/plugins/ifcfg-rh/reader.h.orig +++ system-settings/plugins/ifcfg-rh/reader.h @@ -24,8 +24,7 @@ #include <glib.h> #include <nm-connection.h> -#define TYPE_ETHERNET "Ethernet" -#define TYPE_WIRELESS "Wireless" +#include "shvar.h" NMConnection *connection_from_file (const char *filename, const char *network_file, @@ -35,4 +34,6 @@ NMConnection *connection_from_file (cons GError **error, gboolean *ignore_error); +const char *reader_get_prefix (void); + #endif /* __READER_H__ */ Index: system-settings/plugins/ifcfg-rh/shvar.c =================================================================== --- system-settings/plugins/ifcfg-rh/shvar.c.orig +++ system-settings/plugins/ifcfg-rh/shvar.c @@ -112,8 +112,8 @@ svCreateFile(const char *name) } /* remove escaped characters in place */ -static void -unescape(char *s) { +void +svUnescape(char *s) { int len, i; len = strlen(s); @@ -142,8 +142,8 @@ unescape(char *s) { */ static const char escapees[] = "\"'\\$~`"; /* must be escaped */ static const char spaces[] = " \t|&;()<>"; /* only require "" */ -static char * -escape(const char *s) { +char * +svEscape(const char *s) { char *new; int i, j, mangle = 0, space = 0; int newlen, slen; @@ -202,7 +202,7 @@ svGetValue(shvarFile *s, const char *key if (!strncmp(keyString, line, len)) { value = g_strdup(line + len); if (!verbatim) - unescape(value); + svUnescape(value); break; } } @@ -272,7 +272,7 @@ svTrueValue(shvarFile *s, const char *ke * */ void -svSetValue(shvarFile *s, const char *key, const char *value) +svSetValue(shvarFile *s, const char *key, const char *value, gboolean verbatim) { char *newval = NULL, *val1 = NULL, *val2 = NULL; char *keyValue; @@ -281,7 +281,8 @@ svSetValue(shvarFile *s, const char *key g_assert(key); /* value may be NULL */ - if (value) newval = escape(value); + if (value) + newval = verbatim ? g_strdup(value) : svEscape(value); keyValue = g_strdup_printf("%s=%s", key, newval ? newval : ""); val1 = svGetValue(s, key, FALSE); Index: system-settings/plugins/ifcfg-rh/shvar.h =================================================================== --- system-settings/plugins/ifcfg-rh/shvar.h.orig +++ system-settings/plugins/ifcfg-rh/shvar.h @@ -77,7 +77,7 @@ svTrueValue(shvarFile *s, const char *ke * to the top of the file. */ void -svSetValue(shvarFile *s, const char *key, const char *value); +svSetValue(shvarFile *s, const char *key, const char *value, gboolean verbatim); /* Write the current contents iff modified. Returns -1 on error @@ -95,6 +95,14 @@ svWriteFile(shvarFile *s, int mode); int svCloseFile(shvarFile *s); +/* Return a new escaped string */ +char * +svEscape(const char *s); + +/* Unescape a string in-place */ +void +svUnescape(char *s); + #ifdef __cplusplus } #endif /* __cplusplus */ Index: system-settings/plugins/ifcfg-rh/tests/Makefile.am =================================================================== --- system-settings/plugins/ifcfg-rh/tests/Makefile.am.orig +++ system-settings/plugins/ifcfg-rh/tests/Makefile.am @@ -14,7 +14,8 @@ test_ifcfg_rh_SOURCES = \ test_ifcfg_rh_CPPFLAGS = \ $(GLIB_CFLAGS) \ $(DBUS_CFLAGS) \ - -DTEST_DIR=\"$(abs_srcdir)/\" + -DTEST_IFCFG_DIR=\"$(abs_srcdir)\" \ + -DTEST_SCRATCH_DIR=\"$(abs_builddir)/\" test_ifcfg_rh_LDADD = \ $(DBUS_LIBS) \ Index: system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-leap =================================================================== --- /dev/null +++ system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-leap @@ -0,0 +1,17 @@ +TYPE=Wireless +DEVICE=eth2 +HWADDR=00:16:41:11:22:33 +NM_CONTROLLED=yes +BOOTPROTO=dhcp +ESSID=blahblah +CHANNEL=1 +MODE=Managed +RATE=auto +ONBOOT=yes +USERCTL=yes +PEERDNS=yes +IPV6INIT=no +KEY_MGMT=IEEE8021X +SECURITYMODE=LEAP +IEEE_8021X_IDENTITY="Bill Smith" + Index: system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-bad-hex =================================================================== --- /dev/null +++ system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-bad-hex @@ -0,0 +1,13 @@ +TYPE=Wireless +DEVICE=eth2 +HWADDR=00:16:41:11:22:33 +NM_CONTROLLED=yes +BOOTPROTO=dhcp +ESSID=0x626cxx +CHANNEL=1 +MODE=Managed +RATE=auto +ONBOOT=yes +USERCTL=yes +PEERDNS=yes +IPV6INIT=no Index: system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-hex =================================================================== --- /dev/null +++ system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-hex @@ -0,0 +1,13 @@ +TYPE=Wireless +DEVICE=eth2 +HWADDR=00:16:41:11:22:33 +NM_CONTROLLED=yes +BOOTPROTO=dhcp +ESSID=0x626c6168626c6168 +CHANNEL=1 +MODE=Managed +RATE=auto +ONBOOT=yes +USERCTL=yes +PEERDNS=yes +IPV6INIT=no Index: system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-long-hex =================================================================== --- /dev/null +++ system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-long-hex @@ -0,0 +1,13 @@ +TYPE=Wireless +DEVICE=eth2 +HWADDR=00:16:41:11:22:33 +NM_CONTROLLED=yes +BOOTPROTO=dhcp +ESSID=0x626c6168626c6168626c6168626c6168626c6168626c6168626c6168626c6168AA +CHANNEL=1 +MODE=Managed +RATE=auto +ONBOOT=yes +USERCTL=yes +PEERDNS=yes +IPV6INIT=no Index: system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-long-quoted =================================================================== --- /dev/null +++ system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-long-quoted @@ -0,0 +1,13 @@ +TYPE=Wireless +DEVICE=eth2 +HWADDR=00:16:41:11:22:33 +NM_CONTROLLED=yes +BOOTPROTO=dhcp +ESSID="foo\"bar\\foo\"bar\\foo\"bar\\foo\"bar\\1" +CHANNEL=1 +MODE=Managed +RATE=auto +ONBOOT=yes +USERCTL=yes +PEERDNS=yes +IPV6INIT=no Index: system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-quoted =================================================================== --- /dev/null +++ system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-quoted @@ -0,0 +1,13 @@ +TYPE=Wireless +DEVICE=eth2 +HWADDR=00:16:41:11:22:33 +NM_CONTROLLED=yes +BOOTPROTO=dhcp +ESSID="foo\"bar\\" +CHANNEL=1 +MODE=Managed +RATE=auto +ONBOOT=yes +USERCTL=yes +PEERDNS=yes +IPV6INIT=no Index: system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-eap-ttls-chap =================================================================== --- /dev/null +++ system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-eap-ttls-chap @@ -0,0 +1,20 @@ +# Intel Corporation 82540EP Gigabit Ethernet Controller (Mobile) +TYPE=Wireless +DEVICE=eth2 +HWADDR=00:16:41:11:22:33 +BOOTPROTO=dhcp +ONBOOT=yes +ONBOOT=yes +USERCTL=yes +IPV6INIT=no +NM_CONTROLLED=yes +PEERDNS=yes +ESSID=blahblah +MODE=Managed +RATE=auto +KEY_MGMT=IEEE8021X +IEEE_8021X_EAP_METHODS=TTLS +IEEE_8021X_IDENTITY="David Smith" +IEEE_8021X_CA_CERT=test_ca_cert.pem +IEEE_8021X_INNER_AUTH_METHODS=CHAP + Index: system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-tls =================================================================== --- /dev/null +++ system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-tls @@ -0,0 +1,25 @@ +# Intel Corporation 82540EP Gigabit Ethernet Controller (Mobile) +TYPE=Wireless +DEVICE=eth2 +HWADDR=00:16:41:11:22:33 +BOOTPROTO=dhcp +ONBOOT=yes +ONBOOT=yes +USERCTL=yes +IPV6INIT=no +NM_CONTROLLED=yes +PEERDNS=yes +ESSID=blahblah +MODE=Managed +RATE=auto +CIPHER_PAIRWISE="TKIP CCMP" +CIPHER_GROUP="TKIP CCMP WEP40 WEP104" +KEY_MGMT=WPA-EAP +WPA_ALLOW_WPA=yes +WPA_ALLOW_WPA2=yes +IEEE_8021X_EAP_METHODS=TLS +IEEE_8021X_IDENTITY="Bill Smith" +IEEE_8021X_CA_CERT=test_ca_cert.pem +IEEE_8021X_CLIENT_CERT=test1_key_and_cert.pem +IEEE_8021X_PRIVATE_KEY=test1_key_and_cert.pem + Index: system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-ttls-tls =================================================================== --- /dev/null +++ system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-ttls-tls @@ -0,0 +1,28 @@ +# Intel Corporation 82540EP Gigabit Ethernet Controller (Mobile) +TYPE=Wireless +DEVICE=eth2 +HWADDR=00:16:41:11:22:33 +BOOTPROTO=dhcp +ONBOOT=yes +ONBOOT=yes +USERCTL=yes +IPV6INIT=no +NM_CONTROLLED=yes +PEERDNS=yes +ESSID=blahblah +MODE=Managed +RATE=auto +CIPHER_PAIRWISE="TKIP CCMP" +CIPHER_GROUP="TKIP CCMP WEP40 WEP104" +KEY_MGMT=WPA-EAP +WPA_ALLOW_WPA=yes +WPA_ALLOW_WPA2=yes +IEEE_8021X_EAP_METHODS=TTLS +IEEE_8021X_IDENTITY="Chuck Shumer" +IEEE_8021X_ANON_IDENTITY="anonymous" +IEEE_8021X_CA_CERT=test_ca_cert.pem +IEEE_8021X_INNER_AUTH_METHODS=EAP-TLS +IEEE_8021X_INNER_CA_CERT=test_ca_cert.pem +IEEE_8021X_INNER_CLIENT_CERT=test1_key_and_cert.pem +IEEE_8021X_INNER_PRIVATE_KEY=test1_key_and_cert.pem + Index: system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-peap-mschapv2 =================================================================== --- /dev/null +++ system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-peap-mschapv2 @@ -0,0 +1,15 @@ +# Intel Corporation 82540EP Gigabit Ethernet Controller (Mobile) +TYPE=Ethernet +DEVICE=eth0 +HWADDR=00:11:22:33:44:ee +BOOTPROTO=dhcp +ONBOOT=yes +NM_CONTROLLED=yes +KEY_MGMT=IEEE8021X +IEEE_8021X_EAP_METHODS=PEAP +IEEE_8021X_IDENTITY="David Smith" +IEEE_8021X_CA_CERT=test_ca_cert.pem +IEEE_8021X_PEAP_VERSION=1 +IEEE_8021X_PEAP_FORCE_NEW_LABEL=yes +IEEE_8021X_INNER_AUTH_METHODS=MSCHAPV2 + Index: system-settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-leap =================================================================== --- /dev/null +++ system-settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-leap @@ -0,0 +1 @@ +IEEE_8021X_PASSWORD="foobarblah" Index: system-settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-eap-ttls-chap =================================================================== --- /dev/null +++ system-settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-eap-ttls-chap @@ -0,0 +1,2 @@ +IEEE_8021X_PASSWORD="foobar baz" + Index: system-settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-eap-tls =================================================================== --- /dev/null +++ system-settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-eap-tls @@ -0,0 +1,2 @@ +IEEE_8021X_PRIVATE_KEY_PASSWORD="test1" + Index: system-settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-eap-ttls-tls =================================================================== --- /dev/null +++ system-settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-eap-ttls-tls @@ -0,0 +1,2 @@ +IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD="test1" + Index: system-settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wired-8021x-peap-mschapv2 =================================================================== --- /dev/null +++ system-settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wired-8021x-peap-mschapv2 @@ -0,0 +1,2 @@ +IEEE_8021X_PASSWORD="foobar baz" + Index: system-settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am =================================================================== --- system-settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am.orig +++ system-settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am @@ -7,18 +7,35 @@ EXTRA_DIST = \ network-test-wired-global-gateway \ ifcfg-test-wired-never-default \ network-test-wired-never-default \ + ifcfg-test-wired-8021x-peap-mschapv2 \ + keys-test-wired-8021x-peap-mschapv2 \ ifcfg-test-onboot-no \ ifcfg-test-wifi-open \ + ifcfg-test-wifi-open-ssid-quoted \ + ifcfg-test-wifi-open-ssid-long-quoted \ + ifcfg-test-wifi-open-ssid-hex \ + ifcfg-test-wifi-open-ssid-long-hex \ + ifcfg-test-wifi-open-ssid-bad-hex \ ifcfg-test-wifi-wep \ keys-test-wifi-wep \ ifcfg-test-wifi-wep-adhoc \ keys-test-wifi-wep-adhoc \ + ifcfg-test-wifi-wep-eap-ttls-chap \ + keys-test-wifi-wep-eap-ttls-chap \ + ifcfg-test-wifi-leap \ + keys-test-wifi-leap \ ifcfg-test-wifi-wpa-psk \ keys-test-wifi-wpa-psk \ ifcfg-test-wifi-wpa-psk-adhoc \ keys-test-wifi-wpa-psk-adhoc \ ifcfg-test-wifi-wpa-psk-hex \ - keys-test-wifi-wpa-psk-hex + keys-test-wifi-wpa-psk-hex \ + ifcfg-test-wifi-wpa-eap-tls \ + keys-test-wifi-wpa-eap-tls \ + ifcfg-test-wifi-wpa-eap-ttls-tls \ + keys-test-wifi-wpa-eap-ttls-tls \ + test_ca_cert.pem \ + test1_key_and_cert.pem check-local: @for f in $(EXTRA_DIST); do \ Index: system-settings/plugins/ifcfg-rh/tests/network-scripts/test1_key_and_cert.pem =================================================================== --- /dev/null +++ system-settings/plugins/ifcfg-rh/tests/network-scripts/test1_key_and_cert.pem @@ -0,0 +1,118 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,4DE0615F23D82107 + +QPNCO5Dobvz9dDhN32KkZRoEifW+HDm2PCbRQhKDiscGwB6LgypvVjHNsZiFKwzz +L4R51UqgQeJx7GSGJqE626e9z9J+UNBhop02aOO2X0eSPdvBzr/uJ6Umiyr1xqD7 +zWf7u9l5kXElDJRhK+87GMBewp4Ie9NeXDjhF8hzC5Kiulen4AH3AYnfH3S7DimU +h8GFMg8inrudrTbcjBhCdPeHG2jCygOxw3InRFz7uaN6LIhOaPQvmvpP4Cc1WRnW +ZPq9o+eU3fPWPD5t+Op/VzYLvKwgBy/yK1rQXUm6ZMO7MhhRJ94ZCsJv+nVWpJlv +QyBlxDKxwfkfYbDELdnnDQdHdMbKatLqa0KhSkgpp8LywBtanPz731tyT0r7b3na +eLdra59lRU7ZQLPEdS3lPZd2O/KQvWf8wbg7MjXS9LxQ7R5HOPu6DNJlwXVZBmmo +cAfu2q8ubU2IePvWLD1GOrBi6hE9TiGvFJkw+wBK+t72sz3njv9Xm/zlxruaEk5m +RW/kybU3FP4PtjriBbskz3/VZaaxuRN7OoOYTkmyHmG1ADgcRUV6fea19qqsBlN8 +xb+SRtoH28oT/JVWU5neE2dbNzk5LeVO+w70NNdR5s5xqkBhbGGaJxvXwNP4ltFr +T06SMh8znOLKwWB00aRtwfU7jOwR3mOleQO4ugIHmau3zp1TqzAHW8XtpuV7qVeI +ESZOZuf0vW43BtNzgLXt1+r+bmsMsRwhnyomL9M0TUyyBdVYY9GkzTG9pOESheRo +RSvAZ8qKGUliTpgBcbt2v1+NqkszcHa6FxuvS8YU4uo5/GqsgTxHTNIB232hIrrZ +EIm6QL9TC5oFXMjy6UNqoCm5Nb8DBJ6aErt7pt7aoktqUW3O3QIzQT3IbZ4nAcTt +lVF4d7j29I9t7bcC8GOVU1neilguZUss4ghJg9x4zI5UZdR7hZ8fbFT47TyxB+j5 +r0YdmjbjVTaSyaN2JGh1wvb4TzawGNVx/U2EJE16HigOtPfsfQRJ3x+FROKBdVa4 +aIFYXkRBeIPxX6n9pcw0lBCsnXo6/5iTjQSk2VqO3rHO/wyWiEjNczhL33dY2A8W +GG5ECMO5SqXZHQQzpABqK94dxe3UC8aEESO5NhEqDuV7qQGol0qPKrUA3wb0jb2e +DrejJ9HS2m1SUDmjpvvmEGy6GN7CRibbKt5rNZdJNNvWArOF5d0F6wkixQLl73oE +lq5gLQQk9n7ClleKLhlQpBCorxilBbzmSUekkJLi0eaZiBBFWBX9udqnUZloXTgO +8qwuO8K/GPR9Jy1/UH2Vh1H+wivaqKTVgEb0NotzgzECgTEFKJafl7rUNs1OZRZ3 +VBjevi6+iDpxVFgF71kXfdUC4ph0E1XDl0ja2rrKQGivMkUhWJ57+4EV5+hBkAnt +G0RV45NwHXLrK2bd8F9PlRk2XHW6mIcFRXsW1DjeBhk/sQjvlO9R01GRSgcXtekJ +tmX17FWrMrzXHpvy1IC3fk4RVnSjpzQ8O+17YE8/la9wVaeZZzHyYFmMT7VXjIhW +QozJQ0vJ2jxJRh5GYn3tpJzdaeRfvTBik0pChNdUTnWP+BJ35xoCTs8iwJbmgVZ1 +-----END RSA PRIVATE KEY----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, ST=Berkshire, L=Newbury, O=My Company Ltd, OU=Testing, CN=test/emailAddress=test@test.com + Validity + Not Before: Mar 10 15:13:16 2009 GMT + Not After : Mar 8 15:13:16 2019 GMT + Subject: C=US, ST=Berkshire, O=My Company Ltd, OU=Testing, CN=test1/emailAddress=test@test.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:cd:34:b1:2e:b0:04:c6:f4:2b:a2:c0:a0:39:7a: + 82:ed:96:c4:f7:19:83:91:5c:b4:e7:9c:de:ec:48: + ec:2d:e4:51:08:26:42:ac:d3:98:26:7a:72:f7:49: + c2:9e:66:05:c6:47:29:fe:3b:ac:6b:af:6f:5e:a8: + 03:5a:73:33:ba:19:03:00:35:f5:00:bc:a8:be:14: + ce:46:69:e3:6d:ed:34:37:85:55:87:62:b3:b7:c9: + c0:cc:9a:aa:61:05:5b:cd:a2:17:42:d3:e5:6f:1c: + 60:8d:c2:15:41:46:f8:12:54:d0:38:57:e1:fd:8d: + 44:c8:fb:56:b3:b9:6c:e9:f8:9e:21:11:57:1b:8b: + f9:cf:e3:17:e7:d8:fd:ac:d1:01:c6:92:30:f3:2d: + c9:d6:c1:f0:3d:fd:ca:30:dd:75:74:e7:d1:6b:75: + d8:c5:4d:43:61:fe:f6:ad:7e:4c:63:7c:03:17:a2: + 06:8f:d0:8b:69:d3:7a:07:0f:0b:a2:cf:0c:70:38: + ba:cc:55:35:60:84:58:d8:d2:be:1f:ef:76:a9:ba: + ae:6a:dc:08:97:80:de:42:00:b7:d4:ce:9a:b0:36: + 2a:c7:6f:45:04:7c:ea:41:19:d8:b9:19:04:1f:11: + a9:22:80:bd:69:08:15:0d:3c:de:cd:7e:88:6c:0f: + a3:43 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + CE:03:7E:EF:E7:DE:C9:87:BF:DE:56:F4:C8:A3:40:F6:C8:6F:05:8C + X509v3 Authority Key Identifier: + keyid:B8:35:37:32:BE:CF:4F:79:F5:7B:74:B2:F2:10:5A:BA:80:C5:6A:10 + DirName:/C=US/ST=Berkshire/L=Newbury/O=My Company Ltd/OU=Testing/CN=test/emailAddress=test@test.com + serial:EB:E7:64:FB:79:F7:22:19 + + Signature Algorithm: md5WithRSAEncryption + 7a:20:93:63:40:73:7d:33:01:2e:c0:13:52:a4:a7:e1:4d:82: + f4:fb:b2:7b:d0:2b:5a:3f:0e:3c:28:61:71:ab:01:4d:fe:89: + b5:cd:2f:97:59:93:53:9d:51:86:48:dd:b9:e4:73:5e:22:0b: + 12:0d:25:39:76:16:44:06:0c:40:45:21:6b:a6:b1:e0:bf:76: + 1b:36:f3:1e:41:82:57:d9:59:b7:60:40:43:1c:1d:79:f6:48: + 32:5c:4e:e2:06:89:96:41:d2:54:1f:4a:6f:f6:78:a5:3c:02: + 85:21:e2:65:e1:8a:6d:24:19:95:f8:c0:35:ab:bd:ff:3d:f1: + fb:50:2d:30:1e:67:a6:7c:50:f9:d5:77:66:77:5a:14:0f:5c: + cd:21:09:9b:a3:92:57:19:dd:01:a4:18:c5:f9:70:e4:17:43: + 8d:b1:e6:61:e9:50:89:83:4f:ce:a4:57:68:58:40:70:ae:71: + 1c:47:66:d2:30:54:50:ea:3a:87:32:64:3b:18:42:fe:5a:19: + 07:64:f7:f1:b1:10:07:fd:a7:d2:a7:a8:05:79:5b:25:ba:69: + 7b:1a:3e:b1:3e:e4:17:17:01:ba:eb:54:ae:83:00:ed:66:62: + 8d:c0:3e:8a:b4:27:5f:e9:01:ce:20:c3:34:a9:28:c0:6f:c7: + 3b:65:fe:f9 +-----BEGIN CERTIFICATE----- +MIIEojCCA4qgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBizELMAkGA1UEBhMCVVMx +EjAQBgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMO +TXkgQ29tcGFueSBMdGQxEDAOBgNVBAsTB1Rlc3RpbmcxDTALBgNVBAMTBHRlc3Qx +HDAaBgkqhkiG9w0BCQEWDXRlc3RAdGVzdC5jb20wHhcNMDkwMzEwMTUxMzE2WhcN +MTkwMzA4MTUxMzE2WjB6MQswCQYDVQQGEwJVUzESMBAGA1UECBMJQmVya3NoaXJl +MRcwFQYDVQQKEw5NeSBDb21wYW55IEx0ZDEQMA4GA1UECxMHVGVzdGluZzEOMAwG +A1UEAxMFdGVzdDExHDAaBgkqhkiG9w0BCQEWDXRlc3RAdGVzdC5jb20wggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNNLEusATG9CuiwKA5eoLtlsT3GYOR +XLTnnN7sSOwt5FEIJkKs05gmenL3ScKeZgXGRyn+O6xrr29eqANaczO6GQMANfUA +vKi+FM5GaeNt7TQ3hVWHYrO3ycDMmqphBVvNohdC0+VvHGCNwhVBRvgSVNA4V+H9 +jUTI+1azuWzp+J4hEVcbi/nP4xfn2P2s0QHGkjDzLcnWwfA9/cow3XV059FrddjF +TUNh/vatfkxjfAMXogaP0Itp03oHDwuizwxwOLrMVTVghFjY0r4f73apuq5q3AiX +gN5CALfUzpqwNirHb0UEfOpBGdi5GQQfEakigL1pCBUNPN7NfohsD6NDAgMBAAGj +ggEfMIIBGzAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVy +YXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUzgN+7+feyYe/3lb0yKNA9shvBYww +gcAGA1UdIwSBuDCBtYAUuDU3Mr7PT3n1e3Sy8hBauoDFahChgZGkgY4wgYsxCzAJ +BgNVBAYTAlVTMRIwEAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkx +FzAVBgNVBAoTDk15IENvbXBhbnkgTHRkMRAwDgYDVQQLEwdUZXN0aW5nMQ0wCwYD +VQQDEwR0ZXN0MRwwGgYJKoZIhvcNAQkBFg10ZXN0QHRlc3QuY29tggkA6+dk+3n3 +IhkwDQYJKoZIhvcNAQEEBQADggEBAHogk2NAc30zAS7AE1Kkp+FNgvT7snvQK1o/ +DjwoYXGrAU3+ibXNL5dZk1OdUYZI3bnkc14iCxINJTl2FkQGDEBFIWumseC/dhs2 +8x5BglfZWbdgQEMcHXn2SDJcTuIGiZZB0lQfSm/2eKU8AoUh4mXhim0kGZX4wDWr +vf898ftQLTAeZ6Z8UPnVd2Z3WhQPXM0hCZujklcZ3QGkGMX5cOQXQ42x5mHpUImD +T86kV2hYQHCucRxHZtIwVFDqOocyZDsYQv5aGQdk9/GxEAf9p9KnqAV5WyW6aXsa +PrE+5BcXAbrrVK6DAO1mYo3APoq0J1/pAc4gwzSpKMBvxztl/vk= +-----END CERTIFICATE----- Index: system-settings/plugins/ifcfg-rh/tests/network-scripts/test_ca_cert.pem =================================================================== --- /dev/null +++ system-settings/plugins/ifcfg-rh/tests/network-scripts/test_ca_cert.pem @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEjzCCA3egAwIBAgIJAOvnZPt59yIZMA0GCSqGSIb3DQEBBQUAMIGLMQswCQYD +VQQGEwJVUzESMBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcw +FQYDVQQKEw5NeSBDb21wYW55IEx0ZDEQMA4GA1UECxMHVGVzdGluZzENMAsGA1UE +AxMEdGVzdDEcMBoGCSqGSIb3DQEJARYNdGVzdEB0ZXN0LmNvbTAeFw0wOTAzMTAx +NTEyMTRaFw0xOTAzMDgxNTEyMTRaMIGLMQswCQYDVQQGEwJVUzESMBAGA1UECBMJ +QmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5NeSBDb21wYW55 +IEx0ZDEQMA4GA1UECxMHVGVzdGluZzENMAsGA1UEAxMEdGVzdDEcMBoGCSqGSIb3 +DQEJARYNdGVzdEB0ZXN0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAKot9j+/+CX1/gZLgJHIXCRgCItKLGnf7qGbgqB9T2ACBqR0jllKWwDKrcWU +xjXNIc+GF9Wnv+lX6G0Okn4Zt3/uRNobL+2b/yOF7M3Td3/9W873zdkQQX930YZc +Rr8uxdRPP5bxiCgtcw632y21sSEbG9mjccAUnV/0jdvfmMNj0i8gN6E0fMBiJ9S3 +FkxX/KFvt9JWE9CtoyL7ki7UIDq+6vj7Gd5N0B3dOa1y+rRHZzKlJPcSXQSEYUS4 +HmKDwiKSVahft8c4tDn7KPi0vex91hlgZVd3usL2E/Vq7o5D9FAZ5kZY0AdFXwdm +J4lO4Mj7ac7GE4vNERNcXVIX59sCAwEAAaOB8zCB8DAdBgNVHQ4EFgQUuDU3Mr7P +T3n1e3Sy8hBauoDFahAwgcAGA1UdIwSBuDCBtYAUuDU3Mr7PT3n1e3Sy8hBauoDF +ahChgZGkgY4wgYsxCzAJBgNVBAYTAlVTMRIwEAYDVQQIEwlCZXJrc2hpcmUxEDAO +BgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15IENvbXBhbnkgTHRkMRAwDgYDVQQL +EwdUZXN0aW5nMQ0wCwYDVQQDEwR0ZXN0MRwwGgYJKoZIhvcNAQkBFg10ZXN0QHRl +c3QuY29tggkA6+dk+3n3IhkwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOC +AQEAVRG4aALIvCXCiKfe7K+iJxjBVRDFPEf7JWA9LGgbFOn6pNvbxonrR+0BETdc +JV1ET4ct2xsE7QNFIkp9GKRC+6J32zCo8qtLCD5+v436r8TUG2/t2JRMkb9I2XVT +p7RJoot6M0Ltf8KNQUPYh756xmKZ4USfQUwc58MOSDGY8VWEXJOYij9Pf0e0c52t +qiCEjXH7uXiS8Pgq9TYm7AkWSOrglYhSa83x0f8mtT8Q15nBESIHZ6o8FAS2bBgn +B0BkrKRjtBUkuJG3vTox+bYINh2Gxi1JZHWSV1tN5z3hd4VFcKqanW5OgQwToBqp +3nniskIjbH0xjgZf/nVMyLnjxg== +-----END CERTIFICATE----- Index: system-settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c =================================================================== --- system-settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c.orig +++ system-settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -26,6 +26,8 @@ #include <netinet/in.h> #include <arpa/inet.h> #include <sys/socket.h> +#include <sys/types.h> +#include <sys/stat.h> #include <dbus/dbus-glib.h> @@ -35,12 +37,124 @@ #include <nm-setting-wireless.h> #include <nm-setting-wireless-security.h> #include <nm-setting-ip4-config.h> +#include <nm-setting-8021x.h> +#include <nm-setting-pppoe.h> +#include <nm-setting-ppp.h> +#include <nm-setting-vpn.h> +#include <nm-setting-gsm.h> +#include <nm-setting-cdma.h> +#include <nm-setting-serial.h> #include "nm-test-helpers.h" +#include "common.h" #include "reader.h" +#include "writer.h" + +typedef enum { + CK_CA_CERT = 0, + CK_CLIENT_CERT = 1, + CK_PRIV_KEY = 2 +} CertKeyType; + +static gboolean +verify_cert_or_key (CertKeyType ck_type, + NMSetting8021x *s_compare, + const char *file, + const char *privkey_password, + const char *ifcfg, + const char *test_name, + const char *setting_key) +{ + NMSetting8021x *s_8021x; + GError *error = NULL; + gboolean success = FALSE; + const GByteArray *expected = NULL, *setting = NULL; + gboolean phase2 = FALSE; + + if (strstr (setting_key, "phase2")) + phase2 = TRUE; + + /* CA Cert */ + s_8021x = (NMSetting8021x *) nm_setting_802_1x_new (); + ASSERT (s_8021x != NULL, + test_name, "failed to verify %s: could not create temp 802.1x setting", + ifcfg); + + if (ck_type == CK_CA_CERT) { + if (phase2) + success = nm_setting_802_1x_set_phase2_ca_cert_from_file (s_8021x, file, NULL, &error); + else + success = nm_setting_802_1x_set_ca_cert_from_file (s_8021x, file, NULL, &error); + } else if (ck_type == CK_CLIENT_CERT) { + if (phase2) + success = nm_setting_802_1x_set_phase2_client_cert_from_file (s_8021x, file, NULL, &error); + else + success = nm_setting_802_1x_set_client_cert_from_file (s_8021x, file, NULL, &error); + } else if (ck_type == CK_PRIV_KEY) { + if (phase2) + success = nm_setting_802_1x_set_phase2_private_key_from_file (s_8021x, file, privkey_password, NULL, &error); + else + success = nm_setting_802_1x_set_private_key_from_file (s_8021x, file, privkey_password, NULL, &error); + } + ASSERT (success == TRUE, + test_name, "failed to verify %s: could not load item for %s / %s: %s", + ifcfg, NM_SETTING_802_1X_SETTING_NAME, setting_key, error->message); + + if (ck_type == CK_CA_CERT) { + if (phase2) + expected = nm_setting_802_1x_get_phase2_ca_cert (s_8021x); + else + expected = nm_setting_802_1x_get_ca_cert (s_8021x); + } else if (ck_type == CK_CLIENT_CERT) { + if (phase2) + expected = nm_setting_802_1x_get_phase2_client_cert (s_8021x); + else + expected = nm_setting_802_1x_get_client_cert (s_8021x); + } else if (ck_type == CK_PRIV_KEY) { + if (phase2) + expected = nm_setting_802_1x_get_phase2_private_key (s_8021x); + else + expected = nm_setting_802_1x_get_private_key (s_8021x); + } + ASSERT (expected != NULL, + test_name, "failed to verify %s: failed to get read item for %s / %s", + ifcfg, NM_SETTING_802_1X_SETTING_NAME, setting_key); + + if (ck_type == CK_CA_CERT) { + if (phase2) + setting = nm_setting_802_1x_get_phase2_ca_cert (s_compare); + else + setting = nm_setting_802_1x_get_ca_cert (s_compare); + } else if (ck_type == CK_CLIENT_CERT) { + if (phase2) + setting = nm_setting_802_1x_get_phase2_client_cert (s_compare); + else + setting = nm_setting_802_1x_get_client_cert (s_compare); + } else if (ck_type == CK_PRIV_KEY) { + if (phase2) + setting = nm_setting_802_1x_get_phase2_private_key (s_compare); + else + setting = nm_setting_802_1x_get_private_key (s_compare); + } + ASSERT (setting != NULL, + test_name, "failed to verify %s: missing %s / %s key", + ifcfg, NM_SETTING_802_1X_SETTING_NAME, setting_key); + + ASSERT (setting->len == expected->len, + test_name, "failed to verify %s: unexpected %s / %s certificate length", + test_name, NM_SETTING_802_1X_SETTING_NAME, setting_key); + + ASSERT (memcmp (setting->data, expected->data, setting->len) == 0, + test_name, "failed to verify %s: %s / %s key certificate mismatch", + ifcfg, NM_SETTING_802_1X_SETTING_NAME, setting_key); + + g_object_unref (s_8021x); + return TRUE; +} -#define TEST_IFCFG_MINIMAL TEST_DIR"/network-scripts/ifcfg-test-minimal" + +#define TEST_IFCFG_MINIMAL TEST_IFCFG_DIR"/network-scripts/ifcfg-test-minimal" static void test_read_minimal (void) @@ -163,7 +277,7 @@ test_read_minimal (void) g_object_unref (connection); } -#define TEST_IFCFG_UNMANAGED TEST_DIR"/network-scripts/ifcfg-test-nm-controlled" +#define TEST_IFCFG_UNMANAGED TEST_IFCFG_DIR"/network-scripts/ifcfg-test-nm-controlled" static void test_read_unmanaged (void) @@ -273,7 +387,7 @@ test_read_unmanaged (void) g_object_unref (connection); } -#define TEST_IFCFG_WIRED_STATIC TEST_DIR"/network-scripts/ifcfg-test-wired-static" +#define TEST_IFCFG_WIRED_STATIC TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-static" static void test_read_wired_static (void) @@ -470,7 +584,7 @@ test_read_wired_static (void) g_object_unref (connection); } -#define TEST_IFCFG_WIRED_DHCP TEST_DIR"/network-scripts/ifcfg-test-wired-dhcp" +#define TEST_IFCFG_WIRED_DHCP TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-dhcp" static void test_read_wired_dhcp (void) @@ -636,8 +750,8 @@ test_read_wired_dhcp (void) g_object_unref (connection); } -#define TEST_IFCFG_WIRED_GLOBAL_GATEWAY TEST_DIR"/network-scripts/ifcfg-test-wired-global-gateway" -#define TEST_NETWORK_WIRED_GLOBAL_GATEWAY TEST_DIR"/network-scripts/network-test-wired-global-gateway" +#define TEST_IFCFG_WIRED_GLOBAL_GATEWAY TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-global-gateway" +#define TEST_NETWORK_WIRED_GLOBAL_GATEWAY TEST_IFCFG_DIR"/network-scripts/network-test-wired-global-gateway" static void test_read_wired_global_gateway (void) @@ -757,8 +871,8 @@ test_read_wired_global_gateway (void) g_object_unref (connection); } -#define TEST_IFCFG_WIRED_NEVER_DEFAULT TEST_DIR"/network-scripts/ifcfg-test-wired-never-default" -#define TEST_NETWORK_WIRED_NEVER_DEFAULT TEST_DIR"/network-scripts/network-test-wired-never-default" +#define TEST_IFCFG_WIRED_NEVER_DEFAULT TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-never-default" +#define TEST_NETWORK_WIRED_NEVER_DEFAULT TEST_IFCFG_DIR"/network-scripts/network-test-wired-never-default" static void test_read_wired_never_default (void) @@ -851,7 +965,7 @@ test_read_wired_never_default (void) g_object_unref (connection); } -#define TEST_IFCFG_ONBOOT_NO TEST_DIR"/network-scripts/ifcfg-test-onboot-no" +#define TEST_IFCFG_ONBOOT_NO TEST_IFCFG_DIR"/network-scripts/ifcfg-test-onboot-no" static void test_read_onboot_no (void) @@ -877,7 +991,7 @@ test_read_onboot_no (void) "onboot-no-verify", "failed to verify %s: %s", TEST_IFCFG_ONBOOT_NO, error->message); ASSERT (unmanaged == FALSE, - "onboot-no-verify", "failed to verify %s: unexpected unmanaged value", TEST_IFCFG_WIRED_DHCP); + "onboot-no-verify", "failed to verify %s: unexpected unmanaged value", TEST_IFCFG_ONBOOT_NO); /* ===== CONNECTION SETTING ===== */ @@ -889,7 +1003,7 @@ test_read_onboot_no (void) /* Autoconnect */ ASSERT (nm_setting_connection_get_autoconnect (s_con) == FALSE, - "wired-dhcp-verify-connection", "failed to verify %s: unexpected %s /%s key value", + "onboot-no-verify-connection", "failed to verify %s: unexpected %s /%s key value", TEST_IFCFG_ONBOOT_NO, NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_AUTOCONNECT); @@ -897,10 +1011,197 @@ test_read_onboot_no (void) g_object_unref (connection); } -#define TEST_IFCFG_WIFI_OPEN TEST_DIR"/network-scripts/ifcfg-test-wifi-open" +#define TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2 TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-8021x-peap-mschapv2" +#define TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2_CA_CERT TEST_IFCFG_DIR"/network-scripts/test_ca_cert.pem" + +static void +test_read_wired_8021x_peap_mschapv2 (void) +{ + NMConnection *connection; + NMSettingWired *s_wired; + NMSettingIP4Config *s_ip4; + NMSetting8021x *s_8021x; + NMSetting8021x *tmp_8021x; + gboolean unmanaged = FALSE; + char *keyfile = NULL; + gboolean ignore_error = FALSE; + GError *error = NULL; + const char *tmp; + const char *expected_identity = "David Smith"; + const char *expected_password = "foobar baz"; + gboolean success = FALSE; + const GByteArray *expected_ca_cert; + const GByteArray *read_ca_cert; + + connection = connection_from_file (TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2, + NULL, + TYPE_ETHERNET, + &unmanaged, + &keyfile, + &error, + &ignore_error); + ASSERT (connection != NULL, + "wired-8021x-peap-mschapv2-read", "failed to read %s: %s", TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2, error->message); + + ASSERT (nm_connection_verify (connection, &error), + "wired-8021x-peap-mschapv2-verify", "failed to verify %s: %s", TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2, error->message); + + ASSERT (unmanaged == FALSE, + "wired-8021x-peap-mschapv2-verify", "failed to verify %s: unexpected unmanaged value", TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2); + + /* ===== WIRED SETTING ===== */ + + s_wired = NM_SETTING_WIRED (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED)); + ASSERT (s_wired != NULL, + "wired-8021x-peap-mschapv2-verify-wired", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2, + NM_SETTING_WIRED_SETTING_NAME); + + /* ===== IPv4 SETTING ===== */ + + s_ip4 = NM_SETTING_IP4_CONFIG (nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG)); + ASSERT (s_ip4 != NULL, + "wired-8021x-peap-mschapv2-verify-ip4", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2, + 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, + "wired-8021x-peap-mschapv2-verify-ip4", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_METHOD); + + /* ===== 802.1x SETTING ===== */ + s_8021x = NM_SETTING_802_1X (nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X)); + ASSERT (s_8021x != NULL, + "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2, + NM_SETTING_802_1X_SETTING_NAME); + + /* EAP methods */ + ASSERT (nm_setting_802_1x_get_num_eap_methods (s_8021x) == 1, + "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_EAP); + tmp = nm_setting_802_1x_get_eap_method (s_8021x, 0); + ASSERT (tmp != NULL, + "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: missing %s / %s eap method", + TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_EAP); + ASSERT (strcmp (tmp, "peap") == 0, + "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_EAP); + + /* Identity */ + tmp = nm_setting_802_1x_get_identity (s_8021x); + ASSERT (tmp != NULL, + "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_IDENTITY); + ASSERT (strcmp (tmp, expected_identity) == 0, + "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_IDENTITY); + + /* Password */ + tmp = nm_setting_802_1x_get_password (s_8021x); + ASSERT (tmp != NULL, + "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PASSWORD); + ASSERT (strcmp (tmp, expected_password) == 0, + "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PASSWORD); + + /* PEAP version */ + tmp = nm_setting_802_1x_get_phase1_peapver (s_8021x); + ASSERT (tmp != NULL, + "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PHASE1_PEAPVER); + ASSERT (strcmp (tmp, "1") == 0, + "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PHASE1_PEAPVER); + + /* PEAP Label */ + tmp = nm_setting_802_1x_get_phase1_peaplabel (s_8021x); + ASSERT (tmp != NULL, + "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PHASE1_PEAPLABEL); + ASSERT (strcmp (tmp, "1") == 0, + "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PHASE1_PEAPLABEL); + + /* CA Cert */ + tmp_8021x = (NMSetting8021x *) nm_setting_802_1x_new (); + ASSERT (tmp_8021x != NULL, + "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: could not create temp 802.1x setting", + TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_CA_CERT); + + success = nm_setting_802_1x_set_ca_cert_from_file (tmp_8021x, + TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2_CA_CERT, + NULL, + &error); + ASSERT (success == TRUE, + "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: could not load CA certificate", + TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_CA_CERT); + expected_ca_cert = nm_setting_802_1x_get_ca_cert (tmp_8021x); + ASSERT (expected_ca_cert != NULL, + "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: failed to get CA certificate", + TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_CA_CERT); + + read_ca_cert = nm_setting_802_1x_get_ca_cert (s_8021x); + ASSERT (read_ca_cert != NULL, + "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_CA_CERT); + + ASSERT (read_ca_cert->len == expected_ca_cert->len, + "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: unexpected %s / %s certificate length", + TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_CA_CERT); + + ASSERT (memcmp (read_ca_cert->data, expected_ca_cert->data, read_ca_cert->len) == 0, + "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: %s / %s key certificate mismatch", + TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_CA_CERT); + + g_object_unref (tmp_8021x); + + g_object_unref (connection); +} + +#define TEST_IFCFG_WIFI_OPEN TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-open" static void -test_read_wifi_unencrypted (void) +test_read_wifi_open (void) { NMConnection *connection; NMSettingConnection *s_con; @@ -917,7 +1218,7 @@ test_read_wifi_unencrypted (void) guint64 expected_timestamp = 0; const char *expected_ssid = "blahblah"; const char *expected_mode = "infrastructure"; - const guint32 expected_channel = 0; + const guint32 expected_channel = 1; connection = connection_from_file (TEST_IFCFG_WIFI_OPEN, NULL, @@ -1070,7 +1371,181 @@ test_read_wifi_unencrypted (void) g_object_unref (connection); } -#define TEST_IFCFG_WIFI_WEP TEST_DIR"/network-scripts/ifcfg-test-wifi-wep" +#define TEST_IFCFG_WIFI_OPEN_SSID_HEX TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-open-ssid-hex" + +static void +test_read_wifi_open_ssid_hex (void) +{ + NMConnection *connection; + NMSettingConnection *s_con; + NMSettingWireless *s_wireless; + gboolean unmanaged = FALSE; + char *keyfile = NULL; + gboolean ignore_error = FALSE; + GError *error = NULL; + const char *tmp; + const GByteArray *array; + const char *expected_id = "System blahblah (test-wifi-open-ssid-hex)"; + const char *expected_ssid = "blahblah"; + + connection = connection_from_file (TEST_IFCFG_WIFI_OPEN_SSID_HEX, + NULL, + TYPE_WIRELESS, + &unmanaged, + &keyfile, + &error, + &ignore_error); + ASSERT (connection != NULL, + "wifi-open-ssid-hex-read", "failed to read %s: %s", TEST_IFCFG_WIFI_OPEN_SSID_HEX, error->message); + + ASSERT (nm_connection_verify (connection, &error), + "wifi-open-ssid-hex-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_OPEN_SSID_HEX, error->message); + + /* ===== CONNECTION SETTING ===== */ + + s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION)); + ASSERT (s_con != NULL, + "wifi-open-ssid-hex-verify-connection", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIFI_OPEN_SSID_HEX, + NM_SETTING_CONNECTION_SETTING_NAME); + + /* ID */ + tmp = nm_setting_connection_get_id (s_con); + ASSERT (tmp != NULL, + "wifi-open-ssid-hex-verify-connection", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_WIFI_OPEN_SSID_HEX, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_ID); + ASSERT (strcmp (tmp, expected_id) == 0, + "wifi-open-ssid-hex-verify-connection", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_OPEN_SSID_HEX, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_ID); + + /* ===== WIRELESS SETTING ===== */ + + s_wireless = NM_SETTING_WIRELESS (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS)); + ASSERT (s_wireless != NULL, + "wifi-open-ssid-hex-verify-wireless", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIFI_OPEN_SSID_HEX, + NM_SETTING_WIRELESS_SETTING_NAME); + + /* SSID */ + array = nm_setting_wireless_get_ssid (s_wireless); + ASSERT (array != NULL, + "wifi-open-ssid-hex-verify-wireless", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_WIFI_OPEN_SSID_HEX, + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_SSID); + ASSERT (array->len == strlen (expected_ssid), + "wifi-open-ssid-hex-verify-wireless", "failed to verify %s: unexpected %s / %s key value length", + TEST_IFCFG_WIFI_OPEN_SSID_HEX, + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_SSID); + ASSERT (memcmp (array->data, expected_ssid, strlen (expected_ssid)) == 0, + "wifi-open-ssid-hex-verify-wireless", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_OPEN_SSID_HEX, + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_SSID); + + g_object_unref (connection); +} + +static void +test_read_wifi_open_ssid_bad (const char *file, const char *test) +{ + NMConnection *connection; + gboolean unmanaged = FALSE; + char *keyfile = NULL; + gboolean ignore_error = FALSE; + GError *error = NULL; + + connection = connection_from_file (file, NULL, TYPE_WIRELESS, &unmanaged, &keyfile, &error, &ignore_error); + ASSERT (connection == NULL, test, "unexpected success reading %s", file); + g_clear_error (&error); +} + +#define TEST_IFCFG_WIFI_OPEN_SSID_QUOTED TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-open-ssid-quoted" + +static void +test_read_wifi_open_ssid_quoted (void) +{ + NMConnection *connection; + NMSettingConnection *s_con; + NMSettingWireless *s_wireless; + gboolean unmanaged = FALSE; + char *keyfile = NULL; + gboolean ignore_error = FALSE; + GError *error = NULL; + const char *tmp; + const GByteArray *array; + const char *expected_id = "System foo\"bar\\ (test-wifi-open-ssid-quoted)"; + const char *expected_ssid = "foo\"bar\\"; + + connection = connection_from_file (TEST_IFCFG_WIFI_OPEN_SSID_QUOTED, + NULL, + TYPE_WIRELESS, + &unmanaged, + &keyfile, + &error, + &ignore_error); + ASSERT (connection != NULL, + "wifi-open-ssid-quoted-read", "failed to read %s: %s", TEST_IFCFG_WIFI_OPEN_SSID_QUOTED, error->message); + + ASSERT (nm_connection_verify (connection, &error), + "wifi-open-ssid-quoted-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_OPEN_SSID_QUOTED, error->message); + + /* ===== CONNECTION SETTING ===== */ + + s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION)); + ASSERT (s_con != NULL, + "wifi-open-ssid-quoted-verify-connection", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIFI_OPEN_SSID_QUOTED, + NM_SETTING_CONNECTION_SETTING_NAME); + + /* ID */ + tmp = nm_setting_connection_get_id (s_con); + ASSERT (tmp != NULL, + "wifi-open-ssid-quoted-verify-connection", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_WIFI_OPEN_SSID_QUOTED, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_ID); + ASSERT (strcmp (tmp, expected_id) == 0, + "wifi-open-ssid-quoted-verify-connection", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_OPEN_SSID_QUOTED, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_ID); + + /* ===== WIRELESS SETTING ===== */ + + s_wireless = NM_SETTING_WIRELESS (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS)); + ASSERT (s_wireless != NULL, + "wifi-open-ssid-quoted-verify-wireless", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIFI_OPEN_SSID_QUOTED, + NM_SETTING_WIRELESS_SETTING_NAME); + + /* SSID */ + array = nm_setting_wireless_get_ssid (s_wireless); + ASSERT (array != NULL, + "wifi-open-ssid-quoted-verify-wireless", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_WIFI_OPEN_SSID_QUOTED, + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_SSID); + ASSERT (array->len == strlen (expected_ssid), + "wifi-open-ssid-quoted-verify-wireless", "failed to verify %s: unexpected %s / %s key value length", + TEST_IFCFG_WIFI_OPEN_SSID_QUOTED, + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_SSID); + ASSERT (memcmp (array->data, expected_ssid, strlen (expected_ssid)) == 0, + "wifi-open-ssid-quoted-verify-wireless", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_OPEN_SSID_QUOTED, + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_SSID); + + g_object_unref (connection); +} + +#define TEST_IFCFG_WIFI_WEP TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-wep" static void test_read_wifi_wep (void) @@ -1091,7 +1566,7 @@ test_read_wifi_wep (void) guint64 expected_timestamp = 0; const char *expected_ssid = "blahblah"; const char *expected_mode = "infrastructure"; - const guint32 expected_channel = 0; + const guint32 expected_channel = 1; const char *expected_wep_key0 = "0123456789abcdef0123456789"; connection = connection_from_file (TEST_IFCFG_WIFI_WEP, @@ -1330,7 +1805,7 @@ test_read_wifi_wep (void) g_object_unref (connection); } -#define TEST_IFCFG_WIFI_WEP_ADHOC TEST_DIR"/network-scripts/ifcfg-test-wifi-wep-adhoc" +#define TEST_IFCFG_WIFI_WEP_ADHOC TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-wep-adhoc" static void test_read_wifi_wep_adhoc (void) @@ -1446,8 +1921,8 @@ test_read_wifi_wep_adhoc (void) NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_MODE); - /* Channel (doesn't work yet) */ - ASSERT (nm_setting_wireless_get_channel (s_wireless) == 0, + /* Channel */ + ASSERT (nm_setting_wireless_get_channel (s_wireless) == 11, "wifi-wep-adhoc-verify-wireless", "failed to verify %s: unexpected %s / %s key value", TEST_IFCFG_WIFI_WEP_ADHOC, NM_SETTING_WIRELESS_SETTING_NAME, @@ -1589,41 +2064,25 @@ test_read_wifi_wep_adhoc (void) g_object_unref (connection); } -#define TEST_IFCFG_WIFI_WPA_PSK TEST_DIR"/network-scripts/ifcfg-test-wifi-wpa-psk" +#define TEST_IFCFG_WIFI_LEAP TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-leap" static void -test_read_wifi_wpa_psk (void) +test_read_wifi_leap (void) { NMConnection *connection; NMSettingConnection *s_con; NMSettingWireless *s_wireless; NMSettingWirelessSecurity *s_wsec; - NMSettingIP4Config *s_ip4; gboolean unmanaged = FALSE; char *keyfile = NULL; gboolean ignore_error = FALSE; GError *error = NULL; const char *tmp; - const GByteArray *array; - char expected_mac_address[ETH_ALEN] = { 0x00, 0x16, 0x41, 0x11, 0x22, 0x33 }; - const char *expected_id = "System blahblah (test-wifi-wpa-psk)"; - guint64 expected_timestamp = 0; - const char *expected_ssid = "blahblah"; - const char *expected_mode = "infrastructure"; - const guint32 expected_channel = 0; - const char *expected_key_mgmt = "wpa-psk"; - const char *expected_psk = "1da190379817bc360dda52e85c388c439a21ea5c7bf819c64e9da051807deae6"; - guint32 n, i; - gboolean found_pair_tkip = FALSE; - gboolean found_pair_ccmp = FALSE; - gboolean found_group_tkip = FALSE; - gboolean found_group_ccmp = FALSE; - gboolean found_group_wep40 = FALSE; - gboolean found_group_wep104 = FALSE; - gboolean found_proto_wpa = FALSE; - gboolean found_proto_rsn = FALSE; + const char *expected_id = "System blahblah (test-wifi-leap)"; + const char *expected_identity = "Bill Smith"; + const char *expected_password = "foobarblah"; - connection = connection_from_file (TEST_IFCFG_WIFI_WPA_PSK, + connection = connection_from_file (TEST_IFCFG_WIFI_LEAP, NULL, TYPE_WIRELESS, &unmanaged, @@ -1631,68 +2090,215 @@ test_read_wifi_wpa_psk (void) &error, &ignore_error); ASSERT (connection != NULL, - "wifi-wpa-psk-read", "failed to read %s: %s", TEST_IFCFG_WIFI_WPA_PSK, error->message); + "wifi-leap-read", "failed to read %s: %s", TEST_IFCFG_WIFI_LEAP, error->message); ASSERT (nm_connection_verify (connection, &error), - "wifi-wpa-psk-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_WPA_PSK, error->message); + "wifi-leap-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_LEAP, error->message); /* ===== CONNECTION SETTING ===== */ s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION)); ASSERT (s_con != NULL, - "wifi-wpa-psk-verify-connection", "failed to verify %s: missing %s setting", - TEST_IFCFG_WIFI_WPA_PSK, + "wifi-leap-verify-connection", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIFI_LEAP, NM_SETTING_CONNECTION_SETTING_NAME); /* ID */ tmp = nm_setting_connection_get_id (s_con); ASSERT (tmp != NULL, - "wifi-wpa-psk-verify-connection", "failed to verify %s: missing %s / %s key", - TEST_IFCFG_WIFI_WPA_PSK, + "wifi-leap-verify-connection", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_WIFI_LEAP, NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_ID); ASSERT (strcmp (tmp, expected_id) == 0, - "wifi-wpa-psk-verify-connection", "failed to verify %s: unexpected %s / %s key value", - TEST_IFCFG_WIFI_WPA_PSK, + "wifi-leap-verify-connection", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_LEAP, 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, - "wifi-wpa-psk-verify-connection", "failed to verify %s: unexpected %s /%s key value", - TEST_IFCFG_WIFI_WPA_PSK, - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_TIMESTAMP); - - /* Autoconnect */ - ASSERT (nm_setting_connection_get_autoconnect (s_con) == TRUE, - "wifi-wpa-psk-verify-connection", "failed to verify %s: unexpected %s /%s key value", - TEST_IFCFG_WIFI_WPA_PSK, - NM_SETTING_CONNECTION_SETTING_NAME, - NM_SETTING_CONNECTION_AUTOCONNECT); - /* ===== WIRELESS SETTING ===== */ s_wireless = NM_SETTING_WIRELESS (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS)); ASSERT (s_wireless != NULL, - "wifi-wpa-psk-verify-wireless", "failed to verify %s: missing %s setting", - TEST_IFCFG_WIFI_WPA_PSK, + "wifi-leap-verify-wireless", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIFI_LEAP, NM_SETTING_WIRELESS_SETTING_NAME); - /* MAC address */ - array = nm_setting_wireless_get_mac_address (s_wireless); - ASSERT (array != NULL, - "wifi-wpa-psk-verify-wireless", "failed to verify %s: missing %s / %s key", - TEST_IFCFG_WIFI_WPA_PSK, + /* Security */ + tmp = nm_setting_wireless_get_security (s_wireless); + ASSERT (tmp != NULL, + "wifi-leap-verify-wireless", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_WIFI_LEAP, NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_WIRELESS_MAC_ADDRESS); - ASSERT (array->len == ETH_ALEN, - "wifi-wpa-psk-verify-wireless", "failed to verify %s: unexpected %s / %s key value length", + NM_SETTING_WIRELESS_SEC); + ASSERT (strcmp (tmp, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) == 0, + "wifi-leap-verify-wireless", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_LEAP, + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_SEC); + + + /* ===== WIRELESS SECURITY SETTING ===== */ + + s_wsec = NM_SETTING_WIRELESS_SECURITY (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS_SECURITY)); + ASSERT (s_wsec != NULL, + "wifi-leap-verify-wireless", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIFI_LEAP, + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME); + + /* Key management */ + ASSERT (strcmp (nm_setting_wireless_security_get_key_mgmt (s_wsec), "ieee8021x") == 0, + "wifi-leap-verify-wireless", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_WIFI_LEAP, + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT); + + /* WEP Authentication mode */ + tmp = nm_setting_wireless_security_get_auth_alg (s_wsec); + ASSERT (tmp != NULL, + "wifi-leap-verify-wireless", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_WIFI_LEAP, + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_AUTH_ALG); + ASSERT (strcmp (tmp, "leap") == 0, + "wifi-leap-verify-wireless", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_LEAP, + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_AUTH_ALG); + + /* LEAP Username */ + tmp = nm_setting_wireless_security_get_leap_username (s_wsec); + ASSERT (tmp != NULL, + "wifi-leap-verify-wireless", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_WIFI_LEAP, + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME); + ASSERT (strcmp (tmp, expected_identity) == 0, + "wifi-leap-verify-wireless", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_LEAP, + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME); + + /* LEAP Password */ + tmp = nm_setting_wireless_security_get_leap_password (s_wsec); + ASSERT (tmp != NULL, + "wifi-leap-verify-wireless", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_WIFI_LEAP, + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD); + ASSERT (strcmp (tmp, expected_password) == 0, + "wifi-leap-verify-wireless", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_LEAP, + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD); + + g_object_unref (connection); +} + +#define TEST_IFCFG_WIFI_WPA_PSK TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-wpa-psk" + +static void +test_read_wifi_wpa_psk (void) +{ + NMConnection *connection; + NMSettingConnection *s_con; + NMSettingWireless *s_wireless; + NMSettingWirelessSecurity *s_wsec; + NMSettingIP4Config *s_ip4; + gboolean unmanaged = FALSE; + char *keyfile = NULL; + gboolean ignore_error = FALSE; + GError *error = NULL; + const char *tmp; + const GByteArray *array; + char expected_mac_address[ETH_ALEN] = { 0x00, 0x16, 0x41, 0x11, 0x22, 0x33 }; + const char *expected_id = "System blahblah (test-wifi-wpa-psk)"; + guint64 expected_timestamp = 0; + const char *expected_ssid = "blahblah"; + const char *expected_mode = "infrastructure"; + const guint32 expected_channel = 1; + const char *expected_key_mgmt = "wpa-psk"; + const char *expected_psk = "1da190379817bc360dda52e85c388c439a21ea5c7bf819c64e9da051807deae6"; + guint32 n, i; + gboolean found_pair_tkip = FALSE; + gboolean found_pair_ccmp = FALSE; + gboolean found_group_tkip = FALSE; + gboolean found_group_ccmp = FALSE; + gboolean found_group_wep40 = FALSE; + gboolean found_group_wep104 = FALSE; + gboolean found_proto_wpa = FALSE; + gboolean found_proto_rsn = FALSE; + + connection = connection_from_file (TEST_IFCFG_WIFI_WPA_PSK, + NULL, + TYPE_WIRELESS, + &unmanaged, + &keyfile, + &error, + &ignore_error); + ASSERT (connection != NULL, + "wifi-wpa-psk-read", "failed to read %s: %s", TEST_IFCFG_WIFI_WPA_PSK, error->message); + + ASSERT (nm_connection_verify (connection, &error), + "wifi-wpa-psk-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_WPA_PSK, error->message); + + /* ===== CONNECTION SETTING ===== */ + + s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION)); + ASSERT (s_con != NULL, + "wifi-wpa-psk-verify-connection", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIFI_WPA_PSK, + NM_SETTING_CONNECTION_SETTING_NAME); + + /* ID */ + tmp = nm_setting_connection_get_id (s_con); + ASSERT (tmp != NULL, + "wifi-wpa-psk-verify-connection", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_WIFI_WPA_PSK, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_ID); + ASSERT (strcmp (tmp, expected_id) == 0, + "wifi-wpa-psk-verify-connection", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_WPA_PSK, + 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, + "wifi-wpa-psk-verify-connection", "failed to verify %s: unexpected %s /%s key value", + TEST_IFCFG_WIFI_WPA_PSK, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_TIMESTAMP); + + /* Autoconnect */ + ASSERT (nm_setting_connection_get_autoconnect (s_con) == TRUE, + "wifi-wpa-psk-verify-connection", "failed to verify %s: unexpected %s /%s key value", + TEST_IFCFG_WIFI_WPA_PSK, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_AUTOCONNECT); + + /* ===== WIRELESS SETTING ===== */ + + s_wireless = NM_SETTING_WIRELESS (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS)); + ASSERT (s_wireless != NULL, + "wifi-wpa-psk-verify-wireless", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIFI_WPA_PSK, + NM_SETTING_WIRELESS_SETTING_NAME); + + /* MAC address */ + array = nm_setting_wireless_get_mac_address (s_wireless); + ASSERT (array != NULL, + "wifi-wpa-psk-verify-wireless", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_WIFI_WPA_PSK, + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_MAC_ADDRESS); + ASSERT (array->len == ETH_ALEN, + "wifi-wpa-psk-verify-wireless", "failed to verify %s: unexpected %s / %s key value length", TEST_IFCFG_WIFI_WPA_PSK, NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_MAC_ADDRESS); @@ -1899,7 +2505,7 @@ test_read_wifi_wpa_psk (void) g_object_unref (connection); } -#define TEST_IFCFG_WIFI_WPA_PSK_ADHOC TEST_DIR"/network-scripts/ifcfg-test-wifi-wpa-psk-adhoc" +#define TEST_IFCFG_WIFI_WPA_PSK_ADHOC TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-wpa-psk-adhoc" static void test_read_wifi_wpa_psk_adhoc (void) @@ -2082,7 +2688,7 @@ test_read_wifi_wpa_psk_adhoc (void) g_object_unref (connection); } -#define TEST_IFCFG_WIFI_WPA_PSK_HEX TEST_DIR"/network-scripts/ifcfg-test-wifi-wpa-psk-hex" +#define TEST_IFCFG_WIFI_WPA_PSK_HEX TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-wpa-psk-hex" static void test_read_wifi_wpa_psk_hex (void) @@ -2229,36 +2835,2413 @@ test_read_wifi_wpa_psk_hex (void) g_object_unref (connection); } -int main (int argc, char **argv) +#define TEST_IFCFG_WIFI_WPA_EAP_TLS TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-wpa-eap-tls" +#define TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT TEST_IFCFG_DIR"/network-scripts/test_ca_cert.pem" +#define TEST_IFCFG_WIFI_WPA_EAP_TLS_CLIENT_CERT TEST_IFCFG_DIR"/network-scripts/test1_key_and_cert.pem" +#define TEST_IFCFG_WIFI_WPA_EAP_TLS_PRIVATE_KEY TEST_IFCFG_DIR"/network-scripts/test1_key_and_cert.pem" + +static void +test_read_wifi_wpa_eap_tls (void) { + NMConnection *connection; + NMSettingWireless *s_wireless; + NMSettingIP4Config *s_ip4; + NMSetting8021x *s_8021x; + gboolean unmanaged = FALSE; + char *keyfile = NULL; + gboolean ignore_error = FALSE; GError *error = NULL; - DBusGConnection *bus; - char *basename; + const char *tmp; + const char *expected_identity = "Bill Smith"; + const char *expected_privkey_password = "test1"; - g_type_init (); - bus = dbus_g_bus_get (DBUS_BUS_SESSION, NULL); + connection = connection_from_file (TEST_IFCFG_WIFI_WPA_EAP_TLS, + NULL, + TYPE_ETHERNET, + &unmanaged, + &keyfile, + &error, + &ignore_error); + ASSERT (connection != NULL, + "wifi-wpa-eap-tls-read", "failed to read %s: %s", TEST_IFCFG_WIFI_WPA_EAP_TLS, error->message); - if (!nm_utils_init (&error)) - FAIL ("nm-utils-init", "failed to initialize libnm-util: %s", error->message); + ASSERT (nm_connection_verify (connection, &error), + "wifi-wpa-eap-tls-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_WPA_EAP_TLS, error->message); - /* The tests */ - test_read_unmanaged (); - test_read_minimal (); - test_read_wired_static (); - test_read_wired_dhcp (); - test_read_wired_global_gateway (); - test_read_wired_never_default (); - test_read_onboot_no (); - test_read_wifi_unencrypted (); - test_read_wifi_wep (); - test_read_wifi_wep_adhoc (); - test_read_wifi_wpa_psk (); - test_read_wifi_wpa_psk_adhoc (); - test_read_wifi_wpa_psk_hex (); + ASSERT (unmanaged == FALSE, + "wifi-wpa-eap-tls-verify", "failed to verify %s: unexpected unmanaged value", TEST_IFCFG_WIFI_WPA_EAP_TLS); + + /* ===== WIRELESS SETTING ===== */ + + s_wireless = NM_SETTING_WIRELESS (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS)); + ASSERT (s_wireless != NULL, + "wifi-wpa-eap-tls-verify-wireless", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIFI_WPA_EAP_TLS, + NM_SETTING_WIRELESS_SETTING_NAME); + + /* ===== IPv4 SETTING ===== */ + + s_ip4 = NM_SETTING_IP4_CONFIG (nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG)); + ASSERT (s_ip4 != NULL, + "wifi-wpa-eap-tls-verify-ip4", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIFI_WPA_EAP_TLS, + 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, + "wifi-wpa-eap-tls-verify-ip4", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_WPA_EAP_TLS, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_METHOD); - basename = g_path_get_basename (argv[0]); - fprintf (stdout, "%s: SUCCESS\n", basename); - g_free (basename); + /* ===== 802.1x SETTING ===== */ + s_8021x = NM_SETTING_802_1X (nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X)); + ASSERT (s_8021x != NULL, + "wifi-wpa-eap-tls-verify-8021x", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIFI_WPA_EAP_TLS, + NM_SETTING_802_1X_SETTING_NAME); + + /* EAP methods */ + ASSERT (nm_setting_802_1x_get_num_eap_methods (s_8021x) == 1, + "wifi-wpa-eap-tls-verify-8021x", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_WPA_EAP_TLS, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_EAP); + tmp = nm_setting_802_1x_get_eap_method (s_8021x, 0); + ASSERT (tmp != NULL, + "wifi-wpa-eap-tls-verify-8021x", "failed to verify %s: missing %s / %s eap method", + TEST_IFCFG_WIFI_WPA_EAP_TLS, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_EAP); + ASSERT (strcmp (tmp, "tls") == 0, + "wifi-wpa-eap-tls-verify-8021x", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_WPA_EAP_TLS, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_EAP); + + /* Identity */ + tmp = nm_setting_802_1x_get_identity (s_8021x); + ASSERT (tmp != NULL, + "wifi-wpa-eap-tls-verify-8021x", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_WIFI_WPA_EAP_TLS, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_IDENTITY); + ASSERT (strcmp (tmp, expected_identity) == 0, + "wifi-wpa-eap-tls-verify-8021x", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_WPA_EAP_TLS, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_IDENTITY); + + /* CA Cert */ + verify_cert_or_key (CK_CA_CERT, + s_8021x, + TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT, + NULL, + TEST_IFCFG_WIFI_WPA_EAP_TLS, + "wifi-wpa-eap-tls-verify-8021x", + NM_SETTING_802_1X_CA_CERT); + + /* Client Cert */ + verify_cert_or_key (CK_CLIENT_CERT, + s_8021x, + TEST_IFCFG_WIFI_WPA_EAP_TLS_CLIENT_CERT, + NULL, + TEST_IFCFG_WIFI_WPA_EAP_TLS, + "wifi-wpa-eap-tls-verify-8021x", + NM_SETTING_802_1X_CLIENT_CERT); + + /* Private Key Password */ + ASSERT (nm_setting_802_1x_get_private_key_password (s_8021x) == NULL, + "wifi-wpa-eap-tls-verify-8021x", "failed to verify %s: unexpected %s / %s key", + TEST_IFCFG_WIFI_WPA_EAP_TLS, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD); + + /* Private key */ + verify_cert_or_key (CK_PRIV_KEY, + s_8021x, + TEST_IFCFG_WIFI_WPA_EAP_TLS_PRIVATE_KEY, + expected_privkey_password, + TEST_IFCFG_WIFI_WPA_EAP_TLS, + "wifi-wpa-eap-tls-verify-8021x", + NM_SETTING_802_1X_PRIVATE_KEY); + + g_object_unref (connection); +} + +#define TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-wpa-eap-ttls-tls" +#define TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS_CA_CERT TEST_IFCFG_DIR"/network-scripts/test_ca_cert.pem" +/* Also use TLS defines from the previous test */ + +static void +test_read_wifi_wpa_eap_ttls_tls (void) +{ + NMConnection *connection; + NMSettingWireless *s_wireless; + NMSettingIP4Config *s_ip4; + NMSetting8021x *s_8021x; + gboolean unmanaged = FALSE; + char *keyfile = NULL; + gboolean ignore_error = FALSE; + GError *error = NULL; + const char *tmp; + const char *expected_identity = "Chuck Shumer"; + const char *expected_privkey_password = "test1"; + + connection = connection_from_file (TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS, + NULL, + TYPE_WIRELESS, + &unmanaged, + &keyfile, + &error, + &ignore_error); + ASSERT (connection != NULL, + "wifi-wpa-eap-ttls-tls-read", "failed to read %s: %s", TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS, error->message); + + ASSERT (nm_connection_verify (connection, &error), + "wifi-wpa-eap-ttls-tls-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS, error->message); + + ASSERT (unmanaged == FALSE, + "wifi-wpa-eap-ttls-tls-verify", "failed to verify %s: unexpected unmanaged value", TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS); + + /* ===== WIRELESS SETTING ===== */ + + s_wireless = NM_SETTING_WIRELESS (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS)); + ASSERT (s_wireless != NULL, + "wifi-wpa-eap-ttls-tls-verify-wireless", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS, + NM_SETTING_WIRELESS_SETTING_NAME); + + /* ===== IPv4 SETTING ===== */ + + s_ip4 = NM_SETTING_IP4_CONFIG (nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG)); + ASSERT (s_ip4 != NULL, + "wifi-wpa-eap-ttls-tls-verify-ip4", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS, + 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, + "wifi-wpa-eap-ttls-tls-verify-ip4", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_METHOD); + + /* ===== 802.1x SETTING ===== */ + s_8021x = NM_SETTING_802_1X (nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X)); + ASSERT (s_8021x != NULL, + "wifi-wpa-eap-ttls-tls-verify-8021x", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS, + NM_SETTING_802_1X_SETTING_NAME); + + /* EAP methods */ + ASSERT (nm_setting_802_1x_get_num_eap_methods (s_8021x) == 1, + "wifi-wpa-eap-ttls-tls-verify-8021x", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_EAP); + tmp = nm_setting_802_1x_get_eap_method (s_8021x, 0); + ASSERT (tmp != NULL, + "wifi-wpa-eap-ttls-tls-verify-8021x", "failed to verify %s: missing %s / %s eap method", + TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_EAP); + ASSERT (strcmp (tmp, "ttls") == 0, + "wifi-wpa-eap-ttls-tls-verify-8021x", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_EAP); + + /* CA Cert */ + verify_cert_or_key (CK_CA_CERT, + s_8021x, + TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS_CA_CERT, + NULL, + TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS, + "wifi-wpa-eap-ttls-tls-verify-8021x", + NM_SETTING_802_1X_CA_CERT); + + /* Inner auth method */ + tmp = nm_setting_802_1x_get_phase2_autheap (s_8021x); + ASSERT (tmp != NULL, + "wifi-wpa-eap-ttls-tls-verify-8021x", "failed to verify %s: missing %s / %s eap method", + TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PHASE2_AUTHEAP); + ASSERT (strcmp (tmp, "tls") == 0, + "wifi-wpa-eap-ttls-tls-verify-8021x", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PHASE2_AUTHEAP); + + /* Inner CA Cert */ + verify_cert_or_key (CK_CA_CERT, + s_8021x, + TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT, + NULL, + TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS, + "wifi-wpa-eap-ttls-tls-verify-8021x", + NM_SETTING_802_1X_PHASE2_CA_CERT); + + /* Inner Client Cert */ + verify_cert_or_key (CK_CLIENT_CERT, + s_8021x, + TEST_IFCFG_WIFI_WPA_EAP_TLS_CLIENT_CERT, + NULL, + TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS, + "wifi-wpa-eap-ttls-tls-verify-8021x", + NM_SETTING_802_1X_PHASE2_CLIENT_CERT); + + /* Inner Private Key Password */ + ASSERT (nm_setting_802_1x_get_phase2_private_key_password (s_8021x) == NULL, + "wifi-wpa-eap-ttls-tls-verify-8021x", "failed to verify %s: unexpected %s / %s key", + TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD); + + /* Inner private key */ + verify_cert_or_key (CK_PRIV_KEY, + s_8021x, + TEST_IFCFG_WIFI_WPA_EAP_TLS_PRIVATE_KEY, + expected_privkey_password, + TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS, + "wifi-wpa-eap-ttls-tls-verify-8021x", + NM_SETTING_802_1X_PHASE2_PRIVATE_KEY); + + /* Identity */ + tmp = nm_setting_802_1x_get_identity (s_8021x); + ASSERT (tmp != NULL, + "wifi-wpa-eap-ttls-tls-verify-8021x", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_IDENTITY); + ASSERT (strcmp (tmp, expected_identity) == 0, + "wifi-wpa-eap-ttls-tls-verify-8021x", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_IDENTITY); + + g_object_unref (connection); +} + +#define TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-wep-eap-ttls-chap" +#define TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP_CA_CERT TEST_IFCFG_DIR"/network-scripts/test_ca_cert.pem" + +static void +test_read_wifi_wep_eap_ttls_chap (void) +{ + NMConnection *connection; + NMSettingWireless *s_wireless; + NMSettingWirelessSecurity *s_wsec; + NMSettingIP4Config *s_ip4; + NMSetting8021x *s_8021x; + gboolean unmanaged = FALSE; + char *keyfile = NULL; + gboolean ignore_error = FALSE; + GError *error = NULL; + const char *tmp; + const char *expected_password = "foobar baz"; + const char *expected_identity = "David Smith"; + const char *expected_key_mgmt = "ieee8021x"; + + connection = connection_from_file (TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP, + NULL, + TYPE_WIRELESS, + &unmanaged, + &keyfile, + &error, + &ignore_error); + ASSERT (connection != NULL, + "wifi-wep-eap-ttls-chap-read", "failed to read %s: %s", TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP, error->message); + + ASSERT (nm_connection_verify (connection, &error), + "wifi-wep-eap-ttls-chap-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP, error->message); + + ASSERT (unmanaged == FALSE, + "wifi-wep-eap-ttls-chap-verify", "failed to verify %s: unexpected unmanaged value", TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP); + + /* ===== WIRELESS SETTING ===== */ + + s_wireless = NM_SETTING_WIRELESS (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS)); + ASSERT (s_wireless != NULL, + "wifi-wep-eap-ttls-chap-verify-wireless", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP, + NM_SETTING_WIRELESS_SETTING_NAME); + + /* ===== IPv4 SETTING ===== */ + + s_ip4 = NM_SETTING_IP4_CONFIG (nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG)); + ASSERT (s_ip4 != NULL, + "wifi-wep-eap-ttls-chap-verify-ip4", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP, + 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, + "wifi-wep-eap-ttls-chap-verify-ip4", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_METHOD); + + /* ===== 802.1x SETTING ===== */ + s_wsec = NM_SETTING_WIRELESS_SECURITY (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS_SECURITY)); + ASSERT (s_wsec != NULL, + "wifi-wep-eap-ttls-chap-verify-wireless-security", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP, + NM_SETTING_802_1X_SETTING_NAME); + + /* Key management */ + tmp = nm_setting_wireless_security_get_key_mgmt (s_wsec); + ASSERT (tmp != NULL, + "wifi-wep-eap-ttls-chap-verify-wireless-security", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_WIFI_WPA_PSK, + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT); + ASSERT (strcmp (tmp, expected_key_mgmt) == 0, + "wifi-wep-eap-ttls-chap-verify-wireless-security", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_WPA_PSK, + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT); + + /* ===== 802.1x SETTING ===== */ + s_8021x = NM_SETTING_802_1X (nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X)); + ASSERT (s_8021x != NULL, + "wifi-wep-eap-ttls-chap-verify-8021x", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP, + NM_SETTING_802_1X_SETTING_NAME); + + /* EAP methods */ + ASSERT (nm_setting_802_1x_get_num_eap_methods (s_8021x) == 1, + "wifi-wep-eap-ttls-chap-verify-8021x", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_EAP); + tmp = nm_setting_802_1x_get_eap_method (s_8021x, 0); + ASSERT (tmp != NULL, + "wifi-wep-eap-ttls-chap-verify-8021x", "failed to verify %s: missing %s / %s eap method", + TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_EAP); + ASSERT (strcmp (tmp, "ttls") == 0, + "wifi-wep-eap-ttls-chap-verify-8021x", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_EAP); + + /* CA Cert */ + verify_cert_or_key (CK_CA_CERT, + s_8021x, + TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP_CA_CERT, + NULL, + TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP, + "wifi-wep-eap-ttls-chap-verify-8021x", + NM_SETTING_802_1X_CA_CERT); + + /* Inner auth method */ + tmp = nm_setting_802_1x_get_phase2_auth (s_8021x); + ASSERT (tmp != NULL, + "wifi-wep-eap-ttls-chap-verify-8021x", "failed to verify %s: missing %s / %s eap method", + TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PHASE2_AUTH); + ASSERT (strcmp (tmp, "chap") == 0, + "wifi-wep-eap-ttls-chap-verify-8021x", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PHASE2_AUTH); + + /* Password */ + tmp = nm_setting_802_1x_get_identity (s_8021x); + ASSERT (tmp != NULL, + "wifi-wep-eap-ttls-chap-verify-8021x", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_IDENTITY); + ASSERT (strcmp (tmp, expected_identity) == 0, + "wifi-wep-eap-ttls-chap-verify-8021x", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_IDENTITY); + + /* Password */ + tmp = nm_setting_802_1x_get_password (s_8021x); + ASSERT (tmp != NULL, + "wifi-wep-eap-ttls-chap-verify-8021x", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PASSWORD); + ASSERT (strcmp (tmp, expected_password) == 0, + "wifi-wep-eap-ttls-chap-verify-8021x", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP, + NM_SETTING_802_1X_SETTING_NAME, + NM_SETTING_802_1X_PASSWORD); + + g_object_unref (connection); +} + +static void +test_write_wired_static (void) +{ + NMConnection *connection; + NMConnection *reread; + NMSettingConnection *s_con; + NMSettingWired *s_wired; + NMSettingIP4Config *s_ip4; + static unsigned char tmpmac[] = { 0x31, 0x33, 0x33, 0x37, 0xbe, 0xcd }; + GByteArray *mac; + guint32 mtu = 1492; + char *uuid; + guint64 timestamp = 0x12344433L; + const guint32 ip1 = htonl (0x01010103); + const guint32 ip2 = htonl (0x01010105); + const guint32 gw = htonl (0x01010101); + const guint32 dns1 = htonl (0x04020201); + const guint32 dns2 = htonl (0x04020202); + const guint32 prefix = 24; + const char *dns_search1 = "foobar.com"; + const char *dns_search2 = "lab.foobar.com"; + NMIP4Address *addr; + gboolean success; + GError *error = NULL; + char *testfile = NULL; + gboolean unmanaged = FALSE; + char *keyfile = NULL; + gboolean ignore_error = FALSE; + + connection = nm_connection_new (); + ASSERT (connection != NULL, + "wired-static-write", "failed to allocate new connection"); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + ASSERT (s_con != NULL, + "wired-static-write", "failed to allocate new %s setting", + NM_SETTING_CONNECTION_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + uuid = nm_utils_uuid_generate (); + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, "Test Write Wired Static", + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_CONNECTION_TIMESTAMP, timestamp, + NULL); + g_free (uuid); + + /* Wired setting */ + s_wired = (NMSettingWired *) nm_setting_wired_new (); + ASSERT (s_wired != NULL, + "wired-static-write", "failed to allocate new %s setting", + NM_SETTING_WIRED_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wired)); + + mac = g_byte_array_sized_new (sizeof (tmpmac)); + g_byte_array_append (mac, &tmpmac[0], sizeof (tmpmac)); + + g_object_set (s_wired, + NM_SETTING_WIRED_MAC_ADDRESS, mac, + NM_SETTING_WIRED_MTU, mtu, + NULL); + g_byte_array_free (mac, TRUE); + + /* IP4 setting */ + s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); + ASSERT (s_ip4 != NULL, + "wired-static-write", "failed to allocate new %s setting", + NM_SETTING_IP4_CONFIG_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + + g_object_set (s_ip4, + NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, + NULL); + + addr = nm_ip4_address_new (); + nm_ip4_address_set_address (addr, ip1); + nm_ip4_address_set_prefix (addr, prefix); + nm_ip4_address_set_gateway (addr, gw); + nm_setting_ip4_config_add_address (s_ip4, addr); + nm_ip4_address_unref (addr); + + addr = nm_ip4_address_new (); + nm_ip4_address_set_address (addr, ip2); + nm_ip4_address_set_prefix (addr, prefix); + nm_ip4_address_set_gateway (addr, gw); + nm_setting_ip4_config_add_address (s_ip4, addr); + nm_ip4_address_unref (addr); + + nm_setting_ip4_config_add_dns (s_ip4, dns1); + nm_setting_ip4_config_add_dns (s_ip4, dns2); + + nm_setting_ip4_config_add_dns_search (s_ip4, dns_search1); + nm_setting_ip4_config_add_dns_search (s_ip4, dns_search2); + + ASSERT (nm_connection_verify (connection, &error) == TRUE, + "wired-static-write", "failed to verify connection: %s", + (error && error->message) ? error->message : "(unknown)"); + + /* Save the ifcfg */ + success = writer_new_connection (connection, + TEST_SCRATCH_DIR "/network-scripts/", + &testfile, + &error); + ASSERT (success == TRUE, + "wired-static-write", "failed to write connection to disk: %s", + (error && error->message) ? error->message : "(unknown)"); + + ASSERT (testfile != NULL, + "wired-static-write", "didn't get ifcfg file path back after writing connection"); + + /* re-read the connection for comparison */ + reread = connection_from_file (testfile, + NULL, + TYPE_ETHERNET, + &unmanaged, + &keyfile, + &error, + &ignore_error); + unlink (testfile); + + ASSERT (reread != NULL, + "wired-static-write-reread", "failed to read %s: %s", testfile, error->message); + + ASSERT (nm_connection_verify (reread, &error), + "wired-static-write-reread-verify", "failed to verify %s: %s", testfile, error->message); + + ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE, + "wired-static-write", "written and re-read connection weren't the same."); + + g_free (testfile); + g_object_unref (connection); + g_object_unref (reread); +} + +static void +test_write_wired_dhcp (void) +{ + NMConnection *connection; + NMConnection *reread; + NMSettingConnection *s_con; + NMSettingWired *s_wired; + NMSettingIP4Config *s_ip4; + char *uuid; + gboolean success; + GError *error = NULL; + char *testfile = NULL; + gboolean unmanaged = FALSE; + char *keyfile = NULL; + gboolean ignore_error = FALSE; + + connection = nm_connection_new (); + ASSERT (connection != NULL, + "wired-dhcp-write", "failed to allocate new connection"); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + ASSERT (s_con != NULL, + "wired-dhcp-write", "failed to allocate new %s setting", + NM_SETTING_CONNECTION_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + uuid = nm_utils_uuid_generate (); + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, "Test Write Wired DHCP", + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, + NULL); + g_free (uuid); + + /* Wired setting */ + s_wired = (NMSettingWired *) nm_setting_wired_new (); + ASSERT (s_wired != NULL, + "wired-dhcp-write", "failed to allocate new %s setting", + NM_SETTING_WIRED_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wired)); + + /* IP4 setting */ + s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); + ASSERT (s_ip4 != NULL, + "wired-dhcp-write", "failed to allocate new %s setting", + NM_SETTING_IP4_CONFIG_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + + g_object_set (s_ip4, + NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, + NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, "random-client-id-00:22:33", + NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME, "awesome-hostname", + NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES, TRUE, + NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS, TRUE, + NULL); + + ASSERT (nm_connection_verify (connection, &error) == TRUE, + "wired-dhcp-write", "failed to verify connection: %s", + (error && error->message) ? error->message : "(unknown)"); + + /* Save the ifcfg */ + success = writer_new_connection (connection, + TEST_SCRATCH_DIR "/network-scripts/", + &testfile, + &error); + ASSERT (success == TRUE, + "wired-dhcp-write", "failed to write connection to disk: %s", + (error && error->message) ? error->message : "(unknown)"); + + ASSERT (testfile != NULL, + "wired-dhcp-write", "didn't get ifcfg file path back after writing connection"); + + /* re-read the connection for comparison */ + reread = connection_from_file (testfile, + NULL, + TYPE_ETHERNET, + &unmanaged, + &keyfile, + &error, + &ignore_error); + unlink (testfile); + + ASSERT (reread != NULL, + "wired-dhcp-write-reread", "failed to read %s: %s", testfile, error->message); + + ASSERT (nm_connection_verify (reread, &error), + "wired-dhcp-write-reread-verify", "failed to verify %s: %s", testfile, error->message); + + ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE, + "wired-dhcp-write", "written and re-read connection weren't the same."); + + g_free (testfile); + g_object_unref (connection); + g_object_unref (reread); +} + +static void +test_write_wired_dhcp_8021x_peap_mschapv2 (void) +{ + NMConnection *connection; + NMConnection *reread; + NMSettingConnection *s_con; + NMSettingWired *s_wired; + NMSettingIP4Config *s_ip4; + NMSetting8021x *s_8021x; + char *uuid; + gboolean success; + GError *error = NULL; + char *testfile = NULL; + gboolean unmanaged = FALSE; + char *keyfile = NULL; + gboolean ignore_error = FALSE; + + connection = nm_connection_new (); + ASSERT (connection != NULL, + "wired-dhcp-8021x-peap-mschapv2write", "failed to allocate new connection"); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + ASSERT (s_con != NULL, + "wired-dhcp-8021x-peap-mschapv2write", "failed to allocate new %s setting", + NM_SETTING_CONNECTION_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + uuid = nm_utils_uuid_generate (); + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, "Test Write Wired DHCP 802.1x PEAP MSCHAPv2", + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, + NULL); + g_free (uuid); + + /* Wired setting */ + s_wired = (NMSettingWired *) nm_setting_wired_new (); + ASSERT (s_wired != NULL, + "wired-dhcp-8021x-peap-mschapv2write", "failed to allocate new %s setting", + NM_SETTING_WIRED_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wired)); + + /* IP4 setting */ + s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); + ASSERT (s_ip4 != NULL, + "wired-dhcp-8021x-peap-mschapv2write", "failed to allocate new %s setting", + NM_SETTING_IP4_CONFIG_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + + g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); + + /* 802.1x setting */ + s_8021x = (NMSetting8021x *) nm_setting_802_1x_new (); + ASSERT (s_8021x != NULL, + "wired-dhcp-8021x-peap-mschapv2write", "failed to allocate new %s setting", + NM_SETTING_802_1X_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_8021x)); + + g_object_set (s_8021x, + NM_SETTING_802_1X_IDENTITY, "Bob Saget", + NM_SETTING_802_1X_PASSWORD, "Kids, it was back in October 2008...", + NM_SETTING_802_1X_PHASE1_PEAPVER, "1", + NM_SETTING_802_1X_PHASE1_PEAPLABEL, "1", + NM_SETTING_802_1X_PHASE2_AUTH, "mschapv2", + NULL); + + nm_setting_802_1x_add_eap_method (s_8021x, "peap"); + + success = nm_setting_802_1x_set_ca_cert_from_file (s_8021x, + TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2_CA_CERT, + NULL, + &error); + ASSERT (success == TRUE, + "wired-dhcp-8021x-peap-mschapv2write", "failed to verify connection: %s", + (error && error->message) ? error->message : "(unknown)"); + + ASSERT (nm_connection_verify (connection, &error) == TRUE, + "wired-dhcp-8021x-peap-mschapv2write", "failed to verify connection: %s", + (error && error->message) ? error->message : "(unknown)"); + + /* Save the ifcfg */ + success = writer_new_connection (connection, + TEST_SCRATCH_DIR "/network-scripts/", + &testfile, + &error); + ASSERT (success == TRUE, + "wired-dhcp-8021x-peap-mschapv2write", "failed to write connection to disk: %s", + (error && error->message) ? error->message : "(unknown)"); + + ASSERT (testfile != NULL, + "wired-dhcp-8021x-peap-mschapv2write", "didn't get ifcfg file path back after writing connection"); + + /* re-read the connection for comparison */ + reread = connection_from_file (testfile, + NULL, + TYPE_ETHERNET, + &unmanaged, + &keyfile, + &error, + &ignore_error); + unlink (testfile); + + ASSERT (reread != NULL, + "wired-dhcp-8021x-peap-mschapv2write-reread", "failed to read %s: %s", testfile, error->message); + + ASSERT (keyfile != NULL, + "wired-dhcp-8021x-peap-mschapv2write-reread", "expected keyfile for '%s'", testfile); + unlink (keyfile); + + ASSERT (nm_connection_verify (reread, &error), + "wired-dhcp-8021x-peap-mschapv2write-reread-verify", "failed to verify %s: %s", testfile, error->message); + + ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE, + "wired-dhcp-8021x-peap-mschapv2write", "written and re-read connection weren't the same."); + + g_free (testfile); + g_object_unref (connection); + g_object_unref (reread); +} + +static void +test_write_wifi_open (void) +{ + NMConnection *connection; + NMConnection *reread; + NMSettingConnection *s_con; + NMSettingWireless *s_wifi; + NMSettingIP4Config *s_ip4; + char *uuid; + gboolean success; + GError *error = NULL; + char *testfile = NULL; + gboolean unmanaged = FALSE; + char *keyfile = NULL; + gboolean ignore_error = FALSE; + GByteArray *ssid; + const unsigned char ssid_data[] = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44 }; + GByteArray *bssid; + const unsigned char bssid_data[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 }; + guint32 channel = 9, mtu = 1345; + GByteArray *mac; + const unsigned char mac_data[] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; + + connection = nm_connection_new (); + ASSERT (connection != NULL, + "wifi-open-write", "failed to allocate new connection"); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + ASSERT (s_con != NULL, + "wifi-open-write", "failed to allocate new %s setting", + NM_SETTING_CONNECTION_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + uuid = nm_utils_uuid_generate (); + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, "Test Write Wifi Open", + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, + NULL); + g_free (uuid); + + /* Wifi setting */ + s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); + ASSERT (s_wifi != NULL, + "wifi-open-write", "failed to allocate new %s setting", + NM_SETTING_WIRELESS_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wifi)); + + ssid = g_byte_array_sized_new (sizeof (ssid_data)); + g_byte_array_append (ssid, ssid_data, sizeof (ssid_data)); + bssid = g_byte_array_sized_new (sizeof (bssid_data)); + g_byte_array_append (bssid, bssid_data, sizeof (bssid_data)); + mac = g_byte_array_sized_new (sizeof (mac_data)); + g_byte_array_append (mac, mac_data, sizeof (mac_data)); + + g_object_set (s_wifi, + NM_SETTING_WIRELESS_SSID, ssid, + NM_SETTING_WIRELESS_BSSID, bssid, + NM_SETTING_WIRELESS_MAC_ADDRESS, mac, + NM_SETTING_WIRELESS_MODE, "infrastructure", + NM_SETTING_WIRELESS_BAND, "bg", + NM_SETTING_WIRELESS_CHANNEL, channel, + NM_SETTING_WIRELESS_MTU, mtu, + NULL); + + g_byte_array_free (ssid, TRUE); + g_byte_array_free (bssid, TRUE); + g_byte_array_free (mac, TRUE); + + /* IP4 setting */ + s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); + ASSERT (s_ip4 != NULL, + "wifi-open-write", "failed to allocate new %s setting", + NM_SETTING_IP4_CONFIG_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + + g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); + + ASSERT (nm_connection_verify (connection, &error) == TRUE, + "wifi-open-write", "failed to verify connection: %s", + (error && error->message) ? error->message : "(unknown)"); + + /* Save the ifcfg */ + success = writer_new_connection (connection, + TEST_SCRATCH_DIR "/network-scripts/", + &testfile, + &error); + ASSERT (success == TRUE, + "wifi-open-write", "failed to write connection to disk: %s", + (error && error->message) ? error->message : "(unknown)"); + + ASSERT (testfile != NULL, + "wifi-open-write", "didn't get ifcfg file path back after writing connection"); + + /* re-read the connection for comparison */ + reread = connection_from_file (testfile, + NULL, + TYPE_WIRELESS, + &unmanaged, + &keyfile, + &error, + &ignore_error); + unlink (testfile); + + ASSERT (reread != NULL, + "wifi-open-write-reread", "failed to read %s: %s", testfile, error->message); + + ASSERT (nm_connection_verify (reread, &error), + "wifi-open-write-reread-verify", "failed to verify %s: %s", testfile, error->message); + + ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE, + "wifi-open-write", "written and re-read connection weren't the same."); + + g_free (testfile); + g_object_unref (connection); + g_object_unref (reread); +} + +static void +test_write_wifi_open_hex_ssid (void) +{ + NMConnection *connection; + NMConnection *reread; + NMSettingConnection *s_con; + NMSettingWireless *s_wifi; + NMSettingIP4Config *s_ip4; + char *uuid; + gboolean success; + GError *error = NULL; + char *testfile = NULL; + gboolean unmanaged = FALSE; + char *keyfile = NULL; + gboolean ignore_error = FALSE; + GByteArray *ssid; + const unsigned char ssid_data[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd }; + + connection = nm_connection_new (); + ASSERT (connection != NULL, + "wifi-open-hex-ssid-write", "failed to allocate new connection"); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + ASSERT (s_con != NULL, + "wifi-open-hex-ssid-write", "failed to allocate new %s setting", + NM_SETTING_CONNECTION_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + uuid = nm_utils_uuid_generate (); + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, "Test Write Wifi Open Hex SSID", + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, + NULL); + g_free (uuid); + + /* Wifi setting */ + s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); + ASSERT (s_wifi != NULL, + "wifi-open-hex-ssid-write", "failed to allocate new %s setting", + NM_SETTING_WIRELESS_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wifi)); + + ssid = g_byte_array_sized_new (sizeof (ssid_data)); + g_byte_array_append (ssid, ssid_data, sizeof (ssid_data)); + + g_object_set (s_wifi, + NM_SETTING_WIRELESS_SSID, ssid, + NM_SETTING_WIRELESS_MODE, "infrastructure", + NULL); + + g_byte_array_free (ssid, TRUE); + + /* IP4 setting */ + s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); + ASSERT (s_ip4 != NULL, + "wifi-open-hex-ssid-write", "failed to allocate new %s setting", + NM_SETTING_IP4_CONFIG_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + + g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); + + ASSERT (nm_connection_verify (connection, &error) == TRUE, + "wifi-open-hex-ssid-write", "failed to verify connection: %s", + (error && error->message) ? error->message : "(unknown)"); + + /* Save the ifcfg */ + success = writer_new_connection (connection, + TEST_SCRATCH_DIR "/network-scripts/", + &testfile, + &error); + ASSERT (success == TRUE, + "wifi-open-hex-ssid-write", "failed to write connection to disk: %s", + (error && error->message) ? error->message : "(unknown)"); + + ASSERT (testfile != NULL, + "wifi-open-hex-ssid-write", "didn't get ifcfg file path back after writing connection"); + + /* re-read the connection for comparison */ + reread = connection_from_file (testfile, + NULL, + TYPE_WIRELESS, + &unmanaged, + &keyfile, + &error, + &ignore_error); + unlink (testfile); + + ASSERT (reread != NULL, + "wifi-open-hex-ssid-write-reread", "failed to read %s: %s", testfile, error->message); + + ASSERT (nm_connection_verify (reread, &error), + "wifi-open-hex-ssid-write-reread-verify", "failed to verify %s: %s", testfile, error->message); + + ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE, + "wifi-open-hex-ssid-write", "written and re-read connection weren't the same."); + + g_free (testfile); + g_object_unref (connection); + g_object_unref (reread); +} + +static void +test_write_wifi_wep (void) +{ + NMConnection *connection; + NMConnection *reread; + NMSettingConnection *s_con; + NMSettingWireless *s_wifi; + NMSettingWirelessSecurity *s_wsec; + NMSettingIP4Config *s_ip4; + char *uuid; + gboolean success; + GError *error = NULL; + char *testfile = NULL; + gboolean unmanaged = FALSE; + char *keyfile = NULL; + gboolean ignore_error = FALSE; + GByteArray *ssid; + const unsigned char ssid_data[] = "blahblah"; + struct stat statbuf; + + connection = nm_connection_new (); + ASSERT (connection != NULL, + "wifi-wep-write", "failed to allocate new connection"); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + ASSERT (s_con != NULL, + "wifi-wep-write", "failed to allocate new %s setting", + NM_SETTING_CONNECTION_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + uuid = nm_utils_uuid_generate (); + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, "Test Write Wifi WEP", + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, + NULL); + g_free (uuid); + + /* Wifi setting */ + s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); + ASSERT (s_wifi != NULL, + "wifi-wep-write", "failed to allocate new %s setting", + NM_SETTING_WIRELESS_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wifi)); + + ssid = g_byte_array_sized_new (sizeof (ssid_data)); + g_byte_array_append (ssid, ssid_data, sizeof (ssid_data)); + + g_object_set (s_wifi, + NM_SETTING_WIRELESS_SSID, ssid, + NM_SETTING_WIRELESS_MODE, "infrastructure", + NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NULL); + + g_byte_array_free (ssid, TRUE); + + /* Wireless security setting */ + s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new (); + ASSERT (s_wsec != NULL, + "wifi-wep-write", "failed to allocate new %s setting", + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wsec)); + + g_object_set (s_wsec, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none", + NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, 2, + NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "shared", + NULL); + nm_setting_wireless_security_set_wep_key (s_wsec, 0, "0123456789abcdef0123456789"); + nm_setting_wireless_security_set_wep_key (s_wsec, 1, "11111111111111111111111111"); + nm_setting_wireless_security_set_wep_key (s_wsec, 2, "aaaaaaaaaaaaaaaaaaaaaaaaaa"); + nm_setting_wireless_security_set_wep_key (s_wsec, 3, "BBBBBBBBBBBBBBBBBBBBBBBBBB"); + + /* IP4 setting */ + s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); + ASSERT (s_ip4 != NULL, + "wifi-wep-write", "failed to allocate new %s setting", + NM_SETTING_IP4_CONFIG_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + + g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); + + ASSERT (nm_connection_verify (connection, &error) == TRUE, + "wifi-wep-write", "failed to verify connection: %s", + (error && error->message) ? error->message : "(unknown)"); + + /* Save the ifcfg */ + success = writer_new_connection (connection, + TEST_SCRATCH_DIR "/network-scripts/", + &testfile, + &error); + ASSERT (success == TRUE, + "wifi-wep-write", "failed to write connection to disk: %s", + (error && error->message) ? error->message : "(unknown)"); + + ASSERT (testfile != NULL, + "wifi-wep-write", "didn't get ifcfg file path back after writing connection"); + + /* re-read the connection for comparison */ + reread = connection_from_file (testfile, + NULL, + TYPE_WIRELESS, + &unmanaged, + &keyfile, + &error, + &ignore_error); + unlink (testfile); + + ASSERT (keyfile != NULL, + "wifi-wep-write-reread", "expected keyfile for '%s'", testfile); + + ASSERT (stat (keyfile, &statbuf) == 0, + "wifi-wep-write-reread", "couldn't stat() '%s'", keyfile); + ASSERT (S_ISREG (statbuf.st_mode), + "wifi-wep-write-reread", "keyfile '%s' wasn't a normal file", keyfile); + ASSERT ((statbuf.st_mode & 0077) == 0, + "wifi-wep-write-reread", "keyfile '%s' wasn't readable only by its owner", keyfile); + + unlink (keyfile); + + ASSERT (reread != NULL, + "wifi-wep-write-reread", "failed to read %s: %s", testfile, error->message); + + ASSERT (nm_connection_verify (reread, &error), + "wifi-wep-write-reread-verify", "failed to verify %s: %s", testfile, error->message); + + ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE, + "wifi-wep-write", "written and re-read connection weren't the same."); + + g_free (testfile); + g_object_unref (connection); + g_object_unref (reread); +} + +static void +test_write_wifi_wep_adhoc (void) +{ + NMConnection *connection; + NMConnection *reread; + NMSettingConnection *s_con; + NMSettingWireless *s_wifi; + NMSettingWirelessSecurity *s_wsec; + NMSettingIP4Config *s_ip4; + char *uuid; + gboolean success; + GError *error = NULL; + char *testfile = NULL; + gboolean unmanaged = FALSE; + char *keyfile = NULL; + gboolean ignore_error = FALSE; + GByteArray *ssid; + const unsigned char ssid_data[] = "blahblah"; + struct stat statbuf; + NMIP4Address *addr; + const guint32 ip1 = htonl (0x01010103); + const guint32 gw = htonl (0x01010101); + const guint32 dns1 = htonl (0x04020201); + const guint32 prefix = 24; + + connection = nm_connection_new (); + ASSERT (connection != NULL, + "wifi-wep-adhoc-write", "failed to allocate new connection"); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + ASSERT (s_con != NULL, + "wifi-wep-adhoc-write", "failed to allocate new %s setting", + NM_SETTING_CONNECTION_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + uuid = nm_utils_uuid_generate (); + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, "Test Write Wifi WEP AdHoc", + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, + NULL); + g_free (uuid); + + /* Wifi setting */ + s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); + ASSERT (s_wifi != NULL, + "wifi-wep-adhoc-write", "failed to allocate new %s setting", + NM_SETTING_WIRELESS_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wifi)); + + ssid = g_byte_array_sized_new (sizeof (ssid_data)); + g_byte_array_append (ssid, ssid_data, sizeof (ssid_data)); + + g_object_set (s_wifi, + NM_SETTING_WIRELESS_SSID, ssid, + NM_SETTING_WIRELESS_MODE, "adhoc", + NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NULL); + + g_byte_array_free (ssid, TRUE); + + /* Wireless security setting */ + s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new (); + ASSERT (s_wsec != NULL, + "wifi-wep-adhoc-write", "failed to allocate new %s setting", + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wsec)); + + g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none", NULL); + nm_setting_wireless_security_set_wep_key (s_wsec, 0, "0123456789abcdef0123456789"); + + /* IP4 setting */ + s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); + ASSERT (s_ip4 != NULL, + "wifi-wep-adhoc-write", "failed to allocate new %s setting", + NM_SETTING_IP4_CONFIG_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + + g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, NULL); + + /* IP Address */ + addr = nm_ip4_address_new (); + nm_ip4_address_set_address (addr, ip1); + nm_ip4_address_set_prefix (addr, prefix); + nm_ip4_address_set_gateway (addr, gw); + nm_setting_ip4_config_add_address (s_ip4, addr); + nm_ip4_address_unref (addr); + + nm_setting_ip4_config_add_dns (s_ip4, dns1); + + ASSERT (nm_connection_verify (connection, &error) == TRUE, + "wifi-wep-adhoc-write", "failed to verify connection: %s", + (error && error->message) ? error->message : "(unknown)"); + + /* Save the ifcfg */ + success = writer_new_connection (connection, + TEST_SCRATCH_DIR "/network-scripts/", + &testfile, + &error); + ASSERT (success == TRUE, + "wifi-wep-adhoc-write", "failed to write connection to disk: %s", + (error && error->message) ? error->message : "(unknown)"); + + ASSERT (testfile != NULL, + "wifi-wep-adhoc-write", "didn't get ifcfg file path back after writing connection"); + + /* re-read the connection for comparison */ + reread = connection_from_file (testfile, + NULL, + TYPE_WIRELESS, + &unmanaged, + &keyfile, + &error, + &ignore_error); + unlink (testfile); + + ASSERT (keyfile != NULL, + "wifi-wep-adhoc-write-reread", "expected keyfile for '%s'", testfile); + + ASSERT (stat (keyfile, &statbuf) == 0, + "wifi-wep-adhoc-write-reread", "couldn't stat() '%s'", keyfile); + ASSERT (S_ISREG (statbuf.st_mode), + "wifi-wep-adhoc-write-reread", "keyfile '%s' wasn't a normal file", keyfile); + ASSERT ((statbuf.st_mode & 0077) == 0, + "wifi-wep-adhoc-write-reread", "keyfile '%s' wasn't readable only by its owner", keyfile); + + unlink (keyfile); + + ASSERT (reread != NULL, + "wifi-wep-adhoc-write-reread", "failed to read %s: %s", testfile, error->message); + + ASSERT (nm_connection_verify (reread, &error), + "wifi-wep-adhoc-write-reread-verify", "failed to verify %s: %s", testfile, error->message); + + ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE, + "wifi-wep-adhoc-write", "written and re-read connection weren't the same."); + + g_free (testfile); + g_object_unref (connection); + g_object_unref (reread); +} + +static void +test_write_wifi_wpa_psk (const char *name, + const char *test_name, + gboolean wep_group, + gboolean wpa, + gboolean wpa2) +{ + NMConnection *connection; + NMConnection *reread; + NMSettingConnection *s_con; + NMSettingWireless *s_wifi; + NMSettingWirelessSecurity *s_wsec; + NMSettingIP4Config *s_ip4; + char *uuid, *tmp; + gboolean success; + GError *error = NULL; + char *testfile = NULL; + gboolean unmanaged = FALSE; + char *keyfile = NULL; + gboolean ignore_error = FALSE; + GByteArray *ssid; + const unsigned char ssid_data[] = "blahblah"; + + connection = nm_connection_new (); + ASSERT (connection != NULL, + test_name, "failed to allocate new connection"); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + ASSERT (s_con != NULL, + test_name, "failed to allocate new %s setting", + NM_SETTING_CONNECTION_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + uuid = nm_utils_uuid_generate (); + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, name, + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, + NULL); + g_free (uuid); + + /* Wifi setting */ + s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); + ASSERT (s_wifi != NULL, + test_name, "failed to allocate new %s setting", + NM_SETTING_WIRELESS_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wifi)); + + ssid = g_byte_array_sized_new (sizeof (ssid_data)); + g_byte_array_append (ssid, ssid_data, sizeof (ssid_data)); + + g_object_set (s_wifi, + NM_SETTING_WIRELESS_SSID, ssid, + NM_SETTING_WIRELESS_MODE, "infrastructure", + NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NULL); + + g_byte_array_free (ssid, TRUE); + + /* Wireless security setting */ + s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new (); + ASSERT (s_wsec != NULL, + test_name, "failed to allocate new %s setting", + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wsec)); + + g_object_set (s_wsec, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", + NM_SETTING_WIRELESS_SECURITY_PSK, "7d308b11df1b4243b0f78e5f3fc68cdbb9a264ed0edf4c188edf329ff5b467f0", + NULL); + + if (wep_group) { + nm_setting_wireless_security_add_group (s_wsec, "wep40"); + nm_setting_wireless_security_add_group (s_wsec, "wep104"); + } + if (wpa) { + nm_setting_wireless_security_add_proto (s_wsec, "wpa"); + nm_setting_wireless_security_add_pairwise (s_wsec, "tkip"); + nm_setting_wireless_security_add_group (s_wsec, "tkip"); + } + if (wpa2) { + nm_setting_wireless_security_add_proto (s_wsec, "rsn"); + nm_setting_wireless_security_add_pairwise (s_wsec, "ccmp"); + nm_setting_wireless_security_add_group (s_wsec, "ccmp"); + } + + /* IP4 setting */ + s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); + ASSERT (s_ip4 != NULL, + test_name, "failed to allocate new %s setting", + NM_SETTING_IP4_CONFIG_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + + g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); + + ASSERT (nm_connection_verify (connection, &error) == TRUE, + test_name, "failed to verify connection: %s", + (error && error->message) ? error->message : "(unknown)"); + + /* Save the ifcfg */ + success = writer_new_connection (connection, + TEST_SCRATCH_DIR "/network-scripts/", + &testfile, + &error); + ASSERT (success == TRUE, + test_name, "failed to write connection to disk: %s", + (error && error->message) ? error->message : "(unknown)"); + + ASSERT (testfile != NULL, + test_name, "didn't get ifcfg file path back after writing connection"); + + /* re-read the connection for comparison */ + reread = connection_from_file (testfile, + NULL, + TYPE_WIRELESS, + &unmanaged, + &keyfile, + &error, + &ignore_error); + unlink (testfile); + + tmp = g_strdup_printf ("%s-reread", test_name); + ASSERT (keyfile != NULL, + tmp, "expected keyfile for '%s'", testfile); + unlink (keyfile); + + ASSERT (reread != NULL, + tmp, "failed to read %s: %s", testfile, error->message); + + ASSERT (nm_connection_verify (reread, &error), + tmp, "failed to verify %s: %s", testfile, error->message); + g_free (tmp); + + ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE, + test_name, "written and re-read connection weren't the same."); + + g_free (testfile); + g_object_unref (connection); + g_object_unref (reread); +} + +static void +test_write_wifi_wpa_psk_adhoc (void) +{ + NMConnection *connection; + NMConnection *reread; + NMSettingConnection *s_con; + NMSettingWireless *s_wifi; + NMSettingWirelessSecurity *s_wsec; + NMSettingIP4Config *s_ip4; + char *uuid; + gboolean success; + GError *error = NULL; + char *testfile = NULL; + gboolean unmanaged = FALSE; + char *keyfile = NULL; + gboolean ignore_error = FALSE; + GByteArray *ssid; + const unsigned char ssid_data[] = "blahblah"; + NMIP4Address *addr; + const guint32 ip1 = htonl (0x01010103); + const guint32 gw = htonl (0x01010101); + const guint32 dns1 = htonl (0x04020201); + const guint32 prefix = 24; + + connection = nm_connection_new (); + ASSERT (connection != NULL, + "wifi-wpa-psk-adhoc-write", "failed to allocate new connection"); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + ASSERT (s_con != NULL, + "wifi-wpa-psk-adhoc-write", "failed to allocate new %s setting", + NM_SETTING_CONNECTION_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + uuid = nm_utils_uuid_generate (); + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, "Test Write Wifi WPA PSK", + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, + NULL); + g_free (uuid); + + /* Wifi setting */ + s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); + ASSERT (s_wifi != NULL, + "wifi-wpa-psk-adhoc-write", "failed to allocate new %s setting", + NM_SETTING_WIRELESS_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wifi)); + + ssid = g_byte_array_sized_new (sizeof (ssid_data)); + g_byte_array_append (ssid, ssid_data, sizeof (ssid_data)); + + g_object_set (s_wifi, + NM_SETTING_WIRELESS_SSID, ssid, + NM_SETTING_WIRELESS_MODE, "adhoc", + NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_CHANNEL, 11, + NM_SETTING_WIRELESS_BAND, "bg", + NULL); + + g_byte_array_free (ssid, TRUE); + + /* Wireless security setting */ + s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new (); + ASSERT (s_wsec != NULL, + "wifi-wpa-psk-adhoc-write", "failed to allocate new %s setting", + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wsec)); + + g_object_set (s_wsec, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-none", + NM_SETTING_WIRELESS_SECURITY_PSK, "7d308b11df1b4243b0f78e5f3fc68cdbb9a264ed0edf4c188edf329ff5b467f0", + NULL); + + nm_setting_wireless_security_add_proto (s_wsec, "wpa"); + nm_setting_wireless_security_add_group (s_wsec, "tkip"); + + /* IP4 setting */ + s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); + ASSERT (s_ip4 != NULL, + "wifi-wpa-psk-adhoc-write", "failed to allocate new %s setting", + NM_SETTING_IP4_CONFIG_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + + g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, NULL); + + /* IP Address */ + addr = nm_ip4_address_new (); + nm_ip4_address_set_address (addr, ip1); + nm_ip4_address_set_prefix (addr, prefix); + nm_ip4_address_set_gateway (addr, gw); + nm_setting_ip4_config_add_address (s_ip4, addr); + nm_ip4_address_unref (addr); + + nm_setting_ip4_config_add_dns (s_ip4, dns1); + + ASSERT (nm_connection_verify (connection, &error) == TRUE, + "wifi-wpa-psk-adhoc-write", "failed to verify connection: %s", + (error && error->message) ? error->message : "(unknown)"); + + /* Save the ifcfg */ + success = writer_new_connection (connection, + TEST_SCRATCH_DIR "/network-scripts/", + &testfile, + &error); + ASSERT (success == TRUE, + "wifi-wpa-psk-adhoc-write", "failed to write connection to disk: %s", + (error && error->message) ? error->message : "(unknown)"); + + ASSERT (testfile != NULL, + "wifi-wpa-psk-adhoc-write", "didn't get ifcfg file path back after writing connection"); + + /* re-read the connection for comparison */ + reread = connection_from_file (testfile, + NULL, + TYPE_WIRELESS, + &unmanaged, + &keyfile, + &error, + &ignore_error); + unlink (testfile); + + ASSERT (keyfile != NULL, + "wifi-wpa-psk-adhoc-write-reread", "expected keyfile for '%s'", testfile); + unlink (keyfile); + + ASSERT (reread != NULL, + "wifi-wpa-psk-adhoc-write-reread", "failed to read %s: %s", testfile, error->message); + + ASSERT (nm_connection_verify (reread, &error), + "wifi-wpa-psk-adhoc-write-reread", "failed to verify %s: %s", testfile, error->message); + + ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE, + "wifi-wpa-psk-adhoc-write", "written and re-read connection weren't the same."); + + g_free (testfile); + g_object_unref (connection); + g_object_unref (reread); +} + +static void +test_write_wifi_wpa_eap_tls (void) +{ + NMConnection *connection; + NMConnection *reread; + NMSettingConnection *s_con; + NMSettingWireless *s_wifi; + NMSettingWirelessSecurity *s_wsec; + NMSetting8021x *s_8021x; + NMSettingIP4Config *s_ip4; + char *uuid; + gboolean success; + GError *error = NULL; + char *testfile = NULL; + gboolean unmanaged = FALSE; + char *keyfile = NULL; + gboolean ignore_error = FALSE; + GByteArray *ssid; + const char *ssid_data = "blahblah"; + + connection = nm_connection_new (); + ASSERT (connection != NULL, + "wifi-wpa-eap-tls-write", "failed to allocate new connection"); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + ASSERT (s_con != NULL, + "wifi-wpa-eap-tls-write", "failed to allocate new %s setting", + NM_SETTING_CONNECTION_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + uuid = nm_utils_uuid_generate (); + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, "Test Write Wifi WPA EAP-TLS", + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, + NULL); + g_free (uuid); + + /* Wifi setting */ + s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); + ASSERT (s_wifi != NULL, + "wifi-wpa-eap-tls-write", "failed to allocate new %s setting", + NM_SETTING_WIRELESS_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wifi)); + + ssid = g_byte_array_sized_new (strlen (ssid_data)); + g_byte_array_append (ssid, (const unsigned char *) ssid_data, strlen (ssid_data)); + + g_object_set (s_wifi, + NM_SETTING_WIRELESS_SSID, ssid, + NM_SETTING_WIRELESS_MODE, "infrastructure", + NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NULL); + + g_byte_array_free (ssid, TRUE); + + /* Wireless security setting */ + s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new (); + ASSERT (s_wsec != NULL, + "wifi-wpa-eap-tls-write", "failed to allocate new %s setting", + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wsec)); + + g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap", NULL); + nm_setting_wireless_security_add_proto (s_wsec, "wpa"); + nm_setting_wireless_security_add_pairwise (s_wsec, "tkip"); + nm_setting_wireless_security_add_group (s_wsec, "tkip"); + + /* Wireless security setting */ + s_8021x = (NMSetting8021x *) nm_setting_802_1x_new (); + ASSERT (s_8021x != NULL, + "wifi-wpa-eap-tls-write", "failed to allocate new %s setting", + NM_SETTING_802_1X_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_8021x)); + + g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, "Bill Smith", NULL); + + nm_setting_802_1x_add_eap_method (s_8021x, "tls"); + + success = nm_setting_802_1x_set_ca_cert_from_file (s_8021x, + TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT, + NULL, + &error); + ASSERT (success == TRUE, + "wifi-wpa-eap-tls-write", "failed to set CA certificate '%s': %s", + TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT, error->message); + + success = nm_setting_802_1x_set_client_cert_from_file (s_8021x, + TEST_IFCFG_WIFI_WPA_EAP_TLS_CLIENT_CERT, + NULL, + &error); + ASSERT (success == TRUE, + "wifi-wpa-eap-tls-write", "failed to set client certificate '%s': %s", + TEST_IFCFG_WIFI_WPA_EAP_TLS_CLIENT_CERT, error->message); + + success = nm_setting_802_1x_set_private_key_from_file (s_8021x, + TEST_IFCFG_WIFI_WPA_EAP_TLS_PRIVATE_KEY, + "test1", + NULL, + &error); + ASSERT (success == TRUE, + "wifi-wpa-eap-tls-write", "failed to set private key '%s': %s", + TEST_IFCFG_WIFI_WPA_EAP_TLS_PRIVATE_KEY, error->message); + + /* IP4 setting */ + s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); + ASSERT (s_ip4 != NULL, + "wifi-wpa-eap-tls-write", "failed to allocate new %s setting", + NM_SETTING_IP4_CONFIG_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + + g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); + + ASSERT (nm_connection_verify (connection, &error) == TRUE, + "wifi-wpa-eap-tls-write", "failed to verify connection: %s", + (error && error->message) ? error->message : "(unknown)"); + + /* Save the ifcfg */ + success = writer_new_connection (connection, + TEST_SCRATCH_DIR "/network-scripts/", + &testfile, + &error); + ASSERT (success == TRUE, + "wifi-wpa-eap-tls-write", "failed to write connection to disk: %s", + (error && error->message) ? error->message : "(unknown)"); + + ASSERT (testfile != NULL, + "wifi-wpa-eap-tls-write", "didn't get ifcfg file path back after writing connection"); + + /* re-read the connection for comparison */ + reread = connection_from_file (testfile, + NULL, + TYPE_WIRELESS, + &unmanaged, + &keyfile, + &error, + &ignore_error); + unlink (testfile); + + ASSERT (keyfile != NULL, + "wifi-wpa-eap-tls-write-reread", "expected keyfile for '%s'", testfile); + unlink (keyfile); + + ASSERT (reread != NULL, + "wifi-wpa-eap-tls-write-reread", "failed to read %s: %s", testfile, error->message); + + ASSERT (nm_connection_verify (reread, &error), + "wifi-wpa-eap-tls-write-reread-verify", "failed to verify %s: %s", testfile, error->message); + + ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE, + "wifi-wpa-eap-tls-write", "written and re-read connection weren't the same."); + + g_free (testfile); + g_object_unref (connection); + g_object_unref (reread); +} + +static void +test_write_wifi_wpa_eap_ttls_tls (void) +{ + NMConnection *connection; + NMConnection *reread; + NMSettingConnection *s_con; + NMSettingWireless *s_wifi; + NMSettingWirelessSecurity *s_wsec; + NMSetting8021x *s_8021x; + NMSettingIP4Config *s_ip4; + char *uuid; + gboolean success; + GError *error = NULL; + char *testfile = NULL; + gboolean unmanaged = FALSE; + char *keyfile = NULL; + gboolean ignore_error = FALSE; + GByteArray *ssid; + const char *ssid_data = "blahblah"; + + connection = nm_connection_new (); + ASSERT (connection != NULL, + "wifi-wpa-eap-ttls-tls-write", "failed to allocate new connection"); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + ASSERT (s_con != NULL, + "wifi-wpa-eap-ttls-tls-write", "failed to allocate new %s setting", + NM_SETTING_CONNECTION_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + uuid = nm_utils_uuid_generate (); + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, "Test Write Wifi WPA EAP-TTLS (TLS)", + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, + NULL); + g_free (uuid); + + /* Wifi setting */ + s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); + ASSERT (s_wifi != NULL, + "wifi-wpa-eap-ttls-tls-write", "failed to allocate new %s setting", + NM_SETTING_WIRELESS_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wifi)); + + ssid = g_byte_array_sized_new (strlen (ssid_data)); + g_byte_array_append (ssid, (const unsigned char *) ssid_data, strlen (ssid_data)); + + g_object_set (s_wifi, + NM_SETTING_WIRELESS_SSID, ssid, + NM_SETTING_WIRELESS_MODE, "infrastructure", + NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NULL); + + g_byte_array_free (ssid, TRUE); + + /* Wireless security setting */ + s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new (); + ASSERT (s_wsec != NULL, + "wifi-wpa-eap-ttls-tls-write", "failed to allocate new %s setting", + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wsec)); + + g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap", NULL); + nm_setting_wireless_security_add_proto (s_wsec, "rsn"); + nm_setting_wireless_security_add_pairwise (s_wsec, "ccmp"); + nm_setting_wireless_security_add_group (s_wsec, "ccmp"); + + /* Wireless security setting */ + s_8021x = (NMSetting8021x *) nm_setting_802_1x_new (); + ASSERT (s_8021x != NULL, + "wifi-wpa-eap-ttls-tls-write", "failed to allocate new %s setting", + NM_SETTING_802_1X_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_8021x)); + + nm_setting_802_1x_add_eap_method (s_8021x, "ttls"); + + g_object_set (s_8021x, + NM_SETTING_802_1X_IDENTITY, "Bill Smith", + NM_SETTING_802_1X_ANONYMOUS_IDENTITY, "foobar22", + NM_SETTING_802_1X_PHASE2_AUTHEAP, "tls", + NULL); + + success = nm_setting_802_1x_set_ca_cert_from_file (s_8021x, + TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT, + NULL, + &error); + ASSERT (success == TRUE, + "wifi-wpa-eap-ttls-tls-write", "failed to set CA certificate '%s': %s", + TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT, error->message); + + /* Phase 2 TLS stuff */ + + /* phase2 CA cert */ + success = nm_setting_802_1x_set_phase2_ca_cert_from_file (s_8021x, + TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT, + NULL, + &error); + ASSERT (success == TRUE, + "wifi-wpa-eap-ttls-tls-write", "failed to set inner CA certificate '%s': %s", + TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT, error->message); + + /* phase2 client cert */ + success = nm_setting_802_1x_set_phase2_client_cert_from_file (s_8021x, + TEST_IFCFG_WIFI_WPA_EAP_TLS_CLIENT_CERT, + NULL, + &error); + ASSERT (success == TRUE, + "wifi-wpa-eap-ttls-tls-write", "failed to set inner client certificate '%s': %s", + TEST_IFCFG_WIFI_WPA_EAP_TLS_CLIENT_CERT, error->message); + + /* phase2 private key */ + success = nm_setting_802_1x_set_phase2_private_key_from_file (s_8021x, + TEST_IFCFG_WIFI_WPA_EAP_TLS_PRIVATE_KEY, + "test1", + NULL, + &error); + ASSERT (success == TRUE, + "wifi-wpa-eap-ttls-tls-write", "failed to set private key '%s': %s", + TEST_IFCFG_WIFI_WPA_EAP_TLS_PRIVATE_KEY, error->message); + + /* IP4 setting */ + s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); + ASSERT (s_ip4 != NULL, + "wifi-wpa-eap-ttls-tls-write", "failed to allocate new %s setting", + NM_SETTING_IP4_CONFIG_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + + g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); + + ASSERT (nm_connection_verify (connection, &error) == TRUE, + "wifi-wpa-eap-ttls-tls-write", "failed to verify connection: %s", + (error && error->message) ? error->message : "(unknown)"); + + /* Save the ifcfg */ + success = writer_new_connection (connection, + TEST_SCRATCH_DIR "/network-scripts/", + &testfile, + &error); + ASSERT (success == TRUE, + "wifi-wpa-eap-ttls-tls-write", "failed to write connection to disk: %s", + (error && error->message) ? error->message : "(unknown)"); + + ASSERT (testfile != NULL, + "wifi-wpa-eap-ttls-tls-write", "didn't get ifcfg file path back after writing connection"); + + /* re-read the connection for comparison */ + reread = connection_from_file (testfile, + NULL, + TYPE_WIRELESS, + &unmanaged, + &keyfile, + &error, + &ignore_error); + unlink (testfile); + + ASSERT (reread != NULL, + "wifi-wpa-eap-ttls-tls-write-reread", "failed to read %s: %s", testfile, error->message); + + ASSERT (keyfile != NULL, + "wifi-wpa-eap-ttls-tls-write-reread", "expected keyfile for '%s'", testfile); + unlink (keyfile); + + ASSERT (nm_connection_verify (reread, &error), + "wifi-wpa-eap-ttls-tls-write-reread-verify", "failed to verify %s: %s", testfile, error->message); + + ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE, + "wifi-wpa-eap-ttls-tls-write", "written and re-read connection weren't the same."); + + g_free (testfile); + g_object_unref (connection); + g_object_unref (reread); +} + +static void +test_write_wifi_wpa_eap_ttls_mschapv2 (void) +{ + NMConnection *connection; + NMConnection *reread; + NMSettingConnection *s_con; + NMSettingWireless *s_wifi; + NMSettingWirelessSecurity *s_wsec; + NMSetting8021x *s_8021x; + NMSettingIP4Config *s_ip4; + char *uuid; + gboolean success; + GError *error = NULL; + char *testfile = NULL; + gboolean unmanaged = FALSE; + char *keyfile = NULL; + gboolean ignore_error = FALSE; + GByteArray *ssid; + const char *ssid_data = "blahblah"; + + connection = nm_connection_new (); + ASSERT (connection != NULL, + "wifi-wpa-eap-ttls-mschapv2-write", "failed to allocate new connection"); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + ASSERT (s_con != NULL, + "wifi-wpa-eap-ttls-mschapv2-write", "failed to allocate new %s setting", + NM_SETTING_CONNECTION_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + uuid = nm_utils_uuid_generate (); + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, "Test Write Wifi WPA EAP-TTLS (MSCHAPv2)", + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, + NULL); + g_free (uuid); + + /* Wifi setting */ + s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); + ASSERT (s_wifi != NULL, + "wifi-wpa-eap-ttls-mschapv2-write", "failed to allocate new %s setting", + NM_SETTING_WIRELESS_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wifi)); + + ssid = g_byte_array_sized_new (strlen (ssid_data)); + g_byte_array_append (ssid, (const unsigned char *) ssid_data, strlen (ssid_data)); + + g_object_set (s_wifi, + NM_SETTING_WIRELESS_SSID, ssid, + NM_SETTING_WIRELESS_MODE, "infrastructure", + NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NULL); + + g_byte_array_free (ssid, TRUE); + + /* Wireless security setting */ + s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new (); + ASSERT (s_wsec != NULL, + "wifi-wpa-eap-ttls-mschapv2-write", "failed to allocate new %s setting", + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wsec)); + + g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap", NULL); + nm_setting_wireless_security_add_proto (s_wsec, "wpa"); + nm_setting_wireless_security_add_proto (s_wsec, "rsn"); + nm_setting_wireless_security_add_pairwise (s_wsec, "tkip"); + nm_setting_wireless_security_add_pairwise (s_wsec, "ccmp"); + nm_setting_wireless_security_add_group (s_wsec, "tkip"); + nm_setting_wireless_security_add_group (s_wsec, "ccmp"); + + /* Wireless security setting */ + s_8021x = (NMSetting8021x *) nm_setting_802_1x_new (); + ASSERT (s_8021x != NULL, + "wifi-wpa-eap-ttls-mschapv2-write", "failed to allocate new %s setting", + NM_SETTING_802_1X_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_8021x)); + + nm_setting_802_1x_add_eap_method (s_8021x, "ttls"); + + g_object_set (s_8021x, + NM_SETTING_802_1X_IDENTITY, "Bill Smith", + NM_SETTING_802_1X_PASSWORD, ";alkdfja;dslkfjsad;lkfjsadf", + NM_SETTING_802_1X_ANONYMOUS_IDENTITY, "foobar22", + NM_SETTING_802_1X_PHASE2_AUTHEAP, "mschapv2", + NULL); + + success = nm_setting_802_1x_set_ca_cert_from_file (s_8021x, + TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT, + NULL, + &error); + ASSERT (success == TRUE, + "wifi-wpa-eap-ttls-mschapv2-write", "failed to set CA certificate '%s': %s", + TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT, error->message); + + + /* IP4 setting */ + s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); + ASSERT (s_ip4 != NULL, + "wifi-wpa-eap-ttls-mschapv2-write", "failed to allocate new %s setting", + NM_SETTING_IP4_CONFIG_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + + g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); + + ASSERT (nm_connection_verify (connection, &error) == TRUE, + "wifi-wpa-eap-ttls-mschapv2-write", "failed to verify connection: %s", + (error && error->message) ? error->message : "(unknown)"); + + /* Save the ifcfg */ + success = writer_new_connection (connection, + TEST_SCRATCH_DIR "/network-scripts/", + &testfile, + &error); + ASSERT (success == TRUE, + "wifi-wpa-eap-ttls-mschapv2-write", "failed to write connection to disk: %s", + (error && error->message) ? error->message : "(unknown)"); + + ASSERT (testfile != NULL, + "wifi-wpa-eap-ttls-mschapv2-write", "didn't get ifcfg file path back after writing connection"); + + /* re-read the connection for comparison */ + reread = connection_from_file (testfile, + NULL, + TYPE_WIRELESS, + &unmanaged, + &keyfile, + &error, + &ignore_error); + unlink (testfile); + + ASSERT (reread != NULL, + "wifi-wpa-eap-ttls-mschapv2-write-reread", "failed to read %s: %s", testfile, error->message); + + ASSERT (keyfile != NULL, + "wifi-wpa-eap-ttls-mschapv2-write-reread", "expected keyfile for '%s'", testfile); + unlink (keyfile); + + ASSERT (nm_connection_verify (reread, &error), + "wifi-wpa-eap-ttls-mschapv2-write-reread-verify", "failed to verify %s: %s", testfile, error->message); + + ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE, + "wifi-wpa-eap-ttls-mschapv2-write", "written and re-read connection weren't the same."); + + g_free (testfile); + g_object_unref (connection); + g_object_unref (reread); +} + +static void +test_write_wired_pppoe (void) +{ + NMConnection *connection; + NMSettingConnection *s_con; + NMSettingWired *s_wired; + NMSettingIP4Config *s_ip4; + NMSettingPPPOE *s_pppoe; + NMSettingPPP *s_ppp; + char *uuid; + gboolean success; + GError *error = NULL; + char *testfile = NULL; + + connection = nm_connection_new (); + ASSERT (connection != NULL, + "wired-pppoe-write", "failed to allocate new connection"); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + ASSERT (s_con != NULL, + "wired-pppoe-write", "failed to allocate new %s setting", + NM_SETTING_CONNECTION_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + uuid = nm_utils_uuid_generate (); + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, "Test Write Wired PPPoE", + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, + NULL); + g_free (uuid); + + /* Wired setting */ + s_wired = (NMSettingWired *) nm_setting_wired_new (); + ASSERT (s_wired != NULL, + "wired-pppoe-write", "failed to allocate new %s setting", + NM_SETTING_WIRED_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wired)); + + /* IP4 setting */ + s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); + ASSERT (s_ip4 != NULL, + "wired-pppoe-write", "failed to allocate new %s setting", + NM_SETTING_IP4_CONFIG_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + + g_object_set (s_ip4, + NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, + NULL); + + /* PPPoE setting */ + s_pppoe = (NMSettingPPPOE *) nm_setting_pppoe_new (); + ASSERT (s_pppoe != NULL, + "wired-pppoe-write", "failed to allocate new %s setting", + NM_SETTING_PPPOE_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_pppoe)); + + g_object_set (G_OBJECT (s_pppoe), + NM_SETTING_PPPOE_SERVICE, "stupid-service", + NM_SETTING_PPPOE_USERNAME, "Bill Smith", + NM_SETTING_PPPOE_PASSWORD, "test1", + NULL); + + /* PPP setting */ + s_ppp = (NMSettingPPP *) nm_setting_ppp_new (); + ASSERT (s_ppp != NULL, + "wired-pppoe-write", "failed to allocate new %s setting", + NM_SETTING_PPP_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_ppp)); + + ASSERT (nm_connection_verify (connection, &error) == TRUE, + "wired-pppoe-write", "failed to verify connection: %s", + (error && error->message) ? error->message : "(unknown)"); + + /* Save the ifcfg */ + success = writer_new_connection (connection, + TEST_SCRATCH_DIR "/network-scripts/", + &testfile, + &error); + ASSERT (success == FALSE, + "wired-pppoe-write", "unexpected success writing connection to disk"); + + g_object_unref (connection); +} + +static void +test_write_vpn (void) +{ + NMConnection *connection; + NMSettingConnection *s_con; + NMSettingIP4Config *s_ip4; + NMSettingVPN *s_vpn; + char *uuid; + gboolean success; + GError *error = NULL; + char *testfile = NULL; + + connection = nm_connection_new (); + ASSERT (connection != NULL, + "vpn-write", "failed to allocate new connection"); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + ASSERT (s_con != NULL, + "vpn-write", "failed to allocate new %s setting", + NM_SETTING_CONNECTION_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + uuid = nm_utils_uuid_generate (); + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, "Test Write VPN", + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_VPN_SETTING_NAME, + NULL); + g_free (uuid); + + /* VPN setting */ + s_vpn = (NMSettingVPN *) nm_setting_vpn_new (); + ASSERT (s_vpn != NULL, + "vpn-write", "failed to allocate new %s setting", + NM_SETTING_VPN_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_vpn)); + + g_object_set (s_vpn, + NM_SETTING_VPN_SERVICE_TYPE, "awesomevpn", + NM_SETTING_VPN_USER_NAME, "Bill Smith", + NULL); + + nm_setting_vpn_add_data_item (s_vpn, "server", "vpn.somewhere.com"); + nm_setting_vpn_add_secret (s_vpn, "password", "sup3rs3cr3t"); + + /* IP4 setting */ + s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); + ASSERT (s_ip4 != NULL, + "vpn-write", "failed to allocate new %s setting", + NM_SETTING_IP4_CONFIG_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + + g_object_set (s_ip4, + NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, + NULL); + + ASSERT (nm_connection_verify (connection, &error) == TRUE, + "vpn-write", "failed to verify connection: %s", + (error && error->message) ? error->message : "(unknown)"); + + /* Save the ifcfg */ + success = writer_new_connection (connection, + TEST_SCRATCH_DIR "/network-scripts/", + &testfile, + &error); + ASSERT (success == FALSE, + "vpn-write", "unexpected success writing connection to disk"); + + g_object_unref (connection); +} + +static void +test_write_mobile_broadband (gboolean gsm) +{ + NMConnection *connection; + NMSettingConnection *s_con; + NMSettingIP4Config *s_ip4; + NMSettingGsm *s_gsm; + NMSettingCdma *s_cdma; + NMSettingPPP *s_ppp; + NMSettingSerial *s_serial; + char *uuid; + gboolean success; + GError *error = NULL; + char *testfile = NULL; + + connection = nm_connection_new (); + ASSERT (connection != NULL, + "mobile-broadband-write", "failed to allocate new connection"); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + ASSERT (s_con != NULL, + "mobile-broadband-write", "failed to allocate new %s setting", + NM_SETTING_CONNECTION_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + uuid = nm_utils_uuid_generate (); + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, gsm ? "Test Write GSM" : "Test Write CDMA", + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, + NM_SETTING_CONNECTION_TYPE, gsm ? NM_SETTING_GSM_SETTING_NAME : NM_SETTING_CDMA_SETTING_NAME, + NULL); + g_free (uuid); + + if (gsm) { + /* GSM setting */ + s_gsm = (NMSettingGsm *) nm_setting_gsm_new (); + ASSERT (s_gsm != NULL, + "mobile-broadband-write", "failed to allocate new %s setting", + NM_SETTING_GSM_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_gsm)); + + g_object_set (s_gsm, NM_SETTING_GSM_NUMBER, "*99#", NULL); + } else { + /* CDMA setting */ + s_cdma = (NMSettingCdma *) nm_setting_cdma_new (); + ASSERT (s_cdma != NULL, + "mobile-broadband-write", "failed to allocate new %s setting", + NM_SETTING_CDMA_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_cdma)); + + g_object_set (s_cdma, NM_SETTING_CDMA_NUMBER, "#777", NULL); + } + + /* Serial setting */ + s_serial = (NMSettingSerial *) nm_setting_serial_new (); + ASSERT (s_serial != NULL, + "mobile-broadband-write", "failed to allocate new %s setting", + NM_SETTING_SERIAL_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_serial)); + + g_object_set (s_serial, + NM_SETTING_SERIAL_BAUD, 115200, + NM_SETTING_SERIAL_BITS, 8, + NM_SETTING_SERIAL_PARITY, 'n', + NM_SETTING_SERIAL_STOPBITS, 1, + NULL); + + /* IP4 setting */ + s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); + ASSERT (s_ip4 != NULL, + "mobile-broadband-write", "failed to allocate new %s setting", + NM_SETTING_IP4_CONFIG_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + + g_object_set (s_ip4, + NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, + NULL); + + /* PPP setting */ + s_ppp = (NMSettingPPP *) nm_setting_ppp_new (); + ASSERT (s_ppp != NULL, + "mobile-broadband-write", "failed to allocate new %s setting", + NM_SETTING_PPP_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_ppp)); + + ASSERT (nm_connection_verify (connection, &error) == TRUE, + "mobile-broadband-write", "failed to verify connection: %s", + (error && error->message) ? error->message : "(unknown)"); + + /* Save the ifcfg */ + success = writer_new_connection (connection, + TEST_SCRATCH_DIR "/network-scripts/", + &testfile, + &error); + ASSERT (success == FALSE, + "mobile-broadband-write", "unexpected success writing connection to disk"); + + g_object_unref (connection); +} + +#define TEST_IFCFG_WIFI_OPEN_SSID_BAD_HEX TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-open-ssid-bad-hex" +#define TEST_IFCFG_WIFI_OPEN_SSID_LONG_QUOTED TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-open-ssid-long-quoted" +#define TEST_IFCFG_WIFI_OPEN_SSID_LONG_HEX TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-open-ssid-long-hex" + +int main (int argc, char **argv) +{ + GError *error = NULL; + DBusGConnection *bus; + char *base; + + g_type_init (); + bus = dbus_g_bus_get (DBUS_BUS_SESSION, NULL); + + if (!nm_utils_init (&error)) + FAIL ("nm-utils-init", "failed to initialize libnm-util: %s", error->message); + + /* The tests */ + test_read_unmanaged (); + test_read_minimal (); + test_read_wired_static (); + test_read_wired_dhcp (); + test_read_wired_global_gateway (); + test_read_wired_never_default (); + test_read_onboot_no (); + test_read_wired_8021x_peap_mschapv2 (); + test_read_wifi_open (); + test_read_wifi_open_ssid_hex (); + test_read_wifi_open_ssid_bad (TEST_IFCFG_WIFI_OPEN_SSID_BAD_HEX, "wifi-open-ssid-bad-hex-read"); + test_read_wifi_open_ssid_bad (TEST_IFCFG_WIFI_OPEN_SSID_LONG_HEX, "wifi-open-ssid-long-hex-read"); + test_read_wifi_open_ssid_bad (TEST_IFCFG_WIFI_OPEN_SSID_LONG_QUOTED, "wifi-open-ssid-long-quoted-read"); + test_read_wifi_open_ssid_quoted (); + test_read_wifi_wep (); + test_read_wifi_wep_adhoc (); + test_read_wifi_leap (); + test_read_wifi_wpa_psk (); + test_read_wifi_wpa_psk_adhoc (); + test_read_wifi_wpa_psk_hex (); + test_read_wifi_wpa_eap_tls (); + test_read_wifi_wpa_eap_ttls_tls (); + test_read_wifi_wep_eap_ttls_chap (); + + test_write_wired_static (); + test_write_wired_dhcp (); + test_write_wired_dhcp_8021x_peap_mschapv2 (); + test_write_wifi_open (); + test_write_wifi_open_hex_ssid (); + test_write_wifi_wep (); + test_write_wifi_wep_adhoc (); + test_write_wifi_wpa_psk ("Test Write Wifi WPA PSK", "wifi-wpa-psk-write", FALSE, TRUE, FALSE); + test_write_wifi_wpa_psk ("Test Write Wifi WPA2 PSK", "wifi-wpa2-psk-write", FALSE, FALSE, TRUE); + test_write_wifi_wpa_psk ("Test Write Wifi WPA WPA2 PSK", "wifi-wpa-wpa2-psk-write", FALSE, TRUE, TRUE); + test_write_wifi_wpa_psk ("Test Write Wifi WEP WPA WPA2 PSK", "wifi-wep-wpa-wpa2-psk-write", TRUE, TRUE, TRUE); + test_write_wifi_wpa_psk_adhoc (); + test_write_wifi_wpa_eap_tls (); + test_write_wifi_wpa_eap_ttls_tls (); + test_write_wifi_wpa_eap_ttls_mschapv2 (); + + /* Stuff we expect to fail for now */ + test_write_wired_pppoe (); + test_write_vpn (); + test_write_mobile_broadband (TRUE); + test_write_mobile_broadband (FALSE); + + base = g_path_get_basename (argv[0]); + fprintf (stdout, "%s: SUCCESS\n", base); + g_free (base); return 0; } Index: system-settings/plugins/ifcfg-rh/utils.c =================================================================== --- /dev/null +++ system-settings/plugins/ifcfg-rh/utils.c @@ -0,0 +1,200 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager system settings service + * + * 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. + * + * (C) Copyright 2008 - 2009 Red Hat, Inc. + */ + +#include <glib.h> +#include <stdlib.h> +#include <string.h> +#include "utils.h" +#include "sha1.h" +#include "shvar.h" + +/* + * utils_bin2hexstr + * + * Convert a byte-array into a hexadecimal string. + * + * Code originally by Alex Larsson <alexl@redhat.com> and + * copyright Red Hat, Inc. under terms of the LGPL. + * + */ +char * +utils_bin2hexstr (const char *bytes, int len, int final_len) +{ + static char hex_digits[] = "0123456789abcdef"; + char *result; + int i; + gsize buflen = (len * 2) + 1; + + g_return_val_if_fail (bytes != NULL, NULL); + g_return_val_if_fail (len > 0, NULL); + g_return_val_if_fail (len < 4096, NULL); /* Arbitrary limit */ + if (final_len > -1) + g_return_val_if_fail (final_len < buflen, NULL); + + result = g_malloc0 (buflen); + for (i = 0; i < len; i++) + { + result[2*i] = hex_digits[(bytes[i] >> 4) & 0xf]; + result[2*i+1] = hex_digits[bytes[i] & 0xf]; + } + /* Cut converted key off at the correct length for this cipher type */ + if (final_len > -1) + result[final_len] = '\0'; + else + result[buflen - 1] = '\0'; + + return result; +} + +/* From hostap, Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi> */ + +static int hex2num (char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return -1; +} + +static int hex2byte (const char *hex) +{ + int a, b; + a = hex2num(*hex++); + if (a < 0) + return -1; + b = hex2num(*hex++); + if (b < 0) + return -1; + return (a << 4) | b; +} + +char * +utils_hexstr2bin (const char *hex, size_t len) +{ + size_t i; + int a; + const char * ipos = hex; + char * buf = NULL; + char * opos; + + /* Length must be a multiple of 2 */ + if ((len % 2) != 0) + return NULL; + + opos = buf = g_malloc0 ((len / 2) + 1); + for (i = 0; i < len; i += 2) { + a = hex2byte (ipos); + if (a < 0) { + g_free (buf); + return NULL; + } + *opos++ = a; + ipos += 2; + } + return buf; +} + +/* End from hostap */ + +char * +utils_hash_byte_array (const GByteArray *data) +{ + unsigned char buf[SHA1_MAC_LEN]; + static const char *key = "0123456789abcdefghijklmnopqrstuvwxyz"; + + memset (buf, 0, sizeof (buf)); + sha1_mac ((const unsigned char *) key, strlen (key), (const u_int8_t *) data->data, data->len, &buf[0]); + return utils_bin2hexstr ((const char *) &buf[0], SHA1_MAC_LEN, SHA1_MAC_LEN * 2); +} + +char * +utils_cert_path (const char *parent, const char *suffix) +{ + char *name, *dir, *path; + + name = utils_get_ifcfg_name (parent); + dir = g_path_get_dirname (parent); + path = g_strdup_printf ("%s/%s-%s", dir, name, suffix); + g_free (dir); + g_free (name); + return path; +} + +char * +utils_get_ifcfg_name (const char *file) +{ + char *ifcfg_name; + char *base; + + base = g_path_get_basename (file); + if (!base) + return NULL; + + ifcfg_name = g_strdup (base + strlen (IFCFG_TAG)); + g_free (base); + return ifcfg_name; +} + +char * +utils_get_keys_path (const char *parent) +{ + char *ifcfg_name; + char *keys_file = NULL; + char *tmp = NULL; + + ifcfg_name = utils_get_ifcfg_name (parent); + if (!ifcfg_name) + return NULL; + + tmp = g_path_get_dirname (parent); + if (!tmp) + goto out; + + keys_file = g_strdup_printf ("%s/" KEYS_TAG "%s", tmp, ifcfg_name); + +out: + g_free (tmp); + g_free (ifcfg_name); + return keys_file; +} + +shvarFile * +utils_get_keys_ifcfg (const char *parent, gboolean should_create) +{ + shvarFile *ifcfg = NULL; + char *path; + + path = utils_get_keys_path (parent); + if (!path) + return NULL; + + if (should_create && !g_file_test (path, G_FILE_TEST_EXISTS)) + ifcfg = svCreateFile (path); + + if (!ifcfg) + ifcfg = svNewFile (path); + + g_free (path); + return ifcfg; +} + Index: system-settings/plugins/ifcfg-rh/utils.h =================================================================== --- /dev/null +++ system-settings/plugins/ifcfg-rh/utils.h @@ -0,0 +1,43 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager system settings service + * + * 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. + * + * (C) Copyright 2008 - 2009 Red Hat, Inc. + */ + +#ifndef _UTILS_H_ +#define _UTILS_H_ + +#include <glib.h> +#include "shvar.h" +#include "common.h" + +char *utils_bin2hexstr (const char *bytes, int len, int final_len); + +char *utils_hexstr2bin (const char *hex, size_t len); + +char *utils_hash_byte_array (const GByteArray *data); + +char *utils_cert_path (const char *parent, const char *suffix); + +char *utils_get_ifcfg_name (const char *file); + +char *utils_get_keys_path (const char *parent); + +shvarFile *utils_get_keys_ifcfg (const char *parent, gboolean should_create); + +#endif /* _UTILS_H_ */ + Index: system-settings/plugins/ifcfg-rh/writer.c =================================================================== --- /dev/null +++ system-settings/plugins/ifcfg-rh/writer.c @@ -0,0 +1,1071 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager system settings service - keyfile plugin + * + * 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) 2009 Red Hat, Inc. + */ + +#include <ctype.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <errno.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <unistd.h> +#include <stdio.h> + +#include <nm-setting-connection.h> +#include <nm-setting-wired.h> +#include <nm-setting-wireless.h> +#include <nm-setting-8021x.h> +#include <nm-setting-ip4-config.h> +#include <nm-setting-pppoe.h> + +#include "common.h" +#include "shvar.h" +#include "reader.h" +#include "writer.h" +#include "utils.h" +#include "crypto.h" + +#define PLUGIN_WARN(pname, fmt, args...) \ + { g_warning (" " pname ": " fmt, ##args); } + +static void +set_secret (shvarFile *ifcfg, const char *key, const char *value) +{ + shvarFile *keyfile; + + keyfile = utils_get_keys_ifcfg (ifcfg->fileName, TRUE); + if (!keyfile) { + PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: could not create key file for '%s'", + ifcfg->fileName); + goto error; + } + + /* Clear the secret from the actual ifcfg */ + svSetValue (ifcfg, key, NULL, FALSE); + + svSetValue (keyfile, key, value, FALSE); + if (svWriteFile (keyfile, 0600)) { + PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: could not update key file '%s'", + keyfile->fileName); + svCloseFile (keyfile); + goto error; + } + svCloseFile (keyfile); + return; + +error: + /* Try setting the secret in the actual ifcfg */ + svSetValue (ifcfg, key, value, FALSE); +} + +static gboolean +write_secret_file (const char *path, + const char *data, + gsize len, + GError **error) +{ + char *tmppath; + int fd = -1, written; + gboolean success = FALSE; + + tmppath = g_malloc0 (strlen (path) + 10); + if (!tmppath) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Could not allocate memory for temporary file for '%s'", + path); + return FALSE; + } + + memcpy (tmppath, path, strlen (path)); + strcat (tmppath, ".XXXXXX"); + + errno = 0; + fd = mkstemp (tmppath); + if (fd < 0) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Could not create temporary file for '%s': %d", + path, errno); + goto out; + } + + /* Only readable by root */ + errno = 0; + if (fchmod (fd, S_IRUSR | S_IWUSR)) { + close (fd); + unlink (tmppath); + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Could not set permissions for temporary file '%s': %d", + path, errno); + goto out; + } + + errno = 0; + written = write (fd, data, len); + if (written != len) { + close (fd); + unlink (tmppath); + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Could not write temporary file for '%s': %d", + path, errno); + goto out; + } + close (fd); + + /* Try to rename */ + errno = 0; + if (rename (tmppath, path)) { + unlink (tmppath); + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Could not rename temporary file to '%s': %d", + path, errno); + goto out; + } + success = TRUE; + +out: + return success; +} + +typedef struct ObjectType { + const char *setting_key; + const char *ifcfg_key; + const char *path_tag; + const char *hash_tag; + const char *suffix; +} ObjectType; + +static const ObjectType ca_type = { + NM_SETTING_802_1X_CA_CERT, + "IEEE_8021X_CA_CERT", + TAG_CA_CERT_PATH, + TAG_CA_CERT_HASH, + "ca-cert.der" +}; + +static const ObjectType phase2_ca_type = { + NM_SETTING_802_1X_PHASE2_CA_CERT, + "IEEE_8021X_INNER_CA_CERT", + TAG_PHASE2_CA_CERT_PATH, + TAG_PHASE2_CA_CERT_HASH, + "inner-ca-cert.der" +}; + +static const ObjectType client_type = { + NM_SETTING_802_1X_CLIENT_CERT, + "IEEE_8021X_CLIENT_CERT", + TAG_CLIENT_CERT_PATH, + TAG_CLIENT_CERT_HASH, + "client-cert.der" +}; + +static const ObjectType phase2_client_type = { + NM_SETTING_802_1X_PHASE2_CLIENT_CERT, + "IEEE_8021X_INNER_CLIENT_CERT", + TAG_PHASE2_CLIENT_CERT_PATH, + TAG_PHASE2_CLIENT_CERT_HASH, + "inner-client-cert.der" +}; + +static const ObjectType pk_type = { + NM_SETTING_802_1X_PRIVATE_KEY, + "IEEE_8021X_PRIVATE_KEY", + TAG_PRIVATE_KEY_PATH, + TAG_PRIVATE_KEY_HASH, + "private-key.pem" +}; + +static const ObjectType phase2_pk_type = { + NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, + "IEEE_8021X_INNER_PRIVATE_KEY", + TAG_PHASE2_PRIVATE_KEY_PATH, + TAG_PHASE2_PRIVATE_KEY_HASH, + "inner-private-key.pem" +}; + +static const ObjectType p12_type = { + NM_SETTING_802_1X_PRIVATE_KEY, + "IEEE_8021X_PRIVATE_KEY", + TAG_PRIVATE_KEY_PATH, + TAG_PRIVATE_KEY_HASH, + "private-key.p12" +}; + +static const ObjectType phase2_p12_type = { + NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, + "IEEE_8021X_INNER_PRIVATE_KEY", + TAG_PHASE2_PRIVATE_KEY_PATH, + TAG_PHASE2_PRIVATE_KEY_HASH, + "inner-private-key.p12" +}; + +static gboolean +write_object (NMSetting8021x *s_8021x, + shvarFile *ifcfg, + const GByteArray *object, + const ObjectType *objtype, + gboolean *wrote, + GError **error) +{ + const char *orig_hash, *orig_file; + char *new_hash = NULL, *new_file = NULL; + gboolean success = FALSE; + GError *write_error = NULL; + + g_return_val_if_fail (objtype != NULL, FALSE); + g_return_val_if_fail (ifcfg != NULL, FALSE); + g_return_val_if_fail (wrote != NULL, FALSE); + + *wrote = FALSE; + + if (!object) { + svSetValue (ifcfg, objtype->ifcfg_key, NULL, FALSE); + return TRUE; + } + + new_hash = utils_hash_byte_array (object); + if (!new_hash) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Could not hash certificate/key data for %s / %s", + NM_SETTING_802_1X_SETTING_NAME, objtype->setting_key); + return FALSE; + } + + orig_hash = g_object_get_data (G_OBJECT (s_8021x), objtype->hash_tag); + orig_file = g_object_get_data (G_OBJECT (s_8021x), objtype->path_tag); + + if (!orig_hash || !orig_file || strcmp (new_hash, orig_hash)) { + /* if the cert data has changed, or there wasn't a cert + * originally, write data out to the standard file. + */ + new_file = utils_cert_path (ifcfg->fileName, objtype->suffix); + if (!new_file) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Could not create file path for %s / %s", + NM_SETTING_802_1X_SETTING_NAME, objtype->setting_key); + goto out; + } + + if (!write_secret_file (new_file, (const char *) object->data, object->len, &write_error)) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Could not write certificate/key for %s / %s: %s", + NM_SETTING_802_1X_SETTING_NAME, objtype->setting_key, + (write_error && write_error->message) ? write_error->message : "(unknown)"); + g_clear_error (&write_error); + goto out; + } + *wrote = TRUE; + + svSetValue (ifcfg, objtype->ifcfg_key, new_file, FALSE); + g_object_set_data_full (G_OBJECT (s_8021x), objtype->path_tag, new_file, g_free); + new_file = NULL; /* g_object_set_data_full() took ownership */ + + g_object_set_data_full (G_OBJECT (s_8021x), objtype->hash_tag, new_hash, g_free); + new_hash = NULL; /* g_object_set_data_full() took ownership */ + } else { + /* cert data hasn't changed */ + svSetValue (ifcfg, objtype->ifcfg_key, orig_file, FALSE); + } + success = TRUE; + +out: + g_free (new_hash); + g_free (new_file); + return success; +} + +static gboolean +write_8021x_certs (NMSetting8021x *s_8021x, + gboolean phase2, + shvarFile *ifcfg, + GError **error) +{ + const GByteArray *data; + GByteArray *enc_key = NULL; + const char *password = NULL; + char *generated_pw = NULL; + gboolean success = FALSE, is_pkcs12 = FALSE, wrote; + const ObjectType *otype = NULL; + const char *prop; + + /* CA certificate */ + data = NULL; + if (phase2) { + prop = NM_SETTING_802_1X_PHASE2_CA_CERT; + otype = &phase2_ca_type; + } else { + prop = NM_SETTING_802_1X_CA_CERT; + otype = &ca_type; + } + g_object_get (G_OBJECT (s_8021x), prop, &data, NULL); + if (!write_object (s_8021x, ifcfg, data, otype, &wrote, error)) + return FALSE; + + /* Private key */ + if (phase2) { + if (nm_setting_802_1x_get_phase2_private_key (s_8021x)) { + if (nm_setting_802_1x_get_phase2_private_key_type (s_8021x) == NM_SETTING_802_1X_CK_TYPE_PKCS12) + is_pkcs12 = TRUE; + } + prop = NM_SETTING_802_1X_PHASE2_PRIVATE_KEY; + password = nm_setting_802_1x_get_phase2_private_key_password (s_8021x); + } else { + if (nm_setting_802_1x_get_private_key (s_8021x)) { + if (nm_setting_802_1x_get_private_key_type (s_8021x) == NM_SETTING_802_1X_CK_TYPE_PKCS12) + is_pkcs12 = TRUE; + } + prop = NM_SETTING_802_1X_PRIVATE_KEY; + password = nm_setting_802_1x_get_private_key_password (s_8021x); + } + + if (is_pkcs12) + otype = phase2 ? &phase2_p12_type : &p12_type; + else + otype = phase2 ? &phase2_pk_type : &pk_type; + + data = NULL; + g_object_get (G_OBJECT (s_8021x), prop, &data, NULL); + if (data && !is_pkcs12) { + GByteArray *array; + + if (!password) { + /* Create a random private key */ + array = crypto_random (32, error); + if (!array) + goto out; + + password = generated_pw = utils_bin2hexstr ((const char *) array->data, array->len, -1); + memset (array->data, 0, array->len); + g_byte_array_free (array, TRUE); + } + + /* Re-encrypt the private key if it's not PKCS#12 (which never decrypted by NM) */ + enc_key = crypto_key_to_pem (data, password, error); + if (!enc_key) + goto out; + } + + if (!write_object (s_8021x, ifcfg, enc_key ? enc_key : data, otype, &wrote, error)) + goto out; + + /* Private key password */ + if (phase2) + set_secret (ifcfg, "IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD", password); + else + set_secret (ifcfg, "IEEE_8021X_PRIVATE_KEY_PASSWORD", password); + + if (enc_key) { + memset (enc_key->data, 0, enc_key->len); + g_byte_array_free (enc_key, TRUE); + } + + /* Client certificate */ + if (is_pkcs12) { + svSetValue (ifcfg, + phase2 ? "IEEE_8021X_INNER_CLIENT_CERT" : "IEEE_8021X_CLIENT_CERT", + NULL, FALSE); + } else { + if (phase2) { + prop = NM_SETTING_802_1X_PHASE2_CLIENT_CERT; + otype = &phase2_client_type; + } else { + prop = NM_SETTING_802_1X_CLIENT_CERT; + otype = &client_type; + } + data = NULL; + g_object_get (G_OBJECT (s_8021x), prop, &data, NULL); + if (!write_object (s_8021x, ifcfg, data, otype, &wrote, error)) + goto out; + } + + success = TRUE; + +out: + if (generated_pw) { + memset (generated_pw, 0, strlen (generated_pw)); + g_free (generated_pw); + } + return success; +} + +static gboolean +write_8021x_setting (NMConnection *connection, + shvarFile *ifcfg, + gboolean wired, + GError **error) +{ + NMSetting8021x *s_8021x; + const char *value; + char *tmp = NULL; + gboolean success = FALSE; + GString *phase2_auth; + + s_8021x = (NMSetting8021x *) nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X); + if (!s_8021x) { + /* If wired, clear KEY_MGMT */ + if (wired) + svSetValue (ifcfg, "KEY_MGMT", NULL, FALSE); + return TRUE; + } + + /* If wired, write KEY_MGMT */ + if (wired) + svSetValue (ifcfg, "KEY_MGMT", "IEEE8021X", FALSE); + + /* EAP method */ + if (nm_setting_802_1x_get_num_eap_methods (s_8021x)) { + value = nm_setting_802_1x_get_eap_method (s_8021x, 0); + if (value) + tmp = g_ascii_strup (value, -1); + } + svSetValue (ifcfg, "IEEE_8021X_EAP_METHODS", tmp ? tmp : NULL, FALSE); + g_free (tmp); + + svSetValue (ifcfg, "IEEE_8021X_IDENTITY", + nm_setting_802_1x_get_identity (s_8021x), + FALSE); + + svSetValue (ifcfg, "IEEE_8021X_ANON_IDENTITY", + nm_setting_802_1x_get_anonymous_identity (s_8021x), + FALSE); + + set_secret (ifcfg, "IEEE_8021X_PASSWORD", nm_setting_802_1x_get_password (s_8021x)); + + /* PEAP version */ + value = nm_setting_802_1x_get_phase1_peapver (s_8021x); + svSetValue (ifcfg, "IEEE_8021X_PEAP_VERSION", NULL, FALSE); + if (value && (!strcmp (value, "0") || !strcmp (value, "1"))) + svSetValue (ifcfg, "IEEE_8021X_PEAP_VERSION", value, FALSE); + + /* Force new PEAP label */ + value = nm_setting_802_1x_get_phase1_peaplabel (s_8021x); + svSetValue (ifcfg, "IEEE_8021X_PEAP_FORCE_NEW_LABEL", NULL, FALSE); + if (value && !strcmp (value, "1")) + svSetValue (ifcfg, "IEEE_8021X_PEAP_FORCE_NEW_LABEL", "yes", FALSE); + + /* Phase2 auth methods */ + svSetValue (ifcfg, "IEEE_8021X_INNER_AUTH_METHODS", NULL, FALSE); + phase2_auth = g_string_new (NULL); + + value = nm_setting_802_1x_get_phase2_auth (s_8021x); + if (value) { + tmp = g_ascii_strup (value, -1); + g_string_append (phase2_auth, tmp); + g_free (tmp); + } + + value = nm_setting_802_1x_get_phase2_autheap (s_8021x); + if (value) { + if (phase2_auth->len) + g_string_append_c (phase2_auth, ' '); + + tmp = g_ascii_strup (value, -1); + g_string_append_printf (phase2_auth, "EAP-%s", tmp); + g_free (tmp); + } + + svSetValue (ifcfg, "IEEE_8021X_INNER_AUTH_METHODS", + phase2_auth->len ? phase2_auth->str : NULL, + FALSE); + + g_string_free (phase2_auth, TRUE); + + success = write_8021x_certs (s_8021x, FALSE, ifcfg, error); + if (success) { + /* phase2/inner certs */ + success = write_8021x_certs (s_8021x, TRUE, ifcfg, error); + } + + return success; +} + +static gboolean +write_wireless_security_setting (NMConnection *connection, + shvarFile *ifcfg, + gboolean adhoc, + gboolean *no_8021x, + GError **error) +{ + NMSettingWirelessSecurity *s_wsec; + const char *key_mgmt, *auth_alg, *key, *proto, *cipher, *psk; + gboolean wep = FALSE, wpa = FALSE; + char *tmp; + guint32 i, num; + GString *str; + + s_wsec = (NMSettingWirelessSecurity *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS_SECURITY); + if (!s_wsec) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Missing '%s' setting", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME); + return FALSE; + } + + key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); + g_assert (key_mgmt); + + auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec); + + svSetValue (ifcfg, "DEFAULTKEY", NULL, FALSE); + + if (!strcmp (key_mgmt, "none")) { + wep = TRUE; + *no_8021x = TRUE; + } else if (!strcmp (key_mgmt, "wpa-none") || !strcmp (key_mgmt, "wpa-psk")) { + svSetValue (ifcfg, "KEY_MGMT", "WPA-PSK", FALSE); + wpa = TRUE; + *no_8021x = TRUE; + } else if (!strcmp (key_mgmt, "ieee8021x")) { + svSetValue (ifcfg, "KEY_MGMT", "IEEE8021X", FALSE); + } else if (!strcmp (key_mgmt, "wpa-eap")) { + svSetValue (ifcfg, "KEY_MGMT", "WPA-EAP", FALSE); + wpa = TRUE; + } + + svSetValue (ifcfg, "SECURITYMODE", NULL, FALSE); + if (auth_alg) { + if (!strcmp (auth_alg, "shared")) + svSetValue (ifcfg, "SECURITYMODE", "restricted", FALSE); + else if (!strcmp (auth_alg, "open")) + svSetValue (ifcfg, "SECURITYMODE", "open", FALSE); + else if (!strcmp (auth_alg, "leap")) { + svSetValue (ifcfg, "SECURITYMODE", "leap", FALSE); + svSetValue (ifcfg, "IEEE_8021X_USERNAME", + nm_setting_wireless_security_get_leap_username (s_wsec), + FALSE); + set_secret (ifcfg, "IEEE_8021X_PASSWORD", + nm_setting_wireless_security_get_leap_password (s_wsec)); + *no_8021x = TRUE; + } + } + + if (wep) { + /* Default WEP TX key index */ + tmp = g_strdup_printf ("%d", nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec) + 1); + svSetValue (ifcfg, "DEFAULTKEY", tmp, FALSE); + g_free (tmp); + } + + /* WEP keys */ + set_secret (ifcfg, "KEY", NULL); /* Clear any default key */ + for (i = 0; i < 4; i++) { + key = nm_setting_wireless_security_get_wep_key (s_wsec, i); + tmp = g_strdup_printf ("KEY%d", i + 1); + set_secret (ifcfg, tmp, (wep && key) ? key : NULL); + g_free (tmp); + } + + /* WPA protos */ + svSetValue (ifcfg, "WPA_ALLOW_WPA", NULL, FALSE); + svSetValue (ifcfg, "WPA_ALLOW_WPA2", NULL, FALSE); + num = nm_setting_wireless_security_get_num_protos (s_wsec); + for (i = 0; i < num; i++) { + proto = nm_setting_wireless_security_get_proto (s_wsec, i); + if (proto && !strcmp (proto, "wpa")) + svSetValue (ifcfg, "WPA_ALLOW_WPA", "yes", FALSE); + else if (proto && !strcmp (proto, "rsn")) + svSetValue (ifcfg, "WPA_ALLOW_WPA2", "yes", FALSE); + } + + /* WPA Pairwise ciphers */ + svSetValue (ifcfg, "CIPHER_PAIRWISE", NULL, FALSE); + str = g_string_new (NULL); + num = nm_setting_wireless_security_get_num_pairwise (s_wsec); + for (i = 0; i < num; i++) { + if (i > 0) + g_string_append_c (str, ' '); + cipher = nm_setting_wireless_security_get_pairwise (s_wsec, i); + tmp = g_ascii_strup (cipher, -1); + g_string_append (str, tmp); + g_free (tmp); + } + if (strlen (str->str)) + svSetValue (ifcfg, "CIPHER_PAIRWISE", str->str, FALSE); + g_string_free (str, TRUE); + + /* WPA Group ciphers */ + svSetValue (ifcfg, "CIPHER_GROUP", NULL, FALSE); + str = g_string_new (NULL); + num = nm_setting_wireless_security_get_num_groups (s_wsec); + for (i = 0; i < num; i++) { + if (i > 0) + g_string_append_c (str, ' '); + cipher = nm_setting_wireless_security_get_group (s_wsec, i); + tmp = g_ascii_strup (cipher, -1); + g_string_append (str, tmp); + g_free (tmp); + } + if (strlen (str->str)) + svSetValue (ifcfg, "CIPHER_GROUP", str->str, FALSE); + g_string_free (str, TRUE); + + /* WPA Passphrase */ + psk = nm_setting_wireless_security_get_psk (s_wsec); + set_secret (ifcfg, "WPA_PSK", (wpa && psk) ? psk : NULL); + + return TRUE; +} + +static gboolean +write_wireless_setting (NMConnection *connection, + shvarFile *ifcfg, + gboolean *no_8021x, + GError **error) +{ + NMSettingWireless *s_wireless; + char *tmp, *tmp2; + const GByteArray *ssid, *mac, *bssid; + const char *mode; + char buf[33]; + guint32 mtu, chan, i; + gboolean adhoc = FALSE, hex_ssid = FALSE; + + s_wireless = (NMSettingWireless *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS); + if (!s_wireless) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Missing '%s' setting", NM_SETTING_WIRELESS_SETTING_NAME); + return FALSE; + } + + svSetValue (ifcfg, "HWADDR", NULL, FALSE); + mac = nm_setting_wireless_get_mac_address (s_wireless); + if (mac) { + tmp = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X", + mac->data[0], mac->data[1], mac->data[2], + mac->data[3], mac->data[4], mac->data[5]); + svSetValue (ifcfg, "HWADDR", tmp, FALSE); + g_free (tmp); + } + + svSetValue (ifcfg, "MTU", NULL, FALSE); + mtu = nm_setting_wireless_get_mtu (s_wireless); + if (mtu) { + tmp = g_strdup_printf ("%u", mtu); + svSetValue (ifcfg, "MTU", tmp, FALSE); + g_free (tmp); + } + + ssid = nm_setting_wireless_get_ssid (s_wireless); + if (!ssid) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Missing SSID in '%s' setting", NM_SETTING_WIRELESS_SETTING_NAME); + return FALSE; + } + if (!ssid->len || ssid->len > 32) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Invalid SSID in '%s' setting", NM_SETTING_WIRELESS_SETTING_NAME); + return FALSE; + } + + /* If the SSID contains any non-printable characters, we need to use the + * hex notation of the SSID instead. + */ + for (i = 0; i < ssid->len; i++) { + if (!isprint (ssid->data[i])) { + hex_ssid = TRUE; + break; + } + } + + if (hex_ssid) { + GString *str; + + /* Hex SSIDs don't get quoted */ + str = g_string_sized_new (ssid->len * 2 + 3); + g_string_append (str, "0x"); + for (i = 0; i < ssid->len; i++) + g_string_append_printf (str, "%02X", ssid->data[i]); + svSetValue (ifcfg, "ESSID", str->str, TRUE); + g_string_free (str, TRUE); + } else { + /* Printable SSIDs get quoted */ + memset (buf, 0, sizeof (buf)); + memcpy (buf, ssid->data, ssid->len); + tmp2 = svEscape (buf); + tmp = g_strdup_printf ("\"%s\"", tmp2); + svSetValue (ifcfg, "ESSID", tmp, TRUE); + g_free (tmp2); + g_free (tmp); + } + + mode = nm_setting_wireless_get_mode (s_wireless); + if (!mode || !strcmp (mode, "infrastructure")) { + svSetValue (ifcfg, "MODE", "Managed", FALSE); + } else if (!strcmp (mode, "adhoc")) { + svSetValue (ifcfg, "MODE", "Ad-Hoc", FALSE); + adhoc = TRUE; + } else { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Invalid mode '%s' in '%s' setting", + mode, NM_SETTING_WIRELESS_SETTING_NAME); + return FALSE; + } + + svSetValue (ifcfg, "CHANNEL", NULL, FALSE); + chan = nm_setting_wireless_get_channel (s_wireless); + if (chan) { + tmp = g_strdup_printf ("%u", chan); + svSetValue (ifcfg, "CHANNEL", tmp, FALSE); + g_free (tmp); + } + + svSetValue (ifcfg, "BSSID", NULL, FALSE); + bssid = nm_setting_wireless_get_bssid (s_wireless); + if (bssid) { + tmp = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X", + bssid->data[0], bssid->data[1], bssid->data[2], + bssid->data[3], bssid->data[4], bssid->data[5]); + svSetValue (ifcfg, "BSSID", tmp, FALSE); + g_free (tmp); + } + + if (nm_setting_wireless_get_security (s_wireless)) { + if (!write_wireless_security_setting (connection, ifcfg, adhoc, no_8021x, error)) + return FALSE; + } + + svSetValue (ifcfg, "TYPE", TYPE_WIRELESS, FALSE); + + return TRUE; +} + +static gboolean +write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) +{ + NMSettingWired *s_wired; + const GByteArray *mac; + char *tmp; + guint32 mtu; + + s_wired = (NMSettingWired *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED); + if (!s_wired) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Missing '%s' setting", NM_SETTING_WIRED_SETTING_NAME); + return FALSE; + } + + mac = nm_setting_wired_get_mac_address (s_wired); + if (mac) { + tmp = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X", + mac->data[0], mac->data[1], mac->data[2], + mac->data[3], mac->data[4], mac->data[5]); + svSetValue (ifcfg, "HWADDR", tmp, FALSE); + g_free (tmp); + } + + mtu = nm_setting_wired_get_mtu (s_wired); + if (mtu) { + tmp = g_strdup_printf ("%u", mtu); + svSetValue (ifcfg, "MTU", tmp, FALSE); + g_free (tmp); + } + + svSetValue (ifcfg, "TYPE", TYPE_ETHERNET, FALSE); + + return TRUE; +} + +static void +write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg) +{ + char *tmp; + + svSetValue (ifcfg, "NAME", nm_setting_connection_get_id (s_con), FALSE); + svSetValue (ifcfg, "UUID", nm_setting_connection_get_uuid (s_con), FALSE); + svSetValue (ifcfg, "ONBOOT", + nm_setting_connection_get_autoconnect (s_con) ? "yes" : "no", + FALSE); + + svSetValue (ifcfg, "LAST_CONNECT", NULL, FALSE); + if (nm_setting_connection_get_timestamp (s_con)) { + tmp = g_strdup_printf ("%" G_GUINT64_FORMAT, nm_setting_connection_get_timestamp (s_con)); + svSetValue (ifcfg, "LAST_CONNECT", tmp, FALSE); + g_free (tmp); + } +} + +static gboolean +write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) +{ + NMSettingIP4Config *s_ip4; + const char *value; + char *addr_key, *prefix_key, *gw_key, *tmp; + guint32 i, num; + GString *searches; + + s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG); + if (!s_ip4) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Missing '%s' setting", NM_SETTING_IP4_CONFIG_SETTING_NAME); + return FALSE; + } + + value = nm_setting_ip4_config_get_method (s_ip4); + g_assert (value); + if (!strcmp (value, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) + svSetValue (ifcfg, "BOOTPROTO", "dhcp", FALSE); + else if (!strcmp (value, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) + svSetValue (ifcfg, "BOOTPROTO", "none", FALSE); + else if (!strcmp (value, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) + svSetValue (ifcfg, "BOOTPROTO", "autoip", FALSE); + else if (!strcmp (value, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) + svSetValue (ifcfg, "BOOTPROTO", "shared", FALSE); + + num = nm_setting_ip4_config_get_num_addresses (s_ip4); + for (i = 0; i < 254; i++) { + char buf[INET_ADDRSTRLEN + 1]; + NMIP4Address *addr; + guint32 ip; + + if (i == 0) { + addr_key = g_strdup ("IPADDR"); + prefix_key = g_strdup ("PREFIX"); + gw_key = g_strdup ("GATEWAY"); + } else { + addr_key = g_strdup_printf ("IPADDR%d", i + 1); + prefix_key = g_strdup_printf ("PREFIX%d", i + 1); + gw_key = g_strdup_printf ("GATEWAY%d", i + 1); + } + + if (i >= num) { + svSetValue (ifcfg, addr_key, NULL, FALSE); + svSetValue (ifcfg, prefix_key, NULL, FALSE); + svSetValue (ifcfg, gw_key, NULL, FALSE); + } else { + addr = nm_setting_ip4_config_get_address (s_ip4, i); + + memset (buf, 0, sizeof (buf)); + ip = nm_ip4_address_get_address (addr); + inet_ntop (AF_INET, (const void *) &ip, &buf[0], sizeof (buf)); + svSetValue (ifcfg, addr_key, &buf[0], FALSE); + + tmp = g_strdup_printf ("%u", nm_ip4_address_get_prefix (addr)); + svSetValue (ifcfg, prefix_key, tmp, FALSE); + g_free (tmp); + + if (nm_ip4_address_get_gateway (addr)) { + memset (buf, 0, sizeof (buf)); + ip = nm_ip4_address_get_gateway (addr); + inet_ntop (AF_INET, (const void *) &ip, &buf[0], sizeof (buf)); + svSetValue (ifcfg, gw_key, &buf[0], FALSE); + } else + svSetValue (ifcfg, gw_key, NULL, FALSE); + } + + g_free (addr_key); + g_free (prefix_key); + g_free (gw_key); + } + + num = nm_setting_ip4_config_get_num_dns (s_ip4); + for (i = 0; i < 254; i++) { + char buf[INET_ADDRSTRLEN + 1]; + guint32 ip; + + addr_key = g_strdup_printf ("DNS%d", i + 1); + + if (i >= num) + svSetValue (ifcfg, addr_key, NULL, FALSE); + else { + ip = nm_setting_ip4_config_get_dns (s_ip4, i); + + memset (buf, 0, sizeof (buf)); + inet_ntop (AF_INET, (const void *) &ip, &buf[0], sizeof (buf)); + svSetValue (ifcfg, addr_key, &buf[0], FALSE); + } + g_free (addr_key); + } + + num = nm_setting_ip4_config_get_num_dns_searches (s_ip4); + if (num > 0) { + searches = g_string_new (NULL); + for (i = 0; i < num; i++) { + if (i > 0) + g_string_append_c (searches, ' '); + g_string_append (searches, nm_setting_ip4_config_get_dns_search (s_ip4, i)); + } + svSetValue (ifcfg, "DOMAIN", searches->str, FALSE); + g_string_free (searches, TRUE); + } else + svSetValue (ifcfg, "DOMAIN", NULL, FALSE); + + svSetValue (ifcfg, "PEERDNS", NULL, FALSE); + svSetValue (ifcfg, "PEERROUTES", NULL, FALSE); + svSetValue (ifcfg, "DHCP_HOSTNAME", NULL, FALSE); + svSetValue (ifcfg, "DHCP_CLIENT_ID", NULL, FALSE); + if (!strcmp (value, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) { + svSetValue (ifcfg, "PEERDNS", + nm_setting_ip4_config_get_ignore_auto_dns (s_ip4) ? "no" : "yes", + FALSE); + + svSetValue (ifcfg, "PEERROUTES", + nm_setting_ip4_config_get_ignore_auto_routes (s_ip4) ? "no" : "yes", + FALSE); + + value = nm_setting_ip4_config_get_dhcp_hostname (s_ip4); + if (value) + svSetValue (ifcfg, "DHCP_HOSTNAME", value, FALSE); + + value = nm_setting_ip4_config_get_dhcp_client_id (s_ip4); + if (value) + svSetValue (ifcfg, "DHCP_CLIENT_ID", value, FALSE); + } + + + return TRUE; +} + +static char * +escape_id (const char *id) +{ + char *escaped = g_strdup (id); + char *p = escaped; + + /* Escape random stuff */ + while (*p) { + if (*p == ' ') + *p = '_'; + else if (*p == '/') + *p = '-'; + else if (*p == '\\') + *p = '-'; + p++; + } + + return escaped; +} + +static gboolean +write_connection (NMConnection *connection, + const char *ifcfg_dir, + const char *filename, + const char *keyfile, + char **out_filename, + GError **error) +{ + NMSettingConnection *s_con; + gboolean success = FALSE; + shvarFile *ifcfg = NULL; + char *ifcfg_name = NULL; + const char *type; + gboolean no_8021x = FALSE; + gboolean wired = FALSE; + + s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION)); + if (!s_con) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Missing '%s' setting", NM_SETTING_CONNECTION_SETTING_NAME); + return FALSE; + } + + if (filename) { + /* For existing connections, 'filename' should be full path to ifcfg file */ + ifcfg = svNewFile (filename); + ifcfg_name = g_strdup (filename); + } else { + char *escaped; + + escaped = escape_id (nm_setting_connection_get_id (s_con)); + ifcfg_name = g_strdup_printf ("%s/ifcfg-%s", ifcfg_dir, escaped); + ifcfg = svCreateFile (ifcfg_name); + g_free (escaped); + } + + if (!ifcfg) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Failed to open/create ifcfg file '%s'", ifcfg_name); + goto out; + } + + type = nm_setting_connection_get_connection_type (s_con); + if (!type) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Missing connection type!"); + goto out; + } + + if (!strcmp (type, NM_SETTING_WIRED_SETTING_NAME)) { + // FIXME: can't write PPPoE at this time + if (nm_connection_get_setting (connection, NM_TYPE_SETTING_PPPOE)) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Can't write connection type '%s'", + NM_SETTING_PPPOE_SETTING_NAME); + goto out; + } + + if (!write_wired_setting (connection, ifcfg, error)) + goto out; + wired = TRUE; + } else if (!strcmp (type, NM_SETTING_WIRELESS_SETTING_NAME)) { + if (!write_wireless_setting (connection, ifcfg, &no_8021x, error)) + goto out; + } else { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Can't write connection type '%s'", type); + goto out; + } + + if (!no_8021x) { + if (!write_8021x_setting (connection, ifcfg, wired, error)) + goto out; + } + + if (!write_ip4_setting (connection, ifcfg, error)) + goto out; + + write_connection_setting (s_con, ifcfg); + + if (svWriteFile (ifcfg, 0644)) { + g_set_error (error, ifcfg_plugin_error_quark (), 0, + "Can't write connection '%s'", ifcfg->fileName); + goto out; + } + + /* Only return the filename if this was a newly written ifcfg */ + if (out_filename && !filename) + *out_filename = g_strdup (ifcfg_name); + + success = TRUE; + +out: + if (ifcfg) + svCloseFile (ifcfg); + g_free (ifcfg_name); + return success; +} + +gboolean +writer_new_connection (NMConnection *connection, + const char *ifcfg_dir, + char **out_filename, + GError **error) +{ + return write_connection (connection, ifcfg_dir, NULL, NULL, out_filename, error); +} + +gboolean +writer_update_connection (NMConnection *connection, + const char *ifcfg_dir, + const char *filename, + const char *keyfile, + GError **error) +{ + return write_connection (connection, ifcfg_dir, filename, keyfile, NULL, error); +} + Index: system-settings/plugins/ifcfg-rh/writer.h =================================================================== --- /dev/null +++ system-settings/plugins/ifcfg-rh/writer.h @@ -0,0 +1,39 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager system settings service - keyfile plugin + * + * 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) 2009 Red Hat, Inc. + */ + +#ifndef _WRITER_H_ +#define _WRITER_H_ + +#include <sys/types.h> +#include <glib.h> +#include <nm-connection.h> + +gboolean writer_new_connection (NMConnection *connection, + const char *ifcfg_dir, + char **out_filename, + GError **error); + +gboolean writer_update_connection (NMConnection *connection, + const char *ifcfg_dir, + const char *filename, + const char *keyfile, + GError **error); + +#endif /* _WRITER_H_ */ Index: system-settings/plugins/ifupdown/Makefile.am =================================================================== --- system-settings/plugins/ifupdown/Makefile.am.orig +++ system-settings/plugins/ifupdown/Makefile.am @@ -1,7 +1,6 @@ INCLUDES = \ - -I${top_srcdir}/src \ - $(NULL) + -I${top_srcdir}/src pkglib_LTLIBRARIES = libnm-settings-plugin-ifupdown.la @@ -9,8 +8,7 @@ libnm_settings_plugin_ifupdown_la_SOURCE interface_parser.c interface_parser.h \ nm-ifupdown-connection.c nm-ifupdown-connection.h \ parser.c parser.h \ - plugin.c plugin.h \ - $(NULL) + plugin.c plugin.h libnm_settings_plugin_ifupdown_la_CPPFLAGS = \ $(GLIB_CFLAGS) \ Index: system-settings/plugins/keyfile/io/reader.c =================================================================== --- system-settings/plugins/keyfile/io/reader.c.orig +++ system-settings/plugins/keyfile/io/reader.c @@ -643,7 +643,7 @@ connection_from_file (const char *filena bad_permissions = statbuf.st_mode & 0077; if (bad_owner || bad_permissions) { - g_warning ("Ignorning insecure configuration file '%s'", filename); + g_warning ("Ignoring insecure configuration file '%s'", filename); return NULL; } Index: system-settings/plugins/keyfile/tests/test-keyfile.c =================================================================== --- system-settings/plugins/keyfile/tests/test-keyfile.c.orig +++ system-settings/plugins/keyfile/tests/test-keyfile.c @@ -670,7 +670,7 @@ int main (int argc, char **argv) { GError *error = NULL; DBusGConnection *bus; - char *basename; + char *base; g_type_init (); bus = dbus_g_bus_get (DBUS_BUS_SESSION, NULL); @@ -685,9 +685,9 @@ int main (int argc, char **argv) test_read_valid_wireless_connection (); test_write_wireless_connection (); - basename = g_path_get_basename (argv[0]); - fprintf (stdout, "%s: SUCCESS\n", basename); - g_free (basename); + base = g_path_get_basename (argv[0]); + fprintf (stdout, "%s: SUCCESS\n", base); + g_free (base); return 0; } Index: system-settings/src/Makefile.am =================================================================== --- system-settings/src/Makefile.am.orig +++ system-settings/src/Makefile.am @@ -35,7 +35,6 @@ nm_system_settings_CPPFLAGS = \ $(GLIB_CFLAGS) \ $(GMODULE_CFLAGS) \ $(POLKIT_CFLAGS) \ - -DDBUS_API_SUBJECT_TO_CHANGE \ -DG_DISABLE_DEPRECATED \ -DBINDIR=\"$(bindir)\" \ -DSBINDIR=\"$(sbindir)\" \ Index: system-settings/src/nm-polkit-helpers.c =================================================================== --- system-settings/src/nm-polkit-helpers.c.orig +++ system-settings/src/nm-polkit-helpers.c @@ -98,14 +98,50 @@ check_polkit_privileges (DBusGConnection DBusGMethodInvocation *context, GError **err) { + DBusConnection *tmp; DBusError dbus_error; char *sender; + gulong sender_uid = G_MAXULONG; PolKitCaller *pk_caller; PolKitAction *pk_action; PolKitResult pk_result; - dbus_error_init (&dbus_error); + /* Always allow uid 0 */ + tmp = dbus_g_connection_get_connection (dbus_connection); + if (!tmp) { + g_set_error (err, + NM_SYSCONFIG_SETTINGS_ERROR, + NM_SYSCONFIG_SETTINGS_ERROR_GENERAL, + "Could not get D-Bus connection."); + return FALSE; + } + sender = dbus_g_method_get_sender (context); + + dbus_error_init (&dbus_error); + /* FIXME: do this async */ + sender_uid = dbus_bus_get_unix_user (tmp, sender, &dbus_error); + if (dbus_error_is_set (&dbus_error)) { + g_set_error (err, + NM_SYSCONFIG_SETTINGS_ERROR, + NM_SYSCONFIG_SETTINGS_ERROR_GENERAL, + "Could not determine the Unix user ID of the requestor: %s: %s", + dbus_error.name, dbus_error.message); + dbus_error_free (&dbus_error); + return FALSE; + } + + /* PolicyKit < 1.0 is not compatible with root processes spawned outside + * the session manager, and when asking ConsoleKit for the session of the + * process, ConsoleKit won't be able to get XDG_SESSION_COOKIE because it + * doesn't exist in the caller's environment for non-session-managed + * processes. So, for PK < 1.0, ignore PolicyKit for uid 0. + */ + if (0 == sender_uid) + return TRUE; + + /* Non-root users need to auth via PolicyKit */ + dbus_error_init (&dbus_error); pk_caller = polkit_caller_new_from_dbus_name (dbus_g_connection_get_connection (dbus_connection), sender, &dbus_error); Index: test/Makefile.am =================================================================== --- test/Makefile.am.orig +++ test/Makefile.am @@ -8,7 +8,6 @@ AM_CPPFLAGS = \ $(DBUS_CFLAGS) \ $(GLIB_CFLAGS) \ $(HAL_CFLAGS) \ - -DDBUS_API_SUBJECT_TO_CHANGE \ -DBINDIR=\"$(bindir)\" \ -DNM_RUN_DIR=\"$(rundir)\" \ -DDATADIR=\"$(datadir)\" Index: test/nm-dhcp-opt-test.c =================================================================== --- /dev/null +++ test/nm-dhcp-opt-test.c @@ -0,0 +1,277 @@ +/* nm-dhcp-opt-test - test app for NetworkManager's DHCP Options interface + * + * Dan Williams <dcbw@redhat.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * 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. + * + * (C) Copyright 2005 Red Hat, Inc. + */ + +#include <glib.h> +#include <dbus/dbus.h> +#include <dbus/dbus-glib.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include "NetworkManager.h" + +/* Return codes for functions that use dbus */ +enum +{ + RETURN_SUCCESS = 1, + RETURN_FAILURE = 0, + RETURN_NO_NM = -1 +}; + + +#define DBUS_NO_SERVICE_ERROR "org.freedesktop.DBus.Error.ServiceDoesNotExist" +#define NM_DHCP_OPT_NOT_FOUND_ERROR "org.freedesktop.NetworkManager.OptionNotFound" + +static char *dbus_type_to_string (int type) +{ + switch (type) + { + case DBUS_TYPE_UINT32: + return "uint32"; + + case DBUS_TYPE_BOOLEAN: + return "boolean"; + + case DBUS_TYPE_BYTE: + return "byte"; + + case DBUS_TYPE_STRING: + return "string"; + } + g_assert_not_reached (); + return NULL; +} + + +/* + * call_nm_method + * + * Do a method call on NetworkManager. + * + * Returns: RETURN_SUCCESS on success + * RETURN_FAILURE on failure + * RETURN_NO_NM if NetworkManager service no longer exists + */ +static int call_nm_method (DBusConnection *con, const char *method, int opt, gboolean is_array, int arg_type, void **arg, int *item_count) +{ + DBusMessage *message; + DBusMessage *reply; + DBusError error; + dbus_bool_t ret = TRUE; + DBusMessageIter iter; + + g_return_val_if_fail (con != NULL, RETURN_FAILURE); + g_return_val_if_fail (method != NULL, RETURN_FAILURE); + g_return_val_if_fail (arg != NULL, RETURN_FAILURE); + + if (is_array) + { + g_return_val_if_fail (item_count != NULL, RETURN_FAILURE); + *item_count = 0; + } + + if (!(message = dbus_message_new_method_call (NM_DBUS_SERVICE, NM_DBUS_PATH_DHCP, NM_DBUS_INTERFACE_DHCP, method))) + { + fprintf (stderr, "call_nm_method(): Couldn't allocate the dbus message\n"); + return (RETURN_FAILURE); + } + dbus_message_append_args (message, DBUS_TYPE_UINT32, &opt, DBUS_TYPE_INVALID); + + dbus_error_init (&error); + reply = dbus_connection_send_with_reply_and_block (con, message, -1, &error); + dbus_message_unref (message); + if (dbus_error_is_set (&error)) + { + int ret = RETURN_FAILURE; + + if (!strcmp (error.name, DBUS_NO_SERVICE_ERROR)) + ret = RETURN_NO_NM; + + if (ret != RETURN_SUCCESS && (strcmp (error.name, NM_DHCP_OPT_NOT_FOUND_ERROR) != 0)) + fprintf (stderr, "call_nm_method(): %s raised:\n %s\n\n", error.name, error.message); + + dbus_error_free (&error); + return (ret); + } + + if (reply == NULL) + { + fprintf (stderr, "call_nm_method(): dbus reply message was NULL\n" ); + return (RETURN_FAILURE); + } + + if (is_array) + ret = dbus_message_get_args (reply, NULL, DBUS_TYPE_ARRAY, arg_type, arg, item_count, DBUS_TYPE_INVALID); + else + ret = dbus_message_get_args (reply, NULL, arg_type, arg, DBUS_TYPE_INVALID); + +/* + We simply don't unref the message, so that the values returned stay + valid in the caller of this function. + dbus_message_unref (reply); +*/ + if (!ret) + { + fprintf (stderr, "call_nm_method(): error while getting args.\n"); + return (RETURN_FAILURE); + } + + return (RETURN_SUCCESS); +} + +void print_array (DBusConnection *connection, int opt) +{ + int num_items; + unsigned int *uint32 = NULL; + int *int32 = NULL; + gboolean *bool = NULL; + unsigned char *byte = NULL; + char **string = NULL; + void *item = NULL; + char *method = NULL; + int ret; + const char *name = NULL; + int opt_type = -1; + unsigned int foo; + char buf[INET_ADDRSTRLEN+1]; + + memset (&buf, '\0', sizeof (buf)); + + ret = call_nm_method (connection, "getName", opt, FALSE, DBUS_TYPE_STRING, (void *)(&name), NULL); + if (ret != RETURN_SUCCESS) + return; + + ret = call_nm_method (connection, "getElementType", opt, FALSE, DBUS_TYPE_UINT32, (void *)(&opt_type), NULL); + if (ret != RETURN_SUCCESS) + return; + + switch (opt_type) + { + case DBUS_TYPE_UINT32: + item = &uint32; + method = "getInteger"; + break; + + case DBUS_TYPE_BOOLEAN: + item = &bool; + method = "getBoolean"; + break; + + case DBUS_TYPE_BYTE: + item = &byte; + method = "getByte"; + break; + + case DBUS_TYPE_STRING: + item = &string; + method = "getString"; + break; + + default: + fprintf (stderr, "%d: Type %c\n", opt, opt_type); + g_assert_not_reached (); + break; + } + + ret = call_nm_method (connection, method, opt, TRUE, opt_type, item, &num_items); + if ((ret == RETURN_SUCCESS) && (num_items > 0)) + { + int i; + fprintf (stderr, "%d ('%s'): (%d %s of type %s) ", opt, name, num_items, num_items > 1 ? "elements" : "element", dbus_type_to_string (opt_type)); + for (i = 0; i < num_items; i++) + { + struct in_addr in; + gboolean last = (i == num_items - 1) ? TRUE : FALSE; + + switch (opt_type) + { + case DBUS_TYPE_BYTE: + fprintf (stderr, "%d%s", byte[i], last ? "" : ", "); + break; + case DBUS_TYPE_BOOLEAN: + fprintf (stderr, "%d%s", bool[i], last ? "" : ", "); + break; + case DBUS_TYPE_UINT32: + in.s_addr = uint32[i]; + if (!inet_ntop (AF_INET, &in, buf, INET_ADDRSTRLEN)) + nm_warning ("%s: error converting IP4 address 0x%X", + __func__, ntohl (in.s_addr)); + else + fprintf (stderr, "%u (%s)%s", uint32[i], buf, last ? "" : ", "); + break; + case DBUS_TYPE_STRING: + fprintf (stderr, "'%s'%s", string[i], last ? "" : ", "); + break; + + default: + g_assert_not_reached (); + break; + } + } + fprintf (stderr, "\n"); + } + else + fprintf (stderr, "%d ('%s'): could not get option value\n", opt, name); +} + + +void print_each_dhcp_option (DBusConnection *connection) +{ + DBusMessage *message; + DBusMessage *reply; + DBusMessageIter iter; + DBusError error; + int i; + int opt_type; + int ret; + + g_return_if_fail (connection != NULL); + + /* Loop through all available DHCP options and print each one. */ + for (i = 1; i < 62; i++) + print_array (connection, i); +} + + +int main (int argc, char **argv) +{ + DBusConnection *connection; + DBusError error; + + g_type_init (); + + dbus_error_init (&error); + connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error); + if (connection == NULL) + { + fprintf (stderr, "Error connecting to system bus: %s\n", error.message); + dbus_error_free (&error); + return 1; + } + + print_each_dhcp_option (connection); + + exit (0); +} Index: test/NMLoadModules =================================================================== --- /dev/null +++ test/NMLoadModules @@ -0,0 +1,61 @@ +#! /bin/bash +# Load kernel modules for all network devices + +CWD=`pwd` +cd /etc/sysconfig/network-scripts + +# find all the interfaces besides loopback. +# ignore aliases, alternative configurations, and editor backup files +interfaces=`ls ifcfg* | LANG=C egrep -v '(ifcfg-lo|:|rpmsave|rpmorig|rpmnew)' | \ + LANG=C egrep -v '(~|\.bak)$' | \ + LANG=C egrep 'ifcfg-[A-Za-z0-9\._-]+$' | \ + sed 's/^ifcfg-//g' | + sed 's/[0-9]/ &/' | LANG=C sort -k 1,1 -k 2n | sed 's/ //'` + +# bring up all other interfaces configured to come up at boot time +for i in $interfaces; do + eval $(LANG=C fgrep "DEVICE=" ifcfg-$i) + eval $(LANG=C fgrep "TYPE=" ifcfg-$i) + eval $(LANG=C fgrep "SLAVE=" ifcfg-$i) + eval $(LANG=C fgrep "BRIDGE=" ifcfg-$i) + + if [ -z "$DEVICE" ] ; then DEVICE="$i"; fi + + if [ "${DEVICE##cipcb}" != "$DEVICE" ] ; then + unset DEVICE TYPE SLAVE BRIDGE + continue + fi + + if [ "$TYPE" = "xDSL" ]; then + unset DEVICE TYPE SLAVE BRIDGE + continue + fi + + if [ -n "$BRIDGE" ]; then + unset DEVICE TYPE SLAVE BRIDGE + continue + fi + + if [ "${DEVICE%%.*}" != "$DEVICE" ] ; then + unset DEVICE TYPE SLAVE BRIDGE + continue + fi + + if [ "$SLAVE" = "yes" ]; then + unset DEVICE TYPE SLAVE BRIDGE + continue + fi + unset DEVICE TYPE SLAVE BRIDGE + + # Load the module + LC_ALL= LANG= /sbin/ip -o link | grep -q $i + if [ "$?" = "1" ]; then + alias=`modprobe -c | awk "/^(alias|install)[[:space:]]+$i[[:space:]]/ { print \\$3 }"` + if [ -n "$alias" -a "$alias" != "off" -a "$alias" != "/bin/true" ]; then + modprobe $alias > /dev/null 2>&1 + fi + fi + continue +done + +exit 0 Index: test/nmnetlinktest.c =================================================================== --- /dev/null +++ test/nmnetlinktest.c @@ -0,0 +1,96 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * 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, 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. + * + */ + +#include <sys/types.h> + +#include <sys/socket.h> +#include <asm/types.h> +#include <linux/types.h> +#include <linux/netlink.h> +#include <linux/rtnetlink.h> +#include <linux/if.h> +#include <errno.h> + +#include <glib.h> +#include <nm-netlink-monitor.h> + +static void +device_added (NmNetlinkMonitor *monitor, + const gchar *device_name) +{ + g_print ("interface '%s' connected\n", device_name); +} + + +static void +device_removed (NmNetlinkMonitor *monitor, + const gchar *device_name) +{ + g_print ("interface '%s' disconnected\n", device_name); +} + +int +main (void) +{ + NmNetlinkMonitor *monitor; + GMainLoop *loop; + GError *error; + + g_type_init (); + + monitor = nm_netlink_monitor_new (); + + error = NULL; + nm_netlink_monitor_open_connection (monitor, &error); + + if (error != NULL) + { + g_printerr ("could not open connection: %s\n", + error->message); + g_error_free (error); + return 1; + } + + loop = g_main_loop_new (NULL, FALSE); + + g_signal_connect (G_OBJECT (monitor), + "interface-connected", + G_CALLBACK (device_added), NULL); + + g_signal_connect (G_OBJECT (monitor), + "interface-disconnected", + G_CALLBACK (device_removed), NULL); + + nm_netlink_monitor_attach (monitor, NULL); + + nm_netlink_monitor_request_status (monitor, &error); + + if (error != NULL) + { + g_printerr ("could not request status of interfaces: %s\n", + error->message); + g_error_free (error); + return 2; + } + + g_main_loop_run (loop); + + return 0; +} Index: test/nm-online.c =================================================================== --- test/nm-online.c.orig +++ test/nm-online.c @@ -30,7 +30,6 @@ * Robert Love <rml@novell.com> */ -#define DBUS_API_SUBJECT_TO_CHANGE 1 #define PROGRESS_STEPS 15 #include <ctype.h> Index: docs/NetworkManager =================================================================== --- /dev/null +++ docs/NetworkManager @@ -0,0 +1,195 @@ +********* NOTE ********* +This document is for historical reference only. The autogenerated 'spec.html' is the canonical D-Bus reference. +********* NOTE ********* + + + +NetworkManager DBUS API (unstable) +---------------------------------- + +NetworkManager (NM) exposes a DBUS service and API for two purposes: for programs to obtain information about the network state and network devices, and for programs or users to alter the network state in limited ways. This API is currently unstable and is likely to change in the future. Any methods or objects NOT described in this document are not part of the official API, are not meant for general use, and are not supported in any way. + +There are three types of "objects" that NM allows other programs to interact with: the NetworkManager object, Device objects, and Network objects. There is only one NetworkManager object as it performs system-wide networking functions and controls each Device. There can be a arbitrary number of Devices, including no Devices at all, each of which represent a network device present in the system. A Network is the representation of a wireless network, of which each Device object may have an arbitrary number (as long as it is a wireless device). + + +Object structure: + NetworkManager + / \ + Device Device + / \ (no networks) + Network Network + + +The NetworkManager object +------------------------- + +The following constants are used to uniquely refer to the NetworkManager object when making DBUS method calls against NetworkManager: + +DBUS Service: "org.freedesktop.NetworkManager" +DBUS Object Path: "/org/freedesktop/NetworkManager" +DBUS Interface: "org.freedesktop.NetworkManager" + +Methods: + + Name: getDevices Get the list of network devices NM knows about + Args: (none) + Returns: DBUS String Array Each item in the array is the NM identifier of a Device object + + + Name: getActiveDevice Return the currently active network device + Args: (none) + Returns: DBUS_TYPE_STRING The NM identifier of a Device object + + + Name: setActiveDevice Force NM to use a particular network device + Args: 1) Device object (DBUS_TYPE_STRING) - Network device to switch to + 2) Wireless Network ESSID (DBUS_TYPE_STRING, optional) - ESSID of the wireless network to switch to + Returns: (nothing) + + + Name: status Retrieve status information about the network state + Args: (none) + Returns: DBUS_TYPE_STRING "connecting" - there is a pending network connection (waiting for a + DHCP request to complete, waiting for an encryption + key/passphrase, waiting for a wireless network, etc) + "connected" - there is an active network connection + "scanning" - there is no active network connection, but NetworkManager + is looking for an access point to associate with + "disconnected" - there is no network connection + +Signals: + + Name: DeviceNoLongerActive Signals that a network device is no longer active + Args: 1) Device object (DBUS_TYPE_STRING) - The deactivated network device + + Name: DeviceNowActive Signals that a network device is newly activated + Args: 1) Device object (DBUS_TYPE_STRING) - The newly activated network device + + Name: DeviceActivating Signals that a network device is about to become active + Args: 1) Device object (DBUS_TYPE_STRING) - The device about to become active + + Name: DevicesChanged Signals that a device was either added or removed from the system + Args: 1) Device object (DBUS_TYPE_STRING) - The device which was added or removed + + Name: DeviceActivationFailed Signals that activation for a device could not complete (dhcp failed or so) + Args: 1) Device object (DBUS_TYPE_STRING) - The device for which activation failed + 2) Network name (DBUS_TYPE_STRING, optional) - ESSID of failed wireless network + + Name: DeviceStrengthChanged Signals that the wireless strength percentage for the device has changed. + Args: 1) Device object (DBUS_TYPE_STRING) - The device for which strength changed + 2) Strength (DBUS_TYPE_INT32) - The new strength percentage + +NOTE: the following 3 Signals are likely to change in the near future + + Name: DeviceIP4AddressChange Signals that a device's IPv4 address was changed + Args: 1) Device object (DBUS_TYPE_STRING) - The device whose IPv4 address changed + + Name: WirelessNetworkAppeared Signals that a device found a new wireless network + Args: 1) Device object (DBUS_TYPE_STRING) - The device which noticed the wireless network + 2) Network object (DBUS_TYPE_STRING) - The new wireless network's identifier + + Name: WirelessNetworkDisappeared Signals that a device lost a new wireless network + Args: 1) Device object (DBUS_TYPE_STRING) - The device which lost the wireless network + 2) Network object (DBUS_TYPE_STRING) - The no-longer-visible wireless network's identifier + + + + +The Device object +----------------- + +The Device object is the NM representation of a network device. To refer to a NM Device, you must use the following constants when creating your DBUS message: + +DBUS Service: "org.freedesktop.NetworkManager" +DBUS Interface: "org.freedesktop.NetworkManager.Devices" + +Note that there is no DBUS Object Path listed above, the object path will always the the NM Device identfier returned from such methods as "getActiveDevice" and "getDevices". + +Methods: + + Name: getName Returns the system device name of the Device object (i.e. eth0) + Args: (none) + Returns: DBUS_TYPE_STRING The system device name + + + Name: getType Returns the type of the device (ie wired, wireless, isdn, bluetooth, etc) + Args: (none) + Returns: DBUS_TYPE_INT32 0 - unknown type + 1 - Wired ethernet + 2 - Wireless (802.11a/b/g) + + + Name: getHalUdi Returns the HAL UDI of the device + Args: (none) + Returns: DBUS_TYPE_STRING + + + Name: getIP4Address Returns the IPv4 address of the device + Args: (none) + Returns: DBUS_TYPE_UINT32 The IPv4 address in network byte order + + + Name: getLinkActive Returns the link state of the device + Args: (none) + Returns: DBUS_TYPE_BOOLEAN TRUE - the device has a valid network link + Wired: cable is plugged in + Wireless: good link to a base station + FALSE - the device has no network link + Wired: no cable plugged in + Wireless: no base station, or bad encryption key + + Name: getActiveNetwork (Wireless only) Returns the Network object indentifier of the wireless network + this device is currently associated with, if any + Args: (none) + Returns: DBUS_TYPE_STRING + + + Name: getNetworks (Wireless only) Returns a list of Network objects this device knows about + Args: (none) + Returns: DBUS String Array Each item in the array is a Network object identifier + + + +The Network object +------------------ + +Each Device object that is of type 2 (Wireless device) keeps a list of Network objects that it knows about. Use the following constants to specify a Network object when creating DBUS method calls: + +DBUS Service: "org.freedesktop.NetworkManager" +DBUS Interface: "org.freedesktop.NetworkManager.Devices" + +Again, note that there is no DBUS Object Path above, since the object path used for the method call will be the Network object indentifier returned from a Device object's "getActiveNetwork" or "getNetworks" methods. + +Methods: + + Name: getName Return the name of the network (ESSID) + Args: (none) + Returns: DBUS_TYPE_STRING + + + Name: getAddress Returns the hardware address of the base station this wireless network belongs to. + NOTE: this may change in the near future to an array of addresses. + Args: (none) + Returns: DBUS_TYPE_STRING + + + Name: getStrength Return the strength percentage of the current wireless network + Args: (none) + Returns: DBUS_TYPE_INT32 The strength percentage of the current wireless network + + + Name: getFrequency Returns the frequency/channel this wireless network + Args: (none) + Returns: DBUS_TYPE_DOUBLE A frequency in GHz (i.e. 2.417) + + + Name: getRate Returns the max data rate this wireless network supports + Args: (none) + Returns: DBUS_TYPE_INT32 The max data rate in Mbps (i.e. 11) + + + Name: getEncrypted Returns whether or not this wireless network requires encryption + Args: (none) + Returns: DBUS_TYPE_BOOLEAN + + Index: configure.in =================================================================== --- configure.in.orig +++ configure.in @@ -486,6 +486,7 @@ src/named-manager/Makefile src/vpn-manager/Makefile src/dhcp-manager/Makefile src/supplicant-manager/Makefile +src/supplicant-manager/tests/Makefile src/ppp-manager/Makefile src/dnsmasq-manager/Makefile src/backends/Makefile
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor