diff options
| author | Michael Biebl <biebl@debian.org> | 2012-06-29 20:12:44 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2012-06-29 20:12:44 +0200 |
| commit | 867254ea7c2b193fecf8cd36cc6e5dc53c290d92 (patch) | |
| tree | 7c698b403882736ab70c3efd524c3460f08c391c /cli/src/devices.c | |
| parent | de06e5715e780baade318f3490ac7a4c9ce84e32 (diff) | |
Imported Upstream version 0.9.5.95 upstream/0.9.5.95
Diffstat (limited to 'cli/src/devices.c')
| -rw-r--r-- | cli/src/devices.c | 723 |
1 files changed, 497 insertions, 226 deletions
diff --git a/cli/src/devices.c b/cli/src/devices.c index 0b1b6d6e..6b9367b4 100644 --- a/cli/src/devices.c +++ b/cli/src/devices.c @@ -23,6 +23,7 @@ #include <string.h> #include <stdlib.h> #include <errno.h> +#include <netinet/ether.h> #include <glib.h> #include <glib/gi18n.h> @@ -30,6 +31,7 @@ #include <nm-client.h> #include <nm-device.h> #include <nm-device-ethernet.h> +#include <nm-device-adsl.h> #include <nm-device-wifi.h> #include <nm-device-modem.h> #include <nm-device-bt.h> @@ -46,6 +48,7 @@ #include <nm-vpn-connection.h> #include <nm-setting-connection.h> #include <nm-setting-wired.h> +#include <nm-setting-adsl.h> #include <nm-setting-pppoe.h> #include <nm-setting-wireless.h> #include <nm-setting-gsm.h> @@ -105,17 +108,20 @@ static NmcOutputField nmc_fields_dev_list_general[] = { {"VENDOR", N_("VENDOR"), 20, NULL, 0}, /* 3 */ {"PRODUCT", N_("PRODUCT"), 50, NULL, 0}, /* 4 */ {"DRIVER", N_("DRIVER"), 9, NULL, 0}, /* 5 */ - {"HWADDR", N_("HWADDR"), 19, NULL, 0}, /* 6 */ - {"STATE", N_("STATE"), 14, NULL, 0}, /* 7 */ - {"REASON", N_("REASON"), 25, NULL, 0}, /* 8 */ - {"UDI", N_("UDI"), 64, NULL, 0}, /* 9 */ - {"IP-IFACE", N_("IP-IFACE"), 10, NULL, 0}, /* 10 */ - {"NM-MANAGED", N_("NM-MANAGED"), 15, NULL, 0}, /* 11 */ - {"FIRMWARE-MISSING", N_("FIRMWARE-MISSING"), 18, NULL, 0}, /* 12 */ - {"CONNECTION", N_("CONNECTION"), 51, NULL, 0}, /* 13 */ + {"DRIVER-VERSION", N_("DRIVER-VERSION"), 18, NULL, 0}, /* 6 */ + {"FIRMWARE-VERSION", N_("FIRMWARE-VERSION"), 18, NULL, 0}, /* 7 */ + {"HWADDR", N_("HWADDR"), 19, NULL, 0}, /* 8 */ + {"STATE", N_("STATE"), 14, NULL, 0}, /* 9 */ + {"REASON", N_("REASON"), 25, NULL, 0}, /* 10 */ + {"UDI", N_("UDI"), 64, NULL, 0}, /* 11 */ + {"IP-IFACE", N_("IP-IFACE"), 10, NULL, 0}, /* 12 */ + {"NM-MANAGED", N_("NM-MANAGED"), 15, NULL, 0}, /* 13 */ + {"AUTOCONNECT", N_("AUTOCONNECT"), 15, NULL, 0}, /* 14 */ + {"FIRMWARE-MISSING", N_("FIRMWARE-MISSING"), 18, NULL, 0}, /* 15 */ + {"CONNECTION", N_("CONNECTION"), 51, NULL, 0}, /* 16 */ {NULL, NULL, 0, NULL, 0} }; -#define NMC_FIELDS_DEV_LIST_GENERAL_ALL "NAME,DEVICE,TYPE,VENDOR,PRODUCT,DRIVER,HWADDR,STATE,REASON,UDI,IP-IFACE,NM-MANAGED,FIRMWARE-MISSING,CONNECTION" +#define NMC_FIELDS_DEV_LIST_GENERAL_ALL "NAME,DEVICE,TYPE,VENDOR,PRODUCT,DRIVER,DRIVER-VERSION,FIRMWARE-VERSION,HWADDR,STATE,REASON,UDI,IP-IFACE,NM-MANAGED,AUTOCONNECT,FIRMWARE-MISSING,CONNECTION" #define NMC_FIELDS_DEV_LIST_GENERAL_COMMON "NAME,DEVICE,TYPE,VENDOR,PRODUCT,DRIVER,HWADDR,STATE" /* Available fields for 'dev list' - CAPABILITIES part */ @@ -208,6 +214,8 @@ static NmcOutputField nmc_fields_dev_wimax_list[] = { /* glib main loop variable - defined in nmcli.c */ extern GMainLoop *loop; +static guint progress_id = 0; /* ID of event source for displaying progress */ + static void usage (void) { @@ -222,6 +230,8 @@ usage (void) " list [iface <iface>]\n" " disconnect iface <iface> [--nowait] [--timeout <timeout>]\n" " wifi [list [iface <iface>] [bssid <BSSID>]]\n" + " wifi connect <(B)SSID> [password <password>] [wep-key-type key|phrase] [iface <iface>] [bssid <BSSID>] [name <name>]\n" + " [--private] [--nowait] [--timeout <timeout>]\n" #if WITH_WIMAX " wimax [list [iface <iface>] [nsp <name>]]\n\n" #endif @@ -232,201 +242,12 @@ usage (void) static void quit (void) { - g_main_loop_quit (loop); /* quit main loop */ -} - -static const char * -device_state_to_string (NMDeviceState state) -{ - switch (state) { - case NM_DEVICE_STATE_UNMANAGED: - return _("unmanaged"); - case NM_DEVICE_STATE_UNAVAILABLE: - return _("unavailable"); - case NM_DEVICE_STATE_DISCONNECTED: - return _("disconnected"); - case NM_DEVICE_STATE_PREPARE: - return _("connecting (prepare)"); - case NM_DEVICE_STATE_CONFIG: - return _("connecting (configuring)"); - case NM_DEVICE_STATE_NEED_AUTH: - return _("connecting (need authentication)"); - case NM_DEVICE_STATE_IP_CONFIG: - return _("connecting (getting IP configuration)"); - case NM_DEVICE_STATE_IP_CHECK: - return _("connecting (checking IP connectivity)"); - case NM_DEVICE_STATE_SECONDARIES: - return _("connecting (starting secondary connections)"); - case NM_DEVICE_STATE_ACTIVATED: - return _("connected"); - case NM_DEVICE_STATE_DEACTIVATING: - return _("deactivating"); - case NM_DEVICE_STATE_FAILED: - return _("connection failed"); - default: - return _("unknown"); + if (progress_id) { + g_source_remove (progress_id); + nmc_terminal_erase_line (); } -} - -static const char * -device_reason_to_string (NMDeviceStateReason reason) -{ - switch (reason) { - case NM_DEVICE_STATE_REASON_NONE: - return _("No reason given"); - - case NM_DEVICE_STATE_REASON_UNKNOWN: - return _("Unknown error"); - - case NM_DEVICE_STATE_REASON_NOW_MANAGED: - return _("Device is now managed"); - - case NM_DEVICE_STATE_REASON_NOW_UNMANAGED: - return _("Device is now unmanaged"); - - case NM_DEVICE_STATE_REASON_CONFIG_FAILED: - return _("The device could not be readied for configuration"); - - case NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE: - return _("IP configuration could not be reserved (no available address, timeout, etc)"); - - case NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED: - return _("The IP configuration is no longer valid"); - - case NM_DEVICE_STATE_REASON_NO_SECRETS: - return _("Secrets were required, but not provided"); - - case NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT: - return _("802.1X supplicant disconnected"); - - case NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED: - return _("802.1X supplicant configuration failed"); - - case NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED: - return _("802.1X supplicant failed"); - - case NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT: - return _("802.1X supplicant took too long to authenticate"); - - case NM_DEVICE_STATE_REASON_PPP_START_FAILED: - return _("PPP service failed to start"); - - case NM_DEVICE_STATE_REASON_PPP_DISCONNECT: - return _("PPP service disconnected"); - - case NM_DEVICE_STATE_REASON_PPP_FAILED: - return _("PPP failed"); - - case NM_DEVICE_STATE_REASON_DHCP_START_FAILED: - return _("DHCP client failed to start"); - - case NM_DEVICE_STATE_REASON_DHCP_ERROR: - return _("DHCP client error"); - - case NM_DEVICE_STATE_REASON_DHCP_FAILED: - return _("DHCP client failed"); - - case NM_DEVICE_STATE_REASON_SHARED_START_FAILED: - return _("Shared connection service failed to start"); - - case NM_DEVICE_STATE_REASON_SHARED_FAILED: - return _("Shared connection service failed"); - - case NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED: - return _("AutoIP service failed to start"); - - case NM_DEVICE_STATE_REASON_AUTOIP_ERROR: - return _("AutoIP service error"); - - case NM_DEVICE_STATE_REASON_AUTOIP_FAILED: - return _("AutoIP service failed"); - - case NM_DEVICE_STATE_REASON_MODEM_BUSY: - return _("The line is busy"); - - case NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE: - return _("No dial tone"); - - case NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER: - return _("No carrier could be established"); - case NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT: - return _("The dialing request timed out"); - - case NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED: - return _("The dialing attempt failed"); - - case NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED: - return _("Modem initialization failed"); - - case NM_DEVICE_STATE_REASON_GSM_APN_FAILED: - return _("Failed to select the specified APN"); - - case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING: - return _("Not searching for networks"); - - case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED: - return _("Network registration denied"); - - case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT: - return _("Network registration timed out"); - - case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED: - return _("Failed to register with the requested network"); - - case NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED: - return _("PIN check failed"); - - case NM_DEVICE_STATE_REASON_FIRMWARE_MISSING: - return _("Necessary firmware for the device may be missing"); - - case NM_DEVICE_STATE_REASON_REMOVED: - return _("The device was removed"); - - case NM_DEVICE_STATE_REASON_SLEEPING: - return _("NetworkManager went to sleep"); - - case NM_DEVICE_STATE_REASON_CONNECTION_REMOVED: - return _("The device's active connection disappeared"); - - case NM_DEVICE_STATE_REASON_USER_REQUESTED: - return _("Device disconnected by user or client"); - - case NM_DEVICE_STATE_REASON_CARRIER: - return _("Carrier/link changed"); - - case NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED: - return _("The device's existing connection was assumed"); - - case NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE: - return _("The supplicant is now available"); - - case NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND: - return _("The modem could not be found"); - - case NM_DEVICE_STATE_REASON_BT_FAILED: - return _("The Bluetooth connection failed or timed out"); - - case NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED: - return _("GSM Modem's SIM card not inserted"); - - case NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED: - return _("GSM Modem's SIM PIN required"); - - case NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED: - return _("GSM Modem's SIM PUK required"); - - case NM_DEVICE_STATE_REASON_GSM_SIM_WRONG: - return _("GSM Modem's SIM wrong"); - - case NM_DEVICE_STATE_REASON_INFINIBAND_MODE: - return _("InfiniBand device does not support connected mode"); - - case NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED: - return _("A dependency of the connection failed"); - default: - return _("Unknown"); - } + g_main_loop_quit (loop); /* quit main loop */ } /* Convert device type to string. Use setting names strings to match with @@ -440,6 +261,8 @@ device_type_to_string (NMDevice *device) switch (nm_device_get_device_type (device)) { case NM_DEVICE_TYPE_ETHERNET: return NM_SETTING_WIRED_SETTING_NAME; + case NM_DEVICE_TYPE_ADSL: + return NM_SETTING_ADSL_SETTING_NAME; case NM_DEVICE_TYPE_WIFI: return NM_SETTING_WIRELESS_SETTING_NAME; case NM_DEVICE_TYPE_MODEM: @@ -505,7 +328,7 @@ ap_wpa_rsn_flags_to_string (NM80211ApSecurityFlags flags) i = 0; while (flags_str[i]) - g_free (flags_str[i++]); + g_free (flags_str[i++]); return ret_str; } @@ -745,8 +568,8 @@ show_device_info (gpointer data, gpointer user_data) else if (NM_IS_DEVICE_VLAN (device)) hwaddr = nm_device_vlan_get_hw_address (NM_DEVICE_VLAN (device)); - state_str = g_strdup_printf ("%d (%s)", state, device_state_to_string (state)); - reason_str = g_strdup_printf ("%d (%s)", reason, device_reason_to_string (reason)); + state_str = g_strdup_printf ("%d (%s)", state, nmc_device_state_to_string (state)); + reason_str = g_strdup_printf ("%d (%s)", reason, nmc_device_reason_to_string (reason)); nmc->allowed_fields[0].value = nmc_fields_dev_list_sections[0].name; /* "GENERAL"*/ nmc->allowed_fields[1].value = nm_device_get_iface (device); @@ -754,14 +577,17 @@ show_device_info (gpointer data, gpointer user_data) nmc->allowed_fields[3].value = nm_device_get_vendor (device); nmc->allowed_fields[4].value = nm_device_get_product (device); nmc->allowed_fields[5].value = nm_device_get_driver (device) ? nm_device_get_driver (device) : _("(unknown)"); - nmc->allowed_fields[6].value = hwaddr ? hwaddr : _("(unknown)"); - nmc->allowed_fields[7].value = state_str; - nmc->allowed_fields[8].value = reason_str; - nmc->allowed_fields[9].value = nm_device_get_udi (device); - nmc->allowed_fields[10].value = nm_device_get_ip_iface (device); - nmc->allowed_fields[11].value = nm_device_get_managed (device) ? _("yes") : _("no"); - nmc->allowed_fields[12].value = nm_device_get_firmware_missing (device) ? _("yes") : _("no"); - nmc->allowed_fields[13].value = (acon = nm_device_get_active_connection (device)) ? + nmc->allowed_fields[6].value = nm_device_get_driver_version (device); + nmc->allowed_fields[7].value = nm_device_get_firmware_version (device); + nmc->allowed_fields[8].value = hwaddr ? hwaddr : _("(unknown)"); + nmc->allowed_fields[9].value = state_str; + nmc->allowed_fields[10].value = reason_str; + nmc->allowed_fields[11].value = nm_device_get_udi (device); + nmc->allowed_fields[12].value = nm_device_get_ip_iface (device); + nmc->allowed_fields[13].value = nm_device_get_managed (device) ? _("yes") : _("no"); + nmc->allowed_fields[14].value = nm_device_get_autoconnect (device) ? _("yes") : _("no"); + nmc->allowed_fields[15].value = nm_device_get_firmware_missing (device) ? _("yes") : _("no"); + nmc->allowed_fields[16].value = (acon = nm_device_get_active_connection (device)) ? nm_object_get_path (NM_OBJECT (acon)) : _("not connected"); nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_SECTION_PREFIX; @@ -975,7 +801,7 @@ show_device_status (NMDevice *device, NmCli *nmc) { nmc->allowed_fields[0].value = nm_device_get_iface (device); nmc->allowed_fields[1].value = device_type_to_string (device); - nmc->allowed_fields[2].value = device_state_to_string (nm_device_get_state (device)); + nmc->allowed_fields[2].value = nmc_device_state_to_string (nm_device_get_state (device)); nmc->allowed_fields[3].value = nm_object_get_path (NM_OBJECT (device)); nmc->print_fields.flags &= ~NMC_PF_FLAG_MAIN_HEADER_ADD & ~NMC_PF_FLAG_MAIN_HEADER_ONLY & ~NMC_PF_FLAG_FIELD_NAMES; /* Clear header flags */ @@ -1110,7 +936,7 @@ do_devices_list (NmCli *nmc, int argc, char **argv) device = candidate; } if (!device) { - g_string_printf (nmc->return_text, _("Error: Device '%s' not found."), iface); + g_string_printf (nmc->return_text, _("Error: Device '%s' not found."), iface); nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; goto error; } @@ -1151,6 +977,16 @@ timeout_cb (gpointer user_data) return FALSE; } +static gboolean +progress_cb (gpointer user_data) +{ + NMDevice *device = (NMDevice *) user_data; + + nmc_terminal_show_progress (device ? nmc_device_state_to_string (nm_device_get_state (device)) : ""); + + return TRUE; +} + static void disconnect_device_cb (NMDevice *device, GError *error, gpointer user_data) { @@ -1166,10 +1002,13 @@ disconnect_device_cb (NMDevice *device, GError *error, gpointer user_data) quit (); } else { state = nm_device_get_state (device); - printf (_("Device state: %d (%s)\n"), state, device_state_to_string (state)); if (nmc->nowait_flag || state == NM_DEVICE_STATE_DISCONNECTED) { /* Don't want to wait or device already disconnected */ + if (state == NM_DEVICE_STATE_DISCONNECTED && nmc->print_output == NMC_PRINT_PRETTY) { + nmc_terminal_erase_line (); + printf (_("Device '%s' has been disconnected.\n"), nm_device_get_iface (device)); + } quit (); } else { g_signal_connect (device, "notify::state", G_CALLBACK (device_state_cb), nmc); @@ -1273,6 +1112,10 @@ do_device_disconnect (NmCli *nmc, int argc, char **argv) nmc->should_wait = TRUE; nm_device_disconnect (device, disconnect_device_cb, nmc); + /* Start progress indication */ + if (nmc->print_output == NMC_PRINT_PRETTY) + progress_id = g_timeout_add (120, progress_cb, device); + error: return nmc->return_value; } @@ -1399,7 +1242,7 @@ do_device_wifi_list (NmCli *nmc, int argc, char **argv) } if (!device) { - g_string_printf (nmc->return_text, _("Error: Device '%s' not found."), iface); + g_string_printf (nmc->return_text, _("Error: Device '%s' not found."), iface); nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; goto error; } @@ -1419,7 +1262,7 @@ do_device_wifi_list (NmCli *nmc, int argc, char **argv) g_free (bssid_up); } if (!ap) { - g_string_printf (nmc->return_text, _("Error: Access point with bssid '%s' not found."), bssid_user); + g_string_printf (nmc->return_text, _("Error: Access point with bssid '%s' not found."), bssid_user); nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; goto error; } @@ -1436,7 +1279,7 @@ do_device_wifi_list (NmCli *nmc, int argc, char **argv) show_acces_point_info (device, nmc); } } else { - g_string_printf (nmc->return_text, _("Error: Device '%s' is not a WiFi device."), iface); + g_string_printf (nmc->return_text, _("Error: Device '%s' is not a WiFi device."), iface); nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; goto error; } @@ -1473,7 +1316,7 @@ do_device_wifi_list (NmCli *nmc, int argc, char **argv) } } if (!ap) { - g_string_printf (nmc->return_text, _("Error: Access point with bssid '%s' not found."), bssid_user); + g_string_printf (nmc->return_text, _("Error: Access point with bssid '%s' not found."), bssid_user); nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; goto error; } @@ -1490,6 +1333,433 @@ error: return nmc->return_value; } +static void +monitor_device_state_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data) +{ + NmCli *nmc = (NmCli *) user_data; + NMDeviceState state; + NMDeviceStateReason reason; + + state = nm_device_get_state_reason (device, &reason); + + if (state == NM_DEVICE_STATE_ACTIVATED) { + if (nmc->print_output == NMC_PRINT_PRETTY) { + NMActiveConnection *active = nm_device_get_active_connection (device); + + nmc_terminal_erase_line (); + printf (_("Connection with UUID '%s' created and activated on device '%s'\n"), + nm_active_connection_get_uuid (active), nm_device_get_iface (device)); + } + quit (); + } else if (state == NM_DEVICE_STATE_FAILED) { + g_string_printf (nmc->return_text, _("Error: Connection activation failed: (%d) %s."), + reason, nmc_device_reason_to_string (reason)); + nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION; + quit (); + } +} + +typedef struct { + NmCli *nmc; + NMDevice *device; +} AddAndActivateInfo; + +static void +add_and_activate_cb (NMClient *client, + NMActiveConnection *active, + const char *connection_path, + GError *error, + gpointer user_data) +{ + AddAndActivateInfo *info = (AddAndActivateInfo *) user_data; + NmCli *nmc = info->nmc; + NMDevice *device = info->device; + NMActiveConnectionState state; + + if (error) { + g_string_printf (nmc->return_text, _("Error: Failed to add/activate new connection: (%d) %s"), + error->code, error->message); + nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION; + quit (); + } else { + state = nm_active_connection_get_state (active); + + if (state == NM_ACTIVE_CONNECTION_STATE_UNKNOWN) { + g_string_printf (nmc->return_text, _("Error: Failed to add/activate new connection: Unknown error")); + nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION; + quit (); + } + + if (nmc->nowait_flag || state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) { + /* User doesn't want to wait or already activated */ + if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED && nmc->print_output == NMC_PRINT_PRETTY) { + printf (_("Connection with UUID '%s' created and activated on device '%s'\n"), + nm_active_connection_get_uuid (active), nm_device_get_iface (device)); + } + quit (); + } else { + g_signal_connect (device, "notify::state", G_CALLBACK (monitor_device_state_cb), nmc); + g_timeout_add_seconds (nmc->timeout, timeout_cb, nmc); /* Exit if timeout expires */ + + if (nmc->print_output == NMC_PRINT_PRETTY) + progress_id = g_timeout_add (120, progress_cb, device); + } + } + + g_free (info); +} + +/* + * Find a Wi-Fi device with 'iface' in 'devices' array. If 'iface' is NULL, + * the first Wi-Fi device is returned. 'idx' parameter is updated to the point + * where the function finished so that the function can be called repeatedly + * to get next matching device. + * Returns: found device or NULL + */ +static NMDevice * +find_wifi_device_by_iface (const GPtrArray *devices, const char *iface, int *idx) +{ + NMDevice *device = NULL; + int i; + + for (i = *idx; devices && (i < devices->len); i++) { + NMDevice *candidate = g_ptr_array_index (devices, i); + const char *dev_iface = nm_device_get_iface (candidate); + + if (!NM_IS_DEVICE_WIFI (candidate)) + continue; + + if (iface) { + /* If a iface was specified then use it. */ + if (strcmp (dev_iface, iface) == 0) { + device = candidate; + break; + } + } else { + /* Else return the first Wi-Fi device. */ + device = candidate; + break; + } + } + + *idx = i + 1; + return device; +} + +/* + * Find AP on 'device' according to 'bssid' or 'ssid' parameter. + * Returns: found AP or NULL + */ +static NMAccessPoint * +find_ap_on_device (NMDevice *device, GByteArray *bssid, const char *ssid) +{ + const GPtrArray *aps; + NMAccessPoint *ap = NULL; + int i; + + g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), NULL); + g_return_val_if_fail ((bssid && !ssid) || (!bssid && ssid), NULL); + + aps = nm_device_wifi_get_access_points (NM_DEVICE_WIFI (device)); + for (i = 0; aps && (i < aps->len); i++) { + NMAccessPoint *candidate_ap = g_ptr_array_index (aps, i); + + if (ssid) { + /* Parameter is SSID */ + const GByteArray *candidate_ssid = nm_access_point_get_ssid (candidate_ap); + char *ssid_tmp = nm_utils_ssid_to_utf8 (candidate_ssid); + + /* Compare SSIDs */ + if (strcmp (ssid, ssid_tmp) == 0) { + ap = candidate_ap; + g_free (ssid_tmp); + break; + } + g_free (ssid_tmp); + } else if (bssid) { + /* Parameter is BSSID */ + const char *candidate_bssid = nm_access_point_get_bssid (candidate_ap); + char *bssid_up = nm_utils_hwaddr_ntoa (bssid->data, ARPHRD_ETHER); + + /* Compare BSSIDs */ + if (strcmp (bssid_up, candidate_bssid) == 0) { + ap = candidate_ap; + g_free (bssid_up); + break; + } + g_free (bssid_up); + } + } + + return ap; +} + +static NMCResultCode +do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv) +{ + NMDevice *device = NULL; + NMAccessPoint *ap = NULL; + NMConnection *connection = NULL; + NMSettingConnection *s_con; + NMSettingWireless *s_wifi; + NMSettingWirelessSecurity *s_wsec; + AddAndActivateInfo *info; + const char *param_user = NULL; + const char *iface = NULL; + const char *bssid = NULL; + const char *password = NULL; + const char *con_name = NULL; + gboolean private = FALSE; + gboolean wait = TRUE; + gboolean wep_passphrase = FALSE; + GByteArray *bssid1_arr = NULL; + GByteArray *bssid2_arr = NULL; + const GPtrArray *devices; + int devices_idx; + GError *error = NULL; + + /* Default timeout for waiting for operation completion */ + nmc->timeout = 90; + + /* Get the first compulsory argument (SSID or BSSID) */ + if (argc > 0) { + param_user = *argv; + bssid1_arr = nm_utils_hwaddr_atoba (param_user, ARPHRD_ETHER); + + argc--; + argv++; + } else { + g_string_printf (nmc->return_text, _("Error: SSID or BSSID are missing.")); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + goto error; + } + + /* Get the rest of the parameters */ + while (argc > 0) { + if (strcmp (*argv, "iface") == 0) { + if (next_arg (&argc, &argv) != 0) { + g_string_printf (nmc->return_text, _("Error: %s argument is missing."), *argv); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + goto error; + } + iface = *argv; + } else if (strcmp (*argv, "bssid") == 0) { + if (next_arg (&argc, &argv) != 0) { + g_string_printf (nmc->return_text, _("Error: %s argument is missing."), *argv); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + goto error; + } + bssid = *argv; + bssid2_arr = nm_utils_hwaddr_atoba (bssid, ARPHRD_ETHER); + if (!bssid2_arr) { + g_string_printf (nmc->return_text, _("Error: bssid argument value '%s' is not a valid BSSID."), + bssid); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + goto error; + } + } else if (strcmp (*argv, "password") == 0) { + if (next_arg (&argc, &argv) != 0) { + g_string_printf (nmc->return_text, _("Error: %s argument is missing."), *argv); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + goto error; + } + password = *argv; + } else if (strcmp (*argv, "wep-key-type") == 0) { + if (next_arg (&argc, &argv) != 0) { + g_string_printf (nmc->return_text, _("Error: %s argument is missing."), *argv); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + goto error; + } + if (strcmp (*argv, "key") == 0) + wep_passphrase = FALSE; + else if (strcmp (*argv, "phrase") == 0) + wep_passphrase = TRUE; + else { + g_string_printf (nmc->return_text, + _("Error: wep-key-type argument value '%s' is invalid, use 'key' or 'phrase'."), + *argv); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + goto error; + } + } else if (strcmp (*argv, "name") == 0) { + if (next_arg (&argc, &argv) != 0) { + g_string_printf (nmc->return_text, _("Error: %s argument is missing."), *argv); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + goto error; + } + con_name = *argv; + } else if (strcmp (*argv, "--private") == 0) { + private = TRUE; + } else if (strcmp (*argv, "--nowait") == 0) { + wait = FALSE; + } else if (strcmp (*argv, "--timeout") == 0) { + if (next_arg (&argc, &argv) != 0) { + g_string_printf (nmc->return_text, _("Error: %s argument is missing."), *argv); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + goto error; + } + + errno = 0; + nmc->timeout = strtol (*argv, NULL, 10); + if (errno || nmc->timeout < 0) { + g_string_printf (nmc->return_text, _("Error: timeout value '%s' is not valid."), *argv); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + goto error; + } + } else { + fprintf (stderr, _("Unknown parameter: %s\n"), *argv); + } + + argc--; + argv++; + } + + /* Verify SSID/BSSID parameters */ + if (bssid1_arr && bssid2_arr && memcmp (bssid1_arr->data, bssid2_arr->data, ETH_ALEN)) { + g_string_printf (nmc->return_text, _("Error: BSSID to connect to (%s) differs from bssid argument (%s)."), + param_user, bssid); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + goto error; + } + if (!bssid1_arr && strlen (param_user) > 32) { + g_string_printf (nmc->return_text, _("Error: Parameter '%s' is neither SSID nor BSSID."), param_user); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + goto error; + } + + if (!nmc_is_nm_running (nmc, &error)) { + if (error) { + g_string_printf (nmc->return_text, _("Error: Can't find out if NetworkManager is running: %s."), error->message); + nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; + g_error_free (error); + } else { + g_string_printf (nmc->return_text, _("Error: NetworkManager is not running.")); + nmc->return_value = NMC_RESULT_ERROR_NM_NOT_RUNNING; + } + goto error; + } + + if (!nmc_versions_match (nmc)) + goto error; + + nmc->get_client (nmc); + devices = nm_client_get_devices (nmc->client); + + /* Find a device to activate the connection on */ + devices_idx = 0; + device = find_wifi_device_by_iface (devices, iface, &devices_idx); + + if (!device) { + if (iface) + g_string_printf (nmc->return_text, _("Error: Device '%s' is not a Wi-Fi device."), iface); + else + g_string_printf (nmc->return_text, _("Error: No Wi-Fi device found.")); + nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; + goto error; + } + + /* Find an AP to connect to */ + ap = find_ap_on_device (device, bssid1_arr, bssid1_arr ? NULL : param_user); + if (!ap && !iface) { + /* AP not found. iface was not specified, so try finding the AP on another device. */ + while ((device = find_wifi_device_by_iface (devices, NULL, &devices_idx)) != NULL) { + ap = find_ap_on_device (device, bssid1_arr, bssid1_arr ? NULL : param_user); + if (ap) + break; + } + } + + if (!ap) { + if (!bssid1_arr) + g_string_printf (nmc->return_text, _("Error: No network with SSID '%s' found."), param_user); + else + g_string_printf (nmc->return_text, _("Error: No access point with BSSID '%s' found."), param_user); + nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; + goto error; + } + + /* If there are some connection data from user, create a connection and + * fill them into proper settings. */ + if (con_name || private || bssid2_arr || password) + connection = nm_connection_new (); + + if (con_name || private) { + s_con = (NMSettingConnection *) nm_setting_connection_new (); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + /* Set user provided connection name */ + if (con_name) + g_object_set (s_con, NM_SETTING_CONNECTION_ID, con_name, NULL); + + /* Connection will only be visible to this user when '--private' is specified */ + if (private) + nm_setting_connection_add_permission (s_con, "user", g_get_user_name (), NULL); + } + if (bssid2_arr) { + s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); + nm_connection_add_setting (connection, NM_SETTING (s_wifi)); + + /* 'bssid' parameter is used to restrict the conenction only to the BSSID */ + g_object_set (s_wifi, NM_SETTING_WIRELESS_BSSID, bssid2_arr, NULL); + } + if (password) { + NM80211ApFlags flags = nm_access_point_get_flags (ap); + NM80211ApSecurityFlags wpa_flags = nm_access_point_get_wpa_flags (ap); + NM80211ApSecurityFlags rsn_flags = nm_access_point_get_rsn_flags (ap); + + s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new (); + nm_connection_add_setting (connection, NM_SETTING (s_wsec)); + + /* Set password for WEP or WPA-PSK. */ + if (flags & NM_802_11_AP_FLAGS_PRIVACY) { + if (wpa_flags == NM_802_11_AP_SEC_NONE && rsn_flags == NM_802_11_AP_SEC_NONE) { + /* WEP */ + nm_setting_wireless_security_set_wep_key (s_wsec, 0, password); + g_object_set (G_OBJECT (s_wsec), + NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, + wep_passphrase ? NM_WEP_KEY_TYPE_PASSPHRASE: NM_WEP_KEY_TYPE_KEY, + NULL); + } else if ( !(wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) + && !(rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) { + /* WPA PSK */ + g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_PSK, password, NULL); + } + } + // FIXME: WPA-Enterprise is not supported yet. + // We are not able to determine and fill all the parameters for + // 802.1X authentication automatically without user providing + // the data. Adding nmcli options for the 8021x setting would + // clutter the command. However, that could be solved later by + // implementing add/edit connections support for nmcli. + } + + /* nowait_flag indicates user input. should_wait says whether quit in start(). + * We have to delay exit after add_and_activate_cb() is called, even if + * the user doesn't want to wait, in order to give NM time to check our + * permissions. */ + nmc->nowait_flag = !wait; + nmc->should_wait = TRUE; + + info = g_malloc0 (sizeof (AddAndActivateInfo)); + info->nmc = nmc; + info->device = device; + + nm_client_add_and_activate_connection (nmc->client, + connection, + device, + nm_object_get_path (NM_OBJECT (ap)), + add_and_activate_cb, + info); + +error: + if (bssid1_arr) + g_byte_array_free (bssid1_arr, TRUE); + if (bssid2_arr) + g_byte_array_free (bssid2_arr, TRUE); + + return nmc->return_value; +} + static NMCResultCode do_device_wifi (NmCli *nmc, int argc, char **argv) { @@ -1498,8 +1768,9 @@ do_device_wifi (NmCli *nmc, int argc, char **argv) else if (argc > 0) { if (matches (*argv, "list") == 0) { nmc->return_value = do_device_wifi_list (nmc, argc-1, argv+1); - } - else { + } else if (matches (*argv, "connect") == 0) { + nmc->return_value = do_device_wifi_connect_network (nmc, argc-1, argv+1); + } else { g_string_printf (nmc->return_text, _("Error: 'dev wifi' command '%s' is not valid."), *argv); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; } @@ -1618,7 +1889,7 @@ do_device_wimax_list (NmCli *nmc, int argc, char **argv) } if (!device) { - g_string_printf (nmc->return_text, _("Error: Device '%s' not found."), iface); + g_string_printf (nmc->return_text, _("Error: Device '%s' not found."), iface); nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; goto error; } @@ -1638,7 +1909,7 @@ do_device_wimax_list (NmCli *nmc, int argc, char **argv) g_free (nsp_up); } if (!nsp) { - g_string_printf (nmc->return_text, _("Error: NSP with name '%s' not found."), nsp_user); + g_string_printf (nmc->return_text, _("Error: NSP with name '%s' not found."), nsp_user); nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; goto error; } @@ -1649,7 +1920,7 @@ do_device_wimax_list (NmCli *nmc, int argc, char **argv) show_nsp_info (device, nmc); } } else { - g_string_printf (nmc->return_text, _("Error: Device '%s' is not a WiMAX device."), iface); + g_string_printf (nmc->return_text, _("Error: Device '%s' is not a WiMAX device."), iface); nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; goto error; } @@ -1680,7 +1951,7 @@ do_device_wimax_list (NmCli *nmc, int argc, char **argv) } } if (!nsp) { - g_string_printf (nmc->return_text, _("Error: Access point with nsp '%s' not found."), nsp_user); + g_string_printf (nmc->return_text, _("Error: Access point with nsp '%s' not found."), nsp_user); nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; goto error; } |