diff options
Diffstat (limited to 'clients/common/nm-client-utils.c')
| -rw-r--r-- | clients/common/nm-client-utils.c | 886 |
1 files changed, 0 insertions, 886 deletions
diff --git a/clients/common/nm-client-utils.c b/clients/common/nm-client-utils.c deleted file mode 100644 index 0e1a6bf5..00000000 --- a/clients/common/nm-client-utils.c +++ /dev/null @@ -1,886 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2010 - 2017 Red Hat, Inc. - */ - -#include "libnm/nm-default-client.h" - -#include "nm-client-utils.h" - -#include "nm-glib-aux/nm-secret-utils.h" -#include "nm-glib-aux/nm-io-utils.h" -#include "nm-utils.h" -#include "nm-device-bond.h" -#include "nm-device-bridge.h" -#include "nm-device-team.h" - -/*****************************************************************************/ - -static int -_nmc_objects_sort_by_path_cmp(gconstpointer pa, gconstpointer pb, gpointer user_data) -{ - NMObject *a = *((NMObject **) pa); - NMObject *b = *((NMObject **) pb); - - NM_CMP_SELF(a, b); - NM_CMP_RETURN(nm_utils_dbus_path_cmp(nm_object_get_path(a), nm_object_get_path(b))); - return 0; -} - -const NMObject ** -nmc_objects_sort_by_path(const NMObject *const *objs, gssize len) -{ - const NMObject **arr; - gsize i, l; - - if (len < 0) - l = NM_PTRARRAY_LEN(objs); - else - l = len; - - arr = g_new(const NMObject *, l + 1); - for (i = 0; i < l; i++) - arr[i] = objs[i]; - arr[l] = NULL; - - if (l > 1) { - g_qsort_with_data(arr, l, sizeof(gpointer), _nmc_objects_sort_by_path_cmp, NULL); - } - return arr; -} - -/*****************************************************************************/ -/* - * Convert string to unsigned integer. - * If required, the resulting number is checked to be in the <min,max> range. - */ -static gboolean -nmc_string_to_uint_base(const char * str, - int base, - gboolean range_check, - unsigned long int min, - unsigned long int max, - unsigned long int *value) -{ - char * end; - unsigned long int tmp; - - if (!str || !str[0]) - return FALSE; - - /* FIXME: don't use this function, replace by _nm_utils_ascii_str_to_int64() */ - errno = 0; - tmp = strtoul(str, &end, base); - if (errno || *end != '\0' || (range_check && (tmp < min || tmp > max))) { - return FALSE; - } - *value = tmp; - return TRUE; -} - -gboolean -nmc_string_to_uint(const char * str, - gboolean range_check, - unsigned long int min, - unsigned long int max, - unsigned long int *value) -{ - return nmc_string_to_uint_base(str, 10, range_check, min, max, value); -} - -gboolean -nmc_string_to_bool(const char *str, gboolean *val_bool, GError **error) -{ - const char *s_true[] = {"true", "yes", "on", "1", NULL}; - const char *s_false[] = {"false", "no", "off", "0", 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_bool = TRUE; - else if (nmc_string_is_valid(str, s_false, NULL)) - *val_bool = FALSE; - else { - g_set_error(error, - 1, - 0, - _("'%s' is not valid; use [%s] or [%s]"), - str, - "true, yes, on", - "false, no, off"); - return FALSE; - } - return TRUE; -} - -gboolean -nmc_string_to_ternary(const char *str, NMTernary *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 = NM_TERNARY_TRUE; - else if (nmc_string_is_valid(str, s_false, NULL)) - *val = NM_TERNARY_FALSE; - else if (nmc_string_is_valid(str, s_unknown, NULL)) - *val = NM_TERNARY_DEFAULT; - 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; -} - -/* - * Check whether 'input' is contained in 'allowed' array. It performs case - * insensitive comparison and supports shortcut strings if they are unique. - * Returns: a pointer to found string in allowed array on success or NULL. - * On failure: error->code : 0 - string not found; 1 - string is ambiguous - */ -const char * -nmc_string_is_valid(const char *input, const char **allowed, GError **error) -{ - const char **p; - size_t input_ln, p_len; - const char * partial_match = NULL; - gboolean ambiguous = FALSE; - - g_return_val_if_fail(!error || !*error, NULL); - - if (!input || !*input) - goto finish; - - input_ln = strlen(input); - for (p = allowed; p && *p; p++) { - p_len = strlen(*p); - if (g_ascii_strncasecmp(input, *p, input_ln) == 0) { - if (input_ln == p_len) - return *p; - if (!partial_match) - partial_match = *p; - else - ambiguous = TRUE; - } - } - - if (ambiguous) { - GString *candidates = g_string_new(""); - - for (p = allowed; *p; p++) { - if (g_ascii_strncasecmp(input, *p, input_ln) == 0) { - if (candidates->len > 0) - g_string_append(candidates, ", "); - g_string_append(candidates, *p); - } - } - g_set_error(error, 1, 1, _("'%s' is ambiguous: %s"), input, candidates->str); - g_string_free(candidates, TRUE); - return NULL; - } -finish: - if (!partial_match) { - char *valid_vals = g_strjoinv(", ", (char **) allowed); - - if (!input || !*input) - g_set_error(error, 1, 0, _("missing name, try one of [%s]"), valid_vals); - else - g_set_error(error, 1, 0, _("'%s' not among [%s]"), input, valid_vals); - - g_free(valid_vals); - } - - return partial_match; -} - -gboolean -matches(const char *cmd, const char *pattern) -{ - size_t len = strlen(cmd); - if (!len || len > strlen(pattern)) - return FALSE; - return memcmp(pattern, cmd, len) == 0; -} - -const char * -nmc_bond_validate_mode(const char *mode, GError **error) -{ - unsigned long mode_int; - static const char *valid_modes[] = {"balance-rr", - "active-backup", - "balance-xor", - "broadcast", - "802.3ad", - "balance-tlb", - "balance-alb", - NULL}; - if (nmc_string_to_uint(mode, TRUE, 0, 6, &mode_int)) { - /* Translate bonding mode numbers to mode names: - * https://www.kernel.org/doc/Documentation/networking/bonding.txt - */ - return valid_modes[mode_int]; - } else - return nmc_string_is_valid(mode, valid_modes, error); -} - -NM_UTILS_LOOKUP_STR_DEFINE( - nmc_device_state_to_string, - NMDeviceState, - NM_UTILS_LOOKUP_DEFAULT(N_("unknown")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_UNMANAGED, N_("unmanaged")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_UNAVAILABLE, N_("unavailable")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_DISCONNECTED, N_("disconnected")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_PREPARE, N_("connecting (prepare)")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_CONFIG, N_("connecting (configuring)")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_NEED_AUTH, N_("connecting (need authentication)")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_IP_CONFIG, N_("connecting (getting IP configuration)")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_IP_CHECK, N_("connecting (checking IP connectivity)")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_SECONDARIES, - N_("connecting (starting secondary connections)")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_ACTIVATED, N_("connected")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_DEACTIVATING, N_("deactivating")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_FAILED, N_("connection failed")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_UNKNOWN, N_("unknown")), ); - -static NM_UTILS_LOOKUP_STR_DEFINE( - _device_state_to_string, - NMDeviceState, - NM_UTILS_LOOKUP_DEFAULT(NULL), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_PREPARE, N_("connecting (externally)")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_CONFIG, N_("connecting (externally)")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_NEED_AUTH, N_("connecting (externally)")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_IP_CONFIG, N_("connecting (externally)")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_IP_CHECK, N_("connecting (externally)")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_SECONDARIES, N_("connecting (externally)")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_ACTIVATED, N_("connected (externally)")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_DEACTIVATING, N_("deactivating (externally)")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_FAILED, N_("deactivating (externally)")), - NM_UTILS_LOOKUP_ITEM_IGNORE_OTHER(), ); - -const char * -nmc_device_state_to_string_with_external(NMDevice *device) -{ - NMActiveConnection *ac; - NMDeviceState state; - const char * s; - - state = nm_device_get_state(device); - - if ((ac = nm_device_get_active_connection(device)) - && NM_FLAGS_HAS(nm_active_connection_get_state_flags(ac), NM_ACTIVATION_STATE_FLAG_EXTERNAL) - && (s = _device_state_to_string(state))) - return s; - - return nmc_device_state_to_string(state); -} - -NM_UTILS_LOOKUP_STR_DEFINE(nmc_device_metered_to_string, - NMMetered, - NM_UTILS_LOOKUP_DEFAULT(N_("unknown")), - NM_UTILS_LOOKUP_ITEM(NM_METERED_YES, N_("yes")), - NM_UTILS_LOOKUP_ITEM(NM_METERED_NO, N_("no")), - NM_UTILS_LOOKUP_ITEM(NM_METERED_GUESS_YES, N_("yes (guessed)")), - NM_UTILS_LOOKUP_ITEM(NM_METERED_GUESS_NO, N_("no (guessed)")), - NM_UTILS_LOOKUP_ITEM(NM_METERED_UNKNOWN, N_("unknown")), ); - -NM_UTILS_LOOKUP_STR_DEFINE( - nmc_device_reason_to_string, - NMDeviceStateReason, - /* TRANSLATORS: Unknown reason for a device state change (NMDeviceStateReason) */ - NM_UTILS_LOOKUP_DEFAULT(N_("Unknown")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_NONE, N_("No reason given")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_UNKNOWN, N_("Unknown error")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_NOW_MANAGED, N_("Device is now managed")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_NOW_UNMANAGED, N_("Device is now unmanaged")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_CONFIG_FAILED, - N_("The device could not be readied for configuration")), - NM_UTILS_LOOKUP_ITEM( - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE, - N_("IP configuration could not be reserved (no available address, timeout, etc.)")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED, - N_("The IP configuration is no longer valid")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_NO_SECRETS, - N_("Secrets were required, but not provided")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT, - N_("802.1X supplicant disconnected")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED, - N_("802.1X supplicant configuration failed")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED, N_("802.1X supplicant failed")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT, - N_("802.1X supplicant took too long to authenticate")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_PPP_START_FAILED, - N_("PPP service failed to start")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_PPP_DISCONNECT, N_("PPP service disconnected")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_PPP_FAILED, N_("PPP failed")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_DHCP_START_FAILED, - N_("DHCP client failed to start")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_DHCP_ERROR, N_("DHCP client error")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_DHCP_FAILED, N_("DHCP client failed")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_SHARED_START_FAILED, - N_("Shared connection service failed to start")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_SHARED_FAILED, - N_("Shared connection service failed")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED, - N_("AutoIP service failed to start")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_AUTOIP_ERROR, N_("AutoIP service error")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_AUTOIP_FAILED, N_("AutoIP service failed")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_MODEM_BUSY, N_("The line is busy")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE, N_("No dial tone")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER, - N_("No carrier could be established")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT, - N_("The dialing request timed out")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED, - N_("The dialing attempt failed")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED, - N_("Modem initialization failed")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_GSM_APN_FAILED, - N_("Failed to select the specified APN")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING, - N_("Not searching for networks")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED, - N_("Network registration denied")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT, - N_("Network registration timed out")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED, - N_("Failed to register with the requested network")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED, N_("PIN check failed")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_FIRMWARE_MISSING, - N_("Necessary firmware for the device may be missing")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_REMOVED, N_("The device was removed")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_SLEEPING, N_("NetworkManager went to sleep")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_CONNECTION_REMOVED, - N_("The device's active connection disappeared")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_USER_REQUESTED, - N_("Device disconnected by user or client")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_CARRIER, N_("Carrier/link changed")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED, - N_("The device's existing connection was assumed")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, - N_("The supplicant is now available")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND, - N_("The modem could not be found")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_BT_FAILED, - N_("The Bluetooth connection failed or timed out")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED, - N_("GSM Modem's SIM card not inserted")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED, - N_("GSM Modem's SIM PIN required")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED, - N_("GSM Modem's SIM PUK required")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_GSM_SIM_WRONG, N_("GSM Modem's SIM wrong")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_INFINIBAND_MODE, - N_("InfiniBand device does not support connected mode")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED, - N_("A dependency of the connection failed")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_BR2684_FAILED, - N_("A problem with the RFC 2684 Ethernet over ADSL bridge")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE, - N_("ModemManager is unavailable")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_SSID_NOT_FOUND, - N_("The Wi-Fi network could not be found")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED, - N_("A secondary connection of the base connection failed")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED, N_("DCB or FCoE setup failed")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED, N_("teamd control failed")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_MODEM_FAILED, - N_("Modem failed or no longer available")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_MODEM_AVAILABLE, - N_("Modem now ready and available")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT, N_("SIM PIN was incorrect")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_NEW_ACTIVATION, - N_("New connection activation was enqueued")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_PARENT_CHANGED, N_("The device's parent changed")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED, - N_("The device parent's management changed")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_OVSDB_FAILED, - N_("Open vSwitch database connection failed")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE, - N_("A duplicate IP address was detected")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED, - N_("The selected IP method is not supported")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED, - N_("Failed to configure SR-IOV parameters")), - NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_PEER_NOT_FOUND, - N_("The Wi-Fi P2P peer could not be found")), ); - -NM_UTILS_LOOKUP_STR_DEFINE( - nm_active_connection_state_reason_to_string, - NMActiveConnectionStateReason, - /* TRANSLATORS: Unknown reason for a connection state change (NMActiveConnectionStateReason) */ - NM_UTILS_LOOKUP_DEFAULT(N_("Unknown")), - NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN, N_("Unknown reason")), - NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_NONE, - N_("The connection was disconnected")), - NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_USER_DISCONNECTED, - N_("Disconnected by user")), - NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED, - N_("The base network connection was interrupted")), - NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_STOPPED, - N_("The VPN service stopped unexpectedly")), - NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_IP_CONFIG_INVALID, - N_("The VPN service returned invalid configuration")), - NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_CONNECT_TIMEOUT, - N_("The connection attempt timed out")), - NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT, - N_("The VPN service did not start in time")), - NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_FAILED, - N_("The VPN service failed to start")), - NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_NO_SECRETS, N_("No valid secrets")), - NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_LOGIN_FAILED, N_("Invalid secrets")), - NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_CONNECTION_REMOVED, - N_("The connection was removed")), - NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_DEPENDENCY_FAILED, - N_("Master connection failed")), - NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REALIZE_FAILED, - N_("Could not create a software link")), - NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REMOVED, - N_("The device disappeared")), ); - -NMActiveConnectionState -nmc_activation_get_effective_state(NMActiveConnection *active, - NMDevice * device, - const char ** reason) -{ - NMActiveConnectionState ac_state; - NMActiveConnectionStateReason ac_reason; - NMDeviceState dev_state = NM_DEVICE_STATE_UNKNOWN; - NMDeviceStateReason dev_reason = NM_DEVICE_STATE_REASON_UNKNOWN; - - g_return_val_if_fail(active, NM_ACTIVE_CONNECTION_STATE_UNKNOWN); - g_return_val_if_fail(reason, NM_ACTIVE_CONNECTION_STATE_UNKNOWN); - - *reason = NULL; - ac_reason = nm_active_connection_get_state_reason(active); - - if (device) { - dev_state = nm_device_get_state(device); - dev_reason = nm_device_get_state_reason(device); - } - - ac_state = nm_active_connection_get_state(active); - switch (ac_state) { - case NM_ACTIVE_CONNECTION_STATE_DEACTIVATED: - if (!device || ac_reason != NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED - || nm_device_get_active_connection(device) != active) { - /* (1) - * - we have no device, - * - or, @ac_reason is specific - * - or, @device no longer references the current @active - * >> we complete with @ac_reason. */ - *reason = gettext(nm_active_connection_state_reason_to_string(ac_reason)); - } else if (dev_state <= NM_DEVICE_STATE_DISCONNECTED - || dev_state >= NM_DEVICE_STATE_FAILED) { - /* (2) - * - not (1) - * - and, the device is no longer in an activated state, - * >> we complete with @dev_reason. */ - *reason = gettext(nmc_device_reason_to_string(dev_reason)); - } else { - /* (3) - * we wait for the device go disconnect. We will get a better - * failure reason from the device (2). */ - return NM_ACTIVE_CONNECTION_STATE_UNKNOWN; - } - break; - case NM_ACTIVE_CONNECTION_STATE_ACTIVATING: - /* activating master connection does not automatically activate any slaves, so their - * active connection state will not progress beyond ACTIVATING state. - * Monitor the device instead. */ - if (device - && (NM_IS_DEVICE_BOND(device) || NM_IS_DEVICE_TEAM(device) - || NM_IS_DEVICE_BRIDGE(device)) - && dev_state >= NM_DEVICE_STATE_IP_CONFIG && dev_state <= NM_DEVICE_STATE_ACTIVATED) { - *reason = "master waiting for slaves"; - return NM_ACTIVE_CONNECTION_STATE_ACTIVATED; - } - break; - default: - break; - } - - return ac_state; -} - -static gboolean -can_show_utf8(void) -{ - static gboolean can_show_utf8_set = FALSE; - static gboolean can_show_utf8 = TRUE; - char * locale_str; - - if (G_LIKELY(can_show_utf8_set)) - return can_show_utf8; - - if (!g_get_charset(NULL)) { - /* Non-UTF-8 locale */ - locale_str = g_locale_from_utf8("\342\226\202\342\226\204\342\226\206\342\226\210", - -1, - NULL, - NULL, - NULL); - if (locale_str) - g_free(locale_str); - else - can_show_utf8 = FALSE; - } - - return can_show_utf8; -} - -static gboolean -can_show_graphics(void) -{ - static gboolean can_show_graphics_set = FALSE; - static gboolean can_show_graphics = TRUE; - - if (G_LIKELY(can_show_graphics_set)) - return can_show_graphics; - - can_show_graphics = can_show_utf8(); - - /* The linux console font typically doesn't have characters we need */ - if (g_strcmp0(g_getenv("TERM"), "linux") == 0) - can_show_graphics = FALSE; - - return can_show_graphics; -} - -/** - * nmc_wifi_strength_bars: - * @strength: the access point strength, from 0 to 100 - * - * Converts @strength into a 4-character-wide graphical representation of - * strength suitable for printing to stdout. If the current locale and terminal - * support it, this will use unicode graphics characters to represent - * "bars". Otherwise, it will use 0 to 4 asterisks. - * - * Returns: the graphical representation of the access point strength - */ -const char * -nmc_wifi_strength_bars(guint8 strength) -{ - if (!can_show_graphics()) - return nm_utils_wifi_strength_bars(strength); - - if (strength > 80) - return /* ▂▄▆█ */ "\342\226\202\342\226\204\342\226\206\342\226\210"; - else if (strength > 55) - return /* ▂▄▆_ */ "\342\226\202\342\226\204\342\226\206_"; - else if (strength > 30) - return /* ▂▄__ */ "\342\226\202\342\226\204__"; - else if (strength > 5) - return /* ▂___ */ "\342\226\202___"; - else - return /* ____ */ "____"; -} - -/** - * nmc_utils_password_subst_char: - * - * Returns: the string substituted when hiding actual password glyphs - */ -const char * -nmc_password_subst_char(void) -{ - if (can_show_graphics()) - return "\u2022"; /* Bullet */ - else - return "*"; -} - -/* - * We actually use a small part of qrcodegen.c, but we'd prefer to keep it - * intact. Include it instead of linking to it to give the compiler a - * chance to optimize bits we don't need away. - */ - -#pragma GCC visibility push(hidden) -NM_PRAGMA_WARNING_DISABLE("-Wdeclaration-after-statement") -#undef NDEBUG -#define NDEBUG -#include "qrcodegen.c" -NM_PRAGMA_WARNING_REENABLE -#pragma GCC visibility pop - -void -nmc_print_qrcode(const char *str) -{ - uint8_t tempBuffer[qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MAX)]; - uint8_t qrcode[qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MAX)]; - gboolean term_linux; - int size; - int x; - int y; - - term_linux = g_strcmp0(g_getenv("TERM"), "linux") == 0; - if (!term_linux && !can_show_graphics()) - return; - - if (!qrcodegen_encodeText(str, - tempBuffer, - qrcode, - qrcodegen_Ecc_LOW, - qrcodegen_VERSION_MIN, - qrcodegen_VERSION_MAX, - qrcodegen_Mask_AUTO, - FALSE)) { - return; - } - - size = qrcodegen_getSize(qrcode); - - g_print("\n"); - - if (term_linux) { - /* G1 alternate character set on Linux console. */ - for (y = -1; y < size + 1; y += 1) { - g_print(" \033[37;40;1m\016"); - for (x = -1; x < size + 1; x++) { - g_print(qrcodegen_getModule(qrcode, x, y) ? " " : "\060\060"); - } - g_print("\017\033[0m\n"); - } - } else { - /* UTF-8 */ - for (y = -2; y < size + 2; y += 2) { - g_print(" \033[37;40m"); - for (x = -2; x < size + 2; x++) { - bool top = qrcodegen_getModule(qrcode, x, y); - bool bottom = qrcodegen_getModule(qrcode, x, y + 1); - if (top) { - g_print(bottom ? " " : "\u2584"); - } else { - g_print(bottom ? "\u2580" : "\u2588"); - } - } - g_print("\033[0m\n"); - } - } -} - -/** - * nmc_utils_read_passwd_file: - * @passwd_file: file with passwords to parse - * @out_error_line: returns in case of a syntax error in the file, the line - * on which it occurred. - * @error: location to store error, or %NULL - * - * Parse passwords given in @passwd_file and insert them into a hash table. - * Example of @passwd_file contents: - * wifi.psk:tajne heslo - * 802-1x.password:krakonos - * 802-11-wireless-security:leap-password:my leap password - * - * Returns: (transfer full): hash table with parsed passwords, or %NULL on an error - */ -GHashTable * -nmc_utils_read_passwd_file(const char *passwd_file, gssize *out_error_line, GError **error) -{ - nm_auto_clear_secret_ptr NMSecretPtr contents = {0}; - - NM_SET_OUT(out_error_line, -1); - - if (!passwd_file) - return g_hash_table_new_full(nm_str_hash, - g_str_equal, - g_free, - (GDestroyNotify) nm_free_secret); - - if (!nm_utils_file_get_contents(-1, - passwd_file, - 1024 * 1024, - NM_UTILS_FILE_GET_CONTENTS_FLAG_SECRET, - &contents.str, - &contents.len, - NULL, - error)) - return NULL; - - return nmc_utils_parse_passwd_file(contents.str, out_error_line, error); -} - -GHashTable * -nmc_utils_parse_passwd_file(char * contents /* will be modified */, - gssize * out_error_line, - GError **error) -{ - gs_unref_hashtable GHashTable *pwds_hash = NULL; - const char * contents_str; - gsize contents_line; - - pwds_hash = - g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, (GDestroyNotify) nm_free_secret); - - NM_SET_OUT(out_error_line, -1); - - contents_str = contents; - contents_line = 0; - while (contents_str[0]) { - nm_auto_free_secret char *l_hash_key = NULL; - nm_auto_free_secret char *l_hash_val = NULL; - const char * l_content_line; - const char * l_setting; - const char * l_prop; - const char * l_val; - const char * s; - gsize l_hash_val_len; - - /* consume first line. As line delimiters we accept "\r\n", "\n", and "\r". */ - l_content_line = contents_str; - s = l_content_line; - while (!NM_IN_SET(s[0], '\0', '\r', '\n')) - s++; - if (s[0] != '\0') { - if (s[0] == '\r' && s[1] == '\n') { - ((char *) s)[0] = '\0'; - s += 2; - } else { - ((char *) s)[0] = '\0'; - s += 1; - } - } - contents_str = s; - contents_line++; - - l_content_line = nm_str_skip_leading_spaces(l_content_line); - if (NM_IN_SET(l_content_line[0], '\0', '#')) { - /* a comment or empty line. Ignore. */ - continue; - } - - l_setting = l_content_line; - - s = l_setting; - while (!NM_IN_SET(s[0], '\0', ':', '=')) - s++; - if (s[0] == '\0') { - NM_SET_OUT(out_error_line, contents_line); - nm_utils_error_set(error, - NM_UTILS_ERROR_UNKNOWN, - _("missing colon for \"<setting>.<property>:<secret>\" format")); - return NULL; - } - ((char *) s)[0] = '\0'; - s++; - - l_val = s; - - g_strchomp((char *) l_setting); - - nm_assert(nm_str_is_stripped(l_setting)); - - s = strchr(l_setting, '.'); - if (!s) { - NM_SET_OUT(out_error_line, contents_line); - nm_utils_error_set(error, - NM_UTILS_ERROR_UNKNOWN, - _("missing dot for \"<setting>.<property>:<secret>\" format")); - return NULL; - } else if (s == l_setting) { - NM_SET_OUT(out_error_line, contents_line); - nm_utils_error_set(error, - NM_UTILS_ERROR_UNKNOWN, - _("missing setting for \"<setting>.<property>:<secret>\" format")); - return NULL; - } - ((char *) s)[0] = '\0'; - s++; - - l_prop = s; - if (l_prop[0] == '\0') { - NM_SET_OUT(out_error_line, contents_line); - nm_utils_error_set(error, - NM_UTILS_ERROR_UNKNOWN, - _("missing property for \"<setting>.<property>:<secret>\" format")); - return NULL; - } - - /* Accept wifi-sec or wifi instead of cumbersome '802-11-wireless-security' */ - if (NM_IN_STRSET(l_setting, "wifi-sec", "wifi")) - l_setting = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME; - - if (nm_setting_lookup_type(l_setting) == G_TYPE_INVALID) { - NM_SET_OUT(out_error_line, contents_line); - nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, _("invalid setting name")); - return NULL; - } - - if (nm_streq(l_setting, "vpn") && NM_STR_HAS_PREFIX(l_prop, "secret.")) { - /* in 1.12.0, we wrongly required the VPN secrets to be named - * "vpn.secret". It should be "vpn.secrets". Work around it - * (rh#1628833). */ - l_hash_key = g_strdup_printf("vpn.secrets.%s", &l_prop[NM_STRLEN("secret.")]); - } else - l_hash_key = g_strdup_printf("%s.%s", l_setting, l_prop); - - if (!g_utf8_validate(l_hash_key, -1, NULL)) { - NM_SET_OUT(out_error_line, contents_line); - nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, _("property name is not UTF-8")); - return NULL; - } - - /* Support backslash escaping in the secret value. We strip non-escaped leading/trailing whitespaces. */ - s = nm_utils_buf_utf8safe_unescape(l_val, - NM_UTILS_STR_UTF8_SAFE_UNESCAPE_STRIP_SPACES, - &l_hash_val_len, - (gpointer *) &l_hash_val); - if (!l_hash_val) - l_hash_val = g_strdup(s); - - if (!g_utf8_validate(l_hash_val, -1, NULL)) { - /* In some cases it might make sense to support binary secrets (like the WPA-PSK which has no - * defined encoding. However, all API that follows can only handle UTF-8, and no mechanism - * to escape the secrets. Reject non-UTF-8 early. */ - NM_SET_OUT(out_error_line, contents_line); - nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, _("secret is not UTF-8")); - return NULL; - } - - if (strlen(l_hash_val) != l_hash_val_len) { - NM_SET_OUT(out_error_line, contents_line); - nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, _("secret is not UTF-8")); - return NULL; - } - - g_hash_table_insert(pwds_hash, g_steal_pointer(&l_hash_key), g_steal_pointer(&l_hash_val)); - } - - return g_steal_pointer(&pwds_hash); -} |