diff options
Diffstat (limited to 'clients/cli')
| -rw-r--r-- | clients/cli/common.c | 17 | ||||
| -rw-r--r-- | clients/cli/common.h | 1 | ||||
| -rw-r--r-- | clients/cli/devices.c | 158 | ||||
| -rw-r--r-- | clients/cli/nmcli-completion | 12 | ||||
| -rw-r--r-- | clients/cli/settings-docs.c | 7 | ||||
| -rw-r--r-- | clients/cli/settings.c | 197 | ||||
| -rw-r--r-- | clients/cli/utils.c | 38 | ||||
| -rw-r--r-- | clients/cli/utils.h | 7 |
8 files changed, 393 insertions, 44 deletions
diff --git a/clients/cli/common.c b/clients/cli/common.c index 97d0bb94..35676d0f 100644 --- a/clients/cli/common.c +++ b/clients/cli/common.c @@ -522,6 +522,23 @@ nmc_device_state_to_string (NMDeviceState state) } const char * +nmc_device_metered_to_string (NMMetered value) +{ + switch (value) { + case NM_METERED_YES: + return _("yes"); + case NM_METERED_NO: + return _("no"); + case NM_METERED_GUESS_YES: + return _("yes (guessed)"); + case NM_METERED_GUESS_NO: + return _("no (guessed)"); + default: + return _("unknown"); + } +} + +const char * nmc_device_reason_to_string (NMDeviceStateReason reason) { switch (reason) { diff --git a/clients/cli/common.h b/clients/cli/common.h index 8bb043f4..bb3f44e8 100644 --- a/clients/cli/common.h +++ b/clients/cli/common.h @@ -35,6 +35,7 @@ NMIPRoute *nmc_parse_and_build_route (int family, const char *first, const char const char * nmc_device_state_to_string (NMDeviceState state); const char * nmc_device_reason_to_string (NMDeviceStateReason reason); +const char * nmc_device_metered_to_string (NMMetered value); char ** nmc_vlan_parse_priority_maps (const char *priority_map, diff --git a/clients/cli/devices.c b/clients/cli/devices.c index 979c5906..c9ff8970 100644 --- a/clients/cli/devices.c +++ b/clients/cli/devices.c @@ -78,11 +78,12 @@ static NmcOutputField nmc_fields_dev_show_general[] = { {"CONNECTION", N_("CONNECTION"), 20}, /* 20 */ {"CON-UUID", N_("CON-UUID"), 38}, /* 21 */ {"CON-PATH", N_("CON-PATH"), 51}, /* 22 */ + {"METERED", N_("METERED"), 10}, /* 23 */ {NULL, NULL, 0} }; #define NMC_FIELDS_DEV_SHOW_GENERAL_ALL "NAME,DEVICE,TYPE,NM-TYPE,VENDOR,PRODUCT,DRIVER,DRIVER-VERSION,FIRMWARE-VERSION,HWADDR,MTU,"\ "STATE,REASON,UDI,IP-IFACE,IS-SOFTWARE,NM-MANAGED,AUTOCONNECT,FIRMWARE-MISSING,PHYS-PORT-ID,"\ - "CONNECTION,CON-UUID,CON-PATH" + "CONNECTION,CON-UUID,CON-PATH,METERED" #define NMC_FIELDS_DEV_SHOW_GENERAL_COMMON "NAME,DEVICE,TYPE,VENDOR,PRODUCT,DRIVER,HWADDR,STATE" /* Available fields for 'device show' - CONNECTIONS part */ @@ -275,8 +276,8 @@ usage (void) " delete <ifname> ...\n\n" " wifi [list [ifname <ifname>] [bssid <BSSID>]]\n\n" " wifi connect <(B)SSID> [password <password>] [wep-key-type key|phrase] [ifname <ifname>]\n" - " [bssid <BSSID>] [name <name>] [private yes|no]\n\n" - " wifi rescan [[ifname] <ifname>]\n\n" + " [bssid <BSSID>] [name <name>] [private yes|no] [hidden yes|no]\n\n" + " wifi rescan [ifname <ifname>] [[ssid <SSID to scan>] ...]\n\n" #if WITH_WIMAX " wimax [list [ifname <ifname>] [nsp <name>]]\n\n" #endif @@ -359,7 +360,7 @@ usage_device_wifi (void) "used to list APs for a particular interface, or with a specific BSSID.\n" "\n" "ARGUMENTS := connect <(B)SSID> [password <password>] [wep-key-type key|phrase] [ifname <ifname>]\n" - " [bssid <BSSID>] [name <name>] [private yes|no]\n" + " [bssid <BSSID>] [name <name>] [private yes|no] [hidden yes|no]\n" "\n" "Connect to a Wi-Fi network specified by SSID or BSSID. The command creates\n" "a new connection and then activates it on a device. This is a command-line\n" @@ -370,12 +371,14 @@ usage_device_wifi (void) "only open, WEP and WPA-PSK networks are supported at the moment. It is also\n" "assumed that IP configuration is obtained via DHCP.\n" "\n" - "ARGUMENTS := rescan [[ifname] <ifname>]\n" + "ARGUMENTS := rescan [ifname <ifname>] [[ssid <SSID to scan>] ...]\n" "\n" "Request that NetworkManager immediately re-scan for available access points.\n" "NetworkManager scans Wi-Fi networks periodically, but in some cases it might\n" - "be useful to start scanning manually. Note that this command does not show\n" - "the APs, use 'nmcli device wifi list' for that.\n\n")); + "be useful to start scanning manually. 'ssid' allows scanning for a specific\n" + "SSID, which is useful for APs with hidden SSIDs. More 'ssid' parameters can be\n" + "given. Note that this command does not show the APs,\n" + "use 'nmcli device wifi list' for that.\n\n")); } #if WITH_WIMAX @@ -858,6 +861,8 @@ show_device_info (NMDevice *device, NmCli *nmc) set_val_strc (arr, 20, get_active_connection_id (device)); set_val_strc (arr, 21, acon ? nm_active_connection_get_uuid (acon) : NULL); set_val_strc (arr, 22, acon ? nm_object_get_path (NM_OBJECT (acon)) : NULL); + set_val_strc (arr, 23, nmc_device_metered_to_string (nm_device_get_metered (device))); + g_ptr_array_add (nmc->output_data, arr); print_data (nmc); /* Print all data */ @@ -2300,9 +2305,9 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv) { NMDevice *device = NULL; NMAccessPoint *ap = NULL; - NM80211ApFlags ap_flags; - NM80211ApSecurityFlags ap_wpa_flags; - NM80211ApSecurityFlags ap_rsn_flags; + NM80211ApFlags ap_flags = NM_802_11_AP_FLAGS_NONE; + NM80211ApSecurityFlags ap_wpa_flags = NM_802_11_AP_SEC_NONE; + NM80211ApSecurityFlags ap_rsn_flags = NM_802_11_AP_SEC_NONE; NMConnection *connection = NULL; NMSettingConnection *s_con; NMSettingWireless *s_wifi; @@ -2314,6 +2319,7 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv) const char *password = NULL; const char *con_name = NULL; gboolean private = FALSE; + gboolean hidden = FALSE; gboolean wep_passphrase = FALSE; GByteArray *bssid1_arr = NULL; GByteArray *bssid2_arr = NULL; @@ -2413,6 +2419,19 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv) g_clear_error (&err_tmp); goto error; } + } else if (strcmp (*argv, "hidden") == 0) { + GError *err_tmp = NULL; + if (next_arg (&argc, &argv) != 0) { + g_string_printf (nmc->return_text, _("Error: %s argument is missing."), *(argv-1)); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + goto error; + } + if (!nmc_string_to_bool (*argv, &hidden, &err_tmp)) { + g_string_printf (nmc->return_text, _("Error: %s: %s."), *(argv-1), err_tmp->message); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + g_clear_error (&err_tmp); + goto error; + } } else { g_printerr (_("Unknown parameter: %s\n"), *argv); } @@ -2449,14 +2468,41 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv) goto error; } + /* For hidden SSID first scan it so that NM learns about the AP */ + if (hidden) { + GVariantBuilder builder, array_builder; + GVariant *options; + GError *scan_err = NULL; + + g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT); + g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aay")); + g_variant_builder_add (&array_builder, "@ay", + g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, param_user, strlen (param_user), 1)); + g_variant_builder_add (&builder, "{sv}", "ssids", g_variant_builder_end (&array_builder)); + options = g_variant_builder_end (&builder); + + nm_device_wifi_request_scan_options (NM_DEVICE_WIFI (device), options, NULL, &scan_err); + if (scan_err) { + g_string_printf (nmc->return_text, _("Error: Failed to scan hidden SSID: %s."), + scan_err->message); + g_clear_error (&scan_err); + nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND; + goto error; + } + } + /* Find an AP to connect to */ ap = find_ap_on_device (device, bssid1_arr, bssid1_arr ? NULL : param_user); if (!ap && !ifname) { - /* AP not found. ifname 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) + NMDevice *dev; + + /* AP not found, ifname was not specified, so try finding the AP on another device. */ + while ((dev = find_wifi_device_by_iface (devices, NULL, &devices_idx)) != NULL) { + ap = find_ap_on_device (dev, bssid1_arr, bssid1_arr ? NULL : param_user); + if (ap) { + device = dev; break; + } } } @@ -2471,7 +2517,7 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv) /* If there are some connection data from user, create a connection and * fill them into proper settings. */ - if (con_name || private || bssid2_arr || password) + if (con_name || private || bssid2_arr || password || hidden) connection = nm_simple_connection_new (); if (con_name || private) { @@ -2486,12 +2532,24 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv) if (private) nm_setting_connection_add_permission (s_con, "user", g_get_user_name (), NULL); } - if (bssid2_arr) { + if (bssid2_arr || hidden) { 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); + /* 'bssid' parameter is used to restrict the connection only to the BSSID */ + if (bssid2_arr) + g_object_set (s_wifi, NM_SETTING_WIRELESS_BSSID, bssid2_arr, NULL); + + /* 'hidden' parameter is used to indicate that SSID is not broadcasted */ + if (hidden) { + GBytes *ssid = g_bytes_new (param_user, strlen (param_user)); + + g_object_set (s_wifi, + NM_SETTING_WIRELESS_SSID, ssid, + NM_SETTING_WIRELESS_HIDDEN, hidden, + NULL); + g_bytes_unref (ssid); + } } /* handle password */ @@ -2582,21 +2640,44 @@ do_device_wifi_rescan (NmCli *nmc, int argc, char **argv) { NMDevice *device; const char *ifname = NULL; + GPtrArray *ssids; const GPtrArray *devices; int devices_idx; + GVariantBuilder builder, array_builder; + GVariant *options; + const char *ssid; + int i; nmc->should_wait = TRUE; + ssids = g_ptr_array_new (); + /* Get the parameters */ - if (argc > 0) { + while (argc > 0) { if (strcmp (*argv, "ifname") == 0) { + if (ifname) { + g_string_printf (nmc->return_text, _("Error: '%s' cannot repeat."), *(argv-1)); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + goto error; + } if (next_arg (&argc, &argv) != 0) { g_string_printf (nmc->return_text, _("Error: %s argument is missing."), *(argv-1)); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; goto error; } - } - ifname = *argv; + ifname = *argv; + } else if (strcmp (*argv, "ssid") == 0) { + if (next_arg (&argc, &argv) != 0) { + g_string_printf (nmc->return_text, _("Error: %s argument is missing."), *(argv-1)); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + goto error; + } + g_ptr_array_add (ssids, *argv); + } else + g_printerr (_("Unknown parameter: %s\n"), *argv); + + argc--; + argv++; } /* Find Wi-Fi device to scan on. When no ifname is provided, the first Wi-Fi is used. */ @@ -2605,26 +2686,39 @@ do_device_wifi_rescan (NmCli *nmc, int argc, char **argv) device = find_wifi_device_by_iface (devices, ifname, &devices_idx); if (!device) { - if (ifname) { - const char *err_msg; - if ( nm_device_get_device_type (device) == NM_DEVICE_TYPE_GENERIC - && g_strcmp0 (nm_device_get_type_description (device), "wifi") == 0) - err_msg = _("Error: Device '%s' was not recognized as a Wi-Fi device, check NetworkManager Wi-Fi plugin."); - else - err_msg = _("Error: Device '%s' is not a Wi-Fi device."); - g_string_printf (nmc->return_text, err_msg, ifname); - } else + if (ifname) + g_string_printf (nmc->return_text, _("Error: Device '%s' is not a Wi-Fi device."), ifname); + else g_string_printf (nmc->return_text, _("Error: No Wi-Fi device found.")); nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; goto error; } - nm_device_wifi_request_scan_async (NM_DEVICE_WIFI (device), NULL, - request_rescan_cb, nmc); + if (ssids->len) { + g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT); + g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aay")); + + for (i = 0; i < ssids->len; i++) { + ssid = g_ptr_array_index (ssids, i); + g_variant_builder_add (&array_builder, "@ay", + g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, ssid, strlen (ssid), 1)); + } + + g_variant_builder_add (&builder, "{sv}", "ssids", g_variant_builder_end (&array_builder)); + options = g_variant_builder_end (&builder); + + nm_device_wifi_request_scan_options_async (NM_DEVICE_WIFI (device), options, + NULL, request_rescan_cb, nmc); + } else + nm_device_wifi_request_scan_async (NM_DEVICE_WIFI (device), + NULL, request_rescan_cb, nmc); + + g_ptr_array_free (ssids, FALSE); return nmc->return_value; error: nmc->should_wait = FALSE; + g_ptr_array_free (ssids, FALSE); return nmc->return_value; } diff --git a/clients/cli/nmcli-completion b/clients/cli/nmcli-completion index 38d7e585..4146eae0 100644 --- a/clients/cli/nmcli-completion +++ b/clients/cli/nmcli-completion @@ -455,6 +455,7 @@ _nmcli_compl_ARGS() stp| \ hairpin| \ save| \ + hidden| \ private) if [[ "${#words[@]}" -eq 2 ]]; then _nmcli_list "yes no" @@ -539,7 +540,9 @@ _nmcli_compl_ARGS() # remove the options already seen. for i in ${!OPTIONS[*]}; do if [[ "${OPTIONS[$i]}" = "${REMOVE_OPTIONS[0]}" || "${OPTIONS[$i]}" = "${REMOVE_OPTIONS[1]}" ]]; then - unset OPTIONS[$i] + if ! _nmcli_array_has_value OPTIONS_REPEATABLE "${OPTIONS[$i]}" ; then + unset OPTIONS[$i] + fi fi done for i in ${!OPTIONS_MANDATORY[*]}; do @@ -678,7 +681,7 @@ _nmcli() cur='' fi - local OPTIONS_UNKNOWN_OPTION OPTIONS_TYPE OPTIONS_TYPED OPTIONS OPTIONS_MANDATORY COMMAND_ARGS_WAIT_OPTIONS OPTIONS_IP OPTIONS_MANDATORY OPTIONS_NEXT_GROUP + local OPTIONS_UNKNOWN_OPTION OPTIONS_TYPE OPTIONS_TYPED OPTIONS OPTIONS_MANDATORY COMMAND_ARGS_WAIT_OPTIONS OPTIONS_IP OPTIONS_MANDATORY OPTIONS_NEXT_GROUP OPTIONS_REPEATABLE local COMMAND_CONNECTION_TYPE COMMAND_CONNECTION_ID OPTIONS_MANDATORY_IFNAME HELP_ONLY_AS_FIRST local COMMAND_CONNECTION_ACTIVE="" @@ -1248,13 +1251,14 @@ _nmcli() fi else _nmcli_array_delete_at words 0 3 - local OPTIONS=(password wep-key-type ifname bssid name private) + local OPTIONS=(password wep-key-type ifname bssid name private hidden) _nmcli_compl_ARGS fi ;; r|re|res|resc|resca|rescan) _nmcli_array_delete_at words 0 2 - OPTIONS=(ifname) + OPTIONS_REPEATABLE=(ssid) + OPTIONS=(ifname ssid) _nmcli_compl_ARGS ;; esac diff --git a/clients/cli/settings-docs.c b/clients/cli/settings-docs.c index 2ed41cb8..d48d4b08 100644 --- a/clients/cli/settings-docs.c +++ b/clients/cli/settings-docs.c @@ -99,6 +99,8 @@ NmcPropertyDesc setting_802_3_ethernet[] = { { "s390-options", "Dictionary of key/value pairs of s390-specific device options. Both keys and values must be strings. Allowed keys include \"portno\", \"layer2\", \"portname\", \"protocol\", among others. Key names must contain only alphanumeric characters (ie, [a-zA-Z0-9])." }, { "s390-subchannels", "Identifies specific subchannels that this network device uses for communication with z/VM or s390 host. Like the \"mac-address\" property for non-z/VM devices, this property can be used to ensure this connection only applies to the network device that uses these subchannels. The list should contain exactly 3 strings, and each string may only be composed of hexadecimal characters and the period (.) character." }, { "speed", "If non-zero, request that the device use only the specified speed. In Mbit/s, ie 100 == 100Mbit/s." }, + { "wake-on-lan", "The NMSettingWiredWakeOnLan options to enable. Not all devices support all options. May be any combination of NM_SETTING_WIRED_WAKE_ON_LAN_PHY (0x2), NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST (0x4), NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST (0x8), NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST (0x10), NM_SETTING_WIRED_WAKE_ON_LAN_ARP (0x20), NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC (0x40)." }, + { "wake-on-lan-password", "If specified, the password used with magic-packet-based Wake-on-LAN, represented as an Ethernet MAC address. If NULL, no password will be required." }, }; NmcPropertyDesc setting_adsl[] = { @@ -157,6 +159,7 @@ NmcPropertyDesc setting_connection[] = { { "id", "A human readable unique identifier for the connection, like \"Work Wi-Fi\" or \"T-Mobile 3G\"." }, { "interface-name", "The name of the network interface this connection is bound to. If not set, then the connection can be attached to any interface of the appropriate type (subject to restrictions imposed by other settings). For software devices this specifies the name of the created device. For connection types where interface names cannot easily be made persistent (e.g. mobile broadband or USB Ethernet), this property should not be used. Setting this property restricts the interfaces a connection can be used with, and if interface names change or are reordered the connection may be applied to the wrong interface." }, { "master", "Interface name of the master device or UUID of the master connection." }, + { "metered", "Whether the connection is metered." }, { "name", "The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example \"ppp\" or \"wireless\" or \"wired\"." }, { "permissions", "An array of strings defining what access a given user has to this connection. If this is NULL or empty, all users are allowed to access this connection. Otherwise a user is allowed to access this connection if and only if they are in this list. Each entry is of the form \"[type]:[id]:[reserved]\"; for example, \"user:dcbw:blah\". At this time only the \"user\" [type] is allowed. Any other values are ignored and reserved for future use. [id] is the username that this permission refers to, which may not contain the \":\" character. Any [reserved] information present must be ignored and is reserved for future use. All of [type], [id], and [reserved] must be valid UTF-8." }, { "read-only", "FALSE if the connection can be modified using the provided settings service's D-Bus interface with the right privileges, or TRUE if the connection is read-only and cannot be modified." }, @@ -335,14 +338,14 @@ NmcSettingDesc all_settings[] = { { "802-11-wireless", setting_802_11_wireless, 14 }, { "802-11-wireless-security", setting_802_11_wireless_security, 18 }, { "802-1x", setting_802_1x, 33 }, - { "802-3-ethernet", setting_802_3_ethernet, 12 }, + { "802-3-ethernet", setting_802_3_ethernet, 14 }, { "adsl", setting_adsl, 8 }, { "bluetooth", setting_bluetooth, 3 }, { "bond", setting_bond, 2 }, { "bridge", setting_bridge, 8 }, { "bridge-port", setting_bridge_port, 4 }, { "cdma", setting_cdma, 5 }, - { "connection", setting_connection, 16 }, + { "connection", setting_connection, 17 }, { "dcb", setting_dcb, 16 }, { "generic", setting_generic, 1 }, { "gsm", setting_gsm, 10 }, diff --git a/clients/cli/settings.c b/clients/cli/settings.c index 66e6f622..8c4af22d 100644 --- a/clients/cli/settings.c +++ b/clients/cli/settings.c @@ -30,6 +30,7 @@ #include "settings.h" #include "nm-glib-compat.h" #include "nm-macros-internal.h" +#include "gsystem-local-alloc.h" /* Forward declarations */ static char *wep_key_type_to_string (NMWepKeyType type); @@ -60,6 +61,7 @@ NmcOutputField nmc_fields_setting_connection[] = { SETTING_FIELD (NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES, 13), /* 13 */ SETTING_FIELD (NM_SETTING_CONNECTION_SECONDARIES, 40), /* 14 */ SETTING_FIELD (NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT, 30), /* 15 */ + SETTING_FIELD (NM_SETTING_CONNECTION_METERED, 10), /* 16 */ {NULL, NULL, 0, NULL, FALSE, FALSE, 0} }; #define NMC_FIELDS_SETTING_CONNECTION_ALL "name"","\ @@ -77,7 +79,8 @@ NmcOutputField nmc_fields_setting_connection[] = { NM_SETTING_CONNECTION_SLAVE_TYPE","\ NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES","\ NM_SETTING_CONNECTION_SECONDARIES","\ - NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT + NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT","\ + NM_SETTING_CONNECTION_METERED #define NMC_FIELDS_SETTING_CONNECTION_COMMON NMC_FIELDS_SETTING_CONNECTION_ALL /* Available fields for NM_SETTING_WIRED_SETTING_NAME */ @@ -94,6 +97,8 @@ NmcOutputField nmc_fields_setting_wired[] = { SETTING_FIELD (NM_SETTING_WIRED_S390_SUBCHANNELS, 20), /* 9 */ SETTING_FIELD (NM_SETTING_WIRED_S390_NETTYPE, 15), /* 10 */ SETTING_FIELD (NM_SETTING_WIRED_S390_OPTIONS, 20), /* 11 */ + SETTING_FIELD (NM_SETTING_WIRED_WAKE_ON_LAN, 10), /* 12 */ + SETTING_FIELD (NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD, 20), /* 13 */ {NULL, NULL, 0, NULL, FALSE, FALSE, 0} }; #define NMC_FIELDS_SETTING_WIRED_ALL "name"","\ @@ -107,7 +112,9 @@ NmcOutputField nmc_fields_setting_wired[] = { NM_SETTING_WIRED_MTU","\ NM_SETTING_WIRED_S390_SUBCHANNELS","\ NM_SETTING_WIRED_S390_NETTYPE","\ - NM_SETTING_WIRED_S390_OPTIONS + NM_SETTING_WIRED_S390_OPTIONS","\ + NM_SETTING_WIRED_WAKE_ON_LAN","\ + NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD #define NMC_FIELDS_SETTING_WIRED_COMMON NMC_FIELDS_SETTING_WIRED_ALL /* Available fields for NM_SETTING_802_1X_SETTING_NAME */ @@ -1497,6 +1504,7 @@ DEFINE_GETTER (nmc_property_wired_get_mac_address_blacklist, NM_SETTING_WIRED_MA DEFINE_GETTER (nmc_property_wired_get_s390_subchannels, NM_SETTING_WIRED_S390_SUBCHANNELS) DEFINE_GETTER (nmc_property_wired_get_s390_nettype, NM_SETTING_WIRED_S390_NETTYPE) DEFINE_GETTER (nmc_property_wired_get_s390_options, NM_SETTING_WIRED_S390_OPTIONS) +DEFINE_GETTER (nmc_property_wired_get_wake_on_lan_password, NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD) static char * nmc_property_wired_get_mtu (NMSetting *setting, NmcPropertyGetType get_type) @@ -1511,6 +1519,45 @@ nmc_property_wired_get_mtu (NMSetting *setting, NmcPropertyGetType get_type) return g_strdup_printf ("%d", mtu); } +static char * +nmc_property_wired_get_wake_on_lan (NMSetting *setting, NmcPropertyGetType get_type) +{ + NMSettingWired *s_wired = NM_SETTING_WIRED (setting); + NMSettingWiredWakeOnLan wol; + + wol = nm_setting_wired_get_wake_on_lan (s_wired); + return nm_utils_enum_to_str (nm_setting_wired_wake_on_lan_get_type (), wol); +} + +static gboolean +nmc_property_wired_set_wake_on_lan (NMSetting *setting, const char *prop, + const char *val, GError **error) +{ + NMSettingWiredWakeOnLan wol; + gs_free char *err_token = NULL; + gboolean ret; + + ret = nm_utils_enum_from_str (nm_setting_wired_wake_on_lan_get_type (), val, + (int *) &wol, &err_token); + + if (!ret) { + g_set_error (error, 1, 0, _("invalid option '%s', use a combination of %s or 'default'"), + err_token, + nm_utils_enum_to_str (nm_setting_wired_wake_on_lan_get_type (), + NM_SETTING_WIRED_WAKE_ON_LAN_ALL)); + return FALSE; + } + + if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT) && + NM_FLAGS_ANY (wol, NM_SETTING_WIRED_WAKE_ON_LAN_ALL)) { + g_set_error_literal (error, 1, 0, _("'default' is incompatible with other flags")); + return FALSE; + } + + g_object_set (setting, prop, (guint) wol, NULL); + return TRUE; +} + /* --- NM_SETTING_WIRELESS_SETTING_NAME property get functions --- */ DEFINE_GETTER (nmc_property_wireless_get_mode, NM_SETTING_WIRELESS_MODE) DEFINE_GETTER (nmc_property_wireless_get_band, NM_SETTING_WIRELESS_BAND) @@ -2034,6 +2081,46 @@ validate_uint (NMSetting *setting, const char* prop, guint val, GError **error) return success; } +static char * +flag_values_to_string (GFlagsValue *array, guint n) +{ + GString *str; + guint i; + + str = g_string_new (NULL); + for (i = 0; i < n; i++) + g_string_append_printf (str, "%u, ", array[i].value); + if (str->len) + g_string_truncate (str, str->len-2); /* chop off trailing ', ' */ + return g_string_free (str, FALSE); +} + +static gboolean +validate_flags (NMSetting *setting, const char* prop, guint val, GError **error) +{ + GParamSpec *pspec; + GValue value = G_VALUE_INIT; + gboolean success = TRUE; + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (setting)), prop); + g_assert (G_IS_PARAM_SPEC (pspec)); + + g_value_init (&value, pspec->value_type); + g_value_set_flags (&value, val); + + if (g_param_value_validate (pspec, &value)) { + GParamSpecFlags *pspec_flags = (GParamSpecFlags *) pspec; + char *flag_values = flag_values_to_string (pspec_flags->flags_class->values, + pspec_flags->flags_class->n_values); + g_set_error (error, 1, 0, _("'%u' flags are not valid; use combination of %s"), + val, flag_values); + g_free (flag_values); + success = FALSE; + } + g_value_unset (&value); + return success; +} + static gboolean check_and_set_string (NMSetting *setting, const char *prop, @@ -2257,6 +2344,26 @@ nmc_property_set_int64 (NMSetting *setting, const char *prop, const char *val, G } static gboolean +nmc_property_set_flags (NMSetting *setting, const char *prop, const char *val, GError **error) +{ + unsigned long val_int; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (!nmc_string_to_uint (val, TRUE, 0, G_MAXUINT, &val_int)) { + g_set_error (error, 1, 0, _("'%s' is not a valid number (or out of range)"), val); + return FALSE; + } + + /* Validate the flags according to the property spec */ + if (!validate_flags (setting, prop, (guint) val_int, error)) + return FALSE; + + g_object_set (setting, prop, (guint) val_int, NULL); + return TRUE; +} + +static gboolean nmc_property_set_bool (NMSetting *setting, const char *prop, const char *val, GError **error) { gboolean val_bool; @@ -2684,6 +2791,62 @@ nmc_property_connection_describe_secondaries (NMSetting *setting, const char *pr "Example: private-openvpn, fe6ba5d8-c2fc-4aae-b2e3-97efddd8d9a7\n"); } +/* 'metered' */ +static char * +nmc_property_connection_get_metered (NMSetting *setting, NmcPropertyGetType get_type) +{ + NMSettingConnection *s_conn = NM_SETTING_CONNECTION (setting); + + if (get_type == NMC_PROPERTY_GET_PARSABLE) { + switch (nm_setting_connection_get_metered (s_conn)) { + case NM_METERED_YES: + return g_strdup ("yes"); + case NM_METERED_NO: + return g_strdup ("no"); + case NM_METERED_UNKNOWN: + default: + return g_strdup ("unknown"); + } + } + switch (nm_setting_connection_get_metered (s_conn)) { + case NM_METERED_YES: + return g_strdup (_("yes")); + case NM_METERED_NO: + return g_strdup (_("no")); + case NM_METERED_UNKNOWN: + default: + return g_strdup (_("unknown")); + } +} + +static gboolean +nmc_property_connection_set_metered (NMSetting *setting, const char *prop, + const char *val, GError **error) +{ + NMMetered metered; + NMCTriStateValue ts_val; + + if (!nmc_string_to_tristate (val, &ts_val, error)) + return FALSE; + + switch (ts_val) { + case NMC_TRI_STATE_YES: + metered = NM_METERED_YES; + break; + case NMC_TRI_STATE_NO: + metered = NM_METERED_NO; + break; + case NMC_TRI_STATE_UNKNOWN: + metered = NM_METERED_UNKNOWN; + break; + default: + g_assert_not_reached(); + } + + g_object_set (setting, prop, metered, NULL); + return TRUE; +} + /* --- NM_SETTING_802_1X_SETTING_NAME property setter functions --- */ #define DEFINE_SETTER_STR_LIST(def_func, set_func) \ static gboolean \ @@ -4495,8 +4658,8 @@ nmc_property_dcb_set_flags (NMSetting *setting, const char *prop, const char *va g_strfreev (strv); } - /* Validate the number according to the property spec */ - if (!validate_uint (setting, prop, (guint) flags, error)) + /* Validate the flags according to the property spec */ + if (!validate_flags (setting, prop, (guint) flags, error)) return FALSE; g_object_set (setting, prop, (guint) flags, NULL); @@ -5264,6 +5427,13 @@ nmc_properties_init (void) NULL, NULL, NULL); + nmc_add_prop_funcs (GLUE (CONNECTION, METERED), + nmc_property_connection_get_metered, + nmc_property_connection_set_metered, + NULL, + NULL, + NULL, + NULL); /* Add editable properties for NM_SETTING_DCB_SETTING_NAME */ nmc_add_prop_funcs (GLUE (DCB, APP_FCOE_FLAGS), @@ -5927,7 +6097,7 @@ nmc_properties_init (void) NULL); nmc_add_prop_funcs (GLUE (VLAN, FLAGS), nmc_property_vlan_get_flags, - nmc_property_set_uint, + nmc_property_set_flags, NULL, NULL, NULL, @@ -6078,6 +6248,20 @@ nmc_properties_init (void) nmc_property_wired_describe_s390_options, nmc_property_wired_allowed_s390_options, NULL); + nmc_add_prop_funcs (GLUE (WIRED, WAKE_ON_LAN), + nmc_property_wired_get_wake_on_lan, + nmc_property_wired_set_wake_on_lan, + NULL, + NULL, + NULL, + NULL); + nmc_add_prop_funcs (GLUE (WIRED, WAKE_ON_LAN_PASSWORD), + nmc_property_wired_get_wake_on_lan_password, + nmc_property_set_mac, + NULL, + NULL, + NULL, + NULL); /* Add editable properties for NM_SETTING_WIRELESS_SETTING_NAME */ nmc_add_prop_funcs (GLUE (WIRELESS, SSID), @@ -6624,6 +6808,7 @@ setting_connection_details (NMSetting *setting, NmCli *nmc, const char *one_pro set_val_str (arr, 13, nmc_property_connection_get_autoconnect_slaves (setting, NMC_PROPERTY_GET_PRETTY)); set_val_str (arr, 14, nmc_property_connection_get_secondaries (setting, NMC_PROPERTY_GET_PRETTY)); set_val_str (arr, 15, nmc_property_connection_get_gateway_ping_timeout (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 16, nmc_property_connection_get_metered (setting, NMC_PROPERTY_GET_PRETTY)); g_ptr_array_add (nmc->output_data, arr); print_data (nmc); /* Print all data */ @@ -6660,6 +6845,8 @@ setting_wired_details (NMSetting *setting, NmCli *nmc, const char *one_prop, gb set_val_str (arr, 9, nmc_property_wired_get_s390_subchannels (setting, NMC_PROPERTY_GET_PRETTY)); set_val_str (arr, 10, nmc_property_wired_get_s390_nettype (setting, NMC_PROPERTY_GET_PRETTY)); set_val_str (arr, 11, nmc_property_wired_get_s390_options (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 12, nmc_property_wired_get_wake_on_lan (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 13, nmc_property_wired_get_wake_on_lan_password (setting, NMC_PROPERTY_GET_PRETTY)); g_ptr_array_add (nmc->output_data, arr); print_data (nmc); /* Print all data */ diff --git a/clients/cli/utils.c b/clients/cli/utils.c index dfd002ed..3cc836d8 100644 --- a/clients/cli/utils.c +++ b/clients/cli/utils.c @@ -407,7 +407,10 @@ nmc_string_to_bool (const char *str, gboolean *val_bool, GError **error) if (g_strcmp0 (str, "o") == 0) { g_set_error (error, 1, 0, - _("'%s' is ambiguous (on x off)"), str); + /* Translators: the first %s is the partial value entered by + * the user, the second %s a list of compatible values. + */ + _("'%s' is ambiguous (%s)"), str, "on x off"); return FALSE; } @@ -424,6 +427,39 @@ nmc_string_to_bool (const char *str, gboolean *val_bool, GError **error) return TRUE; } +gboolean +nmc_string_to_tristate (const char *str, NMCTriStateValue *val, GError **error) +{ + const char *s_true[] = { "true", "yes", "on", NULL }; + const char *s_false[] = { "false", "no", "off", NULL }; + const char *s_unknown[] = { "unknown", NULL }; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (g_strcmp0 (str, "o") == 0) { + g_set_error (error, 1, 0, + /* Translators: the first %s is the partial value entered by + * the user, the second %s a list of compatible values. + */ + _("'%s' is ambiguous (%s)"), str, "on x off"); + return FALSE; + } + + if (nmc_string_is_valid (str, s_true, NULL)) + *val = NMC_TRI_STATE_YES; + else if (nmc_string_is_valid (str, s_false, NULL)) + *val = NMC_TRI_STATE_NO; + else if (nmc_string_is_valid (str, s_unknown, NULL)) + *val = NMC_TRI_STATE_UNKNOWN; + else { + g_set_error (error, 1, 0, + _("'%s' is not valid; use [%s], [%s] or [%s]"), + str, "true, yes, on", "false, no, off", "unknown"); + return FALSE; + } + return TRUE; +} + /* * Ask user for input and return the string. * The caller is responsible for freeing the returned string. diff --git a/clients/cli/utils.h b/clients/cli/utils.h index 77e697af..ba649f8f 100644 --- a/clients/cli/utils.h +++ b/clients/cli/utils.h @@ -32,6 +32,12 @@ typedef struct { gboolean found; } nmc_arg_t; +typedef enum { + NMC_TRI_STATE_NO, + NMC_TRI_STATE_YES, + NMC_TRI_STATE_UNKNOWN, +} NMCTriStateValue; + /* === Functions === */ int matches (const char *cmd, const char *pattern); int next_arg (int *argc, char ***argv); @@ -62,6 +68,7 @@ gboolean nmc_string_to_uint (const char *str, unsigned long int max, unsigned long int *value); gboolean nmc_string_to_bool (const char *str, gboolean *val_bool, GError **error); +gboolean nmc_string_to_tristate (const char *str, NMCTriStateValue *val, GError **error); char *nmc_ip4_address_as_string (guint32 ip, GError **error); char *nmc_ip6_address_as_string (const struct in6_addr *ip, GError **error); void nmc_terminal_erase_line (void); |