Blame clients/common/nm-client-utils.c

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