2020-12-23 22:21:36 +01:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
2019-09-25 13:13:40 +02:00
|
|
|
/*
|
2022-05-04 09:19:01 +02:00
|
|
|
* Copyright (C) 2010 - 2022 Red Hat, Inc.
|
2010-02-25 09:52:30 -08:00
|
|
|
*/
|
|
|
|
|
|
2021-02-19 15:23:34 +01:00
|
|
|
#include "libnm-client-aux-extern/nm-default-client.h"
|
2011-03-14 01:00:56 -05:00
|
|
|
|
2017-04-04 13:52:13 +02:00
|
|
|
#include "devices.h"
|
|
|
|
|
|
2010-02-25 09:52:30 -08:00
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
2021-07-02 10:30:22 +02:00
|
|
|
#if HAVE_EDITLINE_READLINE
|
|
|
|
|
#include <editline/readline.h>
|
|
|
|
|
#else
|
2014-05-14 09:22:50 +02:00
|
|
|
#include <readline/readline.h>
|
2021-07-02 10:30:22 +02:00
|
|
|
#endif
|
2020-12-13 16:08:56 +01:00
|
|
|
#include <linux/if_ether.h>
|
2010-02-25 09:52:30 -08:00
|
|
|
|
2021-02-18 17:37:47 +01:00
|
|
|
#include "libnm-glib-aux/nm-secret-utils.h"
|
all: use nm_random_*() instead of g_random_*()
g_random_*() is based on GRand, which is not a CSPRNG. Instead, rely on
kernel to give us good random numbers, which is what nm_random_*() does.
Note that nm_random_*() calls getrandom() (or reads /dev/urandom), which
most likely is slower than GRand. It doesn't matter for our uses though.
It is cumbersome to review all uses of g_rand_*() whether their usage of
a non-cryptographically secure generator is appropriate. Instead, just
always use an appropriate function, thereby avoiding this question. Even
glib documentation refers to reading "/dev/urandom" as alternative. Which
is what nm_random_*() does. These days, it seems unnecessary to not use
the best random generator available, unless it's not fast enough or you
need a stable/seedable stream of random numbers.
In particular in nmcli, we used g_random_int_range() to generate
passwords. That is not appropriate. Sure, it's *only* for the hotspot,
but still.
2023-01-27 12:52:20 +01:00
|
|
|
#include "libnm-glib-aux/nm-random-utils.h"
|
2020-03-18 10:34:07 +01:00
|
|
|
#include "common.h"
|
|
|
|
|
#include "connections.h"
|
2021-03-01 12:42:48 +01:00
|
|
|
#include "libnmc-base/nm-client-utils.h"
|
|
|
|
|
#include "libnmc-base/nm-secret-agent-simple.h"
|
2014-10-30 15:45:43 +01:00
|
|
|
#include "polkit-agent.h"
|
2010-02-25 09:52:30 -08:00
|
|
|
#include "utils.h"
|
|
|
|
|
|
2014-05-15 12:52:26 +02:00
|
|
|
/* define some prompts */
|
2015-03-11 19:10:58 +01:00
|
|
|
#define PROMPT_INTERFACE _("Interface: ")
|
|
|
|
|
#define PROMPT_INTERFACES _("Interface(s): ")
|
2010-02-25 09:52:30 -08:00
|
|
|
|
2018-04-26 20:28:02 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2018-04-30 13:13:52 +02:00
|
|
|
static char *
|
2020-03-11 13:10:04 +01:00
|
|
|
ap_wpa_rsn_flags_to_string(NM80211ApSecurityFlags flags, NMMetaAccessorGetType get_type)
|
2018-04-30 13:13:52 +02:00
|
|
|
{
|
2020-03-11 13:10:04 +01:00
|
|
|
char *flags_str[16];
|
2018-04-30 13:13:52 +02:00
|
|
|
int i = 0;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-30 13:13:52 +02:00
|
|
|
if (flags & NM_802_11_AP_SEC_PAIR_WEP40)
|
2019-01-24 17:28:50 +01:00
|
|
|
flags_str[i++] = "pair_wpe40";
|
2018-04-30 13:13:52 +02:00
|
|
|
if (flags & NM_802_11_AP_SEC_PAIR_WEP104)
|
2019-01-24 17:28:50 +01:00
|
|
|
flags_str[i++] = "pair_wpe104";
|
2018-04-30 13:13:52 +02:00
|
|
|
if (flags & NM_802_11_AP_SEC_PAIR_TKIP)
|
2019-01-24 17:28:50 +01:00
|
|
|
flags_str[i++] = "pair_tkip";
|
2018-04-30 13:13:52 +02:00
|
|
|
if (flags & NM_802_11_AP_SEC_PAIR_CCMP)
|
2019-01-24 17:28:50 +01:00
|
|
|
flags_str[i++] = "pair_ccmp";
|
2018-04-30 13:13:52 +02:00
|
|
|
if (flags & NM_802_11_AP_SEC_GROUP_WEP40)
|
2019-01-24 17:28:50 +01:00
|
|
|
flags_str[i++] = "group_wpe40";
|
2018-04-30 13:13:52 +02:00
|
|
|
if (flags & NM_802_11_AP_SEC_GROUP_WEP104)
|
2019-01-24 17:28:50 +01:00
|
|
|
flags_str[i++] = "group_wpe104";
|
2018-04-30 13:13:52 +02:00
|
|
|
if (flags & NM_802_11_AP_SEC_GROUP_TKIP)
|
2019-01-24 17:28:50 +01:00
|
|
|
flags_str[i++] = "group_tkip";
|
2018-04-30 13:13:52 +02:00
|
|
|
if (flags & NM_802_11_AP_SEC_GROUP_CCMP)
|
2019-01-24 17:28:50 +01:00
|
|
|
flags_str[i++] = "group_ccmp";
|
2018-04-30 13:13:52 +02:00
|
|
|
if (flags & NM_802_11_AP_SEC_KEY_MGMT_PSK)
|
2019-01-24 17:28:50 +01:00
|
|
|
flags_str[i++] = "psk";
|
2018-04-30 13:13:52 +02:00
|
|
|
if (flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)
|
2019-01-24 17:28:50 +01:00
|
|
|
flags_str[i++] = "802.1X";
|
2019-01-22 09:43:58 +01:00
|
|
|
if (flags & NM_802_11_AP_SEC_KEY_MGMT_SAE)
|
|
|
|
|
flags_str[i++] = "sae";
|
2020-12-15 19:05:11 +01:00
|
|
|
if (flags & NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192)
|
|
|
|
|
flags_str[i++] = "wpa-eap-suite-b-192";
|
2020-05-09 03:30:21 +02:00
|
|
|
if (NM_FLAGS_ANY(flags, NM_802_11_AP_SEC_KEY_MGMT_OWE | NM_802_11_AP_SEC_KEY_MGMT_OWE_TM))
|
2019-11-17 22:24:19 +01:00
|
|
|
flags_str[i++] = "owe";
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-01-24 17:28:50 +01:00
|
|
|
/* Make sure you grow flags_str when adding items here. */
|
2020-03-11 13:10:04 +01:00
|
|
|
nm_assert(i < G_N_ELEMENTS(flags_str));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-11 13:10:04 +01:00
|
|
|
if (i == 0) {
|
|
|
|
|
if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY)
|
|
|
|
|
return g_strdup(_("(none)"));
|
|
|
|
|
return g_strdup("(none)");
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-30 13:13:52 +02:00
|
|
|
flags_str[i] = NULL;
|
2019-01-24 17:28:50 +01:00
|
|
|
return g_strjoinv(" ", flags_str);
|
2018-04-30 13:13:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static NMMetaColor
|
|
|
|
|
wifi_signal_to_color(guint8 strength)
|
|
|
|
|
{
|
|
|
|
|
if (strength > 80)
|
|
|
|
|
return NM_META_COLOR_WIFI_SIGNAL_EXCELLENT;
|
|
|
|
|
else if (strength > 55)
|
|
|
|
|
return NM_META_COLOR_WIFI_SIGNAL_GOOD;
|
|
|
|
|
else if (strength > 30)
|
|
|
|
|
return NM_META_COLOR_WIFI_SIGNAL_FAIR;
|
|
|
|
|
else if (strength > 5)
|
|
|
|
|
return NM_META_COLOR_WIFI_SIGNAL_POOR;
|
|
|
|
|
else
|
|
|
|
|
return NM_META_COLOR_WIFI_SIGNAL_UNKNOWN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2021-11-09 13:28:54 +01:00
|
|
|
static gconstpointer
|
|
|
|
|
_metagen_device_status_get_fcn(NMC_META_GENERIC_INFO_GET_FCN_ARGS)
|
2018-04-26 20:28:02 +02:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NMDevice *d = target;
|
2018-04-26 20:28:02 +02:00
|
|
|
NMActiveConnection *ac;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-06-08 23:26:18 +02:00
|
|
|
NMC_HANDLE_COLOR(nmc_device_state_to_color(d));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-26 20:28:02 +02:00
|
|
|
switch (info->info_type) {
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_DEVICE:
|
|
|
|
|
return nm_device_get_iface(d);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_TYPE:
|
|
|
|
|
return nm_device_get_type_description(d);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_STATE:
|
2020-06-10 15:27:59 +02:00
|
|
|
return nmc_meta_generic_get_str_i18n(nmc_device_state_to_string_with_external(d), get_type);
|
2018-07-03 20:57:28 +02:00
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_IP4_CONNECTIVITY:
|
|
|
|
|
return nmc_meta_generic_get_str_i18n(
|
|
|
|
|
nm_connectivity_to_string(nm_device_get_connectivity(d, AF_INET)),
|
|
|
|
|
get_type);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_IP6_CONNECTIVITY:
|
|
|
|
|
return nmc_meta_generic_get_str_i18n(
|
|
|
|
|
nm_connectivity_to_string(nm_device_get_connectivity(d, AF_INET6)),
|
|
|
|
|
get_type);
|
2018-04-26 20:28:02 +02:00
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_DBUS_PATH:
|
|
|
|
|
return nm_object_get_path(NM_OBJECT(d));
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_CONNECTION:
|
|
|
|
|
ac = nm_device_get_active_connection(d);
|
|
|
|
|
return ac ? nm_active_connection_get_id(ac) : NULL;
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_CON_UUID:
|
|
|
|
|
ac = nm_device_get_active_connection(d);
|
|
|
|
|
return ac ? nm_active_connection_get_uuid(ac) : NULL;
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_CON_PATH:
|
|
|
|
|
ac = nm_device_get_active_connection(d);
|
|
|
|
|
return ac ? nm_object_get_path(NM_OBJECT(ac)) : NULL;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-26 20:28:02 +02:00
|
|
|
g_return_val_if_reached(NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const NmcMetaGenericInfo
|
|
|
|
|
*const metagen_device_status[_NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_NUM + 1] = {
|
|
|
|
|
#define _METAGEN_DEVICE_STATUS(type, name) \
|
|
|
|
|
[type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_device_status_get_fcn)
|
2018-07-03 20:57:28 +02:00
|
|
|
_METAGEN_DEVICE_STATUS(NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_DEVICE, "DEVICE"),
|
|
|
|
|
_METAGEN_DEVICE_STATUS(NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_TYPE, "TYPE"),
|
|
|
|
|
_METAGEN_DEVICE_STATUS(NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_STATE, "STATE"),
|
|
|
|
|
_METAGEN_DEVICE_STATUS(NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_IP4_CONNECTIVITY,
|
|
|
|
|
"IP4-CONNECTIVITY"),
|
|
|
|
|
_METAGEN_DEVICE_STATUS(NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_IP6_CONNECTIVITY,
|
|
|
|
|
"IP6-CONNECTIVITY"),
|
|
|
|
|
_METAGEN_DEVICE_STATUS(NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_DBUS_PATH, "DBUS-PATH"),
|
|
|
|
|
_METAGEN_DEVICE_STATUS(NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_CONNECTION, "CONNECTION"),
|
|
|
|
|
_METAGEN_DEVICE_STATUS(NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_CON_UUID, "CON-UUID"),
|
|
|
|
|
_METAGEN_DEVICE_STATUS(NMC_GENERIC_INFO_TYPE_DEVICE_STATUS_CON_PATH, "CON-PATH"),
|
2010-03-18 15:39:15 +01:00
|
|
|
};
|
2018-04-26 20:28:02 +02:00
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
2010-03-18 15:39:15 +01:00
|
|
|
|
2021-11-09 13:28:54 +01:00
|
|
|
static gconstpointer
|
|
|
|
|
_metagen_device_detail_general_get_fcn(NMC_META_GENERIC_INFO_GET_FCN_ARGS)
|
2018-04-26 21:28:14 +02:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NMDevice *d = target;
|
2018-04-26 21:28:14 +02:00
|
|
|
NMActiveConnection *ac;
|
|
|
|
|
NMDeviceStateReason state_reason;
|
2018-07-03 20:57:28 +02:00
|
|
|
NMConnectivityState connectivity;
|
2021-11-09 13:28:54 +01:00
|
|
|
const char *s;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-26 21:28:14 +02:00
|
|
|
NMC_HANDLE_COLOR(NM_META_COLOR_NONE);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-26 21:28:14 +02:00
|
|
|
switch (info->info_type) {
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DEVICE:
|
|
|
|
|
return nm_device_get_iface(d);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_TYPE:
|
|
|
|
|
return nm_device_get_type_description(d);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_TYPE:
|
|
|
|
|
return G_OBJECT_TYPE_NAME(d);
|
2019-08-29 10:55:26 +02:00
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DBUS_PATH:
|
|
|
|
|
return nm_object_get_path(NM_OBJECT(d));
|
2018-04-26 21:28:14 +02:00
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_VENDOR:
|
|
|
|
|
return nm_device_get_vendor(d);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_PRODUCT:
|
|
|
|
|
return nm_device_get_product(d);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DRIVER:
|
|
|
|
|
s = nm_device_get_driver(d);
|
2020-07-03 11:34:12 +02:00
|
|
|
return s ?: nmc_meta_generic_get_unknown(get_type);
|
2018-04-26 21:28:14 +02:00
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DRIVER_VERSION:
|
|
|
|
|
return nm_device_get_driver_version(d);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_FIRMWARE_VERSION:
|
|
|
|
|
return nm_device_get_firmware_version(d);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_HWADDR:
|
|
|
|
|
s = nm_device_get_hw_address(d);
|
2020-07-03 11:34:12 +02:00
|
|
|
return s ?: nmc_meta_generic_get_unknown(get_type);
|
2018-04-26 21:28:14 +02:00
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_MTU:
|
|
|
|
|
return (*out_to_free = g_strdup_printf("%u", (guint) nm_device_get_mtu(d)));
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_STATE:
|
2018-04-27 12:28:23 +02:00
|
|
|
return (*out_to_free = nmc_meta_generic_get_enum_with_detail(
|
|
|
|
|
NMC_META_GENERIC_GET_ENUM_TYPE_PARENTHESES,
|
2020-06-10 15:27:59 +02:00
|
|
|
nm_device_get_state(d),
|
|
|
|
|
nmc_device_state_to_string_with_external(d),
|
2018-04-27 12:28:23 +02:00
|
|
|
get_type));
|
2018-04-26 21:28:14 +02:00
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_REASON:
|
|
|
|
|
state_reason = nm_device_get_state_reason(d);
|
2018-04-27 12:28:23 +02:00
|
|
|
return (*out_to_free = nmc_meta_generic_get_enum_with_detail(
|
|
|
|
|
NMC_META_GENERIC_GET_ENUM_TYPE_PARENTHESES,
|
|
|
|
|
state_reason,
|
|
|
|
|
nmc_device_reason_to_string(state_reason),
|
|
|
|
|
get_type));
|
2018-07-03 20:57:28 +02:00
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_IP4_CONNECTIVITY:
|
|
|
|
|
connectivity = nm_device_get_connectivity(d, AF_INET);
|
|
|
|
|
return (*out_to_free = nmc_meta_generic_get_enum_with_detail(
|
|
|
|
|
NMC_META_GENERIC_GET_ENUM_TYPE_PARENTHESES,
|
|
|
|
|
connectivity,
|
|
|
|
|
nm_connectivity_to_string(connectivity),
|
|
|
|
|
get_type));
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_IP6_CONNECTIVITY:
|
|
|
|
|
connectivity = nm_device_get_connectivity(d, AF_INET6);
|
|
|
|
|
return (*out_to_free = nmc_meta_generic_get_enum_with_detail(
|
|
|
|
|
NMC_META_GENERIC_GET_ENUM_TYPE_PARENTHESES,
|
|
|
|
|
connectivity,
|
|
|
|
|
nm_connectivity_to_string(connectivity),
|
|
|
|
|
get_type));
|
2018-04-26 21:28:14 +02:00
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_UDI:
|
|
|
|
|
return nm_device_get_udi(d);
|
2020-06-10 15:17:39 +02:00
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_PATH:
|
|
|
|
|
return nm_device_get_path(d);
|
2018-04-26 21:28:14 +02:00
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_IP_IFACE:
|
|
|
|
|
return nm_device_get_ip_iface(d);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_IS_SOFTWARE:
|
|
|
|
|
return nmc_meta_generic_get_bool(nm_device_is_software(d), get_type);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_MANAGED:
|
|
|
|
|
return nmc_meta_generic_get_bool(nm_device_get_managed(d), get_type);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_AUTOCONNECT:
|
|
|
|
|
return nmc_meta_generic_get_bool(nm_device_get_autoconnect(d), get_type);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_FIRMWARE_MISSING:
|
|
|
|
|
return nmc_meta_generic_get_bool(nm_device_get_firmware_missing(d), get_type);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_PLUGIN_MISSING:
|
|
|
|
|
return nmc_meta_generic_get_bool(nm_device_get_nm_plugin_missing(d), get_type);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_PHYS_PORT_ID:
|
|
|
|
|
return nm_device_get_physical_port_id(d);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_CONNECTION:
|
|
|
|
|
ac = nm_device_get_active_connection(d);
|
|
|
|
|
return ac ? nm_active_connection_get_id(ac) : NULL;
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_CON_UUID:
|
|
|
|
|
ac = nm_device_get_active_connection(d);
|
|
|
|
|
return ac ? nm_active_connection_get_uuid(ac) : NULL;
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_CON_PATH:
|
|
|
|
|
ac = nm_device_get_active_connection(d);
|
|
|
|
|
return ac ? nm_object_get_path(NM_OBJECT(ac)) : NULL;
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_METERED:
|
2018-04-27 12:28:23 +02:00
|
|
|
return nmc_meta_generic_get_str_i18n(nmc_device_metered_to_string(nm_device_get_metered(d)),
|
|
|
|
|
get_type);
|
2018-04-26 21:28:14 +02:00
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-26 21:28:14 +02:00
|
|
|
g_return_val_if_reached(NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const NmcMetaGenericInfo
|
|
|
|
|
*const metagen_device_detail_general[_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NUM + 1] = {
|
|
|
|
|
#define _METAGEN_DEVICE_DETAIL_GENERAL(type, name) \
|
|
|
|
|
[type] = NMC_META_GENERIC(name, \
|
|
|
|
|
.info_type = type, \
|
|
|
|
|
.get_fcn = _metagen_device_detail_general_get_fcn)
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DEVICE,
|
|
|
|
|
"DEVICE"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_TYPE, "TYPE"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_TYPE,
|
|
|
|
|
"NM-TYPE"),
|
2019-08-29 10:55:26 +02:00
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DBUS_PATH,
|
|
|
|
|
"DBUS-PATH"),
|
2018-04-26 21:28:14 +02:00
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_VENDOR,
|
|
|
|
|
"VENDOR"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_PRODUCT,
|
|
|
|
|
"PRODUCT"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DRIVER,
|
|
|
|
|
"DRIVER"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DRIVER_VERSION,
|
|
|
|
|
"DRIVER-VERSION"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_FIRMWARE_VERSION,
|
|
|
|
|
"FIRMWARE-VERSION"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_HWADDR,
|
|
|
|
|
"HWADDR"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_MTU, "MTU"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_STATE, "STATE"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_REASON,
|
|
|
|
|
"REASON"),
|
2018-07-03 20:57:28 +02:00
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_IP4_CONNECTIVITY,
|
|
|
|
|
"IP4-CONNECTIVITY"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_IP6_CONNECTIVITY,
|
|
|
|
|
"IP6-CONNECTIVITY"),
|
2018-04-26 21:28:14 +02:00
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_UDI, "UDI"),
|
2020-06-10 15:17:39 +02:00
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_PATH, "PATH"),
|
2018-04-26 21:28:14 +02:00
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_IP_IFACE,
|
|
|
|
|
"IP-IFACE"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_IS_SOFTWARE,
|
|
|
|
|
"IS-SOFTWARE"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_MANAGED,
|
|
|
|
|
"NM-MANAGED"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_AUTOCONNECT,
|
|
|
|
|
"AUTOCONNECT"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_FIRMWARE_MISSING,
|
|
|
|
|
"FIRMWARE-MISSING"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(
|
|
|
|
|
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_NM_PLUGIN_MISSING,
|
|
|
|
|
"NM-PLUGIN-MISSING"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_PHYS_PORT_ID,
|
|
|
|
|
"PHYS-PORT-ID"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_CONNECTION,
|
|
|
|
|
"CONNECTION"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_CON_UUID,
|
|
|
|
|
"CON-UUID"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_CON_PATH,
|
|
|
|
|
"CON-PATH"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_GENERAL(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_METERED,
|
|
|
|
|
"METERED"),
|
2010-03-22 18:43:28 +01:00
|
|
|
};
|
2018-04-26 21:28:14 +02:00
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
2010-03-22 18:43:28 +01:00
|
|
|
|
2018-04-27 17:28:43 +02:00
|
|
|
static NMRemoteConnection **
|
|
|
|
|
_device_get_available_connections(NMDevice *d, guint *out_len)
|
|
|
|
|
{
|
|
|
|
|
NMRemoteConnection **avail_cons;
|
2021-11-09 13:28:54 +01:00
|
|
|
const GPtrArray *avail_cons_arr;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-27 17:28:43 +02:00
|
|
|
avail_cons_arr = nm_device_get_available_connections(d);
|
|
|
|
|
if (!avail_cons_arr || avail_cons_arr->len == 0) {
|
|
|
|
|
*out_len = 0;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-27 17:28:43 +02:00
|
|
|
avail_cons = (NMRemoteConnection **) nmc_objects_sort_by_path(
|
|
|
|
|
(const NMObject *const *) avail_cons_arr->pdata,
|
|
|
|
|
avail_cons_arr->len);
|
|
|
|
|
nm_assert(avail_cons_arr->len == NM_PTRARRAY_LEN(avail_cons));
|
|
|
|
|
*out_len = avail_cons_arr->len;
|
|
|
|
|
return avail_cons;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-09 13:28:54 +01:00
|
|
|
static gconstpointer
|
|
|
|
|
_metagen_device_detail_connections_get_fcn(NMC_META_GENERIC_INFO_GET_FCN_ARGS)
|
2018-04-27 17:28:43 +02:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NMDevice *d = target;
|
2018-04-27 17:28:43 +02:00
|
|
|
gs_free NMRemoteConnection **avail_cons = NULL;
|
|
|
|
|
guint avail_cons_len;
|
2021-05-27 10:41:45 +02:00
|
|
|
guint i;
|
|
|
|
|
guint j;
|
2021-11-09 13:28:54 +01:00
|
|
|
char **arr = NULL;
|
|
|
|
|
GString *str;
|
2021-05-27 10:41:45 +02:00
|
|
|
gboolean had_prefix;
|
|
|
|
|
gboolean has_prefix;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-27 17:28:43 +02:00
|
|
|
NMC_HANDLE_COLOR(NM_META_COLOR_NONE);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-27 17:28:43 +02:00
|
|
|
switch (info->info_type) {
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CONNECTIONS_AVAILABLE_CONNECTIONS:
|
|
|
|
|
if (!NM_FLAGS_HAS(get_flags, NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV))
|
|
|
|
|
return NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-27 17:28:43 +02:00
|
|
|
avail_cons = _device_get_available_connections(d, &avail_cons_len);
|
|
|
|
|
if (avail_cons_len == 0)
|
|
|
|
|
goto arr_out;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-27 17:28:43 +02:00
|
|
|
arr = g_new(char *, avail_cons_len + 1);
|
|
|
|
|
j = 0;
|
|
|
|
|
for (i = 0; i < avail_cons_len; i++) {
|
|
|
|
|
NMRemoteConnection *ac = avail_cons[i];
|
2021-11-09 13:28:54 +01:00
|
|
|
const char *ac_id = nm_connection_get_id(NM_CONNECTION(ac));
|
|
|
|
|
const char *ac_uuid = nm_connection_get_uuid(NM_CONNECTION(ac));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-27 17:28:43 +02:00
|
|
|
if (!ac_id || !ac_uuid) {
|
|
|
|
|
const char *ac_path = nm_connection_get_path(NM_CONNECTION(ac));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-27 17:28:43 +02:00
|
|
|
if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) {
|
|
|
|
|
arr[j++] = ac_path ? g_strdup_printf(_("<invisible> | %s"), ac_path)
|
|
|
|
|
: g_strdup(_("<invisible>"));
|
|
|
|
|
} else {
|
|
|
|
|
arr[j++] = ac_path ? g_strdup_printf("<invisible> | %s", ac_path)
|
|
|
|
|
: g_strdup("<invisible>");
|
|
|
|
|
}
|
|
|
|
|
} else
|
|
|
|
|
arr[j++] = g_strdup_printf("%s | %s", ac_uuid, ac_id);
|
|
|
|
|
}
|
|
|
|
|
arr[j] = NULL;
|
|
|
|
|
goto arr_out;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-27 17:28:43 +02:00
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CONNECTIONS_AVAILABLE_CONNECTION_PATHS:
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-27 17:28:43 +02:00
|
|
|
avail_cons = _device_get_available_connections(d, &avail_cons_len);
|
|
|
|
|
if (avail_cons_len == 0)
|
|
|
|
|
return NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-27 17:28:43 +02:00
|
|
|
str = g_string_new(NULL);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-27 17:28:43 +02:00
|
|
|
had_prefix = FALSE;
|
|
|
|
|
for (i = 0; i < avail_cons_len; i++) {
|
|
|
|
|
NMRemoteConnection *ac = avail_cons[i];
|
2021-11-09 13:28:54 +01:00
|
|
|
const char *p = nm_connection_get_path(NM_CONNECTION(ac));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-27 17:28:43 +02:00
|
|
|
if (!p)
|
|
|
|
|
continue;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-27 17:28:43 +02:00
|
|
|
has_prefix = g_str_has_prefix(p, NM_DBUS_PATH_SETTINGS_CONNECTION "/")
|
|
|
|
|
&& p[NM_STRLEN(NM_DBUS_PATH_SETTINGS_CONNECTION "/")];
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-27 17:28:43 +02:00
|
|
|
if (str->len > 0) {
|
|
|
|
|
if (had_prefix && !has_prefix)
|
|
|
|
|
g_string_append_c(str, '}');
|
|
|
|
|
g_string_append_c(str, ',');
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-27 17:28:43 +02:00
|
|
|
if (!has_prefix)
|
|
|
|
|
g_string_append(str, p);
|
|
|
|
|
else {
|
|
|
|
|
if (!had_prefix)
|
|
|
|
|
g_string_printf(str, "%s/{", NM_DBUS_PATH_SETTINGS_CONNECTION);
|
|
|
|
|
g_string_append(str, &p[NM_STRLEN(NM_DBUS_PATH_SETTINGS_CONNECTION "/")]);
|
|
|
|
|
}
|
|
|
|
|
had_prefix = has_prefix;
|
|
|
|
|
}
|
|
|
|
|
if (had_prefix)
|
|
|
|
|
g_string_append_c(str, '}');
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-27 17:28:43 +02:00
|
|
|
return (*out_to_free = g_string_free(str, FALSE));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-27 17:28:43 +02:00
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-27 17:28:43 +02:00
|
|
|
g_return_val_if_reached(NULL);
|
|
|
|
|
|
|
|
|
|
arr_out:
|
|
|
|
|
NM_SET_OUT(out_is_default, !arr || !arr[0]);
|
|
|
|
|
*out_flags |= NM_META_ACCESSOR_GET_OUT_FLAGS_STRV;
|
|
|
|
|
*out_to_free = arr;
|
|
|
|
|
return arr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const NmcMetaGenericInfo *const
|
|
|
|
|
metagen_device_detail_connections[_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CONNECTIONS_NUM + 1] = {
|
|
|
|
|
#define _METAGEN_DEVICE_DETAIL_CONNECTIONS(type, name) \
|
|
|
|
|
[type] = NMC_META_GENERIC(name, \
|
|
|
|
|
.info_type = type, \
|
|
|
|
|
.get_fcn = _metagen_device_detail_connections_get_fcn)
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_CONNECTIONS(
|
|
|
|
|
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CONNECTIONS_AVAILABLE_CONNECTION_PATHS,
|
|
|
|
|
"AVAILABLE-CONNECTION-PATHS"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_CONNECTIONS(
|
|
|
|
|
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CONNECTIONS_AVAILABLE_CONNECTIONS,
|
|
|
|
|
"AVAILABLE-CONNECTIONS"),
|
2012-08-31 12:48:27 +02:00
|
|
|
};
|
2018-04-27 17:28:43 +02:00
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
2012-08-31 12:48:27 +02:00
|
|
|
|
2021-11-09 13:28:54 +01:00
|
|
|
static gconstpointer
|
|
|
|
|
_metagen_device_detail_capabilities_get_fcn(NMC_META_GENERIC_INFO_GET_FCN_ARGS)
|
2018-04-29 19:13:57 +02:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NMDevice *d = target;
|
2018-04-29 19:13:57 +02:00
|
|
|
NMDeviceCapabilities caps;
|
|
|
|
|
guint32 speed;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-29 19:13:57 +02:00
|
|
|
NMC_HANDLE_COLOR(NM_META_COLOR_NONE);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-29 19:13:57 +02:00
|
|
|
caps = nm_device_get_capabilities(d);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-29 19:13:57 +02:00
|
|
|
switch (info->info_type) {
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_CARRIER_DETECT:
|
|
|
|
|
return nmc_meta_generic_get_bool(NM_FLAGS_HAS(caps, NM_DEVICE_CAP_CARRIER_DETECT),
|
|
|
|
|
get_type);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_SPEED:
|
|
|
|
|
speed = 0;
|
|
|
|
|
if (NM_IS_DEVICE_ETHERNET(d)) {
|
|
|
|
|
/* Speed in Mb/s */
|
|
|
|
|
speed = nm_device_ethernet_get_speed(NM_DEVICE_ETHERNET(d));
|
|
|
|
|
} else if (NM_IS_DEVICE_WIFI(d)) {
|
|
|
|
|
/* Speed in b/s */
|
|
|
|
|
speed = nm_device_wifi_get_bitrate(NM_DEVICE_WIFI(d));
|
|
|
|
|
speed /= 1000;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-29 19:13:57 +02:00
|
|
|
if (speed) {
|
|
|
|
|
if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY)
|
|
|
|
|
return (*out_to_free = g_strdup_printf(_("%u Mb/s"), (guint) speed));
|
|
|
|
|
return (*out_to_free = g_strdup_printf("%u Mb/s", (guint) speed));
|
|
|
|
|
}
|
|
|
|
|
return nmc_meta_generic_get_str_i18n(N_("unknown"), get_type);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_IS_SOFTWARE:
|
|
|
|
|
return nmc_meta_generic_get_bool(NM_FLAGS_HAS(caps, NM_DEVICE_CAP_IS_SOFTWARE), get_type);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_SRIOV:
|
|
|
|
|
return nmc_meta_generic_get_bool(NM_FLAGS_HAS(caps, NM_DEVICE_CAP_SRIOV), get_type);
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-29 19:13:57 +02:00
|
|
|
g_return_val_if_reached(NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const NmcMetaGenericInfo
|
|
|
|
|
*const metagen_device_detail_capabilities[_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_NUM
|
|
|
|
|
+ 1] = {
|
|
|
|
|
#define _METAGEN_DEVICE_DETAIL_CAPABILITIES(type, name) \
|
|
|
|
|
[type] = NMC_META_GENERIC(name, \
|
|
|
|
|
.info_type = type, \
|
|
|
|
|
.get_fcn = _metagen_device_detail_capabilities_get_fcn)
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_CAPABILITIES(
|
|
|
|
|
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_CARRIER_DETECT,
|
|
|
|
|
"CARRIER-DETECT"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_CAPABILITIES(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_SPEED,
|
|
|
|
|
"SPEED"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_CAPABILITIES(
|
|
|
|
|
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_IS_SOFTWARE,
|
|
|
|
|
"IS-SOFTWARE"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_CAPABILITIES(NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_CAPABILITIES_SRIOV,
|
|
|
|
|
"SRIOV"),
|
2010-03-22 18:43:28 +01:00
|
|
|
};
|
2018-04-29 19:13:57 +02:00
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
2010-03-22 18:43:28 +01:00
|
|
|
|
2018-04-30 09:00:08 +02:00
|
|
|
static gconstpointer
|
2021-11-09 13:28:54 +01:00
|
|
|
_metagen_device_detail_wired_properties_get_fcn(NMC_META_GENERIC_INFO_GET_FCN_ARGS)
|
2018-04-30 09:00:08 +02:00
|
|
|
{
|
|
|
|
|
NMDevice *d = target;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-30 09:00:08 +02:00
|
|
|
NMC_HANDLE_COLOR(NM_META_COLOR_NONE);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-30 09:00:08 +02:00
|
|
|
switch (info->info_type) {
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIRED_PROPERTIES_CARRIER:
|
|
|
|
|
return nmc_meta_generic_get_bool_onoff(
|
|
|
|
|
nm_device_ethernet_get_carrier(NM_DEVICE_ETHERNET(d)),
|
|
|
|
|
get_type);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIRED_PROPERTIES_S390_SUBCHANNELS:
|
|
|
|
|
if (!NM_FLAGS_HAS(get_flags, NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV))
|
|
|
|
|
return NULL;
|
|
|
|
|
*out_flags |= NM_META_ACCESSOR_GET_OUT_FLAGS_STRV;
|
|
|
|
|
return nm_device_ethernet_get_s390_subchannels(NM_DEVICE_ETHERNET(d));
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-30 09:00:08 +02:00
|
|
|
g_return_val_if_reached(NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const NmcMetaGenericInfo *const
|
|
|
|
|
metagen_device_detail_wired_properties[_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIRED_PROPERTIES_NUM
|
|
|
|
|
+ 1] = {
|
|
|
|
|
#define _METAGEN_DEVICE_DETAIL_WIRED_PROPERTIES(type, name) \
|
|
|
|
|
[type] = NMC_META_GENERIC(name, \
|
|
|
|
|
.info_type = type, \
|
|
|
|
|
.get_fcn = _metagen_device_detail_wired_properties_get_fcn)
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_WIRED_PROPERTIES(
|
|
|
|
|
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIRED_PROPERTIES_CARRIER,
|
|
|
|
|
"CARRIER"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_WIRED_PROPERTIES(
|
|
|
|
|
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIRED_PROPERTIES_S390_SUBCHANNELS,
|
|
|
|
|
"S390-SUBCHANNELS"),
|
2010-03-22 18:43:28 +01:00
|
|
|
};
|
2018-04-30 09:00:08 +02:00
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static gconstpointer
|
2021-11-09 13:28:54 +01:00
|
|
|
_metagen_device_detail_wifi_properties_get_fcn(NMC_META_GENERIC_INFO_GET_FCN_ARGS)
|
2018-04-30 09:00:08 +02:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NMDevice *d = target;
|
2018-04-30 09:00:08 +02:00
|
|
|
NMDeviceWifiCapabilities wcaps;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-30 09:00:08 +02:00
|
|
|
NMC_HANDLE_COLOR(NM_META_COLOR_NONE);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-30 09:00:08 +02:00
|
|
|
wcaps = nm_device_wifi_get_capabilities(NM_DEVICE_WIFI(d));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-30 09:00:08 +02:00
|
|
|
switch (info->info_type) {
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WEP:
|
|
|
|
|
return nmc_meta_generic_get_bool(
|
|
|
|
|
NM_FLAGS_ANY(wcaps, NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104),
|
|
|
|
|
get_type);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WPA:
|
|
|
|
|
return nmc_meta_generic_get_bool(NM_FLAGS_HAS(wcaps, NM_WIFI_DEVICE_CAP_WPA), get_type);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WPA2:
|
|
|
|
|
return nmc_meta_generic_get_bool(NM_FLAGS_HAS(wcaps, NM_WIFI_DEVICE_CAP_RSN), get_type);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_TKIP:
|
|
|
|
|
return nmc_meta_generic_get_bool(NM_FLAGS_HAS(wcaps, NM_WIFI_DEVICE_CAP_CIPHER_TKIP),
|
|
|
|
|
get_type);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_CCMP:
|
|
|
|
|
return nmc_meta_generic_get_bool(NM_FLAGS_HAS(wcaps, NM_WIFI_DEVICE_CAP_CIPHER_CCMP),
|
|
|
|
|
get_type);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_AP:
|
|
|
|
|
return nmc_meta_generic_get_bool(NM_FLAGS_HAS(wcaps, NM_WIFI_DEVICE_CAP_AP), get_type);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_ADHOC:
|
|
|
|
|
return nmc_meta_generic_get_bool(NM_FLAGS_HAS(wcaps, NM_WIFI_DEVICE_CAP_ADHOC), get_type);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_2GHZ:
|
|
|
|
|
return nmc_meta_generic_get_str_i18n(
|
|
|
|
|
NM_FLAGS_HAS(wcaps, NM_WIFI_DEVICE_CAP_FREQ_VALID)
|
|
|
|
|
? (NM_FLAGS_HAS(wcaps, NM_WIFI_DEVICE_CAP_FREQ_2GHZ) ? N_("yes") : N_("no"))
|
|
|
|
|
: N_("unknown"),
|
|
|
|
|
get_type);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_5GHZ:
|
|
|
|
|
return nmc_meta_generic_get_str_i18n(
|
|
|
|
|
NM_FLAGS_HAS(wcaps, NM_WIFI_DEVICE_CAP_FREQ_VALID)
|
|
|
|
|
? (NM_FLAGS_HAS(wcaps, NM_WIFI_DEVICE_CAP_FREQ_5GHZ) ? N_("yes") : N_("no"))
|
|
|
|
|
: N_("unknown"),
|
|
|
|
|
get_type);
|
2019-01-24 15:33:41 +01:00
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_MESH:
|
|
|
|
|
return nmc_meta_generic_get_bool(NM_FLAGS_HAS(wcaps, NM_WIFI_DEVICE_CAP_MESH), get_type);
|
2019-08-19 15:51:31 +02:00
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_IBSS_RSN:
|
|
|
|
|
return nmc_meta_generic_get_bool(NM_FLAGS_HAS(wcaps, NM_WIFI_DEVICE_CAP_IBSS_RSN),
|
|
|
|
|
get_type);
|
2018-04-30 09:00:08 +02:00
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-30 09:00:08 +02:00
|
|
|
g_return_val_if_reached(NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const NmcMetaGenericInfo *const
|
|
|
|
|
metagen_device_detail_wifi_properties[_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_NUM
|
|
|
|
|
+ 1] = {
|
|
|
|
|
#define _METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES(type, name) \
|
|
|
|
|
[type] = NMC_META_GENERIC(name, \
|
|
|
|
|
.info_type = type, \
|
|
|
|
|
.get_fcn = _metagen_device_detail_wifi_properties_get_fcn)
|
2019-08-19 15:51:31 +02:00
|
|
|
_METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES(
|
|
|
|
|
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WEP,
|
|
|
|
|
"WEP"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES(
|
|
|
|
|
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WPA,
|
|
|
|
|
"WPA"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES(
|
|
|
|
|
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_WPA2,
|
|
|
|
|
"WPA2"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES(
|
|
|
|
|
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_TKIP,
|
|
|
|
|
"TKIP"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES(
|
|
|
|
|
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_CCMP,
|
|
|
|
|
"CCMP"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES(
|
|
|
|
|
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_AP,
|
|
|
|
|
"AP"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES(
|
|
|
|
|
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_ADHOC,
|
|
|
|
|
"ADHOC"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES(
|
|
|
|
|
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_2GHZ,
|
|
|
|
|
"2GHZ"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES(
|
|
|
|
|
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_5GHZ,
|
|
|
|
|
"5GHZ"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES(
|
|
|
|
|
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_MESH,
|
|
|
|
|
"MESH"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_WIFI_PROPERTIES(
|
|
|
|
|
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_WIFI_PROPERTIES_IBSS_RSN,
|
|
|
|
|
"IBSS-RSN"),
|
2010-03-22 18:43:28 +01:00
|
|
|
};
|
2018-04-30 09:00:08 +02:00
|
|
|
|
2019-10-10 10:45:36 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static gconstpointer
|
2021-11-09 13:28:54 +01:00
|
|
|
_metagen_device_detail_interface_flags_get_fcn(NMC_META_GENERIC_INFO_GET_FCN_ARGS)
|
2019-10-10 10:45:36 +02:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NMDevice *d = target;
|
2019-10-10 10:45:36 +02:00
|
|
|
NMDeviceInterfaceFlags flags;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 10:45:36 +02:00
|
|
|
NMC_HANDLE_COLOR(NM_META_COLOR_NONE);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 10:45:36 +02:00
|
|
|
flags = nm_device_get_interface_flags(d);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 10:45:36 +02:00
|
|
|
switch (info->info_type) {
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_INTERFACE_FLAGS_UP:
|
|
|
|
|
return nmc_meta_generic_get_bool(NM_FLAGS_HAS(flags, NM_DEVICE_INTERFACE_FLAG_UP),
|
|
|
|
|
get_type);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_INTERFACE_FLAGS_LOWER_UP:
|
|
|
|
|
return nmc_meta_generic_get_bool(NM_FLAGS_HAS(flags, NM_DEVICE_INTERFACE_FLAG_LOWER_UP),
|
|
|
|
|
get_type);
|
2019-10-12 17:14:38 +02:00
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_INTERFACE_FLAGS_CARRIER:
|
|
|
|
|
return nmc_meta_generic_get_bool(NM_FLAGS_HAS(flags, NM_DEVICE_INTERFACE_FLAG_CARRIER),
|
|
|
|
|
get_type);
|
2021-04-14 13:01:01 +02:00
|
|
|
case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_INTERFACE_FLAGS_PROMISC:
|
|
|
|
|
return nmc_meta_generic_get_bool(NM_FLAGS_HAS(flags, NM_DEVICE_INTERFACE_FLAG_PROMISC),
|
|
|
|
|
get_type);
|
2019-10-10 10:45:36 +02:00
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 10:45:36 +02:00
|
|
|
g_return_val_if_reached(NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const NmcMetaGenericInfo *const
|
|
|
|
|
metagen_device_detail_interface_flags[_NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_INTERFACE_FLAGS_NUM
|
|
|
|
|
+ 1] = {
|
|
|
|
|
#define _METAGEN_DEVICE_DETAIL_INTERFACE_FLAGS(type, name) \
|
|
|
|
|
[type] = NMC_META_GENERIC(name, \
|
|
|
|
|
.info_type = type, \
|
|
|
|
|
.get_fcn = _metagen_device_detail_interface_flags_get_fcn)
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_INTERFACE_FLAGS(
|
|
|
|
|
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_INTERFACE_FLAGS_UP,
|
|
|
|
|
"UP"),
|
|
|
|
|
_METAGEN_DEVICE_DETAIL_INTERFACE_FLAGS(
|
|
|
|
|
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_INTERFACE_FLAGS_LOWER_UP,
|
|
|
|
|
"LOWER-UP"),
|
2019-10-12 17:14:38 +02:00
|
|
|
_METAGEN_DEVICE_DETAIL_INTERFACE_FLAGS(
|
|
|
|
|
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_INTERFACE_FLAGS_CARRIER,
|
|
|
|
|
"CARRIER"),
|
2021-04-14 13:01:01 +02:00
|
|
|
_METAGEN_DEVICE_DETAIL_INTERFACE_FLAGS(
|
|
|
|
|
NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_INTERFACE_FLAGS_PROMISC,
|
|
|
|
|
"PROMISC"),
|
2019-10-10 10:45:36 +02:00
|
|
|
};
|
|
|
|
|
|
2018-04-30 09:00:08 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
const NmcMetaGenericInfo *const metagen_device_detail_wimax_properties[] = {
|
|
|
|
|
NMC_META_GENERIC("CTR-FREQ"),
|
|
|
|
|
NMC_META_GENERIC("RSSI"),
|
|
|
|
|
NMC_META_GENERIC("CINR"),
|
|
|
|
|
NMC_META_GENERIC("TX-POW"),
|
|
|
|
|
NMC_META_GENERIC("BSID"),
|
2011-01-06 17:01:55 -06:00
|
|
|
};
|
2018-04-30 09:00:08 +02:00
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
2013-12-10 12:00:53 +01:00
|
|
|
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
const NmcMetaGenericInfo *const nmc_fields_dev_wifi_list[] = {
|
|
|
|
|
NMC_META_GENERIC("NAME"), /* 0 */
|
|
|
|
|
NMC_META_GENERIC("SSID"), /* 1 */
|
|
|
|
|
NMC_META_GENERIC("SSID-HEX"), /* 2 */
|
|
|
|
|
NMC_META_GENERIC("BSSID"), /* 3 */
|
|
|
|
|
NMC_META_GENERIC("MODE"), /* 4 */
|
|
|
|
|
NMC_META_GENERIC("CHAN"), /* 5 */
|
|
|
|
|
NMC_META_GENERIC("FREQ"), /* 6 */
|
|
|
|
|
NMC_META_GENERIC("RATE"), /* 7 */
|
|
|
|
|
NMC_META_GENERIC("SIGNAL"), /* 8 */
|
|
|
|
|
NMC_META_GENERIC("BARS"), /* 9 */
|
|
|
|
|
NMC_META_GENERIC("SECURITY"), /* 10 */
|
|
|
|
|
NMC_META_GENERIC("WPA-FLAGS"), /* 11 */
|
|
|
|
|
NMC_META_GENERIC("RSN-FLAGS"), /* 12 */
|
|
|
|
|
NMC_META_GENERIC("DEVICE"), /* 13 */
|
|
|
|
|
NMC_META_GENERIC("ACTIVE"), /* 14 */
|
|
|
|
|
NMC_META_GENERIC("IN-USE"), /* 15 */
|
|
|
|
|
NMC_META_GENERIC("DBUS-PATH"), /* 16 */
|
|
|
|
|
NULL,
|
2010-03-18 15:39:15 +01:00
|
|
|
};
|
2019-08-21 15:11:41 +02:00
|
|
|
#define NMC_FIELDS_DEV_WIFI_LIST_COMMON "IN-USE,BSSID,SSID,MODE,CHAN,RATE,SIGNAL,BARS,SECURITY"
|
2010-03-22 18:43:28 +01:00
|
|
|
#define NMC_FIELDS_DEV_WIFI_LIST_FOR_DEV_LIST "NAME," NMC_FIELDS_DEV_WIFI_LIST_COMMON
|
2010-03-18 15:39:15 +01:00
|
|
|
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
const NmcMetaGenericInfo *const nmc_fields_dev_wimax_list[] = {
|
|
|
|
|
NMC_META_GENERIC("NAME"), /* 0 */
|
|
|
|
|
NMC_META_GENERIC("NSP"), /* 1 */
|
|
|
|
|
NMC_META_GENERIC("SIGNAL"), /* 2 */
|
|
|
|
|
NMC_META_GENERIC("TYPE"), /* 3 */
|
|
|
|
|
NMC_META_GENERIC("DEVICE"), /* 4 */
|
|
|
|
|
NMC_META_GENERIC("ACTIVE"), /* 5 */
|
|
|
|
|
NMC_META_GENERIC("DBUS-PATH"), /* 6 */
|
|
|
|
|
NULL,
|
2011-01-06 17:01:55 -06:00
|
|
|
};
|
|
|
|
|
#define NMC_FIELDS_DEV_WIMAX_LIST_COMMON "NSP,SIGNAL,TYPE,DEVICE,ACTIVE"
|
|
|
|
|
#define NMC_FIELDS_DEV_WIMAX_LIST_FOR_DEV_LIST "NAME," NMC_FIELDS_DEV_WIMAX_LIST_COMMON
|
|
|
|
|
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
const NmcMetaGenericInfo *const nmc_fields_dev_show_master_prop[] = {
|
|
|
|
|
NMC_META_GENERIC("NAME"), /* 0 */
|
|
|
|
|
NMC_META_GENERIC("SLAVES"), /* 1 */
|
|
|
|
|
NULL,
|
2012-10-22 14:31:11 +02:00
|
|
|
};
|
2014-09-23 14:49:43 +02:00
|
|
|
#define NMC_FIELDS_DEV_SHOW_MASTER_PROP_COMMON "NAME,SLAVES"
|
2012-10-22 14:31:11 +02:00
|
|
|
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
const NmcMetaGenericInfo *const nmc_fields_dev_show_team_prop[] = {
|
|
|
|
|
NMC_META_GENERIC("NAME"), /* 0 */
|
|
|
|
|
NMC_META_GENERIC("SLAVES"), /* 1 */
|
|
|
|
|
NMC_META_GENERIC("CONFIG"), /* 2 */
|
|
|
|
|
NULL,
|
2016-05-16 14:42:41 +02:00
|
|
|
};
|
|
|
|
|
#define NMC_FIELDS_DEV_SHOW_TEAM_PROP_COMMON "NAME,SLAVES,CONFIG"
|
|
|
|
|
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
const NmcMetaGenericInfo *const nmc_fields_dev_show_vlan_prop[] = {
|
|
|
|
|
NMC_META_GENERIC("NAME"), /* 0 */
|
|
|
|
|
NMC_META_GENERIC("PARENT"), /* 1 */
|
|
|
|
|
NMC_META_GENERIC("ID"), /* 2 */
|
|
|
|
|
NULL,
|
2012-10-22 15:18:34 +02:00
|
|
|
};
|
2014-07-21 13:08:53 +02:00
|
|
|
#define NMC_FIELDS_DEV_SHOW_VLAN_PROP_COMMON "NAME,PARENT,ID"
|
2012-10-22 15:18:34 +02:00
|
|
|
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
const NmcMetaGenericInfo *const nmc_fields_dev_show_bluetooth[] = {
|
|
|
|
|
NMC_META_GENERIC("NAME"), /* 0 */
|
|
|
|
|
NMC_META_GENERIC("CAPABILITIES"), /* 1 */
|
|
|
|
|
NULL,
|
2014-09-24 12:00:47 +02:00
|
|
|
};
|
|
|
|
|
#define NMC_FIELDS_DEV_SHOW_BLUETOOTH_COMMON "NAME,CAPABILITIES"
|
|
|
|
|
|
2013-12-10 12:00:53 +01:00
|
|
|
/* Available sections for 'device show' */
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
const NmcMetaGenericInfo *const nmc_fields_dev_show_sections[] = {
|
2019-10-10 10:45:36 +02:00
|
|
|
NMC_META_GENERIC_WITH_NESTED("GENERAL", metagen_device_detail_general), /* 0 */
|
|
|
|
|
NMC_META_GENERIC_WITH_NESTED("CAPABILITIES", metagen_device_detail_capabilities), /* 1 */
|
|
|
|
|
NMC_META_GENERIC_WITH_NESTED("INTERFACE-FLAGS", metagen_device_detail_interface_flags), /* 2 */
|
|
|
|
|
NMC_META_GENERIC_WITH_NESTED("WIFI-PROPERTIES", metagen_device_detail_wifi_properties), /* 3 */
|
|
|
|
|
NMC_META_GENERIC_WITH_NESTED("AP", nmc_fields_dev_wifi_list + 1), /* 4 */
|
|
|
|
|
NMC_META_GENERIC_WITH_NESTED("WIRED-PROPERTIES",
|
|
|
|
|
metagen_device_detail_wired_properties), /* 5 */
|
|
|
|
|
NMC_META_GENERIC_WITH_NESTED("WIMAX-PROPERTIES",
|
|
|
|
|
metagen_device_detail_wimax_properties), /* 6 */
|
|
|
|
|
NMC_META_GENERIC_WITH_NESTED("NSP", nmc_fields_dev_wimax_list + 1), /* 7 */
|
|
|
|
|
NMC_META_GENERIC_WITH_NESTED("IP4", metagen_ip4_config), /* 8 */
|
|
|
|
|
NMC_META_GENERIC_WITH_NESTED("DHCP4", metagen_dhcp_config), /* 9 */
|
|
|
|
|
NMC_META_GENERIC_WITH_NESTED("IP6", metagen_ip6_config), /* 10 */
|
|
|
|
|
NMC_META_GENERIC_WITH_NESTED("DHCP6", metagen_dhcp_config), /* 11 */
|
|
|
|
|
NMC_META_GENERIC_WITH_NESTED("BOND", nmc_fields_dev_show_master_prop + 1), /* 12 */
|
|
|
|
|
NMC_META_GENERIC_WITH_NESTED("TEAM", nmc_fields_dev_show_team_prop + 1), /* 13 */
|
|
|
|
|
NMC_META_GENERIC_WITH_NESTED("BRIDGE", nmc_fields_dev_show_master_prop + 1), /* 14 */
|
|
|
|
|
NMC_META_GENERIC_WITH_NESTED("VLAN", nmc_fields_dev_show_vlan_prop + 1), /* 15 */
|
|
|
|
|
NMC_META_GENERIC_WITH_NESTED("BLUETOOTH", nmc_fields_dev_show_bluetooth + 1), /* 16 */
|
|
|
|
|
NMC_META_GENERIC_WITH_NESTED("CONNECTIONS", metagen_device_detail_connections), /* 17 */
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
NULL,
|
2013-12-10 12:00:53 +01:00
|
|
|
};
|
2013-12-16 17:08:28 +01:00
|
|
|
#define NMC_FIELDS_DEV_SHOW_SECTIONS_COMMON \
|
|
|
|
|
"GENERAL.DEVICE,GENERAL.TYPE,GENERAL.HWADDR,GENERAL.MTU,GENERAL.STATE," \
|
|
|
|
|
"GENERAL.CONNECTION,GENERAL.CON-PATH,WIRED-PROPERTIES,IP4,IP6"
|
2013-12-10 12:00:53 +01:00
|
|
|
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
const NmcMetaGenericInfo *const nmc_fields_dev_lldp_list[] = {
|
|
|
|
|
NMC_META_GENERIC("NAME"), /* 0 */
|
|
|
|
|
NMC_META_GENERIC("DEVICE"), /* 1 */
|
|
|
|
|
NMC_META_GENERIC("CHASSIS-ID"), /* 2 */
|
|
|
|
|
NMC_META_GENERIC("PORT-ID"), /* 3 */
|
|
|
|
|
NMC_META_GENERIC("PORT-DESCRIPTION"), /* 4 */
|
|
|
|
|
NMC_META_GENERIC("SYSTEM-NAME"), /* 5 */
|
|
|
|
|
NMC_META_GENERIC("SYSTEM-DESCRIPTION"), /* 6 */
|
|
|
|
|
NMC_META_GENERIC("SYSTEM-CAPABILITIES"), /* 7 */
|
|
|
|
|
NMC_META_GENERIC("IEEE-802-1-PVID"), /* 8 */
|
|
|
|
|
NMC_META_GENERIC("IEEE-802-1-PPVID"), /* 9 */
|
|
|
|
|
NMC_META_GENERIC("IEEE-802-1-PPVID-FLAGS"), /* 10 */
|
|
|
|
|
NMC_META_GENERIC("IEEE-802-1-VID"), /* 11 */
|
|
|
|
|
NMC_META_GENERIC("IEEE-802-1-VLAN-NAME"), /* 12 */
|
|
|
|
|
NMC_META_GENERIC("DESTINATION"), /* 13 */
|
|
|
|
|
NMC_META_GENERIC("CHASSIS-ID-TYPE"), /* 14 */
|
|
|
|
|
NMC_META_GENERIC("PORT-ID-TYPE"), /* 15 */
|
|
|
|
|
NULL,
|
2015-11-10 14:06:02 +01:00
|
|
|
};
|
|
|
|
|
#define NMC_FIELDS_DEV_LLDP_LIST_COMMON \
|
|
|
|
|
"DEVICE,CHASSIS-ID,PORT-ID,PORT-DESCRIPTION,SYSTEM-NAME,SYSTEM-DESCRIPTION," \
|
|
|
|
|
"SYSTEM-CAPABILITIES"
|
2010-03-18 15:39:15 +01:00
|
|
|
|
2012-04-28 22:32:21 +01:00
|
|
|
static guint progress_id = 0; /* ID of event source for displaying progress */
|
|
|
|
|
|
2010-02-25 09:52:30 -08:00
|
|
|
static void
|
|
|
|
|
usage(void)
|
|
|
|
|
{
|
2014-09-19 16:04:40 -04:00
|
|
|
g_printerr(_("Usage: nmcli device { COMMAND | help }\n\n"
|
2016-07-14 22:06:10 +02:00
|
|
|
"COMMAND := { status | show | set | connect | reapply | modify | disconnect | "
|
|
|
|
|
"delete | monitor | wifi | lldp }\n\n"
|
2014-09-19 16:04:40 -04:00
|
|
|
" status\n\n"
|
|
|
|
|
" show [<ifname>]\n\n"
|
2015-09-18 10:49:19 +02:00
|
|
|
" set [ifname] <ifname> [autoconnect yes|no] [managed yes|no]\n\n"
|
2014-09-19 16:04:40 -04:00
|
|
|
" connect <ifname>\n\n"
|
2016-04-30 14:14:31 +02:00
|
|
|
" reapply <ifname>\n\n"
|
2016-07-14 22:06:10 +02:00
|
|
|
" modify <ifname> ([+|-]<setting>.<property> <value>)+\n\n"
|
2015-03-11 19:10:58 +01:00
|
|
|
" disconnect <ifname> ...\n\n"
|
|
|
|
|
" delete <ifname> ...\n\n"
|
2015-03-27 13:11:06 +01:00
|
|
|
" monitor <ifname> ...\n\n"
|
2018-10-31 13:48:35 +01:00
|
|
|
" wifi [list [ifname <ifname>] [bssid <BSSID>] [--rescan yes|no|auto]]\n\n"
|
2014-09-19 16:04:40 -04:00
|
|
|
" wifi connect <(B)SSID> [password <password>] [wep-key-type key|phrase] [ifname "
|
|
|
|
|
"<ifname>]\n"
|
2015-07-10 13:16:21 +02:00
|
|
|
" [bssid <BSSID>] [name <name>] [private yes|no] [hidden "
|
|
|
|
|
"yes|no]\n\n"
|
2015-12-04 13:29:42 +01:00
|
|
|
" wifi hotspot [ifname <ifname>] [con-name <name>] [ssid <SSID>] [band a|bg] "
|
|
|
|
|
"[channel <channel>] [password <password>]\n\n"
|
2015-07-14 09:50:56 +02:00
|
|
|
" wifi rescan [ifname <ifname>] [[ssid <SSID to scan>] ...]\n\n"
|
2019-09-11 16:45:12 +02:00
|
|
|
" wifi show-password [ifname <ifname>]\n\n"
|
2015-11-10 14:06:02 +01:00
|
|
|
" lldp [list [ifname <ifname>]]\n\n"));
|
2010-02-25 09:52:30 -08:00
|
|
|
}
|
|
|
|
|
|
2013-12-18 14:49:06 +01:00
|
|
|
static void
|
|
|
|
|
usage_device_status(void)
|
|
|
|
|
{
|
2014-09-19 16:04:40 -04:00
|
|
|
g_printerr(
|
|
|
|
|
_("Usage: nmcli device status { help }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Show status for all devices.\n"
|
|
|
|
|
"By default, the following columns are shown:\n"
|
|
|
|
|
" DEVICE - interface name\n"
|
|
|
|
|
" TYPE - device type\n"
|
|
|
|
|
" STATE - device state\n"
|
|
|
|
|
" CONNECTION - connection activated on device (if any)\n"
|
|
|
|
|
"Displayed columns can be changed using '--fields' global option. 'status' is\n"
|
|
|
|
|
"the default command, which means 'nmcli device' calls 'nmcli device status'.\n\n"));
|
2013-12-18 14:49:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
usage_device_show(void)
|
|
|
|
|
{
|
2014-09-19 16:04:40 -04:00
|
|
|
g_printerr(_("Usage: nmcli device show { ARGUMENTS | help }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"ARGUMENTS := [<ifname>]\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Show details of device(s).\n"
|
|
|
|
|
"The command lists details for all devices, or for a given device.\n\n"));
|
2013-12-18 14:49:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
usage_device_connect(void)
|
|
|
|
|
{
|
2014-09-19 16:04:40 -04:00
|
|
|
g_printerr(_("Usage: nmcli device connect { ARGUMENTS | help }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"ARGUMENTS := <ifname>\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Connect the device.\n"
|
|
|
|
|
"NetworkManager will try to find a suitable connection that will be activated.\n"
|
|
|
|
|
"It will also consider connections that are not set to auto-connect.\n\n"));
|
2013-12-18 14:49:06 +01:00
|
|
|
}
|
|
|
|
|
|
2015-05-14 18:33:53 +02:00
|
|
|
static void
|
|
|
|
|
usage_device_reapply(void)
|
|
|
|
|
{
|
|
|
|
|
g_printerr(_("Usage: nmcli device reapply { ARGUMENTS | help }\n"
|
|
|
|
|
"\n"
|
2016-04-30 14:14:31 +02:00
|
|
|
"ARGUMENTS := <ifname>\n"
|
2015-05-14 18:33:53 +02:00
|
|
|
"\n"
|
|
|
|
|
"Attempts to update device with changes to the currently active connection\n"
|
2019-08-21 15:10:15 +02:00
|
|
|
"made since it was last applied.\n\n"));
|
2015-05-14 18:33:53 +02:00
|
|
|
}
|
|
|
|
|
|
2016-06-22 18:25:48 +02:00
|
|
|
static void
|
|
|
|
|
usage_device_modify(void)
|
|
|
|
|
{
|
2016-07-14 22:06:10 +02:00
|
|
|
g_printerr(_(
|
2020-12-13 04:13:41 +00:00
|
|
|
"Usage: nmcli device modify { ARGUMENTS | help }\n"
|
2016-06-22 18:25:48 +02:00
|
|
|
"\n"
|
|
|
|
|
"ARGUMENTS := <ifname> ([+|-]<setting>.<property> <value>)+\n"
|
|
|
|
|
"\n"
|
2020-07-01 17:20:40 -04:00
|
|
|
"Modify one or more properties that are currently active on the device without modifying\n"
|
2016-06-22 18:25:48 +02:00
|
|
|
"the connection profile. The changes have immediate effect. For multi-valued\n"
|
|
|
|
|
"properties you can use optional '+' or '-' prefix to the property name.\n"
|
|
|
|
|
"The '+' sign allows appending items instead of overwriting the whole value.\n"
|
|
|
|
|
"The '-' sign allows removing selected items instead of the whole value.\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Examples:\n"
|
|
|
|
|
"nmcli dev mod em1 ipv4.method manual ipv4.addr \"192.168.1.2/24, 10.10.1.5/8\"\n"
|
|
|
|
|
"nmcli dev mod em1 +ipv4.dns 8.8.4.4\n"
|
|
|
|
|
"nmcli dev mod em1 -ipv4.dns 1\n"
|
|
|
|
|
"nmcli dev mod em1 -ipv6.addr \"abbe::cafe/56\"\n"));
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-18 14:49:06 +01:00
|
|
|
static void
|
|
|
|
|
usage_device_disconnect(void)
|
|
|
|
|
{
|
2014-09-19 16:04:40 -04:00
|
|
|
g_printerr(_("Usage: nmcli device disconnect { ARGUMENTS | help }\n"
|
|
|
|
|
"\n"
|
2015-03-11 19:10:58 +01:00
|
|
|
"ARGUMENTS := <ifname> ...\n"
|
2014-09-19 16:04:40 -04:00
|
|
|
"\n"
|
2015-03-11 19:10:58 +01:00
|
|
|
"Disconnect devices.\n"
|
2014-09-19 16:04:40 -04:00
|
|
|
"The command disconnects the device and prevents it from auto-activating\n"
|
|
|
|
|
"further connections without user/manual intervention.\n\n"));
|
2013-12-18 14:49:06 +01:00
|
|
|
}
|
|
|
|
|
|
2014-06-19 11:25:17 +02:00
|
|
|
static void
|
|
|
|
|
usage_device_delete(void)
|
|
|
|
|
{
|
2014-09-19 16:04:40 -04:00
|
|
|
g_printerr(_("Usage: nmcli device delete { ARGUMENTS | help }\n"
|
|
|
|
|
"\n"
|
2015-03-11 19:10:58 +01:00
|
|
|
"ARGUMENTS := <ifname> ...\n"
|
2014-09-19 16:04:40 -04:00
|
|
|
"\n"
|
2015-03-11 19:10:58 +01:00
|
|
|
"Delete the software devices.\n"
|
|
|
|
|
"The command removes the interfaces. It only works for software devices\n"
|
2014-09-19 16:04:40 -04:00
|
|
|
"(like bonds, bridges, etc.). Hardware devices cannot be deleted by the\n"
|
|
|
|
|
"command.\n\n"));
|
2014-06-19 11:25:17 +02:00
|
|
|
}
|
|
|
|
|
|
2015-03-23 14:11:43 +01:00
|
|
|
static void
|
|
|
|
|
usage_device_set(void)
|
|
|
|
|
{
|
|
|
|
|
g_printerr(_("Usage: nmcli device set { ARGUMENTS | help }\n"
|
|
|
|
|
"\n"
|
2015-09-18 10:49:19 +02:00
|
|
|
"ARGUMENTS := DEVICE { PROPERTY [ PROPERTY ... ] }\n"
|
|
|
|
|
"DEVICE := [ifname] <ifname> \n"
|
2015-03-23 14:11:43 +01:00
|
|
|
"PROPERTY := { autoconnect { yes | no } |\n"
|
|
|
|
|
" { managed { yes | no }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Modify device properties.\n\n"));
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-27 13:11:06 +01:00
|
|
|
static void
|
|
|
|
|
usage_device_monitor(void)
|
|
|
|
|
{
|
|
|
|
|
g_printerr(_("Usage: nmcli device monitor { ARGUMENTS | help }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"ARGUMENTS := [<ifname>] ...\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Monitor device activity.\n"
|
|
|
|
|
"This command prints a line whenever the specified devices change state.\n"
|
|
|
|
|
"Monitors all devices in case no interface is specified.\n\n"));
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-18 14:49:06 +01:00
|
|
|
static void
|
|
|
|
|
usage_device_wifi(void)
|
|
|
|
|
{
|
2014-09-19 16:04:40 -04:00
|
|
|
g_printerr(
|
|
|
|
|
_("Usage: nmcli device wifi { ARGUMENTS | help }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Perform operation on Wi-Fi devices.\n"
|
|
|
|
|
"\n"
|
2018-10-31 13:48:35 +01:00
|
|
|
"ARGUMENTS := [list [ifname <ifname>] [bssid <BSSID>] [--rescan yes|no|auto]]\n"
|
2014-09-19 16:04:40 -04:00
|
|
|
"\n"
|
|
|
|
|
"List available Wi-Fi access points. The 'ifname' and 'bssid' options can be\n"
|
2018-11-21 11:40:35 +01:00
|
|
|
"used to list APs for a particular interface, or with a specific BSSID. The\n"
|
|
|
|
|
"--rescan flag tells whether a new Wi-Fi scan should be triggered.\n"
|
2014-09-19 16:04:40 -04:00
|
|
|
"\n"
|
|
|
|
|
"ARGUMENTS := connect <(B)SSID> [password <password>] [wep-key-type key|phrase] [ifname "
|
|
|
|
|
"<ifname>]\n"
|
2016-10-12 15:06:04 +02:00
|
|
|
" [bssid <BSSID>] [name <name>] [private yes|no] [hidden yes|no]\n"
|
2014-09-19 16:04:40 -04:00
|
|
|
"\n"
|
2018-06-12 06:52:01 +02:00
|
|
|
"Connect to a Wi-Fi network specified by SSID or BSSID. The command finds a\n"
|
|
|
|
|
"matching connection or creates one and then activates it on a device. This\n"
|
|
|
|
|
"is a command-line counterpart of clicking an SSID in a GUI client. If a\n"
|
|
|
|
|
"connection for the network already exists, it is possible to bring up the\n"
|
|
|
|
|
"existing profile as follows: nmcli con up id <name>. Note that only open,\n"
|
|
|
|
|
"WEP and WPA-PSK networks are supported if no previous connection exists.\n"
|
|
|
|
|
"It is also assumed that IP configuration is obtained via DHCP.\n"
|
2014-09-19 16:04:40 -04:00
|
|
|
"\n"
|
2016-10-12 15:06:04 +02:00
|
|
|
"ARGUMENTS := hotspot [ifname <ifname>] [con-name <name>] [ssid <SSID>]\n"
|
|
|
|
|
" [band a|bg] [channel <channel>] [password <password>]\n"
|
2015-10-02 22:46:53 +02:00
|
|
|
"\n"
|
|
|
|
|
"Create a Wi-Fi hotspot. Use 'connection down' or 'device disconnect'\n"
|
|
|
|
|
"to stop the hotspot.\n"
|
|
|
|
|
"Parameters of the hotspot can be influenced by the optional parameters:\n"
|
|
|
|
|
"ifname - Wi-Fi device to use\n"
|
|
|
|
|
"con-name - name of the created hotspot connection profile\n"
|
|
|
|
|
"ssid - SSID of the hotspot\n"
|
|
|
|
|
"band - Wi-Fi band to use\n"
|
|
|
|
|
"channel - Wi-Fi channel to use\n"
|
2015-10-13 17:48:06 +02:00
|
|
|
"password - password to use for the hotspot\n"
|
2015-10-02 22:46:53 +02:00
|
|
|
"\n"
|
2015-07-14 09:50:56 +02:00
|
|
|
"ARGUMENTS := rescan [ifname <ifname>] [[ssid <SSID to scan>] ...]\n"
|
2014-09-19 16:04:40 -04:00
|
|
|
"\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"
|
2015-07-14 09:50:56 +02:00
|
|
|
"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"));
|
2013-12-18 14:49:06 +01:00
|
|
|
}
|
|
|
|
|
|
2015-11-10 14:06:02 +01:00
|
|
|
static void
|
|
|
|
|
usage_device_lldp(void)
|
|
|
|
|
{
|
|
|
|
|
g_printerr(_("Usage: nmcli device lldp { ARGUMENTS | help }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"ARGUMENTS := [list [ifname <ifname>]]\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"List neighboring devices discovered through LLDP. The 'ifname' option can be\n"
|
|
|
|
|
"used to list neighbors for a particular interface.\n\n"));
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-04 09:19:01 +02:00
|
|
|
static void
|
|
|
|
|
usage_device_checkpoint(void)
|
|
|
|
|
{
|
|
|
|
|
g_printerr(_("Usage: nmcli device checkpoint { ARGUMENTS | help }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"ARGUMENTS := [--timeout <seconds>] -- COMMAND...\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Runs the command with a configuration checkpoint taken and asks for a\n"
|
|
|
|
|
"confirmation when finished. When the confirmation is not given, the\n"
|
|
|
|
|
"checkpoint is automatically restored after timeout.\n\n"));
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-25 09:52:30 -08:00
|
|
|
static void
|
|
|
|
|
quit(void)
|
|
|
|
|
{
|
2017-11-29 10:19:12 +01:00
|
|
|
if (nm_clear_g_source(&progress_id))
|
2012-04-28 22:32:21 +01:00
|
|
|
nmc_terminal_erase_line();
|
2017-04-06 19:39:36 +02:00
|
|
|
g_main_loop_quit(loop);
|
2010-02-25 09:52:30 -08:00
|
|
|
}
|
|
|
|
|
|
2013-04-24 15:27:11 -04:00
|
|
|
static int
|
|
|
|
|
compare_devices(const void *a, const void *b)
|
|
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NMDevice *da = *(NMDevice **) a;
|
|
|
|
|
NMDevice *db = *(NMDevice **) b;
|
2018-11-09 16:46:05 +01:00
|
|
|
NMActiveConnection *da_ac = nm_device_get_active_connection(da);
|
|
|
|
|
NMActiveConnection *db_ac = nm_device_get_active_connection(db);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-11-09 16:46:05 +01:00
|
|
|
NM_CMP_DIRECT(nm_device_get_state(db), nm_device_get_state(da));
|
|
|
|
|
NM_CMP_RETURN(nmc_active_connection_cmp(db_ac, da_ac));
|
|
|
|
|
NM_CMP_DIRECT_STRCMP0(nm_device_get_type_description(da), nm_device_get_type_description(db));
|
|
|
|
|
NM_CMP_DIRECT_STRCMP0(nm_device_get_iface(da), nm_device_get_iface(db));
|
|
|
|
|
NM_CMP_DIRECT_STRCMP0(nm_object_get_path(NM_OBJECT(da)), nm_object_get_path(NM_OBJECT(db)));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-11-09 16:46:05 +01:00
|
|
|
g_return_val_if_reached(0);
|
2013-04-24 15:27:11 -04:00
|
|
|
}
|
|
|
|
|
|
2016-07-01 21:45:43 +02:00
|
|
|
NMDevice **
|
|
|
|
|
nmc_get_devices_sorted(NMClient *client)
|
2013-04-24 15:27:11 -04:00
|
|
|
{
|
|
|
|
|
const GPtrArray *devs;
|
2021-11-09 13:28:54 +01:00
|
|
|
NMDevice **sorted;
|
2013-04-24 15:27:11 -04:00
|
|
|
|
|
|
|
|
devs = nm_client_get_devices(client);
|
|
|
|
|
|
|
|
|
|
sorted = g_new(NMDevice *, devs->len + 1);
|
2020-05-13 22:12:09 +02:00
|
|
|
if (devs->len > 0)
|
|
|
|
|
memcpy(sorted, devs->pdata, devs->len * sizeof(NMDevice *));
|
2013-04-24 15:27:11 -04:00
|
|
|
sorted[devs->len] = NULL;
|
|
|
|
|
|
|
|
|
|
qsort(sorted, devs->len, sizeof(NMDevice *), compare_devices);
|
|
|
|
|
return sorted;
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-23 10:49:20 +02:00
|
|
|
static void
|
2016-07-12 10:15:01 +02:00
|
|
|
complete_device(NMDevice **devices, const char *prefix, gboolean wifi_only)
|
2016-06-23 10:49:20 +02:00
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; devices[i]; i++) {
|
|
|
|
|
const char *iface = nm_device_get_iface(devices[i]);
|
|
|
|
|
|
2016-07-12 10:15:01 +02:00
|
|
|
if (wifi_only && !NM_IS_DEVICE_WIFI(devices[i]))
|
|
|
|
|
continue;
|
|
|
|
|
|
2016-06-23 10:49:20 +02:00
|
|
|
if (g_str_has_prefix(iface, prefix))
|
|
|
|
|
g_print("%s\n", iface);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-12 14:36:53 +02:00
|
|
|
void
|
|
|
|
|
nmc_complete_device(NMClient *client, const char *prefix, gboolean wifi_only)
|
|
|
|
|
{
|
|
|
|
|
gs_free NMDevice **devices = NULL;
|
|
|
|
|
|
|
|
|
|
devices = nmc_get_devices_sorted(client);
|
|
|
|
|
complete_device(devices, prefix, wifi_only);
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-18 11:33:14 +02:00
|
|
|
static void destroy_queue_element(gpointer data);
|
|
|
|
|
|
2022-05-04 10:21:02 +02:00
|
|
|
static GPtrArray *
|
2022-05-04 09:52:22 +02:00
|
|
|
get_device_list(NmCli *nmc, int *argc, const char *const **argv)
|
2015-03-27 12:31:08 +01:00
|
|
|
{
|
2022-05-04 09:52:22 +02:00
|
|
|
int arg_num;
|
|
|
|
|
const char *const *arg_ptr;
|
|
|
|
|
|
2020-04-05 13:05:58 +02:00
|
|
|
gs_strfreev char **arg_arr = NULL;
|
2021-11-09 13:28:54 +01:00
|
|
|
NMDevice **devices;
|
2022-05-04 10:21:02 +02:00
|
|
|
GPtrArray *queue = NULL;
|
2021-11-09 13:28:54 +01:00
|
|
|
NMDevice *device;
|
2015-03-27 12:31:08 +01:00
|
|
|
int i;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2022-05-04 09:52:22 +02:00
|
|
|
if (*argc == 0 && nmc->ask) {
|
|
|
|
|
gs_free char *line = NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2022-05-04 09:52:22 +02:00
|
|
|
line = nmc_readline(&nmc->nmc_config, PROMPT_INTERFACES);
|
|
|
|
|
nmc_string_to_arg_array(line, NULL, FALSE, &arg_arr, &arg_num);
|
|
|
|
|
arg_ptr = (const char *const *) arg_arr;
|
|
|
|
|
|
|
|
|
|
argc = &arg_num;
|
|
|
|
|
argv = &arg_ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*argc == 0) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: No interface specified."));
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
2022-12-22 11:23:46 +01:00
|
|
|
return NULL;
|
2015-03-27 12:31:08 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-07-01 21:45:43 +02:00
|
|
|
devices = nmc_get_devices_sorted(nmc->client);
|
2022-05-04 09:52:22 +02:00
|
|
|
while (*argc > 0) {
|
2022-05-04 09:56:10 +02:00
|
|
|
if (strcmp(**argv, "--") == 0) {
|
|
|
|
|
(*argc)--;
|
|
|
|
|
(*argv)++;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-04 09:52:22 +02:00
|
|
|
if (*argc == 1 && nmc->complete)
|
|
|
|
|
complete_device(devices, **argv, FALSE);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-03-27 12:31:08 +01:00
|
|
|
device = NULL;
|
|
|
|
|
for (i = 0; devices[i]; i++) {
|
2022-05-04 09:52:22 +02:00
|
|
|
if (!g_strcmp0(nm_device_get_iface(devices[i]), **argv)) {
|
2015-03-27 12:31:08 +01:00
|
|
|
device = devices[i];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-03-27 12:31:08 +01:00
|
|
|
if (device) {
|
2022-05-04 10:21:02 +02:00
|
|
|
if (!queue)
|
2022-05-18 11:33:14 +02:00
|
|
|
queue = g_ptr_array_new_with_free_func(destroy_queue_element);
|
2022-05-04 10:21:02 +02:00
|
|
|
if (!g_ptr_array_find(queue, device, NULL))
|
2022-05-18 11:33:14 +02:00
|
|
|
g_ptr_array_add(queue, g_object_ref(device));
|
2015-03-27 12:31:08 +01:00
|
|
|
else
|
2022-05-04 09:52:22 +02:00
|
|
|
g_printerr(_("Warning: argument '%s' is duplicated.\n"), **argv);
|
2015-03-27 12:31:08 +01:00
|
|
|
} else {
|
2016-06-23 10:49:20 +02:00
|
|
|
if (!nmc->complete)
|
2022-05-04 09:52:22 +02:00
|
|
|
g_printerr(_("Error: Device '%s' not found.\n"), **argv);
|
2015-03-27 12:31:08 +01:00
|
|
|
g_string_printf(nmc->return_text, _("Error: not all devices found."));
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-03-27 12:31:08 +01:00
|
|
|
/* Take next argument */
|
2022-05-04 09:52:22 +02:00
|
|
|
next_arg(nmc->ask ? NULL : nmc, argc, argv, NULL);
|
2015-03-27 12:31:08 +01:00
|
|
|
}
|
|
|
|
|
g_free(devices);
|
|
|
|
|
|
|
|
|
|
return queue;
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-27 11:54:25 +02:00
|
|
|
static NMDevice *
|
2020-04-05 13:05:58 +02:00
|
|
|
get_device(NmCli *nmc, int *argc, const char *const **argv, GError **error)
|
2016-06-27 11:54:25 +02:00
|
|
|
{
|
|
|
|
|
gs_free NMDevice **devices = NULL;
|
2021-11-09 13:28:54 +01:00
|
|
|
gs_free char *ifname_ask = NULL;
|
|
|
|
|
const char *ifname = NULL;
|
2016-06-27 11:54:25 +02:00
|
|
|
int i;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-27 11:54:25 +02:00
|
|
|
if (*argc == 0) {
|
2018-10-09 11:50:26 +02:00
|
|
|
if (nmc->ask) {
|
|
|
|
|
ifname = ifname_ask = nmc_readline(&nmc->nmc_config, PROMPT_INTERFACE);
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-27 11:54:25 +02:00
|
|
|
if (!ifname_ask) {
|
|
|
|
|
g_set_error_literal(error,
|
|
|
|
|
NMCLI_ERROR,
|
|
|
|
|
NMC_RESULT_ERROR_USER_INPUT,
|
2016-07-15 11:38:01 +02:00
|
|
|
_("No interface specified"));
|
2016-06-27 11:54:25 +02:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ifname = **argv;
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg(nmc, argc, argv, NULL);
|
2016-06-27 11:54:25 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-07-01 21:45:43 +02:00
|
|
|
devices = nmc_get_devices_sorted(nmc->client);
|
2016-06-27 11:54:25 +02:00
|
|
|
for (i = 0; devices[i]; i++) {
|
2016-06-23 10:49:20 +02:00
|
|
|
if (!g_strcmp0(nm_device_get_iface(devices[i]), ifname))
|
|
|
|
|
break;
|
2016-06-27 11:54:25 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-23 10:49:20 +02:00
|
|
|
if (nmc->complete && !*argc)
|
2016-07-12 10:15:01 +02:00
|
|
|
complete_device(devices, ifname, FALSE);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-23 10:49:20 +02:00
|
|
|
if (devices[i] == NULL) {
|
|
|
|
|
g_set_error(error,
|
|
|
|
|
NMCLI_ERROR,
|
|
|
|
|
NMC_RESULT_ERROR_NOT_FOUND,
|
2016-07-15 11:38:01 +02:00
|
|
|
_("Device '%s' not found"),
|
|
|
|
|
ifname);
|
2016-06-23 10:49:20 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-23 10:49:20 +02:00
|
|
|
return devices[i];
|
2016-06-27 11:54:25 +02:00
|
|
|
}
|
|
|
|
|
|
2022-03-08 12:27:30 +01:00
|
|
|
static bool
|
|
|
|
|
_ap_is_wep(NMAccessPoint *ap)
|
|
|
|
|
{
|
|
|
|
|
NM80211ApFlags flags = nm_access_point_get_flags(ap);
|
|
|
|
|
NM80211ApSecurityFlags wpa_flags = nm_access_point_get_wpa_flags(ap);
|
|
|
|
|
NM80211ApSecurityFlags rsn_flags = nm_access_point_get_rsn_flags(ap);
|
|
|
|
|
|
|
|
|
|
if ((flags & NM_802_11_AP_FLAGS_PRIVACY) && (wpa_flags == NM_802_11_AP_SEC_NONE)
|
|
|
|
|
&& (rsn_flags == NM_802_11_AP_SEC_NONE)) {
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-26 11:51:07 +01:00
|
|
|
static int
|
|
|
|
|
compare_aps(gconstpointer a, gconstpointer b, gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMAccessPoint *apa = *(NMAccessPoint **) a;
|
|
|
|
|
NMAccessPoint *apb = *(NMAccessPoint **) b;
|
|
|
|
|
|
2022-03-08 12:09:05 +01:00
|
|
|
/* Sort the deprecated WEP connections last. */
|
2022-05-12 12:32:50 +02:00
|
|
|
NM_CMP_DIRECT(_ap_is_wep(apa), _ap_is_wep(apb));
|
2022-03-08 12:09:05 +01:00
|
|
|
|
2020-03-09 17:08:08 +01:00
|
|
|
NM_CMP_DIRECT(nm_access_point_get_strength(apb), nm_access_point_get_strength(apa));
|
|
|
|
|
NM_CMP_DIRECT(nm_access_point_get_frequency(apa), nm_access_point_get_frequency(apb));
|
|
|
|
|
NM_CMP_DIRECT(nm_access_point_get_max_bitrate(apb), nm_access_point_get_max_bitrate(apa));
|
2015-02-26 11:51:07 +01:00
|
|
|
|
2020-03-09 17:08:08 +01:00
|
|
|
/* as fallback, just give it some stable order and use the D-Bus path (literally). */
|
|
|
|
|
NM_CMP_DIRECT_STRCMP0(nm_object_get_path(NM_OBJECT(apa)), nm_object_get_path(NM_OBJECT(apb)));
|
2015-02-26 11:51:07 +01:00
|
|
|
|
2020-03-09 17:08:08 +01:00
|
|
|
return 0;
|
2015-02-26 11:51:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static GPtrArray *
|
|
|
|
|
sort_access_points(const GPtrArray *aps)
|
|
|
|
|
{
|
|
|
|
|
GPtrArray *sorted;
|
2020-03-09 17:10:20 +01:00
|
|
|
guint i;
|
2015-02-26 11:51:07 +01:00
|
|
|
|
2016-02-04 16:42:00 +01:00
|
|
|
g_return_val_if_fail(aps, NULL);
|
|
|
|
|
|
2015-02-26 11:51:07 +01:00
|
|
|
sorted = g_ptr_array_sized_new(aps->len);
|
2020-03-09 17:10:20 +01:00
|
|
|
g_ptr_array_set_free_func(sorted, nm_g_object_unref);
|
2016-02-04 16:42:00 +01:00
|
|
|
for (i = 0; i < aps->len; i++)
|
2020-03-09 17:10:20 +01:00
|
|
|
g_ptr_array_add(sorted, g_object_ref(aps->pdata[i]));
|
2015-02-26 11:51:07 +01:00
|
|
|
g_ptr_array_sort_with_data(sorted, compare_aps, NULL);
|
|
|
|
|
return sorted;
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-18 15:39:15 +01:00
|
|
|
typedef struct {
|
2022-02-28 18:49:25 +01:00
|
|
|
NmCli *nmc;
|
|
|
|
|
NMAccessPoint *active_ap;
|
|
|
|
|
const char *device;
|
|
|
|
|
GPtrArray *output_data;
|
2022-02-28 19:20:37 +01:00
|
|
|
int *p_index;
|
|
|
|
|
guint32 output_flags;
|
2010-03-18 15:39:15 +01:00
|
|
|
} APInfo;
|
|
|
|
|
|
2010-02-25 09:52:30 -08:00
|
|
|
static void
|
2022-02-28 19:20:37 +01:00
|
|
|
fill_output_access_point(NMAccessPoint *ap, const APInfo *info)
|
2010-02-25 09:52:30 -08:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NmcOutputField *arr;
|
2022-02-28 18:49:25 +01:00
|
|
|
gboolean active;
|
2011-02-21 15:41:12 +01:00
|
|
|
NM80211ApSecurityFlags wpa_flags, rsn_flags;
|
|
|
|
|
guint32 freq, bitrate;
|
2010-03-18 15:39:15 +01:00
|
|
|
guint8 strength;
|
2021-11-09 13:28:54 +01:00
|
|
|
GBytes *ssid;
|
|
|
|
|
const char *bssid;
|
2010-03-18 15:39:15 +01:00
|
|
|
NM80211Mode mode;
|
2021-11-09 13:28:54 +01:00
|
|
|
char *channel_str;
|
|
|
|
|
char *freq_str;
|
|
|
|
|
char *ssid_str = NULL;
|
|
|
|
|
char *ssid_hex_str = NULL;
|
|
|
|
|
char *bitrate_str;
|
|
|
|
|
char *strength_str;
|
|
|
|
|
char *wpa_flags_str;
|
|
|
|
|
char *rsn_flags_str;
|
|
|
|
|
GString *security_str;
|
|
|
|
|
char *ap_name;
|
|
|
|
|
const char *sig_bars;
|
2021-05-27 10:41:45 +02:00
|
|
|
NMMetaColor color;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2022-02-28 18:49:25 +01:00
|
|
|
active = (info->active_ap == ap);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2010-03-18 15:39:15 +01:00
|
|
|
/* Get AP properties */
|
|
|
|
|
wpa_flags = nm_access_point_get_wpa_flags(ap);
|
|
|
|
|
rsn_flags = nm_access_point_get_rsn_flags(ap);
|
|
|
|
|
ssid = nm_access_point_get_ssid(ap);
|
2011-09-06 13:37:23 +02:00
|
|
|
bssid = nm_access_point_get_bssid(ap);
|
2010-03-18 15:39:15 +01:00
|
|
|
freq = nm_access_point_get_frequency(ap);
|
|
|
|
|
mode = nm_access_point_get_mode(ap);
|
|
|
|
|
bitrate = nm_access_point_get_max_bitrate(ap);
|
2013-10-31 14:13:33 +01:00
|
|
|
strength = MIN(nm_access_point_get_strength(ap), 100);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2010-03-18 15:39:15 +01:00
|
|
|
/* Convert to strings */
|
2014-01-08 11:39:22 -06:00
|
|
|
if (ssid) {
|
2014-07-02 14:25:43 -04:00
|
|
|
const guint8 *ssid_data;
|
|
|
|
|
gsize ssid_len;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2014-07-02 14:25:43 -04:00
|
|
|
ssid_data = g_bytes_get_data(ssid, &ssid_len);
|
|
|
|
|
ssid_str = nm_utils_ssid_to_utf8(ssid_data, ssid_len);
|
|
|
|
|
ssid_hex_str = ssid_to_hex((const char *) ssid_data, ssid_len);
|
2014-01-08 11:39:22 -06:00
|
|
|
}
|
2013-05-17 10:38:09 +02:00
|
|
|
channel_str = g_strdup_printf("%u", nm_utils_wifi_freq_to_channel(freq));
|
2010-03-18 15:39:15 +01:00
|
|
|
freq_str = g_strdup_printf(_("%u MHz"), freq);
|
2014-04-01 14:56:32 +02:00
|
|
|
bitrate_str = g_strdup_printf(_("%u Mbit/s"), bitrate / 1000);
|
2020-05-14 11:53:37 +02:00
|
|
|
strength_str = nm_strdup_int(strength);
|
2020-03-11 13:10:04 +01:00
|
|
|
wpa_flags_str = ap_wpa_rsn_flags_to_string(wpa_flags, NM_META_ACCESSOR_GET_TYPE_PRETTY);
|
|
|
|
|
rsn_flags_str = ap_wpa_rsn_flags_to_string(rsn_flags, NM_META_ACCESSOR_GET_TYPE_PRETTY);
|
2017-12-15 16:46:07 +01:00
|
|
|
sig_bars = nmc_wifi_strength_bars(strength);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2010-03-18 15:39:15 +01:00
|
|
|
security_str = g_string_new(NULL);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2022-03-08 12:27:30 +01:00
|
|
|
if (_ap_is_wep(ap)) {
|
2019-01-22 11:17:16 +01:00
|
|
|
g_string_append(security_str, "WEP ");
|
2022-03-08 12:27:30 +01:00
|
|
|
} else {
|
|
|
|
|
if (wpa_flags != NM_802_11_AP_SEC_NONE) {
|
|
|
|
|
g_string_append(security_str, "WPA1 ");
|
|
|
|
|
}
|
|
|
|
|
if ((rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK)
|
|
|
|
|
|| (rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) {
|
|
|
|
|
g_string_append(security_str, "WPA2 ");
|
|
|
|
|
}
|
|
|
|
|
if (rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_SAE) {
|
|
|
|
|
g_string_append(security_str, "WPA3 ");
|
|
|
|
|
}
|
2022-06-16 19:59:01 +02:00
|
|
|
if (NM_FLAGS_ANY(rsn_flags, NM_802_11_AP_SEC_KEY_MGMT_OWE)) {
|
2022-03-08 12:27:30 +01:00
|
|
|
g_string_append(security_str, "OWE ");
|
2022-06-16 19:59:01 +02:00
|
|
|
} else if (NM_FLAGS_ANY(rsn_flags, NM_802_11_AP_SEC_KEY_MGMT_OWE_TM)) {
|
|
|
|
|
g_string_append(security_str, "OWE-TM ");
|
2022-03-08 12:27:30 +01:00
|
|
|
}
|
|
|
|
|
if ((wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)
|
|
|
|
|
|| (rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) {
|
|
|
|
|
g_string_append(security_str, "802.1X ");
|
|
|
|
|
}
|
2013-05-24 22:36:24 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2010-03-18 15:39:15 +01:00
|
|
|
if (security_str->len > 0)
|
|
|
|
|
g_string_truncate(security_str, security_str->len - 1); /* Chop off last space */
|
2020-09-28 16:03:33 +02:00
|
|
|
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
arr = nmc_dup_fields_array((const NMMetaAbstractInfo *const *) nmc_fields_dev_wifi_list,
|
2013-05-22 08:37:50 +02:00
|
|
|
info->output_flags);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2022-02-28 19:20:37 +01:00
|
|
|
ap_name = g_strdup_printf("AP[%d]", ++(*info->p_index)); /* AP */
|
2013-05-22 08:37:50 +02:00
|
|
|
set_val_str(arr, 0, ap_name);
|
|
|
|
|
set_val_str(arr, 1, ssid_str);
|
2013-05-16 16:26:15 +02:00
|
|
|
set_val_str(arr, 2, ssid_hex_str);
|
|
|
|
|
set_val_strc(arr, 3, bssid);
|
|
|
|
|
set_val_strc(arr,
|
|
|
|
|
4,
|
|
|
|
|
mode == NM_802_11_MODE_ADHOC ? _("Ad-Hoc")
|
2013-05-20 15:40:58 +02:00
|
|
|
: mode == NM_802_11_MODE_INFRA ? _("Infra")
|
2019-01-24 15:33:41 +01:00
|
|
|
: mode == NM_802_11_MODE_MESH ? _("Mesh")
|
2013-05-20 15:40:58 +02:00
|
|
|
: _("N/A"));
|
2013-05-17 10:38:09 +02:00
|
|
|
set_val_str(arr, 5, channel_str);
|
|
|
|
|
set_val_str(arr, 6, freq_str);
|
|
|
|
|
set_val_str(arr, 7, bitrate_str);
|
|
|
|
|
set_val_str(arr, 8, strength_str);
|
2013-05-17 11:23:21 +02:00
|
|
|
set_val_strc(arr, 9, sig_bars);
|
cli: workaround coverity false positive in "devices.c"
Error: RESOURCE_LEAK (CWE-772): [#def268] [important]
NetworkManager-1.31.5/src/nmcli/devices.c:1367: alloc_fn: Storage is returned from allocation function "g_string_free".
NetworkManager-1.31.5/src/nmcli/devices.c:1367: leaked_storage: Ignoring storage allocated by "g_string_free(security_str, 0)" leaks it.
# 1365| g_ptr_array_add(info->output_data, arr);
# 1366|
# 1367|-> g_string_free(security_str, FALSE);
# 1368| }
# 1369|
Error: RESOURCE_LEAK (CWE-772): [#def269] [important]
NetworkManager-1.31.5/src/nmcli/devices.c:1451: alloc_fn: Storage is returned from allocation function "g_string_free".
NetworkManager-1.31.5/src/nmcli/devices.c:1451: leaked_storage: Ignoring storage allocated by "g_string_free(slaves_str, 0)" leaks it.
# 1449| print_data(&nmc->nmc_config, &nmc->pager_data, out_indices, NULL, 0, &out);
# 1450|
# 1451|-> g_string_free(slaves_str, FALSE);
# 1452|
# 1453| return TRUE;
Error: RESOURCE_LEAK (CWE-772): [#def270] [important]
NetworkManager-1.31.5/src/nmcli/devices.c:1517: alloc_fn: Storage is returned from allocation function "g_string_free".
NetworkManager-1.31.5/src/nmcli/devices.c:1517: leaked_storage: Ignoring storage allocated by "g_string_free(slaves_str, 0)" leaks it.
# 1515| print_data(&nmc->nmc_config, &nmc->pager_data, out_indices, NULL, 0, &out);
# 1516|
# 1517|-> g_string_free(slaves_str, FALSE);
# 1518|
# 1519| return TRUE;
2021-05-27 10:34:39 +02:00
|
|
|
set_val_str(arr, 10, g_string_free(security_str, FALSE));
|
2013-05-17 11:23:21 +02:00
|
|
|
set_val_str(arr, 11, wpa_flags_str);
|
|
|
|
|
set_val_str(arr, 12, rsn_flags_str);
|
|
|
|
|
set_val_strc(arr, 13, info->device);
|
|
|
|
|
set_val_strc(arr, 14, active ? _("yes") : _("no"));
|
2013-05-20 16:36:20 +02:00
|
|
|
set_val_strc(arr, 15, active ? "*" : " ");
|
|
|
|
|
set_val_strc(arr, 16, nm_object_get_path(NM_OBJECT(ap)));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-02-24 15:10:57 +01:00
|
|
|
/* Set colors */
|
2018-03-29 12:31:33 +02:00
|
|
|
color = wifi_signal_to_color(strength);
|
2022-03-08 12:09:05 +01:00
|
|
|
if (_ap_is_wep(ap))
|
|
|
|
|
color = NM_META_COLOR_WIFI_DEPRECATED;
|
2016-07-01 21:45:43 +02:00
|
|
|
set_val_color_all(arr, color);
|
2015-02-24 15:10:57 +01:00
|
|
|
if (active)
|
2018-03-29 12:31:33 +02:00
|
|
|
arr[15].color = NM_META_COLOR_CONNECTION_ACTIVATED;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 14:56:19 +02:00
|
|
|
g_ptr_array_add(info->output_data, arr);
|
2010-02-25 09:52:30 -08:00
|
|
|
}
|
|
|
|
|
|
2022-02-28 19:20:37 +01:00
|
|
|
static void
|
|
|
|
|
fill_output_access_point_void(gpointer data, gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
fill_output_access_point(data, user_data);
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-24 12:00:47 +02:00
|
|
|
static char *
|
|
|
|
|
bluetooth_caps_to_string(NMBluetoothCapabilities caps)
|
|
|
|
|
{
|
|
|
|
|
char *caps_str[8]; /* Enough space for caps and terminating NULL */
|
|
|
|
|
char *ret_str;
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
|
|
if (caps & NM_BT_CAPABILITY_DUN)
|
|
|
|
|
caps_str[i++] = g_strdup("DUN");
|
|
|
|
|
if (caps & NM_BT_CAPABILITY_NAP)
|
|
|
|
|
caps_str[i++] = g_strdup("NAP");
|
|
|
|
|
|
|
|
|
|
if (i == 0)
|
|
|
|
|
caps_str[i++] = g_strdup(_("(none)"));
|
|
|
|
|
|
|
|
|
|
caps_str[i] = NULL;
|
|
|
|
|
|
|
|
|
|
ret_str = g_strjoinv(" ", caps_str);
|
|
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
while (caps_str[i])
|
|
|
|
|
g_free(caps_str[i++]);
|
|
|
|
|
|
|
|
|
|
return ret_str;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-31 13:21:47 +02:00
|
|
|
static char *
|
2013-05-22 08:37:50 +02:00
|
|
|
construct_header_name(const char *base, const char *spec)
|
|
|
|
|
{
|
|
|
|
|
if (spec == NULL)
|
2017-03-31 13:21:47 +02:00
|
|
|
return g_strdup(base);
|
2013-05-22 08:37:50 +02:00
|
|
|
|
2017-03-31 13:21:47 +02:00
|
|
|
return g_strdup_printf("%s (%s)", base, spec);
|
2013-05-22 08:37:50 +02:00
|
|
|
}
|
2010-02-25 09:52:30 -08:00
|
|
|
|
2014-09-23 14:49:43 +02:00
|
|
|
static gboolean
|
2021-11-09 13:28:54 +01:00
|
|
|
print_bond_bridge_info(NMDevice *device,
|
|
|
|
|
NmCli *nmc,
|
2016-05-16 14:42:41 +02:00
|
|
|
const char *group_prefix,
|
|
|
|
|
const char *one_field)
|
2014-09-23 14:49:43 +02:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
const GPtrArray *slaves = NULL;
|
|
|
|
|
GString *slaves_str;
|
2014-09-23 14:49:43 +02:00
|
|
|
int idx;
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
const NMMetaAbstractInfo *const *tmpl;
|
2021-11-09 13:28:54 +01:00
|
|
|
NmcOutputField *arr;
|
2017-03-30 14:56:19 +02:00
|
|
|
NMC_OUTPUT_DATA_DEFINE_SCOPED(out);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2014-09-23 14:49:43 +02:00
|
|
|
if (NM_IS_DEVICE_BOND(device))
|
|
|
|
|
slaves = nm_device_bond_get_slaves(NM_DEVICE_BOND(device));
|
|
|
|
|
else if (NM_IS_DEVICE_BRIDGE(device))
|
|
|
|
|
slaves = nm_device_bridge_get_slaves(NM_DEVICE_BRIDGE(device));
|
2016-05-16 14:42:41 +02:00
|
|
|
else
|
|
|
|
|
g_return_val_if_reached(FALSE);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2014-09-23 14:49:43 +02:00
|
|
|
slaves_str = g_string_new(NULL);
|
|
|
|
|
for (idx = 0; slaves && idx < slaves->len; idx++) {
|
2021-11-09 13:28:54 +01:00
|
|
|
NMDevice *slave = g_ptr_array_index(slaves, idx);
|
2014-09-23 14:49:43 +02:00
|
|
|
const char *iface = nm_device_get_iface(slave);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2014-09-23 14:49:43 +02:00
|
|
|
if (iface) {
|
|
|
|
|
g_string_append(slaves_str, iface);
|
|
|
|
|
g_string_append_c(slaves_str, ' ');
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
}
|
2014-09-23 14:49:43 +02:00
|
|
|
if (slaves_str->len > 0)
|
|
|
|
|
g_string_truncate(slaves_str, slaves_str->len - 1); /* Chop off last space */
|
2020-09-28 16:03:33 +02:00
|
|
|
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
tmpl = (const NMMetaAbstractInfo *const *) nmc_fields_dev_show_master_prop;
|
|
|
|
|
out_indices = parse_output_fields(one_field, tmpl, FALSE, NULL, NULL);
|
|
|
|
|
arr = nmc_dup_fields_array(tmpl, NMC_OF_FLAG_FIELD_NAMES);
|
2017-03-30 14:56:19 +02:00
|
|
|
g_ptr_array_add(out.output_data, arr);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
arr = nmc_dup_fields_array(tmpl, NMC_OF_FLAG_SECTION_PREFIX);
|
2014-09-23 14:49:43 +02:00
|
|
|
set_val_strc(arr, 0, group_prefix); /* i.e. BOND, TEAM, BRIDGE */
|
cli: workaround coverity false positive in "devices.c"
Error: RESOURCE_LEAK (CWE-772): [#def268] [important]
NetworkManager-1.31.5/src/nmcli/devices.c:1367: alloc_fn: Storage is returned from allocation function "g_string_free".
NetworkManager-1.31.5/src/nmcli/devices.c:1367: leaked_storage: Ignoring storage allocated by "g_string_free(security_str, 0)" leaks it.
# 1365| g_ptr_array_add(info->output_data, arr);
# 1366|
# 1367|-> g_string_free(security_str, FALSE);
# 1368| }
# 1369|
Error: RESOURCE_LEAK (CWE-772): [#def269] [important]
NetworkManager-1.31.5/src/nmcli/devices.c:1451: alloc_fn: Storage is returned from allocation function "g_string_free".
NetworkManager-1.31.5/src/nmcli/devices.c:1451: leaked_storage: Ignoring storage allocated by "g_string_free(slaves_str, 0)" leaks it.
# 1449| print_data(&nmc->nmc_config, &nmc->pager_data, out_indices, NULL, 0, &out);
# 1450|
# 1451|-> g_string_free(slaves_str, FALSE);
# 1452|
# 1453| return TRUE;
Error: RESOURCE_LEAK (CWE-772): [#def270] [important]
NetworkManager-1.31.5/src/nmcli/devices.c:1517: alloc_fn: Storage is returned from allocation function "g_string_free".
NetworkManager-1.31.5/src/nmcli/devices.c:1517: leaked_storage: Ignoring storage allocated by "g_string_free(slaves_str, 0)" leaks it.
# 1515| print_data(&nmc->nmc_config, &nmc->pager_data, out_indices, NULL, 0, &out);
# 1516|
# 1517|-> g_string_free(slaves_str, FALSE);
# 1518|
# 1519| return TRUE;
2021-05-27 10:34:39 +02:00
|
|
|
set_val_str(arr, 1, g_string_free(slaves_str, FALSE));
|
2017-03-30 14:56:19 +02:00
|
|
|
g_ptr_array_add(out.output_data, arr);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 14:56:19 +02:00
|
|
|
print_data_prepare_width(out.output_data);
|
2020-04-02 19:10:15 +02:00
|
|
|
print_data(&nmc->nmc_config, &nmc->pager_data, out_indices, NULL, 0, &out);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2014-09-23 14:49:43 +02:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-16 14:42:41 +02:00
|
|
|
static char *
|
|
|
|
|
sanitize_team_config(const char *config)
|
|
|
|
|
{
|
|
|
|
|
char *ret;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (!config)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
ret = g_strdup(config);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < strlen(ret); i++) {
|
|
|
|
|
if (ret[i] == '\n')
|
|
|
|
|
ret[i] = ' ';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
print_team_info(NMDevice *device, NmCli *nmc, const char *group_prefix, const char *one_field)
|
|
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
const GPtrArray *slaves = NULL;
|
|
|
|
|
GString *slaves_str;
|
2016-05-16 14:42:41 +02:00
|
|
|
int idx;
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
const NMMetaAbstractInfo *const *tmpl;
|
2021-11-09 13:28:54 +01:00
|
|
|
NmcOutputField *arr;
|
2017-03-30 14:56:19 +02:00
|
|
|
NMC_OUTPUT_DATA_DEFINE_SCOPED(out);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-05-16 14:42:41 +02:00
|
|
|
if (NM_IS_DEVICE_TEAM(device))
|
|
|
|
|
slaves = nm_device_team_get_slaves(NM_DEVICE_TEAM(device));
|
|
|
|
|
else
|
|
|
|
|
g_return_val_if_reached(FALSE);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-05-16 14:42:41 +02:00
|
|
|
slaves_str = g_string_new(NULL);
|
|
|
|
|
for (idx = 0; slaves && idx < slaves->len; idx++) {
|
2021-11-09 13:28:54 +01:00
|
|
|
NMDevice *slave = g_ptr_array_index(slaves, idx);
|
2016-05-16 14:42:41 +02:00
|
|
|
const char *iface = nm_device_get_iface(slave);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-05-16 14:42:41 +02:00
|
|
|
if (iface) {
|
|
|
|
|
g_string_append(slaves_str, iface);
|
|
|
|
|
g_string_append_c(slaves_str, ' ');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (slaves_str->len > 0)
|
|
|
|
|
g_string_truncate(slaves_str, slaves_str->len - 1); /* Chop off last space */
|
2020-09-28 16:03:33 +02:00
|
|
|
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
tmpl = (const NMMetaAbstractInfo *const *) nmc_fields_dev_show_team_prop;
|
|
|
|
|
out_indices = parse_output_fields(one_field, tmpl, FALSE, NULL, NULL);
|
|
|
|
|
arr = nmc_dup_fields_array(tmpl, NMC_OF_FLAG_FIELD_NAMES);
|
2017-03-30 14:56:19 +02:00
|
|
|
g_ptr_array_add(out.output_data, arr);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
arr = nmc_dup_fields_array(tmpl, NMC_OF_FLAG_SECTION_PREFIX);
|
2016-05-16 14:42:41 +02:00
|
|
|
set_val_strc(arr, 0, group_prefix); /* TEAM */
|
cli: workaround coverity false positive in "devices.c"
Error: RESOURCE_LEAK (CWE-772): [#def268] [important]
NetworkManager-1.31.5/src/nmcli/devices.c:1367: alloc_fn: Storage is returned from allocation function "g_string_free".
NetworkManager-1.31.5/src/nmcli/devices.c:1367: leaked_storage: Ignoring storage allocated by "g_string_free(security_str, 0)" leaks it.
# 1365| g_ptr_array_add(info->output_data, arr);
# 1366|
# 1367|-> g_string_free(security_str, FALSE);
# 1368| }
# 1369|
Error: RESOURCE_LEAK (CWE-772): [#def269] [important]
NetworkManager-1.31.5/src/nmcli/devices.c:1451: alloc_fn: Storage is returned from allocation function "g_string_free".
NetworkManager-1.31.5/src/nmcli/devices.c:1451: leaked_storage: Ignoring storage allocated by "g_string_free(slaves_str, 0)" leaks it.
# 1449| print_data(&nmc->nmc_config, &nmc->pager_data, out_indices, NULL, 0, &out);
# 1450|
# 1451|-> g_string_free(slaves_str, FALSE);
# 1452|
# 1453| return TRUE;
Error: RESOURCE_LEAK (CWE-772): [#def270] [important]
NetworkManager-1.31.5/src/nmcli/devices.c:1517: alloc_fn: Storage is returned from allocation function "g_string_free".
NetworkManager-1.31.5/src/nmcli/devices.c:1517: leaked_storage: Ignoring storage allocated by "g_string_free(slaves_str, 0)" leaks it.
# 1515| print_data(&nmc->nmc_config, &nmc->pager_data, out_indices, NULL, 0, &out);
# 1516|
# 1517|-> g_string_free(slaves_str, FALSE);
# 1518|
# 1519| return TRUE;
2021-05-27 10:34:39 +02:00
|
|
|
set_val_str(arr, 1, g_string_free(slaves_str, FALSE));
|
2016-05-16 14:42:41 +02:00
|
|
|
set_val_str(arr, 2, sanitize_team_config(nm_device_team_get_config(NM_DEVICE_TEAM(device))));
|
2017-03-30 14:56:19 +02:00
|
|
|
g_ptr_array_add(out.output_data, arr);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 14:56:19 +02:00
|
|
|
print_data_prepare_width(out.output_data);
|
2020-04-02 19:10:15 +02:00
|
|
|
print_data(&nmc->nmc_config, &nmc->pager_data, out_indices, NULL, 0, &out);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-05-16 14:42:41 +02:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-10 13:19:14 +01:00
|
|
|
static gboolean
|
2013-05-22 08:37:50 +02:00
|
|
|
show_device_info(NMDevice *device, NmCli *nmc)
|
2010-02-25 09:52:30 -08:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
GError *error = NULL;
|
2010-03-25 13:39:49 -07:00
|
|
|
NMDeviceState state = NM_DEVICE_STATE_UNKNOWN;
|
2021-11-09 13:28:54 +01:00
|
|
|
GArray *sections_array;
|
2010-03-24 19:05:35 +01:00
|
|
|
int k;
|
2021-11-09 13:28:54 +01:00
|
|
|
const char *fields_str = NULL;
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
const NMMetaAbstractInfo *const *tmpl;
|
2021-11-09 13:28:54 +01:00
|
|
|
NmcOutputField *arr;
|
2010-03-24 19:05:35 +01:00
|
|
|
gboolean was_output = FALSE;
|
2021-11-09 13:28:54 +01:00
|
|
|
NMIPConfig *cfg4, *cfg6;
|
|
|
|
|
NMDhcpConfig *dhcp4, *dhcp6;
|
|
|
|
|
const char *base_hdr = _("Device details");
|
|
|
|
|
GPtrArray *fields_in_section = NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-02-11 15:17:03 +01:00
|
|
|
if (!nmc->required_fields || g_ascii_strcasecmp(nmc->required_fields, "common") == 0)
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
fields_str = NMC_FIELDS_DEV_SHOW_SECTIONS_COMMON;
|
2020-02-11 15:17:03 +01:00
|
|
|
else if (g_ascii_strcasecmp(nmc->required_fields, "all") == 0) {
|
2020-05-06 23:18:54 +02:00
|
|
|
/* pass */
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
} else
|
2010-03-24 19:05:35 +01:00
|
|
|
fields_str = nmc->required_fields;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
sections_array =
|
|
|
|
|
parse_output_fields(fields_str,
|
|
|
|
|
(const NMMetaAbstractInfo *const *) nmc_fields_dev_show_sections,
|
|
|
|
|
TRUE,
|
|
|
|
|
&fields_in_section,
|
|
|
|
|
&error);
|
2010-03-24 19:05:35 +01:00
|
|
|
if (error) {
|
2013-12-10 12:00:53 +01:00
|
|
|
g_string_printf(nmc->return_text, _("Error: 'device show': %s"), error->message);
|
2010-03-24 19:05:35 +01:00
|
|
|
g_error_free(error);
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
2014-01-10 13:19:14 +01:00
|
|
|
return FALSE;
|
2010-03-24 19:05:35 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 14:56:19 +02:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
gs_unref_array GArray *out_indices = NULL;
|
|
|
|
|
gs_free char *header_name = NULL;
|
|
|
|
|
gs_free NmcOutputField *row = NULL;
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
int i;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 14:56:19 +02:00
|
|
|
/* Main header (pretty only) */
|
2017-03-31 13:21:47 +02:00
|
|
|
header_name = construct_header_name(base_hdr, nm_device_get_iface(device));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 14:56:19 +02:00
|
|
|
/* Lazy way to retrieve sorted array from 0 to the number of dev fields */
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
out_indices =
|
|
|
|
|
parse_output_fields(NULL,
|
2018-04-26 21:28:14 +02:00
|
|
|
(const NMMetaAbstractInfo *const *) metagen_device_detail_general,
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
FALSE,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-26 21:28:14 +02:00
|
|
|
row = g_new0(NmcOutputField, G_N_ELEMENTS(metagen_device_detail_general));
|
|
|
|
|
for (i = 0; i < G_N_ELEMENTS(metagen_device_detail_general); i++)
|
|
|
|
|
row[i].info = (const NMMetaAbstractInfo *) &metagen_device_detail_general[i];
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-04-02 19:10:15 +02:00
|
|
|
print_required_fields(&nmc->nmc_config,
|
|
|
|
|
&nmc->pager_data,
|
|
|
|
|
NMC_OF_FLAG_MAIN_HEADER_ONLY,
|
|
|
|
|
out_indices,
|
|
|
|
|
header_name,
|
|
|
|
|
0,
|
|
|
|
|
row);
|
2017-03-30 14:56:19 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2010-03-24 19:05:35 +01:00
|
|
|
/* Loop through the required sections and print them. */
|
|
|
|
|
for (k = 0; k < sections_array->len; k++) {
|
2022-09-08 12:05:56 +02:00
|
|
|
int section_idx = nm_g_array_index(sections_array, int, k);
|
2013-12-10 12:00:53 +01:00
|
|
|
char *section_fld = (char *) g_ptr_array_index(fields_in_section, k);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-05-02 10:47:20 +02:00
|
|
|
if (NM_IN_SET(nmc->nmc_config.print_output, NMC_PRINT_NORMAL, NMC_PRINT_PRETTY)
|
|
|
|
|
&& !nmc->nmc_config.multiline_output && was_output)
|
2014-09-19 16:04:40 -04:00
|
|
|
g_print("\n"); /* Print empty line between groups in tabular mode */
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2010-03-24 19:05:35 +01:00
|
|
|
was_output = FALSE;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2014-08-25 10:51:26 -04:00
|
|
|
state = nm_device_get_state(device);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-26 21:28:14 +02:00
|
|
|
if (nmc_fields_dev_show_sections[section_idx]->nested == metagen_device_detail_general) {
|
|
|
|
|
gs_free char *f = section_fld ? g_strdup_printf("GENERAL.%s", section_fld) : NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-26 21:28:14 +02:00
|
|
|
nmc_print(&nmc->nmc_config,
|
|
|
|
|
(gpointer[]){device, NULL},
|
2020-09-28 16:03:33 +02:00
|
|
|
NULL,
|
2018-04-26 21:28:14 +02:00
|
|
|
NULL,
|
|
|
|
|
NMC_META_GENERIC_GROUP("GENERAL", metagen_device_detail_general, N_("NAME")),
|
|
|
|
|
f,
|
|
|
|
|
NULL);
|
2010-03-24 19:05:35 +01:00
|
|
|
was_output = TRUE;
|
2018-04-26 21:28:14 +02:00
|
|
|
continue;
|
2010-03-24 19:05:35 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-29 19:13:57 +02:00
|
|
|
if (nmc_fields_dev_show_sections[section_idx]->nested
|
|
|
|
|
== metagen_device_detail_capabilities) {
|
|
|
|
|
gs_free char *f = section_fld ? g_strdup_printf("CAPABILITIES.%s", section_fld) : NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-29 19:13:57 +02:00
|
|
|
nmc_print(&nmc->nmc_config,
|
|
|
|
|
(gpointer[]){device, NULL},
|
2020-09-28 16:03:33 +02:00
|
|
|
NULL,
|
2018-04-29 19:13:57 +02:00
|
|
|
NULL,
|
|
|
|
|
NMC_META_GENERIC_GROUP("CAPABILITIES",
|
|
|
|
|
metagen_device_detail_capabilities,
|
|
|
|
|
N_("NAME")),
|
|
|
|
|
f,
|
|
|
|
|
NULL);
|
2010-03-24 19:05:35 +01:00
|
|
|
was_output = TRUE;
|
2018-04-29 19:13:57 +02:00
|
|
|
continue;
|
2010-02-25 09:52:30 -08:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 10:45:36 +02:00
|
|
|
if (nmc_fields_dev_show_sections[section_idx]->nested
|
|
|
|
|
== metagen_device_detail_interface_flags) {
|
|
|
|
|
gs_free char *f =
|
|
|
|
|
section_fld ? g_strdup_printf("INTERFACE-FLAGS.%s", section_fld) : NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 10:45:36 +02:00
|
|
|
nmc_print(&nmc->nmc_config,
|
|
|
|
|
(gpointer[]){device, NULL},
|
2020-09-28 16:03:33 +02:00
|
|
|
NULL,
|
2019-10-10 10:45:36 +02:00
|
|
|
NULL,
|
|
|
|
|
NMC_META_GENERIC_GROUP("INTERFACE-FLAGS",
|
|
|
|
|
metagen_device_detail_interface_flags,
|
|
|
|
|
N_("NAME")),
|
|
|
|
|
f,
|
|
|
|
|
NULL);
|
|
|
|
|
was_output = TRUE;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-30 09:00:08 +02:00
|
|
|
if (nmc_fields_dev_show_sections[section_idx]->nested
|
|
|
|
|
== metagen_device_detail_wifi_properties) {
|
|
|
|
|
if (NM_IS_DEVICE_WIFI(device)) {
|
|
|
|
|
gs_free char *f =
|
|
|
|
|
section_fld ? g_strdup_printf("WIFI-PROPERTIES.%s", section_fld) : NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-30 09:00:08 +02:00
|
|
|
nmc_print(&nmc->nmc_config,
|
|
|
|
|
(gpointer[]){device, NULL},
|
2020-09-28 16:03:33 +02:00
|
|
|
NULL,
|
2018-04-30 09:00:08 +02:00
|
|
|
NULL,
|
|
|
|
|
NMC_META_GENERIC_GROUP("WIFI-PROPERTIES",
|
|
|
|
|
metagen_device_detail_wifi_properties,
|
|
|
|
|
N_("NAME")),
|
|
|
|
|
f,
|
|
|
|
|
NULL);
|
|
|
|
|
was_output = TRUE;
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2010-03-24 19:05:35 +01:00
|
|
|
/* Wireless specific information */
|
|
|
|
|
if ((NM_IS_DEVICE_WIFI(device))) {
|
|
|
|
|
/* section AP */
|
2020-02-11 15:17:03 +01:00
|
|
|
if (!g_ascii_strcasecmp(nmc_fields_dev_show_sections[section_idx]->name,
|
|
|
|
|
nmc_fields_dev_show_sections[4]->name)) {
|
2022-02-28 18:49:25 +01:00
|
|
|
NMAccessPoint *active_ap = NULL;
|
2017-03-30 14:56:19 +02:00
|
|
|
NMC_OUTPUT_DATA_DEFINE_SCOPED(out);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2022-02-28 18:49:25 +01:00
|
|
|
if (state == NM_DEVICE_STATE_ACTIVATED)
|
|
|
|
|
active_ap = nm_device_wifi_get_active_access_point(NM_DEVICE_WIFI(device));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
tmpl = (const NMMetaAbstractInfo *const *) nmc_fields_dev_wifi_list;
|
2018-04-24 11:20:03 +02:00
|
|
|
out_indices =
|
|
|
|
|
parse_output_fields(section_fld ?: NMC_FIELDS_DEV_WIFI_LIST_FOR_DEV_LIST,
|
2017-03-31 12:55:43 +02:00
|
|
|
tmpl,
|
|
|
|
|
FALSE,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL);
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
arr = nmc_dup_fields_array(tmpl, NMC_OF_FLAG_FIELD_NAMES);
|
2017-03-30 14:56:19 +02:00
|
|
|
g_ptr_array_add(out.output_data, arr);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 14:56:19 +02:00
|
|
|
{
|
2022-02-28 19:20:37 +01:00
|
|
|
gs_unref_ptrarray GPtrArray *aps = NULL;
|
|
|
|
|
int info_index = 0;
|
|
|
|
|
const APInfo info = {
|
2021-11-09 13:28:54 +01:00
|
|
|
.nmc = nmc,
|
2022-02-28 19:20:37 +01:00
|
|
|
.p_index = &info_index,
|
2021-11-09 13:28:54 +01:00
|
|
|
.output_flags = NMC_OF_FLAG_SECTION_PREFIX,
|
2022-02-28 18:49:25 +01:00
|
|
|
.active_ap = active_ap,
|
2021-11-09 13:28:54 +01:00
|
|
|
.device = nm_device_get_iface(device),
|
|
|
|
|
.output_data = out.output_data,
|
2017-03-30 14:56:19 +02:00
|
|
|
};
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 14:56:19 +02:00
|
|
|
aps = sort_access_points(
|
|
|
|
|
nm_device_wifi_get_access_points(NM_DEVICE_WIFI(device)));
|
2022-02-28 19:20:37 +01:00
|
|
|
g_ptr_array_foreach(aps, fill_output_access_point_void, (gpointer) &info);
|
2017-03-30 14:56:19 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 14:56:19 +02:00
|
|
|
print_data_prepare_width(out.output_data);
|
2020-04-02 19:10:15 +02:00
|
|
|
print_data(&nmc->nmc_config, &nmc->pager_data, out_indices, NULL, 0, &out);
|
2010-03-24 19:05:35 +01:00
|
|
|
was_output = TRUE;
|
2020-09-28 16:03:33 +02:00
|
|
|
}
|
2010-03-24 19:05:35 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-30 09:00:08 +02:00
|
|
|
if (nmc_fields_dev_show_sections[section_idx]->nested
|
|
|
|
|
== metagen_device_detail_wired_properties) {
|
|
|
|
|
if ((NM_IS_DEVICE_ETHERNET(device))) {
|
|
|
|
|
gs_free char *f =
|
|
|
|
|
section_fld ? g_strdup_printf("WIRED-PROPERTIES.%s", section_fld) : NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-30 09:00:08 +02:00
|
|
|
nmc_print(&nmc->nmc_config,
|
|
|
|
|
(gpointer[]){device, NULL},
|
2020-09-28 16:03:33 +02:00
|
|
|
NULL,
|
2018-04-30 09:00:08 +02:00
|
|
|
NULL,
|
|
|
|
|
NMC_META_GENERIC_GROUP("WIRED-PROPERTIES",
|
|
|
|
|
metagen_device_detail_wired_properties,
|
|
|
|
|
N_("NAME")),
|
|
|
|
|
f,
|
|
|
|
|
NULL);
|
2010-03-24 19:05:35 +01:00
|
|
|
was_output = TRUE;
|
|
|
|
|
}
|
2018-04-30 09:00:08 +02:00
|
|
|
continue;
|
2011-02-14 16:06:37 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2012-01-03 16:37:53 +01:00
|
|
|
/* IP configuration info */
|
2013-04-04 10:20:24 -04:00
|
|
|
cfg4 = nm_device_get_ip4_config(device);
|
|
|
|
|
cfg6 = nm_device_get_ip6_config(device);
|
|
|
|
|
dhcp4 = nm_device_get_dhcp4_config(device);
|
|
|
|
|
dhcp6 = nm_device_get_dhcp6_config(device);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-04-04 10:20:24 -04:00
|
|
|
/* IP4 */
|
2020-02-11 15:17:03 +01:00
|
|
|
if (cfg4
|
|
|
|
|
&& !g_ascii_strcasecmp(nmc_fields_dev_show_sections[section_idx]->name,
|
|
|
|
|
nmc_fields_dev_show_sections[8]->name))
|
2018-04-26 20:09:53 +02:00
|
|
|
was_output = print_ip_config(cfg4, AF_INET, &nmc->nmc_config, section_fld);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-04-04 10:20:24 -04:00
|
|
|
/* DHCP4 */
|
2020-02-11 15:17:03 +01:00
|
|
|
if (dhcp4
|
|
|
|
|
&& !g_ascii_strcasecmp(nmc_fields_dev_show_sections[section_idx]->name,
|
|
|
|
|
nmc_fields_dev_show_sections[9]->name))
|
2018-04-26 20:09:53 +02:00
|
|
|
was_output = print_dhcp_config(dhcp4, AF_INET, &nmc->nmc_config, section_fld);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-04-04 10:20:24 -04:00
|
|
|
/* IP6 */
|
2020-02-11 15:17:03 +01:00
|
|
|
if (cfg6
|
|
|
|
|
&& !g_ascii_strcasecmp(nmc_fields_dev_show_sections[section_idx]->name,
|
|
|
|
|
nmc_fields_dev_show_sections[10]->name))
|
2018-04-26 20:09:53 +02:00
|
|
|
was_output = print_ip_config(cfg6, AF_INET6, &nmc->nmc_config, section_fld);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-04-04 10:20:24 -04:00
|
|
|
/* DHCP6 */
|
2020-02-11 15:17:03 +01:00
|
|
|
if (dhcp6
|
|
|
|
|
&& !g_ascii_strcasecmp(nmc_fields_dev_show_sections[section_idx]->name,
|
|
|
|
|
nmc_fields_dev_show_sections[11]->name))
|
2018-04-26 20:09:53 +02:00
|
|
|
was_output = print_dhcp_config(dhcp6, AF_INET6, &nmc->nmc_config, section_fld);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2014-09-23 14:49:43 +02:00
|
|
|
/* Bond specific information */
|
|
|
|
|
if (NM_IS_DEVICE_BOND(device)) {
|
2020-02-11 15:17:03 +01:00
|
|
|
if (!g_ascii_strcasecmp(nmc_fields_dev_show_sections[section_idx]->name,
|
|
|
|
|
nmc_fields_dev_show_sections[12]->name))
|
2019-10-10 10:45:36 +02:00
|
|
|
was_output = print_bond_bridge_info(device,
|
|
|
|
|
nmc,
|
|
|
|
|
nmc_fields_dev_show_sections[12]->name,
|
|
|
|
|
section_fld);
|
2014-09-23 14:49:43 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2014-09-23 14:49:43 +02:00
|
|
|
/* Team specific information */
|
|
|
|
|
if (NM_IS_DEVICE_TEAM(device)) {
|
2020-02-11 15:17:03 +01:00
|
|
|
if (!g_ascii_strcasecmp(nmc_fields_dev_show_sections[section_idx]->name,
|
|
|
|
|
nmc_fields_dev_show_sections[13]->name))
|
2019-10-10 10:45:36 +02:00
|
|
|
was_output = print_team_info(device,
|
|
|
|
|
nmc,
|
|
|
|
|
nmc_fields_dev_show_sections[13]->name,
|
|
|
|
|
section_fld);
|
2014-09-23 14:49:43 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2014-09-23 14:49:43 +02:00
|
|
|
/* Bridge specific information */
|
|
|
|
|
if (NM_IS_DEVICE_BRIDGE(device)) {
|
2020-02-11 15:17:03 +01:00
|
|
|
if (!g_ascii_strcasecmp(nmc_fields_dev_show_sections[section_idx]->name,
|
|
|
|
|
nmc_fields_dev_show_sections[14]->name))
|
2019-10-10 10:45:36 +02:00
|
|
|
was_output = print_bond_bridge_info(device,
|
|
|
|
|
nmc,
|
|
|
|
|
nmc_fields_dev_show_sections[14]->name,
|
|
|
|
|
section_fld);
|
2012-10-22 14:31:11 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2012-10-22 15:18:34 +02:00
|
|
|
/* VLAN-specific information */
|
|
|
|
|
if ((NM_IS_DEVICE_VLAN(device))) {
|
2020-02-11 15:17:03 +01:00
|
|
|
if (!g_ascii_strcasecmp(nmc_fields_dev_show_sections[section_idx]->name,
|
|
|
|
|
nmc_fields_dev_show_sections[15]->name)) {
|
2012-10-22 15:18:34 +02:00
|
|
|
char *vlan_id_str =
|
|
|
|
|
g_strdup_printf("%u", nm_device_vlan_get_vlan_id(NM_DEVICE_VLAN(device)));
|
2014-07-21 13:08:53 +02:00
|
|
|
NMDevice *parent = nm_device_vlan_get_parent(NM_DEVICE_VLAN(device));
|
2017-03-30 14:56:19 +02:00
|
|
|
NMC_OUTPUT_DATA_DEFINE_SCOPED(out);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
tmpl = (const NMMetaAbstractInfo *const *) nmc_fields_dev_show_vlan_prop;
|
|
|
|
|
out_indices = parse_output_fields(section_fld, tmpl, FALSE, NULL, NULL);
|
|
|
|
|
arr = nmc_dup_fields_array(tmpl, NMC_OF_FLAG_FIELD_NAMES);
|
2017-03-30 14:56:19 +02:00
|
|
|
g_ptr_array_add(out.output_data, arr);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
arr = nmc_dup_fields_array(tmpl, NMC_OF_FLAG_SECTION_PREFIX);
|
2019-10-10 10:45:36 +02:00
|
|
|
set_val_strc(arr, 0, nmc_fields_dev_show_sections[15]->name); /* "VLAN" */
|
2014-07-21 13:08:53 +02:00
|
|
|
set_val_strc(arr, 1, parent ? nm_device_get_iface(parent) : NULL);
|
|
|
|
|
set_val_str(arr, 2, vlan_id_str);
|
2017-03-30 14:56:19 +02:00
|
|
|
g_ptr_array_add(out.output_data, arr);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 14:56:19 +02:00
|
|
|
print_data_prepare_width(out.output_data);
|
2020-04-02 19:10:15 +02:00
|
|
|
print_data(&nmc->nmc_config, &nmc->pager_data, out_indices, NULL, 0, &out);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2012-10-22 15:18:34 +02:00
|
|
|
was_output = TRUE;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
}
|
|
|
|
|
|
2014-09-24 12:00:47 +02:00
|
|
|
if (NM_IS_DEVICE_BT(device)) {
|
2020-02-11 15:17:03 +01:00
|
|
|
if (!g_ascii_strcasecmp(nmc_fields_dev_show_sections[section_idx]->name,
|
|
|
|
|
nmc_fields_dev_show_sections[16]->name)) {
|
2017-03-30 14:56:19 +02:00
|
|
|
NMC_OUTPUT_DATA_DEFINE_SCOPED(out);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
tmpl = (const NMMetaAbstractInfo *const *) nmc_fields_dev_show_bluetooth;
|
|
|
|
|
out_indices = parse_output_fields(section_fld, tmpl, FALSE, NULL, NULL);
|
|
|
|
|
arr = nmc_dup_fields_array(tmpl, NMC_OF_FLAG_FIELD_NAMES);
|
2017-03-30 14:56:19 +02:00
|
|
|
g_ptr_array_add(out.output_data, arr);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
arr = nmc_dup_fields_array(tmpl, NMC_OF_FLAG_SECTION_PREFIX);
|
2019-10-10 10:45:36 +02:00
|
|
|
set_val_strc(arr, 0, nmc_fields_dev_show_sections[16]->name); /* "BLUETOOTH" */
|
2014-09-24 12:00:47 +02:00
|
|
|
set_val_str(
|
|
|
|
|
arr,
|
|
|
|
|
1,
|
|
|
|
|
bluetooth_caps_to_string(nm_device_bt_get_capabilities(NM_DEVICE_BT(device))));
|
2017-03-30 14:56:19 +02:00
|
|
|
g_ptr_array_add(out.output_data, arr);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 14:56:19 +02:00
|
|
|
print_data_prepare_width(out.output_data);
|
2020-04-02 19:10:15 +02:00
|
|
|
print_data(&nmc->nmc_config, &nmc->pager_data, out_indices, NULL, 0, &out);
|
2014-09-24 12:00:47 +02:00
|
|
|
was_output = TRUE;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
}
|
|
|
|
|
|
2018-04-27 17:28:43 +02:00
|
|
|
if (nmc_fields_dev_show_sections[section_idx]->nested
|
|
|
|
|
== metagen_device_detail_connections) {
|
|
|
|
|
gs_free char *f = section_fld ? g_strdup_printf("CONNECTIONS.%s", section_fld) : NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-27 17:28:43 +02:00
|
|
|
nmc_print(&nmc->nmc_config,
|
|
|
|
|
(gpointer[]){device, NULL},
|
2018-04-30 13:01:20 +02:00
|
|
|
NULL,
|
2018-04-27 17:28:43 +02:00
|
|
|
NULL,
|
|
|
|
|
NMC_META_GENERIC_GROUP("CONNECTIONS",
|
|
|
|
|
metagen_device_detail_connections,
|
|
|
|
|
N_("NAME")),
|
|
|
|
|
f,
|
|
|
|
|
NULL);
|
2012-08-31 12:48:27 +02:00
|
|
|
was_output = TRUE;
|
2018-04-27 17:28:43 +02:00
|
|
|
continue;
|
2010-02-25 09:52:30 -08:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
}
|
|
|
|
|
|
2010-03-24 19:05:35 +01:00
|
|
|
if (sections_array)
|
|
|
|
|
g_array_free(sections_array, TRUE);
|
2013-12-10 12:00:53 +01:00
|
|
|
if (fields_in_section)
|
|
|
|
|
g_ptr_array_free(fields_in_section, TRUE);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2014-01-10 13:19:14 +01:00
|
|
|
return TRUE;
|
2010-02-25 09:52:30 -08:00
|
|
|
}
|
|
|
|
|
|
2018-03-29 12:31:33 +02:00
|
|
|
NMMetaColor
|
2020-06-08 23:26:18 +02:00
|
|
|
nmc_device_state_to_color(NMDevice *device)
|
2015-03-26 17:52:35 +01:00
|
|
|
{
|
2020-06-08 23:26:18 +02:00
|
|
|
NMDeviceState state;
|
|
|
|
|
NMActiveConnection *ac;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-06-08 23:26:18 +02:00
|
|
|
if (!device)
|
|
|
|
|
return NM_META_COLOR_DEVICE_UNKNOWN;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-06-08 23:26:18 +02:00
|
|
|
ac = nm_device_get_active_connection(device);
|
|
|
|
|
if (ac
|
|
|
|
|
&& NM_FLAGS_HAS(nm_active_connection_get_state_flags(ac),
|
|
|
|
|
NM_ACTIVATION_STATE_FLAG_EXTERNAL))
|
|
|
|
|
return NM_META_COLOR_CONNECTION_EXTERNAL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-06-08 23:26:18 +02:00
|
|
|
state = nm_device_get_state(device);
|
2015-03-26 17:52:35 +01:00
|
|
|
if (state <= NM_DEVICE_STATE_UNAVAILABLE)
|
2018-03-29 12:31:33 +02:00
|
|
|
return NM_META_COLOR_DEVICE_UNAVAILABLE;
|
2015-03-26 17:52:35 +01:00
|
|
|
else if (state == NM_DEVICE_STATE_DISCONNECTED)
|
2018-03-29 12:31:33 +02:00
|
|
|
return NM_META_COLOR_DEVICE_DISCONNECTED;
|
2015-03-26 17:52:35 +01:00
|
|
|
else if (state >= NM_DEVICE_STATE_PREPARE && state <= NM_DEVICE_STATE_SECONDARIES)
|
2018-03-29 12:31:33 +02:00
|
|
|
return NM_META_COLOR_DEVICE_ACTIVATING;
|
2015-03-26 17:52:35 +01:00
|
|
|
else if (state == NM_DEVICE_STATE_ACTIVATED)
|
2018-03-29 12:31:33 +02:00
|
|
|
return NM_META_COLOR_DEVICE_ACTIVATED;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-08-09 20:37:32 +02:00
|
|
|
return NM_META_COLOR_DEVICE_UNKNOWN;
|
2015-03-26 17:52:35 +01:00
|
|
|
}
|
|
|
|
|
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
static void
|
2020-04-05 13:05:58 +02:00
|
|
|
do_devices_status(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
|
2010-02-25 09:52:30 -08:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
GError *error = NULL;
|
2018-04-26 20:28:02 +02:00
|
|
|
gs_free NMDevice **devices = NULL;
|
2021-11-09 13:28:54 +01:00
|
|
|
const char *fields_str = NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg(nmc, &argc, &argv, NULL);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-23 10:49:20 +02:00
|
|
|
if (nmc->complete)
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
return;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-07-30 12:23:03 +02:00
|
|
|
if (argc) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: invalid extra argument '%s'."), *argv);
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2010-02-25 09:52:30 -08:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-02-11 15:17:03 +01:00
|
|
|
if (!nmc->required_fields || g_ascii_strcasecmp(nmc->required_fields, "common") == 0)
|
2018-04-26 20:28:02 +02:00
|
|
|
fields_str = "DEVICE,TYPE,STATE,CONNECTION";
|
2020-02-11 15:17:03 +01:00
|
|
|
else if (!nmc->required_fields || g_ascii_strcasecmp(nmc->required_fields, "all") == 0) {
|
2020-05-06 23:18:54 +02:00
|
|
|
/* pass */
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
} else
|
2010-03-18 15:39:15 +01:00
|
|
|
fields_str = nmc->required_fields;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-26 20:28:02 +02:00
|
|
|
devices = nmc_get_devices_sorted(nmc->client);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-04-26 20:28:02 +02:00
|
|
|
if (!nmc_print(&nmc->nmc_config,
|
|
|
|
|
(gpointer *) devices,
|
2018-04-30 13:01:20 +02:00
|
|
|
NULL,
|
2018-04-26 20:28:02 +02:00
|
|
|
N_("Status of devices"),
|
|
|
|
|
(const NMMetaAbstractInfo *const *) metagen_device_status,
|
|
|
|
|
fields_str,
|
|
|
|
|
&error)) {
|
2013-12-10 12:00:53 +01:00
|
|
|
g_string_printf(nmc->return_text, _("Error: 'device status': %s"), error->message);
|
2010-03-18 15:39:15 +01:00
|
|
|
g_error_free(error);
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2010-03-18 15:39:15 +01:00
|
|
|
}
|
2010-02-25 09:52:30 -08:00
|
|
|
}
|
|
|
|
|
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
static void
|
2020-04-05 13:05:58 +02:00
|
|
|
do_device_show(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
|
2010-02-25 09:52:30 -08:00
|
|
|
{
|
2016-06-27 11:54:25 +02:00
|
|
|
gs_free_error GError *error = NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg(nmc, &argc, &argv, NULL);
|
2016-06-23 12:19:10 +02:00
|
|
|
if (!nmc->mode_specified)
|
2017-03-30 12:45:41 +02:00
|
|
|
nmc->nmc_config_mutable.multiline_output =
|
|
|
|
|
TRUE; /* multiline mode is default for 'device show' */
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-27 11:54:25 +02:00
|
|
|
if (argc) {
|
|
|
|
|
NMDevice *device;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-27 11:54:25 +02:00
|
|
|
device = get_device(nmc, &argc, &argv, &error);
|
2010-02-25 09:52:30 -08:00
|
|
|
if (!device) {
|
2016-06-27 11:54:25 +02:00
|
|
|
g_string_printf(nmc->return_text, _("Error: %s."), error->message);
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = error->code;
|
|
|
|
|
return;
|
2016-06-27 11:54:25 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-27 11:54:25 +02:00
|
|
|
if (argc) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: invalid extra argument '%s'."), *argv);
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2010-02-25 09:52:30 -08:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-23 10:49:20 +02:00
|
|
|
if (nmc->complete)
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
return;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2010-03-18 15:39:15 +01:00
|
|
|
show_device_info(device, nmc);
|
2010-02-25 09:52:30 -08:00
|
|
|
} else {
|
2016-07-01 21:45:43 +02:00
|
|
|
NMDevice **devices = nmc_get_devices_sorted(nmc->client);
|
2016-06-27 11:54:25 +02:00
|
|
|
int i;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-23 10:49:20 +02:00
|
|
|
/* nmc_do_cmd() should not call this with argc=0. */
|
2019-08-21 15:10:47 +02:00
|
|
|
nm_assert(!nmc->complete);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-04-03 10:01:42 +02:00
|
|
|
/* Show details for all devices */
|
2013-04-24 15:27:11 -04:00
|
|
|
for (i = 0; devices[i]; i++) {
|
2016-06-27 11:54:25 +02:00
|
|
|
if (!show_device_info(devices[i], nmc))
|
2014-01-10 13:19:14 +01:00
|
|
|
break;
|
2013-04-24 15:27:11 -04:00
|
|
|
if (devices[i + 1])
|
2014-09-19 16:04:40 -04:00
|
|
|
g_print("\n"); /* Empty line */
|
2013-04-03 10:01:42 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-27 11:54:25 +02:00
|
|
|
g_free(devices);
|
2010-02-25 09:52:30 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
timeout_cb(gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
/* Time expired -> exit nmcli */
|
|
|
|
|
|
|
|
|
|
NmCli *nmc = (NmCli *) user_data;
|
|
|
|
|
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: Timeout %d sec expired."), nmc->timeout);
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_TIMEOUT_EXPIRED;
|
|
|
|
|
quit();
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-03 11:54:52 +02:00
|
|
|
static gboolean
|
|
|
|
|
progress_cb(gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMDevice *device = (NMDevice *) user_data;
|
|
|
|
|
|
2020-06-10 15:27:59 +02:00
|
|
|
nmc_terminal_show_progress(device ? gettext(nmc_device_state_to_string_with_external(device))
|
|
|
|
|
: "");
|
2012-05-03 11:54:52 +02:00
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-13 00:35:05 +02:00
|
|
|
typedef struct {
|
2021-11-09 13:28:54 +01:00
|
|
|
NmCli *nmc;
|
|
|
|
|
NMDevice *device;
|
2019-10-10 15:43:04 +02:00
|
|
|
NMActiveConnection *active;
|
2021-11-09 13:28:54 +01:00
|
|
|
char *specific_object;
|
2019-08-01 08:58:34 +02:00
|
|
|
bool hotspot : 1;
|
|
|
|
|
bool create : 1;
|
2014-09-13 00:35:05 +02:00
|
|
|
} AddAndActivateInfo;
|
|
|
|
|
|
2019-08-01 08:58:34 +02:00
|
|
|
static AddAndActivateInfo *
|
2021-11-09 13:28:54 +01:00
|
|
|
add_and_activate_info_new(NmCli *nmc,
|
|
|
|
|
NMDevice *device,
|
2019-08-01 08:58:34 +02:00
|
|
|
gboolean hotspot,
|
|
|
|
|
gboolean create,
|
|
|
|
|
const char *specific_object)
|
|
|
|
|
{
|
|
|
|
|
AddAndActivateInfo *info;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-08-01 08:58:34 +02:00
|
|
|
info = g_slice_new(AddAndActivateInfo);
|
|
|
|
|
*info = (AddAndActivateInfo){
|
|
|
|
|
.nmc = nmc,
|
|
|
|
|
.device = g_object_ref(device),
|
|
|
|
|
.hotspot = hotspot,
|
|
|
|
|
.create = create,
|
|
|
|
|
.specific_object = g_strdup(specific_object),
|
|
|
|
|
};
|
|
|
|
|
return info;
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-30 14:09:40 +02:00
|
|
|
static void
|
|
|
|
|
add_and_activate_info_free(AddAndActivateInfo *info)
|
|
|
|
|
{
|
|
|
|
|
g_object_unref(info->device);
|
2019-10-10 15:43:04 +02:00
|
|
|
g_clear_object(&info->active);
|
2019-07-30 14:14:51 +02:00
|
|
|
g_free(info->specific_object);
|
2019-08-01 08:58:34 +02:00
|
|
|
nm_g_slice_free(info);
|
2019-07-30 14:09:40 +02:00
|
|
|
}
|
|
|
|
|
|
2020-07-19 11:40:50 +02:00
|
|
|
NM_AUTO_DEFINE_FCN0(AddAndActivateInfo *,
|
|
|
|
|
_nm_auto_free_add_and_activate_info,
|
|
|
|
|
add_and_activate_info_free);
|
2019-08-01 09:10:56 +02:00
|
|
|
#define nm_auto_free_add_and_activate_info nm_auto(_nm_auto_free_add_and_activate_info)
|
|
|
|
|
|
2022-10-28 08:50:07 +02:00
|
|
|
static void add_and_activate_notify_state_cb(GObject *src, GParamSpec *pspec, gpointer user_data);
|
|
|
|
|
|
2019-10-10 15:43:04 +02:00
|
|
|
static void
|
2022-10-28 08:50:07 +02:00
|
|
|
add_and_activate_check_state(AddAndActivateInfo *info)
|
2019-10-10 15:43:04 +02:00
|
|
|
{
|
|
|
|
|
NMDeviceState state;
|
|
|
|
|
NMDeviceStateReason reason;
|
|
|
|
|
NMActiveConnectionState ac_state;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 15:43:04 +02:00
|
|
|
state = nm_device_get_state(info->device);
|
|
|
|
|
ac_state = nm_active_connection_get_state(info->active);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 15:43:04 +02:00
|
|
|
if (ac_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING)
|
|
|
|
|
return;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 15:43:04 +02:00
|
|
|
if (state == NM_DEVICE_STATE_ACTIVATED) {
|
|
|
|
|
nmc_terminal_erase_line();
|
|
|
|
|
g_print(_("Device '%s' successfully activated with '%s'.\n"),
|
|
|
|
|
nm_device_get_iface(info->device),
|
|
|
|
|
nm_active_connection_get_uuid(info->active));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
if (info->hotspot)
|
|
|
|
|
g_print(
|
|
|
|
|
_("Hint: \"nmcli dev wifi show-password\" shows the Wi-Fi name and password.\n"));
|
2019-10-10 15:43:04 +02:00
|
|
|
} else if (state <= NM_DEVICE_STATE_DISCONNECTED || state >= NM_DEVICE_STATE_DEACTIVATING) {
|
|
|
|
|
reason = nm_device_get_state_reason(info->device);
|
2022-10-03 13:46:02 +02:00
|
|
|
g_string_printf(info->nmc->return_text,
|
2022-10-03 13:51:49 +02:00
|
|
|
_("Error: Connection activation failed: %s."),
|
2022-10-03 13:46:02 +02:00
|
|
|
gettext(nmc_device_reason_to_string(reason)));
|
|
|
|
|
info->nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION;
|
2019-10-10 15:43:04 +02:00
|
|
|
} else {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2022-10-28 08:50:07 +02:00
|
|
|
g_signal_handlers_disconnect_by_func(info->active,
|
|
|
|
|
G_CALLBACK(add_and_activate_notify_state_cb),
|
|
|
|
|
info);
|
|
|
|
|
g_signal_handlers_disconnect_by_func(info->device,
|
|
|
|
|
G_CALLBACK(add_and_activate_notify_state_cb),
|
|
|
|
|
info);
|
2019-10-10 15:43:04 +02:00
|
|
|
add_and_activate_info_free(info);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 15:43:04 +02:00
|
|
|
quit();
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-28 08:50:07 +02:00
|
|
|
static void
|
|
|
|
|
add_and_activate_notify_state_cb(GObject *src, GParamSpec *pspec, gpointer user_data)
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
add_and_activate_check_state(user_data);
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-13 00:35:05 +02:00
|
|
|
static void
|
2014-09-11 16:27:13 -04:00
|
|
|
add_and_activate_cb(GObject *client, GAsyncResult *result, gpointer user_data)
|
2014-09-13 00:35:05 +02:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
nm_auto_free_add_and_activate_info AddAndActivateInfo *info = user_data;
|
|
|
|
|
NmCli *nmc = info->nmc;
|
|
|
|
|
gs_unref_object NMActiveConnection *active = NULL;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
2022-05-12 12:31:32 +02:00
|
|
|
const char *deprecated;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-06-12 06:52:01 +02:00
|
|
|
if (info->create)
|
|
|
|
|
active = nm_client_add_and_activate_connection_finish(NM_CLIENT(client), result, &error);
|
|
|
|
|
else
|
|
|
|
|
active = nm_client_activate_connection_finish(NM_CLIENT(client), result, &error);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2014-09-11 16:27:13 -04:00
|
|
|
if (error) {
|
2019-08-01 09:10:56 +02:00
|
|
|
if (info->hotspot) {
|
2015-10-02 22:46:53 +02:00
|
|
|
g_string_printf(nmc->return_text,
|
|
|
|
|
_("Error: Failed to setup a Wi-Fi hotspot: %s"),
|
|
|
|
|
error->message);
|
2019-08-01 09:10:56 +02:00
|
|
|
} else if (info->create) {
|
2015-10-02 22:46:53 +02:00
|
|
|
g_string_printf(nmc->return_text,
|
|
|
|
|
_("Error: Failed to add/activate new connection: %s"),
|
|
|
|
|
error->message);
|
2019-08-01 09:10:56 +02:00
|
|
|
} else {
|
2018-06-12 06:52:01 +02:00
|
|
|
g_string_printf(nmc->return_text,
|
|
|
|
|
_("Error: Failed to activate connection: %s"),
|
|
|
|
|
error->message);
|
2019-08-01 09:10:56 +02:00
|
|
|
}
|
2014-09-13 00:35:05 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION;
|
|
|
|
|
quit();
|
2019-08-01 09:10:56 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2022-05-12 12:31:32 +02:00
|
|
|
deprecated =
|
|
|
|
|
nmc_connection_check_deprecated(NM_CONNECTION(nm_active_connection_get_connection(active)));
|
|
|
|
|
if (deprecated)
|
|
|
|
|
g_printerr(_("Warning: %s.\n"), deprecated);
|
|
|
|
|
|
2019-08-01 09:10:56 +02:00
|
|
|
if (nmc->nowait_flag) {
|
|
|
|
|
quit();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 15:43:04 +02:00
|
|
|
if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
|
|
|
|
|
progress_id = g_timeout_add(120, progress_cb, info->device);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 15:43:04 +02:00
|
|
|
info->active = g_steal_pointer(&active);
|
2022-10-28 08:50:07 +02:00
|
|
|
g_signal_connect(info->device,
|
|
|
|
|
"notify::" NM_DEVICE_STATE,
|
|
|
|
|
G_CALLBACK(add_and_activate_notify_state_cb),
|
|
|
|
|
info);
|
|
|
|
|
g_signal_connect(info->active,
|
|
|
|
|
"notify::" NM_ACTIVE_CONNECTION_STATE,
|
|
|
|
|
G_CALLBACK(add_and_activate_notify_state_cb),
|
|
|
|
|
info);
|
|
|
|
|
add_and_activate_check_state(g_steal_pointer(&info));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-08-01 09:10:56 +02:00
|
|
|
g_timeout_add_seconds(nmc->timeout, timeout_cb, nmc); /* Exit if timeout expires */
|
2014-09-13 00:35:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
create_connect_connection_for_device(AddAndActivateInfo *info)
|
|
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NMConnection *connection;
|
2014-09-13 00:35:05 +02:00
|
|
|
NMSettingConnection *s_con;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2014-09-13 00:35:05 +02:00
|
|
|
/* Create new connection and tie it to the device */
|
|
|
|
|
connection = nm_simple_connection_new();
|
|
|
|
|
s_con = (NMSettingConnection *) nm_setting_connection_new();
|
|
|
|
|
nm_connection_add_setting(connection, NM_SETTING(s_con));
|
|
|
|
|
g_object_set(s_con, NM_SETTING_CONNECTION_ID, nm_device_get_iface(info->device), NULL);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2014-09-11 16:27:13 -04:00
|
|
|
nm_client_add_and_activate_connection_async(info->nmc->client,
|
|
|
|
|
connection,
|
|
|
|
|
info->device,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
|
|
|
|
add_and_activate_cb,
|
|
|
|
|
info);
|
2014-09-13 00:35:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2014-09-11 16:27:13 -04:00
|
|
|
connect_device_cb(GObject *client, GAsyncResult *result, gpointer user_data)
|
2014-09-13 00:35:05 +02:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
nm_auto_free_add_and_activate_info AddAndActivateInfo *info = user_data;
|
|
|
|
|
NmCli *nmc = info->nmc;
|
|
|
|
|
gs_unref_object NMActiveConnection *active = NULL;
|
|
|
|
|
GError *error = NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2014-09-11 16:27:13 -04:00
|
|
|
active = nm_client_activate_connection_finish(NM_CLIENT(client), result, &error);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-09-16 21:03:34 -05:00
|
|
|
if (error) {
|
2014-09-13 00:35:05 +02:00
|
|
|
/* If no connection existed for the device, create one and activate it */
|
2014-10-15 15:27:25 -04:00
|
|
|
if (g_error_matches(error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_CONNECTION)) {
|
2018-06-12 06:52:01 +02:00
|
|
|
info->create = TRUE;
|
2019-08-01 09:10:56 +02:00
|
|
|
create_connect_connection_for_device(g_steal_pointer(&info));
|
2014-09-13 00:35:05 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-09-16 21:03:34 -05:00
|
|
|
g_string_printf(nmc->return_text, _("Error: Device activation failed: %s"), error->message);
|
2014-09-11 16:27:13 -04:00
|
|
|
g_error_free(error);
|
2013-09-16 21:03:34 -05:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION;
|
|
|
|
|
quit();
|
2019-08-01 09:10:56 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-08-01 09:10:56 +02:00
|
|
|
nm_assert(NM_IS_ACTIVE_CONNECTION(active));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-08-01 09:10:56 +02:00
|
|
|
if (nmc->nowait_flag) {
|
|
|
|
|
quit();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-08-01 09:10:56 +02:00
|
|
|
if (nmc->secret_agent) {
|
|
|
|
|
NMRemoteConnection *connection = nm_active_connection_get_connection(active);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-08-01 09:10:56 +02:00
|
|
|
nm_secret_agent_simple_enable(nmc->secret_agent,
|
|
|
|
|
nm_connection_get_path(NM_CONNECTION(connection)));
|
2013-09-16 21:03:34 -05:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 15:43:04 +02:00
|
|
|
info->active = g_steal_pointer(&active);
|
2022-10-28 08:50:07 +02:00
|
|
|
g_signal_connect(info->device,
|
|
|
|
|
"notify::" NM_DEVICE_STATE,
|
|
|
|
|
G_CALLBACK(add_and_activate_notify_state_cb),
|
|
|
|
|
info);
|
|
|
|
|
g_signal_connect(info->active,
|
|
|
|
|
"notify::" NM_ACTIVE_CONNECTION_STATE,
|
|
|
|
|
G_CALLBACK(add_and_activate_notify_state_cb),
|
|
|
|
|
info);
|
|
|
|
|
add_and_activate_check_state(g_steal_pointer(&info));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-08-01 09:10:56 +02:00
|
|
|
/* Start timer not to loop forever if "notify::state" signal is not issued */
|
|
|
|
|
g_timeout_add_seconds(nmc->timeout, timeout_cb, nmc);
|
2013-09-16 21:03:34 -05:00
|
|
|
}
|
|
|
|
|
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
static void
|
2020-04-05 13:05:58 +02:00
|
|
|
do_device_connect(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
|
2013-09-16 21:03:34 -05:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NMDevice *device = NULL;
|
|
|
|
|
AddAndActivateInfo *info;
|
2016-06-27 11:54:25 +02:00
|
|
|
gs_free_error GError *error = NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-09-16 21:03:34 -05:00
|
|
|
/* Set default timeout for connect operation. */
|
|
|
|
|
if (nmc->timeout == -1)
|
|
|
|
|
nmc->timeout = 90;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg(nmc, &argc, &argv, NULL);
|
2016-06-27 11:54:25 +02:00
|
|
|
device = get_device(nmc, &argc, &argv, &error);
|
|
|
|
|
if (!device) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: %s."), error->message);
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = error->code;
|
|
|
|
|
return;
|
2013-09-16 21:03:34 -05:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-27 11:54:25 +02:00
|
|
|
if (*argv) {
|
2013-09-16 21:03:34 -05:00
|
|
|
g_string_printf(nmc->return_text, _("Error: extra argument not allowed: '%s'."), *argv);
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2013-09-16 21:03:34 -05:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-23 10:49:20 +02:00
|
|
|
if (nmc->complete)
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
return;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-09-16 21:03:34 -05:00
|
|
|
/*
|
|
|
|
|
* Use nowait_flag instead of should_wait, because exiting has to be postponed
|
|
|
|
|
* till connect_device_cb() is called, giving NM time to check our permissions.
|
|
|
|
|
*/
|
|
|
|
|
nmc->nowait_flag = (nmc->timeout == 0);
|
2015-03-27 12:39:17 +01:00
|
|
|
nmc->should_wait++;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2014-11-20 12:36:14 +01:00
|
|
|
/* Create secret agent */
|
|
|
|
|
nmc->secret_agent = nm_secret_agent_simple_new("nmcli-connect");
|
2016-09-09 17:33:09 +02:00
|
|
|
if (nmc->secret_agent) {
|
|
|
|
|
g_signal_connect(nmc->secret_agent,
|
|
|
|
|
NM_SECRET_AGENT_SIMPLE_REQUEST_SECRETS,
|
|
|
|
|
G_CALLBACK(nmc_secrets_requested),
|
|
|
|
|
nmc);
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-08-01 08:58:34 +02:00
|
|
|
info = add_and_activate_info_new(nmc, device, FALSE, FALSE, NULL);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2014-09-11 16:27:13 -04:00
|
|
|
nm_client_activate_connection_async(nmc->client,
|
|
|
|
|
NULL, /* let NM find a connection automatically */
|
|
|
|
|
device,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
|
|
|
|
connect_device_cb,
|
|
|
|
|
info);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-09-16 21:03:34 -05:00
|
|
|
/* Start progress indication */
|
2017-03-30 12:45:41 +02:00
|
|
|
if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
|
2013-09-16 21:03:34 -05:00
|
|
|
progress_id = g_timeout_add(120, progress_cb, device);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-11 19:10:58 +01:00
|
|
|
typedef struct {
|
2021-11-09 13:28:54 +01:00
|
|
|
NmCli *nmc;
|
2022-05-18 11:33:14 +02:00
|
|
|
GPtrArray *queue;
|
2015-03-11 19:10:58 +01:00
|
|
|
guint timeout_id;
|
|
|
|
|
gboolean cmd_disconnect;
|
2018-11-23 09:56:01 +01:00
|
|
|
GCancellable *cancellable;
|
2015-03-11 19:10:58 +01:00
|
|
|
} DeviceCbInfo;
|
|
|
|
|
|
|
|
|
|
static void device_cb_info_finish(DeviceCbInfo *info, NMDevice *device);
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
device_op_timeout_cb(gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
DeviceCbInfo *info = user_data;
|
|
|
|
|
|
|
|
|
|
timeout_cb(info->nmc);
|
|
|
|
|
device_cb_info_finish(info, NULL);
|
|
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-16 21:03:34 -05:00
|
|
|
static void
|
2015-03-11 19:10:58 +01:00
|
|
|
device_removed_cb(NMClient *client, NMDevice *device, DeviceCbInfo *info)
|
2013-09-16 21:03:34 -05:00
|
|
|
{
|
2015-03-11 19:10:58 +01:00
|
|
|
/* Success: device has been removed.
|
|
|
|
|
* It can also happen when disconnecting a software device.
|
|
|
|
|
*/
|
2022-05-18 11:33:14 +02:00
|
|
|
if (!g_ptr_array_find(info->queue, device, NULL))
|
2015-03-11 19:10:58 +01:00
|
|
|
return;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-03-11 19:10:58 +01:00
|
|
|
if (info->cmd_disconnect)
|
|
|
|
|
g_print(_("Device '%s' successfully disconnected.\n"), nm_device_get_iface(device));
|
|
|
|
|
else
|
|
|
|
|
g_print(_("Device '%s' successfully removed.\n"), nm_device_get_iface(device));
|
|
|
|
|
device_cb_info_finish(info, device);
|
|
|
|
|
}
|
2013-09-16 21:03:34 -05:00
|
|
|
|
2015-03-11 19:10:58 +01:00
|
|
|
static void
|
|
|
|
|
disconnect_state_cb(NMDevice *device, GParamSpec *pspec, DeviceCbInfo *info)
|
|
|
|
|
{
|
2022-05-18 11:33:14 +02:00
|
|
|
if (!g_ptr_array_find(info->queue, device, NULL))
|
2015-03-11 19:10:58 +01:00
|
|
|
return;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-04-23 10:00:47 -04:00
|
|
|
if (nm_device_get_state(device) <= NM_DEVICE_STATE_DISCONNECTED) {
|
2014-11-10 16:56:34 +01:00
|
|
|
g_print(_("Device '%s' successfully disconnected.\n"), nm_device_get_iface(device));
|
2015-03-11 19:10:58 +01:00
|
|
|
device_cb_info_finish(info, device);
|
2013-09-16 21:03:34 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-10 16:56:34 +01:00
|
|
|
static void
|
2015-03-11 19:10:58 +01:00
|
|
|
destroy_queue_element(gpointer data)
|
2014-11-10 16:56:34 +01:00
|
|
|
{
|
2015-03-11 19:10:58 +01:00
|
|
|
g_signal_handlers_disconnect_matched(data,
|
|
|
|
|
G_SIGNAL_MATCH_FUNC,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
disconnect_state_cb,
|
|
|
|
|
NULL);
|
|
|
|
|
g_object_unref(data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
device_cb_info_finish(DeviceCbInfo *info, NMDevice *device)
|
|
|
|
|
{
|
|
|
|
|
if (device) {
|
2022-05-18 11:33:14 +02:00
|
|
|
if (!g_ptr_array_remove(info->queue, device))
|
|
|
|
|
return;
|
|
|
|
|
if (info->queue->len)
|
2015-03-11 19:10:58 +01:00
|
|
|
return;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-03-11 19:10:58 +01:00
|
|
|
if (info->timeout_id)
|
|
|
|
|
g_source_remove(info->timeout_id);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2022-05-18 11:33:14 +02:00
|
|
|
g_ptr_array_free(info->queue, TRUE);
|
2015-03-11 19:10:58 +01:00
|
|
|
g_signal_handlers_disconnect_by_func(info->nmc->client, device_removed_cb, info);
|
2018-11-23 09:56:01 +01:00
|
|
|
nm_clear_g_cancellable(&info->cancellable);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-03-11 19:10:58 +01:00
|
|
|
g_slice_free(DeviceCbInfo, info);
|
2014-11-10 16:56:34 +01:00
|
|
|
quit();
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-14 18:33:53 +02:00
|
|
|
static void
|
|
|
|
|
reapply_device_cb(GObject *object, GAsyncResult *result, gpointer user_data)
|
|
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NMDevice *device = NM_DEVICE(object);
|
2015-05-14 18:33:53 +02:00
|
|
|
DeviceCbInfo *info = (DeviceCbInfo *) user_data;
|
2021-11-09 13:28:54 +01:00
|
|
|
NmCli *nmc = info->nmc;
|
|
|
|
|
GError *error = NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-05-14 18:33:53 +02:00
|
|
|
if (!nm_device_reapply_finish(device, result, &error)) {
|
2016-04-30 14:14:31 +02:00
|
|
|
g_string_printf(nmc->return_text,
|
|
|
|
|
_("Error: Reapplying connection to device '%s' (%s) failed: %s"),
|
|
|
|
|
nm_device_get_iface(device),
|
|
|
|
|
nm_object_get_path(NM_OBJECT(device)),
|
|
|
|
|
error->message);
|
2015-05-14 18:33:53 +02:00
|
|
|
g_error_free(error);
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_DEV_DISCONNECT;
|
|
|
|
|
device_cb_info_finish(info, device);
|
|
|
|
|
} else {
|
2017-03-30 12:45:41 +02:00
|
|
|
if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
|
2015-05-14 18:33:53 +02:00
|
|
|
nmc_terminal_erase_line();
|
|
|
|
|
g_print(_("Connection successfully reapplied to device '%s'.\n"),
|
2016-04-30 13:46:18 +02:00
|
|
|
nm_device_get_iface(device));
|
2015-05-14 18:33:53 +02:00
|
|
|
device_cb_info_finish(info, device);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
static void
|
2020-04-05 13:05:58 +02:00
|
|
|
do_device_reapply(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
|
2015-05-14 18:33:53 +02:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NMDevice *device;
|
|
|
|
|
DeviceCbInfo *info = NULL;
|
2016-06-27 11:54:25 +02:00
|
|
|
gs_free_error GError *error = NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-05-14 18:33:53 +02:00
|
|
|
/* Set default timeout for reapply operation. */
|
|
|
|
|
if (nmc->timeout == -1)
|
|
|
|
|
nmc->timeout = 10;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg(nmc, &argc, &argv, NULL);
|
2016-06-27 11:54:25 +02:00
|
|
|
device = get_device(nmc, &argc, &argv, &error);
|
|
|
|
|
if (!device) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: %s."), error->message);
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = error->code;
|
|
|
|
|
return;
|
2015-05-14 18:33:53 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-27 11:54:25 +02:00
|
|
|
if (argc) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: invalid extra argument '%s'."), *argv);
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2015-05-14 18:33:53 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-23 10:49:20 +02:00
|
|
|
if (nmc->complete)
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
return;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-05-14 18:33:53 +02:00
|
|
|
nmc->nowait_flag = (nmc->timeout == 0);
|
2016-06-22 17:44:39 +02:00
|
|
|
nmc->should_wait++;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2022-05-18 11:33:14 +02:00
|
|
|
info = g_slice_new0(DeviceCbInfo);
|
|
|
|
|
info->nmc = nmc;
|
|
|
|
|
|
|
|
|
|
info->queue = g_ptr_array_new_with_free_func(destroy_queue_element);
|
|
|
|
|
g_ptr_array_add(info->queue, g_object_ref(device));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-04-30 14:14:31 +02:00
|
|
|
/* Now reapply the connection to the device */
|
|
|
|
|
nm_device_reapply_async(device, NULL, 0, 0, NULL, reapply_device_cb, info);
|
2015-05-14 18:33:53 +02:00
|
|
|
}
|
|
|
|
|
|
2016-06-22 18:25:48 +02:00
|
|
|
typedef struct {
|
|
|
|
|
NmCli *nmc;
|
|
|
|
|
int argc;
|
|
|
|
|
char **argv;
|
|
|
|
|
} ModifyInfo;
|
|
|
|
|
|
2020-07-13 16:25:30 +02:00
|
|
|
static void
|
|
|
|
|
modify_info_free(ModifyInfo *info)
|
|
|
|
|
{
|
|
|
|
|
g_strfreev(info->argv);
|
|
|
|
|
nm_g_slice_free(info);
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-19 11:40:50 +02:00
|
|
|
NM_AUTO_DEFINE_FCN_VOID0(ModifyInfo *, _auto_free_modify_info, modify_info_free);
|
2020-07-13 16:25:30 +02:00
|
|
|
|
2016-06-22 18:25:48 +02:00
|
|
|
static void
|
|
|
|
|
modify_reapply_cb(GObject *object, GAsyncResult *result, gpointer user_data)
|
|
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NMDevice *device = NM_DEVICE(object);
|
2020-07-13 16:25:30 +02:00
|
|
|
nm_auto(_auto_free_modify_info) ModifyInfo *info = user_data;
|
2021-11-09 13:28:54 +01:00
|
|
|
NmCli *nmc = info->nmc;
|
|
|
|
|
GError *error = NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-22 18:25:48 +02:00
|
|
|
if (!nm_device_reapply_finish(device, result, &error)) {
|
|
|
|
|
g_string_printf(nmc->return_text,
|
|
|
|
|
_("Error: Reapplying connection to device '%s' (%s) failed: %s"),
|
|
|
|
|
nm_device_get_iface(device),
|
|
|
|
|
nm_object_get_path(NM_OBJECT(device)),
|
|
|
|
|
error->message);
|
|
|
|
|
g_error_free(error);
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_DEV_DISCONNECT;
|
|
|
|
|
} else {
|
2017-03-30 12:45:41 +02:00
|
|
|
if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
|
2016-06-22 18:25:48 +02:00
|
|
|
nmc_terminal_erase_line();
|
|
|
|
|
g_print(_("Connection successfully reapplied to device '%s'.\n"),
|
|
|
|
|
nm_device_get_iface(device));
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-22 18:25:48 +02:00
|
|
|
quit();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
modify_get_applied_cb(GObject *object, GAsyncResult *result, gpointer user_data)
|
|
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NMDevice *device = NM_DEVICE(object);
|
2020-07-13 16:25:30 +02:00
|
|
|
nm_auto(_auto_free_modify_info) ModifyInfo *info = user_data;
|
2021-11-09 13:28:54 +01:00
|
|
|
NmCli *nmc = info->nmc;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
guint64 version_id;
|
|
|
|
|
int argc;
|
|
|
|
|
const char *const *argv;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-22 18:25:48 +02:00
|
|
|
connection = nm_device_get_applied_connection_finish(device, result, &version_id, &error);
|
|
|
|
|
if (!connection) {
|
|
|
|
|
g_string_printf(nmc->return_text,
|
|
|
|
|
_("Error: Reading applied connection from device '%s' (%s) failed: %s"),
|
|
|
|
|
nm_device_get_iface(device),
|
|
|
|
|
nm_object_get_path(NM_OBJECT(device)),
|
|
|
|
|
error->message);
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
|
|
|
|
|
quit();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-04-05 13:05:58 +02:00
|
|
|
argc = info->argc;
|
|
|
|
|
argv = (const char *const *) info->argv;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-04-05 13:05:58 +02:00
|
|
|
if (!nmc_process_connection_properties(info->nmc, connection, &argc, &argv, TRUE, &error)) {
|
2016-06-22 18:25:48 +02:00
|
|
|
g_string_assign(nmc->return_text, error->message);
|
|
|
|
|
nmc->return_value = error->code;
|
|
|
|
|
quit();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-07-13 16:25:30 +02:00
|
|
|
if (nmc->complete) {
|
2016-06-22 18:25:48 +02:00
|
|
|
quit();
|
2020-07-13 16:25:30 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-07-13 16:25:30 +02:00
|
|
|
nm_device_reapply_async(device,
|
|
|
|
|
connection,
|
|
|
|
|
version_id,
|
|
|
|
|
0,
|
|
|
|
|
NULL,
|
|
|
|
|
modify_reapply_cb,
|
|
|
|
|
g_steal_pointer(&info));
|
2016-06-22 18:25:48 +02:00
|
|
|
}
|
|
|
|
|
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
static void
|
2020-04-05 13:05:58 +02:00
|
|
|
do_device_modify(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
|
2016-06-22 18:25:48 +02:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NMDevice *device = NULL;
|
|
|
|
|
ModifyInfo *info;
|
2016-06-22 18:25:48 +02:00
|
|
|
gs_free_error GError *error = NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg(nmc, &argc, &argv, NULL);
|
2016-06-22 18:25:48 +02:00
|
|
|
device = get_device(nmc, &argc, &argv, &error);
|
|
|
|
|
if (!device) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: %s."), error->message);
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = error->code;
|
|
|
|
|
return;
|
2016-06-22 18:25:48 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-22 18:25:48 +02:00
|
|
|
if (nmc->timeout == -1)
|
|
|
|
|
nmc->timeout = 10;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-22 18:25:48 +02:00
|
|
|
nmc->nowait_flag = (nmc->timeout == 0);
|
|
|
|
|
nmc->should_wait++;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-07-13 16:25:30 +02:00
|
|
|
info = g_slice_new(ModifyInfo);
|
|
|
|
|
*info = (ModifyInfo){
|
|
|
|
|
.nmc = nmc,
|
|
|
|
|
.argc = argc,
|
2021-07-29 10:02:11 +02:00
|
|
|
.argv = nm_strv_dup(argv, argc, TRUE),
|
2020-07-13 16:25:30 +02:00
|
|
|
};
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-22 18:25:48 +02:00
|
|
|
nm_device_get_applied_connection_async(device, 0, NULL, modify_get_applied_cb, info);
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-25 09:52:30 -08:00
|
|
|
static void
|
2014-09-11 16:27:13 -04:00
|
|
|
disconnect_device_cb(GObject *object, GAsyncResult *result, gpointer user_data)
|
2010-02-25 09:52:30 -08:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NMDevice *device = NM_DEVICE(object);
|
2015-03-11 19:10:58 +01:00
|
|
|
DeviceCbInfo *info = (DeviceCbInfo *) user_data;
|
2021-11-09 13:28:54 +01:00
|
|
|
NmCli *nmc;
|
2010-02-25 09:52:30 -08:00
|
|
|
NMDeviceState state;
|
2021-11-09 13:28:54 +01:00
|
|
|
GError *error = NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2014-09-11 16:27:13 -04:00
|
|
|
if (!nm_device_disconnect_finish(device, result, &error)) {
|
2018-11-23 09:56:01 +01:00
|
|
|
if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
|
|
|
return;
|
|
|
|
|
nmc = info->nmc;
|
2015-03-11 19:10:58 +01:00
|
|
|
g_string_printf(nmc->return_text, _("Error: not all devices disconnected."));
|
|
|
|
|
g_printerr(_("Error: Device '%s' (%s) disconnecting failed: %s\n"),
|
|
|
|
|
nm_device_get_iface(device),
|
|
|
|
|
nm_object_get_path(NM_OBJECT(device)),
|
|
|
|
|
error->message);
|
2014-09-11 16:27:13 -04:00
|
|
|
g_error_free(error);
|
2010-02-25 09:52:30 -08:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_DEV_DISCONNECT;
|
2015-03-11 19:10:58 +01:00
|
|
|
device_cb_info_finish(info, device);
|
2010-02-25 09:52:30 -08:00
|
|
|
} else {
|
2018-11-23 09:56:01 +01:00
|
|
|
nmc = info->nmc;
|
2010-02-25 09:52:30 -08:00
|
|
|
state = nm_device_get_state(device);
|
2015-04-23 10:00:47 -04:00
|
|
|
if (nmc->nowait_flag || state <= NM_DEVICE_STATE_DISCONNECTED) {
|
2010-02-25 09:52:30 -08:00
|
|
|
/* Don't want to wait or device already disconnected */
|
2015-04-23 10:00:47 -04:00
|
|
|
if (state <= NM_DEVICE_STATE_DISCONNECTED) {
|
2017-03-30 12:45:41 +02:00
|
|
|
if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
|
2013-09-19 15:15:10 +02:00
|
|
|
nmc_terminal_erase_line();
|
2015-03-11 19:10:58 +01:00
|
|
|
g_print(_("Device '%s' successfully disconnected.\n"), nm_device_get_iface(device));
|
2012-05-03 11:54:52 +02:00
|
|
|
}
|
2015-03-11 19:10:58 +01:00
|
|
|
device_cb_info_finish(info, device);
|
2010-02-25 09:52:30 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
static void
|
2020-04-05 13:05:58 +02:00
|
|
|
do_devices_disconnect(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
|
2010-02-25 09:52:30 -08:00
|
|
|
{
|
2022-05-04 10:21:02 +02:00
|
|
|
NMDevice *device;
|
|
|
|
|
DeviceCbInfo *info = NULL;
|
|
|
|
|
gs_unref_ptrarray GPtrArray *queue = NULL;
|
|
|
|
|
guint i;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-05-14 12:43:43 +02:00
|
|
|
/* Set default timeout for disconnect operation. */
|
|
|
|
|
if (nmc->timeout == -1)
|
|
|
|
|
nmc->timeout = 10;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg(nmc, &argc, &argv, NULL);
|
2022-05-04 09:52:22 +02:00
|
|
|
queue = get_device_list(nmc, &argc, &argv);
|
2022-05-04 09:56:10 +02:00
|
|
|
if (argc) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: invalid extra argument '%s'."), *argv);
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2015-03-27 12:31:08 +01:00
|
|
|
if (!queue)
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
return;
|
2016-06-23 10:49:20 +02:00
|
|
|
if (nmc->complete)
|
2022-05-04 10:21:02 +02:00
|
|
|
return;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-03-11 19:10:58 +01:00
|
|
|
info = g_slice_new0(DeviceCbInfo);
|
2022-05-18 11:33:14 +02:00
|
|
|
info->queue = g_steal_pointer(&queue);
|
2015-03-11 19:10:58 +01:00
|
|
|
info->nmc = nmc;
|
|
|
|
|
info->cmd_disconnect = TRUE;
|
2018-11-23 09:56:01 +01:00
|
|
|
info->cancellable = g_cancellable_new();
|
2015-03-11 19:10:58 +01:00
|
|
|
if (nmc->timeout > 0)
|
|
|
|
|
info->timeout_id = g_timeout_add_seconds(nmc->timeout, device_op_timeout_cb, info);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-03-11 19:10:58 +01:00
|
|
|
g_signal_connect(nmc->client, NM_CLIENT_DEVICE_REMOVED, G_CALLBACK(device_removed_cb), info);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-05-14 12:43:43 +02:00
|
|
|
nmc->nowait_flag = (nmc->timeout == 0);
|
2015-03-27 12:39:17 +01:00
|
|
|
nmc->should_wait++;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2022-05-18 11:33:14 +02:00
|
|
|
for (i = 0; i < info->queue->len; i++) {
|
|
|
|
|
device = info->queue->pdata[i];
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-03-11 19:10:58 +01:00
|
|
|
g_signal_connect(device, "notify::" NM_DEVICE_STATE, G_CALLBACK(disconnect_state_cb), info);
|
2018-11-23 09:56:01 +01:00
|
|
|
nm_device_disconnect_async(device, info->cancellable, disconnect_device_cb, info);
|
2015-03-11 19:10:58 +01:00
|
|
|
}
|
2010-02-25 09:52:30 -08:00
|
|
|
}
|
|
|
|
|
|
2014-06-19 11:25:17 +02:00
|
|
|
static void
|
2014-09-11 16:27:13 -04:00
|
|
|
delete_device_cb(GObject *object, GAsyncResult *result, gpointer user_data)
|
2014-06-19 11:25:17 +02:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NMDevice *device = NM_DEVICE(object);
|
2015-03-11 19:10:58 +01:00
|
|
|
DeviceCbInfo *info = (DeviceCbInfo *) user_data;
|
2021-11-09 13:28:54 +01:00
|
|
|
NmCli *nmc = info->nmc;
|
|
|
|
|
GError *error = NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2014-09-11 16:27:13 -04:00
|
|
|
if (!nm_device_delete_finish(device, result, &error)) {
|
2015-03-11 19:10:58 +01:00
|
|
|
g_string_printf(nmc->return_text, _("Error: not all devices deleted."));
|
|
|
|
|
g_printerr(_("Error: Device '%s' (%s) deletion failed: %s\n"),
|
|
|
|
|
nm_device_get_iface(device),
|
|
|
|
|
nm_object_get_path(NM_OBJECT(device)),
|
|
|
|
|
error->message);
|
2014-09-11 16:27:13 -04:00
|
|
|
g_error_free(error);
|
2014-06-19 11:25:17 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
|
2015-03-11 19:10:58 +01:00
|
|
|
device_cb_info_finish(info, device);
|
|
|
|
|
} else {
|
2018-10-19 14:51:12 +02:00
|
|
|
g_print(_("Device '%s' successfully removed.\n"), nm_device_get_iface(device));
|
|
|
|
|
device_cb_info_finish(info, device);
|
2014-06-19 11:25:17 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
static void
|
2020-04-05 13:05:58 +02:00
|
|
|
do_devices_delete(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
|
2014-06-19 11:25:17 +02:00
|
|
|
{
|
2022-05-04 10:21:02 +02:00
|
|
|
DeviceCbInfo *info = NULL;
|
|
|
|
|
gs_unref_ptrarray GPtrArray *queue = NULL;
|
|
|
|
|
guint i;
|
2014-06-19 11:25:17 +02:00
|
|
|
|
|
|
|
|
/* Set default timeout for delete operation. */
|
|
|
|
|
if (nmc->timeout == -1)
|
|
|
|
|
nmc->timeout = 10;
|
|
|
|
|
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg(nmc, &argc, &argv, NULL);
|
2022-05-04 09:52:22 +02:00
|
|
|
queue = get_device_list(nmc, &argc, &argv);
|
2022-05-04 09:56:10 +02:00
|
|
|
if (argc) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: invalid extra argument '%s'."), *argv);
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2015-03-27 12:31:08 +01:00
|
|
|
if (!queue)
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
return;
|
2016-06-23 10:49:20 +02:00
|
|
|
if (nmc->complete)
|
2022-05-04 10:21:02 +02:00
|
|
|
return;
|
2014-06-19 11:25:17 +02:00
|
|
|
|
2022-05-18 11:33:14 +02:00
|
|
|
info = g_slice_new0(DeviceCbInfo);
|
|
|
|
|
info->queue = g_steal_pointer(&queue);
|
|
|
|
|
info->nmc = nmc;
|
2015-03-11 19:10:58 +01:00
|
|
|
if (nmc->timeout > 0)
|
|
|
|
|
info->timeout_id = g_timeout_add_seconds(nmc->timeout, device_op_timeout_cb, info);
|
|
|
|
|
|
2014-06-19 11:25:17 +02:00
|
|
|
nmc->nowait_flag = (nmc->timeout == 0);
|
2015-03-27 12:39:17 +01:00
|
|
|
nmc->should_wait++;
|
2014-06-19 11:25:17 +02:00
|
|
|
|
2022-06-23 15:12:19 +02:00
|
|
|
for (i = 0; i < info->queue->len; i++) {
|
|
|
|
|
nm_device_delete_async(info->queue->pdata[i], NULL, delete_device_cb, info);
|
2015-03-11 19:10:58 +01:00
|
|
|
}
|
2014-06-19 11:25:17 +02:00
|
|
|
}
|
|
|
|
|
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
static void
|
2020-04-05 13:05:58 +02:00
|
|
|
do_device_set(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
|
2015-03-23 14:11:43 +01:00
|
|
|
{
|
|
|
|
|
#define DEV_SET_AUTOCONNECT 0
|
|
|
|
|
#define DEV_SET_MANAGED 1
|
|
|
|
|
NMDevice *device = NULL;
|
|
|
|
|
int i;
|
|
|
|
|
struct {
|
|
|
|
|
int idx;
|
|
|
|
|
gboolean value;
|
|
|
|
|
} values[2] = {
|
|
|
|
|
[DEV_SET_AUTOCONNECT] = {-1},
|
|
|
|
|
[DEV_SET_MANAGED] = {-1},
|
|
|
|
|
};
|
2016-06-24 18:45:19 +02:00
|
|
|
gs_free_error GError *error = NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg(nmc, &argc, &argv, NULL);
|
|
|
|
|
if (argc >= 1 && g_strcmp0(*argv, "ifname") == 0)
|
|
|
|
|
next_arg(nmc, &argc, &argv, NULL);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-24 18:45:19 +02:00
|
|
|
device = get_device(nmc, &argc, &argv, &error);
|
2015-03-23 14:11:43 +01:00
|
|
|
if (!device) {
|
2016-06-24 18:45:19 +02:00
|
|
|
g_string_printf(nmc->return_text, _("Error: %s."), error->message);
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = error->code;
|
|
|
|
|
return;
|
2015-03-23 14:11:43 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-10-09 13:51:04 +02:00
|
|
|
if (!argc) {
|
2015-03-23 14:11:43 +01:00
|
|
|
g_string_printf(nmc->return_text, _("Error: No property specified."));
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2015-03-23 14:11:43 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-03-23 14:11:43 +01:00
|
|
|
i = 0;
|
2016-06-24 18:45:19 +02:00
|
|
|
do {
|
2015-03-23 14:11:43 +01:00
|
|
|
gboolean flag;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-24 18:07:24 +02:00
|
|
|
if (argc == 1 && nmc->complete)
|
2019-04-12 15:40:01 +02:00
|
|
|
nmc_complete_strings(*argv, "managed", "autoconnect");
|
2020-09-28 16:03:33 +02:00
|
|
|
|
cli: make match() return boolean
Coccinelle semantic patch:
@@
@@
-int
+gboolean
matches (...);
@@
expression pattern, cmd, len;
@@
-int
+gboolean
matches (...)
{
...
- return memcmp (pattern, cmd, len);
+ return memcmp (pattern, cmd, len) == 0;
}
@@
expression prefix, str;
@@
(
-matches (prefix, str) != 0
+!matches (prefix, str)
|
-matches (prefix, str) == 0
+matches (prefix, str)
)
@@
expression prefix, str;
@@
-(matches (prefix, str))
+matches (prefix, str)
@@
expression prefix, str;
@@
-(!matches (prefix, str))
+!matches (prefix, str)
spatch --smpl-spacing --sp-file match.cocci --dir clients/cli/ \
--include-headers --macro-file shared/nm-utils/gsystem-local-alloc.h
2017-02-15 12:20:55 +01:00
|
|
|
if (matches(*argv, "managed")) {
|
2017-03-29 12:02:14 +02:00
|
|
|
argc--;
|
|
|
|
|
argv++;
|
2017-03-24 14:00:25 +01:00
|
|
|
if (!argc) {
|
2015-11-25 16:39:00 +01:00
|
|
|
g_string_printf(nmc->return_text,
|
|
|
|
|
_("Error: '%s' argument is missing."),
|
|
|
|
|
*(argv - 1));
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2015-03-23 14:11:43 +01:00
|
|
|
}
|
2016-06-24 18:07:24 +02:00
|
|
|
if (argc == 1 && nmc->complete)
|
|
|
|
|
nmc_complete_bool(*argv);
|
2016-06-24 18:45:19 +02:00
|
|
|
if (!nmc_string_to_bool(*argv, &flag, &error)) {
|
2015-03-23 14:11:43 +01:00
|
|
|
g_string_printf(nmc->return_text, _("Error: 'managed': %s."), error->message);
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2015-03-23 14:11:43 +01:00
|
|
|
}
|
|
|
|
|
values[DEV_SET_MANAGED].idx = ++i;
|
|
|
|
|
values[DEV_SET_MANAGED].value = flag;
|
cli: make match() return boolean
Coccinelle semantic patch:
@@
@@
-int
+gboolean
matches (...);
@@
expression pattern, cmd, len;
@@
-int
+gboolean
matches (...)
{
...
- return memcmp (pattern, cmd, len);
+ return memcmp (pattern, cmd, len) == 0;
}
@@
expression prefix, str;
@@
(
-matches (prefix, str) != 0
+!matches (prefix, str)
|
-matches (prefix, str) == 0
+matches (prefix, str)
)
@@
expression prefix, str;
@@
-(matches (prefix, str))
+matches (prefix, str)
@@
expression prefix, str;
@@
-(!matches (prefix, str))
+!matches (prefix, str)
spatch --smpl-spacing --sp-file match.cocci --dir clients/cli/ \
--include-headers --macro-file shared/nm-utils/gsystem-local-alloc.h
2017-02-15 12:20:55 +01:00
|
|
|
} else if (matches(*argv, "autoconnect")) {
|
2017-03-29 12:02:14 +02:00
|
|
|
argc--;
|
|
|
|
|
argv++;
|
2017-03-24 14:00:25 +01:00
|
|
|
if (!argc) {
|
2015-11-25 16:39:00 +01:00
|
|
|
g_string_printf(nmc->return_text,
|
|
|
|
|
_("Error: '%s' argument is missing."),
|
|
|
|
|
*(argv - 1));
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2015-03-23 14:11:43 +01:00
|
|
|
}
|
2016-06-24 18:07:24 +02:00
|
|
|
if (argc == 1 && nmc->complete)
|
|
|
|
|
nmc_complete_bool(*argv);
|
2016-06-24 18:45:19 +02:00
|
|
|
if (!nmc_string_to_bool(*argv, &flag, &error)) {
|
2015-03-23 14:11:43 +01:00
|
|
|
g_string_printf(nmc->return_text, _("Error: 'autoconnect': %s."), error->message);
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2015-03-23 14:11:43 +01:00
|
|
|
}
|
|
|
|
|
values[DEV_SET_AUTOCONNECT].idx = ++i;
|
|
|
|
|
values[DEV_SET_AUTOCONNECT].value = flag;
|
|
|
|
|
} else {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: property '%s' is not known."), *argv);
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2015-03-23 14:11:43 +01:00
|
|
|
}
|
2017-03-30 16:09:46 +02:00
|
|
|
} while (next_arg(nmc, &argc, &argv, NULL) == 0);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-24 18:07:24 +02:00
|
|
|
if (nmc->complete)
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
return;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-03-23 14:11:43 +01:00
|
|
|
/* when multiple properties are specified, set them in the order as they
|
|
|
|
|
* are specified on the command line. */
|
|
|
|
|
if (values[DEV_SET_AUTOCONNECT].idx >= 0 && values[DEV_SET_MANAGED].idx >= 0
|
|
|
|
|
&& values[DEV_SET_MANAGED].idx < values[DEV_SET_AUTOCONNECT].idx) {
|
|
|
|
|
nm_device_set_managed(device, values[DEV_SET_MANAGED].value);
|
|
|
|
|
values[DEV_SET_MANAGED].idx = -1;
|
|
|
|
|
}
|
|
|
|
|
if (values[DEV_SET_AUTOCONNECT].idx >= 0)
|
|
|
|
|
nm_device_set_autoconnect(device, values[DEV_SET_AUTOCONNECT].value);
|
|
|
|
|
if (values[DEV_SET_MANAGED].idx >= 0)
|
2015-11-06 14:51:40 +01:00
|
|
|
nm_device_set_managed(device, values[DEV_SET_MANAGED].value);
|
2015-03-23 14:11:43 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-27 13:11:06 +01:00
|
|
|
static void
|
|
|
|
|
device_state(NMDevice *device, GParamSpec *pspec, NmCli *nmc)
|
|
|
|
|
{
|
2020-06-10 15:27:59 +02:00
|
|
|
gs_free char *str = NULL;
|
2018-03-29 12:31:33 +02:00
|
|
|
NMMetaColor color;
|
2016-07-01 21:45:43 +02:00
|
|
|
|
2020-06-08 23:26:18 +02:00
|
|
|
color = nmc_device_state_to_color(device);
|
2018-03-29 12:31:33 +02:00
|
|
|
str = nmc_colorize(&nmc->nmc_config,
|
|
|
|
|
color,
|
|
|
|
|
"%s: %s\n",
|
2016-07-01 21:45:43 +02:00
|
|
|
nm_device_get_iface(device),
|
2020-06-10 15:27:59 +02:00
|
|
|
gettext(nmc_device_state_to_string_with_external(device)));
|
2015-03-27 13:11:06 +01:00
|
|
|
|
|
|
|
|
g_print("%s", str);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
device_ac(NMDevice *device, GParamSpec *pspec, NmCli *nmc)
|
|
|
|
|
{
|
|
|
|
|
NMActiveConnection *ac = nm_device_get_active_connection(device);
|
2021-11-09 13:28:54 +01:00
|
|
|
const char *id = ac ? nm_active_connection_get_id(ac) : NULL;
|
2015-03-27 13:11:06 +01:00
|
|
|
|
|
|
|
|
if (!id)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
g_print(_("%s: using connection '%s'\n"), nm_device_get_iface(device), id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
device_watch(NmCli *nmc, NMDevice *device)
|
|
|
|
|
{
|
|
|
|
|
nmc->should_wait++;
|
|
|
|
|
g_signal_connect(device, "notify::" NM_DEVICE_STATE, G_CALLBACK(device_state), nmc);
|
|
|
|
|
g_signal_connect(device, "notify::" NM_DEVICE_ACTIVE_CONNECTION, G_CALLBACK(device_ac), nmc);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
device_unwatch(NmCli *nmc, NMDevice *device)
|
|
|
|
|
{
|
|
|
|
|
g_signal_handlers_disconnect_by_func(device, device_state, nmc);
|
|
|
|
|
if (g_signal_handlers_disconnect_by_func(device, device_ac, nmc))
|
|
|
|
|
nmc->should_wait--;
|
|
|
|
|
|
|
|
|
|
/* Terminate if all the watched devices disappeared. */
|
|
|
|
|
if (!nmc->should_wait)
|
|
|
|
|
quit();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
device_added(NMClient *client, NMDevice *device, NmCli *nmc)
|
|
|
|
|
{
|
|
|
|
|
g_print(_("%s: device created\n"), nm_device_get_iface(device));
|
|
|
|
|
device_watch(nmc, NM_DEVICE(device));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
device_removed(NMClient *client, NMDevice *device, NmCli *nmc)
|
|
|
|
|
{
|
|
|
|
|
g_print(_("%s: device removed\n"), nm_device_get_iface(device));
|
|
|
|
|
device_unwatch(nmc, device);
|
|
|
|
|
}
|
|
|
|
|
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
static void
|
2020-04-05 13:05:58 +02:00
|
|
|
do_devices_monitor(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
|
2015-03-27 13:11:06 +01:00
|
|
|
{
|
2022-05-04 10:21:02 +02:00
|
|
|
const GPtrArray *devices;
|
|
|
|
|
gs_unref_ptrarray GPtrArray *devices_free = NULL;
|
|
|
|
|
guint i;
|
|
|
|
|
|
2016-06-23 10:49:20 +02:00
|
|
|
if (nmc->complete)
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
return;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg(nmc, &argc, &argv, NULL);
|
2022-05-04 10:21:02 +02:00
|
|
|
if (argc > 0) {
|
|
|
|
|
devices = devices_free = get_device_list(nmc, &argc, &argv);
|
2022-05-04 09:56:10 +02:00
|
|
|
if (argc) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: invalid extra argument '%s'."), *argv);
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-10-19 11:41:13 +02:00
|
|
|
if (!devices)
|
|
|
|
|
return;
|
2022-05-04 10:21:02 +02:00
|
|
|
} else {
|
2015-03-27 13:11:06 +01:00
|
|
|
/* No devices specified. Monitor all. */
|
2022-05-04 10:21:02 +02:00
|
|
|
devices = nm_client_get_devices(nmc->client);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-03-27 13:11:06 +01:00
|
|
|
/* We'll watch the device additions too, never exit. */
|
|
|
|
|
nmc->should_wait++;
|
|
|
|
|
g_signal_connect(nmc->client, NM_CLIENT_DEVICE_ADDED, G_CALLBACK(device_added), nmc);
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2022-05-04 10:21:02 +02:00
|
|
|
for (i = 0; i < devices->len; i++)
|
|
|
|
|
device_watch(nmc, g_ptr_array_index(devices, i));
|
|
|
|
|
|
2015-03-27 13:11:06 +01:00
|
|
|
g_signal_connect(nmc->client, NM_CLIENT_DEVICE_REMOVED, G_CALLBACK(device_removed), nmc);
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-12 00:13:30 +02:00
|
|
|
/*
|
|
|
|
|
* Find a Wi-Fi device with 'iface' in 'devices' array. If 'iface' is NULL,
|
|
|
|
|
* the first Wi-Fi device is returned. 'idx' parameter is updated to the point
|
|
|
|
|
* where the function finished so that the function can be called repeatedly
|
|
|
|
|
* to get next matching device.
|
|
|
|
|
* Returns: found device or NULL
|
|
|
|
|
*/
|
|
|
|
|
static NMDevice *
|
2016-07-12 14:45:36 +02:00
|
|
|
find_wifi_device_by_iface(NMDevice **devices, const char *iface, int *idx)
|
2016-07-12 00:13:30 +02:00
|
|
|
{
|
|
|
|
|
int i;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-07-12 12:33:31 +02:00
|
|
|
for (i = idx ? *idx : 0; devices[i]; i++) {
|
2016-07-12 14:45:36 +02:00
|
|
|
const char *dev_iface = nm_device_get_iface(devices[i]);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-07-12 14:45:36 +02:00
|
|
|
if (!NM_IS_DEVICE_WIFI(devices[i]))
|
2016-07-12 00:13:30 +02:00
|
|
|
continue;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-07-12 00:13:30 +02:00
|
|
|
if (iface) {
|
|
|
|
|
/* If a iface was specified then use it. */
|
2016-07-12 14:45:36 +02:00
|
|
|
if (g_strcmp0(dev_iface, iface) == 0)
|
2016-07-12 00:13:30 +02:00
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
/* Else return the first Wi-Fi device. */
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-07-12 12:33:31 +02:00
|
|
|
if (idx)
|
|
|
|
|
*idx = i + 1;
|
2016-07-12 14:45:36 +02:00
|
|
|
return devices[i];
|
2016-07-12 00:13:30 +02:00
|
|
|
}
|
|
|
|
|
|
2016-07-12 14:31:25 +02:00
|
|
|
/*
|
2018-06-22 03:21:25 +02:00
|
|
|
* Find AP on 'device' according to 'bssid' and 'ssid' parameters.
|
2016-07-12 14:31:25 +02:00
|
|
|
* Returns: found AP or NULL
|
|
|
|
|
*/
|
|
|
|
|
static NMAccessPoint *
|
2016-07-12 14:36:53 +02:00
|
|
|
find_ap_on_device(NMDevice *device, const char *bssid, const char *ssid, gboolean complete)
|
2016-07-12 14:31:25 +02:00
|
|
|
{
|
|
|
|
|
const GPtrArray *aps;
|
2021-11-09 13:28:54 +01:00
|
|
|
NMAccessPoint *ap = NULL;
|
2016-07-12 14:31:25 +02:00
|
|
|
int i;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-07-12 14:31:25 +02:00
|
|
|
g_return_val_if_fail(NM_IS_DEVICE_WIFI(device), NULL);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-07-12 14:31:25 +02:00
|
|
|
aps = nm_device_wifi_get_access_points(NM_DEVICE_WIFI(device));
|
|
|
|
|
for (i = 0; i < aps->len; i++) {
|
|
|
|
|
NMAccessPoint *candidate_ap = g_ptr_array_index(aps, i);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-07-12 14:36:53 +02:00
|
|
|
if (bssid) {
|
|
|
|
|
const char *candidate_bssid = nm_access_point_get_bssid(candidate_ap);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-06-22 03:21:25 +02:00
|
|
|
if (!candidate_bssid)
|
|
|
|
|
continue;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-07-12 14:36:53 +02:00
|
|
|
/* Compare BSSIDs */
|
|
|
|
|
if (complete) {
|
|
|
|
|
if (g_str_has_prefix(candidate_bssid, bssid))
|
|
|
|
|
g_print("%s\n", candidate_bssid);
|
2018-06-22 03:21:25 +02:00
|
|
|
} else if (strcmp(bssid, candidate_bssid) != 0)
|
|
|
|
|
continue;
|
2016-07-12 14:36:53 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-07-12 14:31:25 +02:00
|
|
|
if (ssid) {
|
|
|
|
|
/* Parameter is SSID */
|
|
|
|
|
GBytes *candidate_ssid;
|
2021-11-09 13:28:54 +01:00
|
|
|
char *ssid_tmp;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-07-12 14:31:25 +02:00
|
|
|
candidate_ssid = nm_access_point_get_ssid(candidate_ap);
|
2016-07-12 14:36:53 +02:00
|
|
|
if (!candidate_ssid)
|
|
|
|
|
continue;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-07-12 14:36:53 +02:00
|
|
|
ssid_tmp = nm_utils_ssid_to_utf8(g_bytes_get_data(candidate_ssid, NULL),
|
|
|
|
|
g_bytes_get_size(candidate_ssid));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-07-12 14:36:53 +02:00
|
|
|
/* Compare SSIDs */
|
|
|
|
|
if (complete) {
|
|
|
|
|
if (g_str_has_prefix(ssid_tmp, ssid))
|
|
|
|
|
g_print("%s\n", ssid_tmp);
|
2018-06-22 03:21:25 +02:00
|
|
|
} else if (strcmp(ssid, ssid_tmp) != 0) {
|
2016-07-12 14:36:53 +02:00
|
|
|
g_free(ssid_tmp);
|
2018-06-22 03:21:25 +02:00
|
|
|
continue;
|
2016-07-12 14:31:25 +02:00
|
|
|
}
|
2016-07-12 14:36:53 +02:00
|
|
|
g_free(ssid_tmp);
|
2016-07-12 14:31:25 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-06-22 03:21:25 +02:00
|
|
|
if (complete)
|
|
|
|
|
continue;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-06-22 03:21:25 +02:00
|
|
|
ap = candidate_ap;
|
|
|
|
|
break;
|
2016-07-12 14:31:25 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-07-12 14:31:25 +02:00
|
|
|
return ap;
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-26 15:50:15 +01:00
|
|
|
static void
|
|
|
|
|
show_access_point_info(NMDeviceWifi *wifi, NmCli *nmc, NmcOutputData *out)
|
|
|
|
|
{
|
2022-02-28 18:49:25 +01:00
|
|
|
NMAccessPoint *active_ap = NULL;
|
2018-02-26 15:50:15 +01:00
|
|
|
NmcOutputField *arr;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2022-02-28 18:49:25 +01:00
|
|
|
if (nm_device_get_state(NM_DEVICE(wifi)) == NM_DEVICE_STATE_ACTIVATED)
|
|
|
|
|
active_ap = nm_device_wifi_get_active_access_point(wifi);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-02-26 15:50:15 +01:00
|
|
|
arr = nmc_dup_fields_array((const NMMetaAbstractInfo *const *) nmc_fields_dev_wifi_list,
|
|
|
|
|
NMC_OF_FLAG_MAIN_HEADER_ADD | NMC_OF_FLAG_FIELD_NAMES);
|
|
|
|
|
g_ptr_array_add(out->output_data, arr);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-02-26 15:50:15 +01:00
|
|
|
{
|
2022-02-28 19:20:37 +01:00
|
|
|
gs_unref_ptrarray GPtrArray *aps = NULL;
|
|
|
|
|
int info_index = 0;
|
|
|
|
|
const APInfo info = {
|
2021-11-09 13:28:54 +01:00
|
|
|
.nmc = nmc,
|
2022-02-28 19:20:37 +01:00
|
|
|
.p_index = &info_index,
|
2021-11-09 13:28:54 +01:00
|
|
|
.output_flags = 0,
|
2022-02-28 18:49:25 +01:00
|
|
|
.active_ap = active_ap,
|
2021-11-09 13:28:54 +01:00
|
|
|
.device = nm_device_get_iface(NM_DEVICE(wifi)),
|
|
|
|
|
.output_data = out->output_data,
|
2018-02-26 15:50:15 +01:00
|
|
|
};
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-02-26 15:50:15 +01:00
|
|
|
aps = sort_access_points(nm_device_wifi_get_access_points(wifi));
|
2022-02-28 19:20:37 +01:00
|
|
|
g_ptr_array_foreach(aps, fill_output_access_point_void, (gpointer) &info);
|
2018-02-26 15:50:15 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-02-26 15:50:15 +01:00
|
|
|
print_data_prepare_width(out->output_data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2021-11-09 13:28:54 +01:00
|
|
|
wifi_print_aps(NMDeviceWifi *wifi,
|
|
|
|
|
NmCli *nmc,
|
|
|
|
|
GArray *_out_indices,
|
2018-02-26 15:50:15 +01:00
|
|
|
const NMMetaAbstractInfo *const *tmpl,
|
2021-11-09 13:28:54 +01:00
|
|
|
const char *bssid_user,
|
|
|
|
|
gboolean *bssid_found)
|
2018-02-26 15:50:15 +01:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NMAccessPoint *ap = NULL;
|
2018-02-26 15:50:15 +01:00
|
|
|
const GPtrArray *aps;
|
|
|
|
|
guint i;
|
2021-11-09 13:28:54 +01:00
|
|
|
NmcOutputField *arr;
|
|
|
|
|
const char *base_hdr = _("Wi-Fi scan list");
|
2018-02-26 15:50:15 +01:00
|
|
|
NMC_OUTPUT_DATA_DEFINE_SCOPED(out);
|
2021-11-09 13:28:54 +01:00
|
|
|
gs_free char *header_name = NULL;
|
2018-02-26 15:50:15 +01:00
|
|
|
static gboolean empty_line = FALSE;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-02-26 15:50:15 +01:00
|
|
|
if (empty_line)
|
|
|
|
|
g_print("\n"); /* Empty line between devices' APs */
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-02-26 15:50:15 +01:00
|
|
|
/* Main header name */
|
|
|
|
|
header_name = construct_header_name(base_hdr, nm_device_get_iface(NM_DEVICE(wifi)));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-02-26 15:50:15 +01:00
|
|
|
out_indices = g_array_ref(_out_indices);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-02-26 15:50:15 +01:00
|
|
|
if (bssid_user) {
|
|
|
|
|
/* Specific AP requested - list only that */
|
|
|
|
|
aps = nm_device_wifi_get_access_points(wifi);
|
|
|
|
|
for (i = 0; i < aps->len; i++) {
|
|
|
|
|
NMAccessPoint *candidate_ap = g_ptr_array_index(aps, i);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-18 11:54:07 +01:00
|
|
|
if (nm_utils_hwaddr_matches(bssid_user,
|
|
|
|
|
-1,
|
|
|
|
|
nm_access_point_get_bssid(candidate_ap),
|
|
|
|
|
-1))
|
2018-02-26 15:50:15 +01:00
|
|
|
ap = candidate_ap;
|
|
|
|
|
}
|
|
|
|
|
if (ap) {
|
2022-02-28 19:20:37 +01:00
|
|
|
int info_index = 0;
|
|
|
|
|
const APInfo info = {
|
|
|
|
|
.nmc = nmc,
|
|
|
|
|
.p_index = &info_index,
|
|
|
|
|
.output_flags = 0,
|
|
|
|
|
.device = nm_device_get_iface(NM_DEVICE(wifi)),
|
|
|
|
|
.output_data = out.output_data,
|
2022-02-28 18:48:47 +01:00
|
|
|
};
|
|
|
|
|
|
2018-02-26 15:50:15 +01:00
|
|
|
/* Add headers (field names) */
|
|
|
|
|
arr = nmc_dup_fields_array(tmpl, NMC_OF_FLAG_MAIN_HEADER_ADD | NMC_OF_FLAG_FIELD_NAMES);
|
|
|
|
|
g_ptr_array_add(out.output_data, arr);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2022-02-28 18:48:47 +01:00
|
|
|
fill_output_access_point(ap, &info);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-02-26 15:50:15 +01:00
|
|
|
print_data_prepare_width(out.output_data);
|
2020-04-02 19:10:15 +02:00
|
|
|
print_data(&nmc->nmc_config, &nmc->pager_data, out_indices, header_name, 0, &out);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-18 10:34:07 +01:00
|
|
|
*bssid_found = TRUE;
|
2018-02-26 15:50:15 +01:00
|
|
|
empty_line = TRUE;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
show_access_point_info(wifi, nmc, &out);
|
2020-04-02 19:10:15 +02:00
|
|
|
print_data(&nmc->nmc_config, &nmc->pager_data, out_indices, header_name, 0, &out);
|
2018-02-26 15:50:15 +01:00
|
|
|
empty_line = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-18 10:34:07 +01:00
|
|
|
static gint64
|
|
|
|
|
_device_wifi_get_last_scan(NMDeviceWifi *wifi)
|
|
|
|
|
{
|
|
|
|
|
gint64 timestamp;
|
|
|
|
|
|
|
|
|
|
timestamp = nm_device_wifi_get_last_scan(wifi);
|
|
|
|
|
if (timestamp == -1)
|
|
|
|
|
return G_MININT64;
|
|
|
|
|
return timestamp;
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-26 15:50:15 +01:00
|
|
|
typedef struct {
|
2021-11-09 13:28:54 +01:00
|
|
|
NmCli *nmc;
|
|
|
|
|
NMDevice **devices;
|
2018-10-31 10:00:22 +01:00
|
|
|
const NMMetaAbstractInfo *const *tmpl;
|
2021-11-09 13:28:54 +01:00
|
|
|
char *bssid_user;
|
|
|
|
|
GArray *out_indices;
|
2020-03-18 10:34:07 +01:00
|
|
|
gint64 rescan_cutoff_msec;
|
|
|
|
|
guint pending;
|
2018-10-31 10:00:22 +01:00
|
|
|
} ScanInfo;
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
2021-11-09 13:28:54 +01:00
|
|
|
ScanInfo *scan_info;
|
2018-10-31 10:00:22 +01:00
|
|
|
NMDeviceWifi *wifi;
|
2018-02-26 15:50:15 +01:00
|
|
|
gulong last_scan_id;
|
|
|
|
|
guint timeout_id;
|
|
|
|
|
GCancellable *scan_cancellable;
|
|
|
|
|
} WifiListData;
|
|
|
|
|
|
|
|
|
|
static void
|
2020-03-18 10:34:07 +01:00
|
|
|
wifi_list_finish(WifiListData *wifi_list_data, gboolean force_finished)
|
2018-02-26 15:50:15 +01:00
|
|
|
{
|
2020-03-18 10:34:07 +01:00
|
|
|
ScanInfo *scan_info = wifi_list_data->scan_info;
|
2021-11-09 13:28:54 +01:00
|
|
|
NmCli *nmc = scan_info->nmc;
|
2020-03-18 10:34:07 +01:00
|
|
|
gboolean bssid_found = FALSE;
|
2018-10-31 10:00:22 +01:00
|
|
|
guint i;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-18 10:34:07 +01:00
|
|
|
if (!force_finished
|
|
|
|
|
&& scan_info->rescan_cutoff_msec > _device_wifi_get_last_scan(wifi_list_data->wifi)) {
|
|
|
|
|
/* wait longer... */
|
|
|
|
|
return;
|
2018-02-26 15:50:15 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-18 10:34:07 +01:00
|
|
|
nm_clear_g_signal_handler(wifi_list_data->wifi, &wifi_list_data->last_scan_id);
|
|
|
|
|
nm_clear_g_source(&wifi_list_data->timeout_id);
|
|
|
|
|
nm_clear_g_cancellable(&wifi_list_data->scan_cancellable);
|
|
|
|
|
nm_g_slice_free(wifi_list_data);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-18 10:34:07 +01:00
|
|
|
if (--scan_info->pending > 0)
|
|
|
|
|
return;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-18 10:34:07 +01:00
|
|
|
for (i = 0; scan_info->devices[i]; i++) {
|
|
|
|
|
wifi_print_aps(NM_DEVICE_WIFI(scan_info->devices[i]),
|
2020-03-19 14:45:09 +01:00
|
|
|
nmc,
|
2020-03-18 10:34:07 +01:00
|
|
|
scan_info->out_indices,
|
|
|
|
|
scan_info->tmpl,
|
|
|
|
|
scan_info->bssid_user,
|
|
|
|
|
&bssid_found);
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-18 10:34:07 +01:00
|
|
|
if (scan_info->bssid_user && !bssid_found) {
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND;
|
|
|
|
|
g_string_printf(nmc->return_text,
|
|
|
|
|
_("Error: Access point with bssid '%s' not found."),
|
|
|
|
|
scan_info->bssid_user);
|
2018-10-31 10:00:22 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-18 10:34:07 +01:00
|
|
|
for (i = 0; scan_info->devices[i]; i++)
|
|
|
|
|
g_object_unref(scan_info->devices[i]);
|
|
|
|
|
g_free(scan_info->devices);
|
|
|
|
|
g_array_unref(scan_info->out_indices);
|
2020-04-05 13:05:58 +02:00
|
|
|
g_free(scan_info->bssid_user);
|
2020-03-18 10:34:07 +01:00
|
|
|
nm_g_slice_free(scan_info);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-19 14:45:09 +01:00
|
|
|
nmc->should_wait--;
|
2020-03-18 10:34:07 +01:00
|
|
|
g_main_loop_quit(loop);
|
2018-02-26 15:50:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
wifi_last_scan_updated(GObject *gobject, GParamSpec *pspec, gpointer user_data)
|
|
|
|
|
{
|
2020-03-18 10:34:07 +01:00
|
|
|
wifi_list_finish(user_data, FALSE);
|
2018-02-26 15:50:15 +01:00
|
|
|
}
|
|
|
|
|
|
cli: repeatedly trigger Wi-Fi scans while waiting for scan result
NetworkManager will reject scan requests, if it is currently scanning.
That is very wrong. Even if NetworkManager wants to ratelimit scan
requests or not scan at critical moments, it should never reject a
request, but remember and start scanning as soon as it can.
That should be fixed.
But regardless, also nmcli can do better.
If you issue
$ nmcli device wifi list --rescan yes
once, it works as expected.
If you issue it again right after, the scan request of nmcli will be
rejected. But nmcli cannot just merely complete and print the result.
Instead, it will wait in the hope that a scan result will be present
soon. But if the request was simply rejected, then the result will
never come, and nmcli hangs for the 15 seconds timeout.
Instead, repeatedly re-trigger scan requests, in the hope that as soon
as possible we will be ready.
2020-04-23 14:28:27 +02:00
|
|
|
static void wifi_list_rescan_cb(GObject *source_object, GAsyncResult *res, gpointer user_data);
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
wifi_list_rescan_retry_cb(gpointer user_data, GCancellable *cancellable)
|
|
|
|
|
{
|
|
|
|
|
WifiListData *wifi_list_data;
|
|
|
|
|
|
|
|
|
|
if (g_cancellable_is_cancelled(cancellable))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
wifi_list_data = user_data;
|
|
|
|
|
nm_device_wifi_request_scan_async(wifi_list_data->wifi,
|
|
|
|
|
wifi_list_data->scan_cancellable,
|
|
|
|
|
wifi_list_rescan_cb,
|
|
|
|
|
wifi_list_data);
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-26 15:50:15 +01:00
|
|
|
static void
|
|
|
|
|
wifi_list_rescan_cb(GObject *source_object, GAsyncResult *res, gpointer user_data)
|
|
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NMDeviceWifi *wifi = NM_DEVICE_WIFI(source_object);
|
2018-02-26 15:50:15 +01:00
|
|
|
gs_free_error GError *error = NULL;
|
2021-11-09 13:28:54 +01:00
|
|
|
WifiListData *wifi_list_data;
|
2020-03-18 10:34:07 +01:00
|
|
|
gboolean force_finished;
|
cli: repeatedly trigger Wi-Fi scans while waiting for scan result
NetworkManager will reject scan requests, if it is currently scanning.
That is very wrong. Even if NetworkManager wants to ratelimit scan
requests or not scan at critical moments, it should never reject a
request, but remember and start scanning as soon as it can.
That should be fixed.
But regardless, also nmcli can do better.
If you issue
$ nmcli device wifi list --rescan yes
once, it works as expected.
If you issue it again right after, the scan request of nmcli will be
rejected. But nmcli cannot just merely complete and print the result.
Instead, it will wait in the hope that a scan result will be present
soon. But if the request was simply rejected, then the result will
never come, and nmcli hangs for the 15 seconds timeout.
Instead, repeatedly re-trigger scan requests, in the hope that as soon
as possible we will be ready.
2020-04-23 14:28:27 +02:00
|
|
|
gboolean done;
|
2018-02-26 15:50:15 +01:00
|
|
|
|
2020-03-18 10:34:07 +01:00
|
|
|
nm_device_wifi_request_scan_finish(wifi, res, &error);
|
|
|
|
|
if (nm_utils_error_is_cancelled(error))
|
|
|
|
|
return;
|
2018-02-26 15:50:15 +01:00
|
|
|
|
cli: repeatedly trigger Wi-Fi scans while waiting for scan result
NetworkManager will reject scan requests, if it is currently scanning.
That is very wrong. Even if NetworkManager wants to ratelimit scan
requests or not scan at critical moments, it should never reject a
request, but remember and start scanning as soon as it can.
That should be fixed.
But regardless, also nmcli can do better.
If you issue
$ nmcli device wifi list --rescan yes
once, it works as expected.
If you issue it again right after, the scan request of nmcli will be
rejected. But nmcli cannot just merely complete and print the result.
Instead, it will wait in the hope that a scan result will be present
soon. But if the request was simply rejected, then the result will
never come, and nmcli hangs for the 15 seconds timeout.
Instead, repeatedly re-trigger scan requests, in the hope that as soon
as possible we will be ready.
2020-04-23 14:28:27 +02:00
|
|
|
wifi_list_data = user_data;
|
|
|
|
|
|
2020-03-18 10:34:07 +01:00
|
|
|
if (g_error_matches(error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_NOT_ALLOWED)) {
|
cli: repeatedly trigger Wi-Fi scans while waiting for scan result
NetworkManager will reject scan requests, if it is currently scanning.
That is very wrong. Even if NetworkManager wants to ratelimit scan
requests or not scan at critical moments, it should never reject a
request, but remember and start scanning as soon as it can.
That should be fixed.
But regardless, also nmcli can do better.
If you issue
$ nmcli device wifi list --rescan yes
once, it works as expected.
If you issue it again right after, the scan request of nmcli will be
rejected. But nmcli cannot just merely complete and print the result.
Instead, it will wait in the hope that a scan result will be present
soon. But if the request was simply rejected, then the result will
never come, and nmcli hangs for the 15 seconds timeout.
Instead, repeatedly re-trigger scan requests, in the hope that as soon
as possible we will be ready.
2020-04-23 14:28:27 +02:00
|
|
|
if (nm_device_get_state(NM_DEVICE(wifi)) < NM_DEVICE_STATE_DISCONNECTED) {
|
|
|
|
|
/* the device is either unmanaged or unavailable.
|
|
|
|
|
*
|
|
|
|
|
* If it's unmanaged, we don't expect any scan result and are done.
|
|
|
|
|
* If it's unavailable, that usually means that we wait for wpa_supplicant
|
|
|
|
|
* to start. In that case, also quit (without scan results). */
|
|
|
|
|
force_finished = TRUE;
|
|
|
|
|
done = TRUE;
|
|
|
|
|
} else {
|
|
|
|
|
/* This likely means that scanning is already in progress. There's
|
|
|
|
|
* a good chance we'll get updated results soon; wait for them.
|
|
|
|
|
*
|
|
|
|
|
* But also, NetworkManager ratelimits (and rejects requests). That
|
|
|
|
|
* means, possibly we were just ratelimited, so waiting will not lead
|
|
|
|
|
* to a new scan result. Instead, repeatedly ask new scans... */
|
|
|
|
|
nm_utils_invoke_on_timeout(1000,
|
|
|
|
|
wifi_list_data->scan_cancellable,
|
|
|
|
|
wifi_list_rescan_retry_cb,
|
|
|
|
|
wifi_list_data);
|
|
|
|
|
force_finished = FALSE;
|
|
|
|
|
done = FALSE;
|
|
|
|
|
}
|
|
|
|
|
} else if (error) {
|
2020-03-18 10:34:07 +01:00
|
|
|
force_finished = TRUE;
|
cli: repeatedly trigger Wi-Fi scans while waiting for scan result
NetworkManager will reject scan requests, if it is currently scanning.
That is very wrong. Even if NetworkManager wants to ratelimit scan
requests or not scan at critical moments, it should never reject a
request, but remember and start scanning as soon as it can.
That should be fixed.
But regardless, also nmcli can do better.
If you issue
$ nmcli device wifi list --rescan yes
once, it works as expected.
If you issue it again right after, the scan request of nmcli will be
rejected. But nmcli cannot just merely complete and print the result.
Instead, it will wait in the hope that a scan result will be present
soon. But if the request was simply rejected, then the result will
never come, and nmcli hangs for the 15 seconds timeout.
Instead, repeatedly re-trigger scan requests, in the hope that as soon
as possible we will be ready.
2020-04-23 14:28:27 +02:00
|
|
|
done = TRUE;
|
|
|
|
|
} else {
|
2020-03-18 10:34:07 +01:00
|
|
|
force_finished = FALSE;
|
cli: repeatedly trigger Wi-Fi scans while waiting for scan result
NetworkManager will reject scan requests, if it is currently scanning.
That is very wrong. Even if NetworkManager wants to ratelimit scan
requests or not scan at critical moments, it should never reject a
request, but remember and start scanning as soon as it can.
That should be fixed.
But regardless, also nmcli can do better.
If you issue
$ nmcli device wifi list --rescan yes
once, it works as expected.
If you issue it again right after, the scan request of nmcli will be
rejected. But nmcli cannot just merely complete and print the result.
Instead, it will wait in the hope that a scan result will be present
soon. But if the request was simply rejected, then the result will
never come, and nmcli hangs for the 15 seconds timeout.
Instead, repeatedly re-trigger scan requests, in the hope that as soon
as possible we will be ready.
2020-04-23 14:28:27 +02:00
|
|
|
done = TRUE;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
cli: repeatedly trigger Wi-Fi scans while waiting for scan result
NetworkManager will reject scan requests, if it is currently scanning.
That is very wrong. Even if NetworkManager wants to ratelimit scan
requests or not scan at critical moments, it should never reject a
request, but remember and start scanning as soon as it can.
That should be fixed.
But regardless, also nmcli can do better.
If you issue
$ nmcli device wifi list --rescan yes
once, it works as expected.
If you issue it again right after, the scan request of nmcli will be
rejected. But nmcli cannot just merely complete and print the result.
Instead, it will wait in the hope that a scan result will be present
soon. But if the request was simply rejected, then the result will
never come, and nmcli hangs for the 15 seconds timeout.
Instead, repeatedly re-trigger scan requests, in the hope that as soon
as possible we will be ready.
2020-04-23 14:28:27 +02:00
|
|
|
if (done)
|
|
|
|
|
g_clear_object(&wifi_list_data->scan_cancellable);
|
2020-03-18 10:34:07 +01:00
|
|
|
wifi_list_finish(wifi_list_data, force_finished);
|
2018-02-26 15:50:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
wifi_list_scan_timeout(gpointer user_data)
|
|
|
|
|
{
|
2020-03-18 10:34:07 +01:00
|
|
|
WifiListData *wifi_list_data = user_data;
|
2018-02-26 15:50:15 +01:00
|
|
|
|
2020-03-18 10:34:07 +01:00
|
|
|
wifi_list_data->timeout_id = 0;
|
|
|
|
|
wifi_list_finish(user_data, TRUE);
|
2018-02-26 15:50:15 +01:00
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-12 14:36:53 +02:00
|
|
|
static void
|
2021-11-09 13:28:54 +01:00
|
|
|
complete_aps(NMDevice **devices,
|
2016-07-12 14:36:53 +02:00
|
|
|
const char *ifname,
|
|
|
|
|
const char *bssid_prefix,
|
|
|
|
|
const char *ssid_prefix)
|
|
|
|
|
{
|
|
|
|
|
int devices_idx = 0;
|
|
|
|
|
NMDevice *device;
|
|
|
|
|
|
|
|
|
|
while ((device = find_wifi_device_by_iface(devices, ifname, &devices_idx)))
|
|
|
|
|
find_ap_on_device(device, bssid_prefix, ssid_prefix, TRUE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nmc_complete_bssid(NMClient *client, const char *ifname, const char *bssid_prefix)
|
|
|
|
|
{
|
|
|
|
|
gs_free NMDevice **devices = NULL;
|
|
|
|
|
|
|
|
|
|
devices = nmc_get_devices_sorted(client);
|
|
|
|
|
complete_aps(devices, ifname, bssid_prefix, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
static void
|
2020-04-05 13:05:58 +02:00
|
|
|
do_device_wifi_list(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
|
2010-02-25 09:52:30 -08:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
GError *error = NULL;
|
|
|
|
|
NMDevice *device = NULL;
|
|
|
|
|
const char *ifname = NULL;
|
|
|
|
|
const char *bssid_user = NULL;
|
|
|
|
|
const char *rescan = NULL;
|
|
|
|
|
gs_free NMDevice **devices = NULL;
|
|
|
|
|
const char *fields_str = NULL;
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
const NMMetaAbstractInfo *const *tmpl;
|
2021-11-09 13:28:54 +01:00
|
|
|
gs_unref_array GArray *out_indices = NULL;
|
|
|
|
|
int option;
|
|
|
|
|
gint64 rescan_cutoff_msec;
|
|
|
|
|
ScanInfo *scan_info = NULL;
|
|
|
|
|
gboolean ifname_handled;
|
|
|
|
|
NMDevice *ifname_handled_candidate;
|
|
|
|
|
guint i, j;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-07-12 10:16:24 +02:00
|
|
|
devices = nmc_get_devices_sorted(nmc->client);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-02-26 15:50:15 +01:00
|
|
|
while ((option = next_arg(nmc, &argc, &argv, "ifname", "hwaddr", "bssid", "--rescan", NULL))
|
|
|
|
|
> 0) {
|
2018-02-25 14:27:18 +01:00
|
|
|
switch (option) {
|
|
|
|
|
case 1: /* ifname */
|
2017-03-29 12:02:14 +02:00
|
|
|
argc--;
|
|
|
|
|
argv++;
|
2017-03-24 14:00:25 +01:00
|
|
|
if (!argc) {
|
2012-11-16 22:43:29 +01:00
|
|
|
g_string_printf(nmc->return_text, _("Error: %s argument is missing."), *(argv - 1));
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2010-02-25 09:52:30 -08:00
|
|
|
}
|
2013-04-18 14:54:01 +02:00
|
|
|
ifname = *argv;
|
2017-06-11 22:31:43 +02:00
|
|
|
if (argc == 1 && nmc->complete)
|
|
|
|
|
complete_device(devices, ifname, TRUE);
|
2018-02-25 14:27:18 +01:00
|
|
|
break;
|
|
|
|
|
case 2: /* hwaddr is deprecated and will be removed later */
|
|
|
|
|
case 3: /* bssid */
|
2017-03-29 12:02:14 +02:00
|
|
|
argc--;
|
|
|
|
|
argv++;
|
2017-03-24 14:00:25 +01:00
|
|
|
if (!argc) {
|
2012-11-16 22:43:29 +01:00
|
|
|
g_string_printf(nmc->return_text, _("Error: %s argument is missing."), *(argv - 1));
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2010-03-18 15:39:15 +01:00
|
|
|
}
|
2011-09-06 13:37:23 +02:00
|
|
|
bssid_user = *argv;
|
2016-07-12 10:16:24 +02:00
|
|
|
if (argc == 1 && nmc->complete)
|
|
|
|
|
complete_aps(devices, NULL, bssid_user, NULL);
|
2018-02-26 15:50:15 +01:00
|
|
|
break;
|
|
|
|
|
case 4: /* --rescan */
|
|
|
|
|
argc--;
|
|
|
|
|
argv++;
|
|
|
|
|
if (!argc) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: %s argument is missing."), *(argv - 1));
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2018-02-26 15:50:15 +01:00
|
|
|
}
|
|
|
|
|
rescan = *argv;
|
|
|
|
|
if (argc == 1 && nmc->complete)
|
2019-04-12 15:40:01 +02:00
|
|
|
nmc_complete_strings(rescan, "auto", "no", "yes");
|
2018-02-25 14:27:18 +01:00
|
|
|
break;
|
|
|
|
|
default:
|
2019-08-21 15:10:47 +02:00
|
|
|
nm_assert_not_reached();
|
2018-02-25 14:27:18 +01:00
|
|
|
break;
|
2010-02-25 09:52:30 -08:00
|
|
|
}
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-10 19:15:21 +01:00
|
|
|
if (nmc->complete)
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
return;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-02-11 15:17:03 +01:00
|
|
|
if (!nmc->required_fields || g_ascii_strcasecmp(nmc->required_fields, "common") == 0)
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
fields_str = NMC_FIELDS_DEV_WIFI_LIST_COMMON;
|
2020-02-11 15:17:03 +01:00
|
|
|
else if (!nmc->required_fields || g_ascii_strcasecmp(nmc->required_fields, "all") == 0) {
|
2020-05-06 23:18:54 +02:00
|
|
|
/* pass */
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
} else
|
2010-03-18 15:39:15 +01:00
|
|
|
fields_str = nmc->required_fields;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
tmpl = (const NMMetaAbstractInfo *const *) nmc_fields_dev_wifi_list;
|
2017-03-31 13:21:47 +02:00
|
|
|
out_indices = parse_output_fields(fields_str, tmpl, FALSE, NULL, &error);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2010-03-18 15:39:15 +01:00
|
|
|
if (error) {
|
2013-12-10 12:00:53 +01:00
|
|
|
g_string_printf(nmc->return_text, _("Error: 'device wifi': %s"), error->message);
|
2010-03-18 15:39:15 +01:00
|
|
|
g_error_free(error);
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2010-03-18 15:39:15 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-07-30 12:23:03 +02:00
|
|
|
if (argc) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: invalid extra argument '%s'."), *argv);
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2019-07-30 12:23:03 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-18 10:34:07 +01:00
|
|
|
if (NM_IN_STRSET(rescan, NULL, "auto"))
|
|
|
|
|
rescan_cutoff_msec = nm_utils_get_timestamp_msec() - (30 * NM_UTILS_MSEC_PER_SEC);
|
|
|
|
|
else if (nm_streq(rescan, "no"))
|
|
|
|
|
rescan_cutoff_msec = G_MININT64;
|
|
|
|
|
else if (nm_streq(rescan, "yes"))
|
2020-04-02 12:01:18 +02:00
|
|
|
rescan_cutoff_msec = nm_utils_get_timestamp_msec();
|
2020-03-18 10:34:07 +01:00
|
|
|
else {
|
2018-02-26 15:50:15 +01:00
|
|
|
g_string_printf(nmc->return_text,
|
|
|
|
|
_("Error: invalid rescan argument: '%s' not among [auto, no, yes]"),
|
|
|
|
|
rescan);
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2018-02-26 15:50:15 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-10 19:15:21 +01:00
|
|
|
ifname_handled = (ifname == NULL);
|
|
|
|
|
ifname_handled_candidate = NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-10 19:15:21 +01:00
|
|
|
j = 0;
|
|
|
|
|
for (i = 0; devices[i]; i++) {
|
|
|
|
|
const char *dev_iface;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-10 19:15:21 +01:00
|
|
|
device = devices[i];
|
|
|
|
|
dev_iface = nm_device_get_iface(device);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-10 19:15:21 +01:00
|
|
|
if (ifname) {
|
|
|
|
|
if (!nm_streq0(ifname, dev_iface))
|
|
|
|
|
continue;
|
|
|
|
|
if (!NM_IS_DEVICE_WIFI(device)) {
|
|
|
|
|
if (nm_device_get_device_type(device) == NM_DEVICE_TYPE_GENERIC
|
|
|
|
|
&& nm_streq0(nm_device_get_type_description(device), "wifi"))
|
|
|
|
|
ifname_handled_candidate = device;
|
|
|
|
|
else if (!ifname_handled_candidate)
|
|
|
|
|
ifname_handled_candidate = device;
|
|
|
|
|
continue;
|
2016-06-05 11:46:06 +02:00
|
|
|
}
|
2020-03-10 19:15:21 +01:00
|
|
|
ifname_handled = TRUE;
|
|
|
|
|
} else {
|
|
|
|
|
if (!NM_IS_DEVICE_WIFI(device))
|
|
|
|
|
continue;
|
2010-02-25 09:52:30 -08:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-10 19:15:21 +01:00
|
|
|
devices[j++] = device;
|
2018-10-31 10:00:22 +01:00
|
|
|
}
|
|
|
|
|
devices[j] = NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-10 19:15:21 +01:00
|
|
|
if (!ifname_handled) {
|
|
|
|
|
if (!ifname_handled_candidate) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: Device '%s' not found."), ifname);
|
|
|
|
|
} else if (nm_device_get_device_type(ifname_handled_candidate) == NM_DEVICE_TYPE_GENERIC
|
|
|
|
|
&& nm_streq0(nm_device_get_type_description(ifname_handled_candidate), "wifi")) {
|
|
|
|
|
g_string_printf(nmc->return_text,
|
|
|
|
|
_("Error: Device '%s' was not recognized as a Wi-Fi device, check "
|
|
|
|
|
"NetworkManager Wi-Fi plugin."),
|
|
|
|
|
ifname);
|
|
|
|
|
} else {
|
|
|
|
|
g_string_printf(nmc->return_text,
|
|
|
|
|
_("Error: Device '%s' is not a Wi-Fi device."),
|
|
|
|
|
ifname);
|
|
|
|
|
}
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND;
|
|
|
|
|
return;
|
2020-03-10 19:15:21 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-20 10:38:09 +01:00
|
|
|
if (!devices[0]) {
|
|
|
|
|
if (bssid_user) {
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND;
|
|
|
|
|
g_string_printf(nmc->return_text,
|
|
|
|
|
_("Error: Access point with bssid '%s' not found."),
|
|
|
|
|
bssid_user);
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND;
|
2020-03-20 10:38:09 +01:00
|
|
|
}
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
return;
|
2020-03-20 10:38:09 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-18 10:34:07 +01:00
|
|
|
scan_info = g_slice_new(ScanInfo);
|
|
|
|
|
*scan_info = (ScanInfo){
|
|
|
|
|
.out_indices = g_array_ref(out_indices),
|
|
|
|
|
.tmpl = tmpl,
|
2020-04-05 13:05:58 +02:00
|
|
|
.bssid_user = g_strdup(bssid_user),
|
2020-03-18 10:34:07 +01:00
|
|
|
.nmc = nmc,
|
|
|
|
|
.rescan_cutoff_msec = rescan_cutoff_msec,
|
|
|
|
|
};
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-18 10:34:07 +01:00
|
|
|
for (i = 0; devices[i]; i++)
|
|
|
|
|
g_object_ref(devices[i]);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-18 10:34:07 +01:00
|
|
|
for (i = 0; devices[i]; i++) {
|
|
|
|
|
NMDeviceWifi *wifi = NM_DEVICE_WIFI(devices[i]);
|
|
|
|
|
WifiListData *wifi_list_data;
|
|
|
|
|
int timeout_msec;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-18 10:34:07 +01:00
|
|
|
if (rescan_cutoff_msec <= _device_wifi_get_last_scan(wifi))
|
|
|
|
|
timeout_msec = 0;
|
|
|
|
|
else
|
|
|
|
|
timeout_msec = 15000;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-18 10:34:07 +01:00
|
|
|
wifi_list_data = g_slice_new(WifiListData);
|
|
|
|
|
*wifi_list_data = (WifiListData){
|
2020-03-10 20:01:00 +01:00
|
|
|
.wifi = wifi,
|
|
|
|
|
.scan_info = scan_info,
|
2020-03-18 10:34:07 +01:00
|
|
|
.timeout_id = g_timeout_add(timeout_msec, wifi_list_scan_timeout, wifi_list_data),
|
2020-03-10 20:01:00 +01:00
|
|
|
};
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-18 10:34:07 +01:00
|
|
|
scan_info->pending++;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-18 10:34:07 +01:00
|
|
|
if (timeout_msec > 0) {
|
|
|
|
|
wifi_list_data->last_scan_id = g_signal_connect(wifi,
|
|
|
|
|
"notify::" NM_DEVICE_WIFI_LAST_SCAN,
|
|
|
|
|
G_CALLBACK(wifi_last_scan_updated),
|
|
|
|
|
wifi_list_data),
|
|
|
|
|
wifi_list_data->scan_cancellable = g_cancellable_new(),
|
|
|
|
|
nm_device_wifi_request_scan_async(wifi,
|
|
|
|
|
wifi_list_data->scan_cancellable,
|
|
|
|
|
wifi_list_rescan_cb,
|
|
|
|
|
wifi_list_data);
|
2010-02-25 09:52:30 -08:00
|
|
|
}
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-18 10:34:07 +01:00
|
|
|
scan_info->devices = g_steal_pointer(&devices);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-03-18 10:34:07 +01:00
|
|
|
nmc->should_wait++;
|
2010-02-25 09:52:30 -08:00
|
|
|
}
|
|
|
|
|
|
2019-07-30 14:14:51 +02:00
|
|
|
static void
|
|
|
|
|
activate_update2_cb(GObject *source_object, GAsyncResult *res, gpointer user_data)
|
|
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NMRemoteConnection *remote_con = NM_REMOTE_CONNECTION(source_object);
|
|
|
|
|
AddAndActivateInfo *info = user_data;
|
|
|
|
|
NmCli *nmc = info->nmc;
|
|
|
|
|
gs_unref_variant GVariant *ret = NULL;
|
|
|
|
|
GError *error = NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-07-30 14:14:51 +02:00
|
|
|
ret = nm_remote_connection_update2_finish(remote_con, res, &error);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-07-30 14:14:51 +02:00
|
|
|
if (!ret) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: %s."), error->message);
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
|
|
|
|
|
g_error_free(error);
|
|
|
|
|
quit();
|
2019-09-02 12:26:42 +02:00
|
|
|
add_and_activate_info_free(info);
|
2019-07-30 14:14:51 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-07-30 14:14:51 +02:00
|
|
|
nm_client_activate_connection_async(nmc->client,
|
|
|
|
|
NM_CONNECTION(remote_con),
|
|
|
|
|
info->device,
|
|
|
|
|
info->specific_object,
|
|
|
|
|
NULL,
|
|
|
|
|
add_and_activate_cb,
|
2019-09-02 12:26:42 +02:00
|
|
|
info);
|
2019-07-30 14:14:51 +02:00
|
|
|
}
|
|
|
|
|
|
2019-10-10 17:59:24 +02:00
|
|
|
static void
|
2021-11-09 13:28:54 +01:00
|
|
|
save_and_activate_connection(NmCli *nmc,
|
|
|
|
|
NMDevice *device,
|
2019-10-10 17:59:24 +02:00
|
|
|
NMConnection *connection,
|
|
|
|
|
gboolean hotspot,
|
2021-11-09 13:28:54 +01:00
|
|
|
const char *specific_object)
|
2019-10-10 17:59:24 +02:00
|
|
|
{
|
|
|
|
|
AddAndActivateInfo *info;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 17:59:24 +02:00
|
|
|
info = add_and_activate_info_new(nmc,
|
|
|
|
|
device,
|
|
|
|
|
hotspot,
|
|
|
|
|
!NM_IS_REMOTE_CONNECTION(connection),
|
|
|
|
|
specific_object);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 17:59:24 +02:00
|
|
|
if (NM_IS_REMOTE_CONNECTION(connection)) {
|
|
|
|
|
nm_remote_connection_update2(NM_REMOTE_CONNECTION(connection),
|
|
|
|
|
nm_connection_to_dbus(connection, NM_CONNECTION_SERIALIZE_ALL),
|
|
|
|
|
NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT,
|
|
|
|
|
NULL,
|
2020-09-28 16:03:33 +02:00
|
|
|
NULL,
|
2019-10-10 17:59:24 +02:00
|
|
|
activate_update2_cb,
|
|
|
|
|
info);
|
|
|
|
|
} else {
|
|
|
|
|
nm_client_add_and_activate_connection_async(nmc->client,
|
|
|
|
|
connection,
|
|
|
|
|
info->device,
|
|
|
|
|
info->specific_object,
|
|
|
|
|
NULL,
|
|
|
|
|
add_and_activate_cb,
|
|
|
|
|
info);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
static void
|
2020-04-05 13:05:58 +02:00
|
|
|
do_device_wifi_connect(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
|
2012-04-28 22:32:21 +01:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NMDevice *device = NULL;
|
|
|
|
|
NMAccessPoint *ap = NULL;
|
|
|
|
|
NM80211ApFlags ap_flags;
|
|
|
|
|
NM80211ApSecurityFlags ap_wpa_flags;
|
|
|
|
|
NM80211ApSecurityFlags ap_rsn_flags;
|
2019-10-10 17:59:24 +02:00
|
|
|
gs_unref_object NMConnection *connection = NULL;
|
2021-11-09 13:28:54 +01:00
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
NMSettingWireless *s_wifi;
|
|
|
|
|
const char *param_user = NULL;
|
|
|
|
|
const char *ifname = NULL;
|
|
|
|
|
const char *bssid = NULL;
|
|
|
|
|
const char *password = NULL;
|
|
|
|
|
const char *con_name = NULL;
|
2012-04-28 22:32:21 +01:00
|
|
|
gboolean private = FALSE;
|
2021-11-09 13:28:54 +01:00
|
|
|
gboolean hidden = FALSE;
|
|
|
|
|
gboolean wep_passphrase = FALSE;
|
|
|
|
|
GByteArray *bssid1_arr = NULL;
|
|
|
|
|
GByteArray *bssid2_arr = NULL;
|
2016-07-12 14:45:36 +02:00
|
|
|
gs_free NMDevice **devices = NULL;
|
2012-04-28 22:32:21 +01:00
|
|
|
int devices_idx;
|
2021-11-09 13:28:54 +01:00
|
|
|
char *ssid_ask = NULL;
|
|
|
|
|
char *passwd_ask = NULL;
|
|
|
|
|
const GPtrArray *avail_cons;
|
2018-06-12 06:52:01 +02:00
|
|
|
gboolean name_match = FALSE;
|
|
|
|
|
int i;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-05-14 12:43:43 +02:00
|
|
|
/* Set default timeout waiting for operation completion. */
|
|
|
|
|
if (nmc->timeout == -1)
|
|
|
|
|
nmc->timeout = 90;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-07-12 09:45:23 +02:00
|
|
|
devices = nmc_get_devices_sorted(nmc->client);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg(nmc, &argc, &argv, NULL);
|
2012-04-28 22:32:21 +01:00
|
|
|
/* Get the first compulsory argument (SSID or BSSID) */
|
|
|
|
|
if (argc > 0) {
|
|
|
|
|
param_user = *argv;
|
2014-07-04 15:59:19 -04:00
|
|
|
bssid1_arr = nm_utils_hwaddr_atoba(param_user, ETH_ALEN);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-07-12 09:45:23 +02:00
|
|
|
if (argc == 1 && nmc->complete)
|
|
|
|
|
complete_aps(devices, NULL, param_user, param_user);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg(nmc, &argc, &argv, NULL);
|
2012-04-28 22:32:21 +01:00
|
|
|
} else {
|
2016-07-12 09:45:23 +02:00
|
|
|
/* nmc_do_cmd() should not call this with argc=0. */
|
2019-08-21 15:10:47 +02:00
|
|
|
nm_assert(!nmc->complete);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2012-11-22 14:32:45 +01:00
|
|
|
if (nmc->ask) {
|
2018-10-09 11:50:26 +02:00
|
|
|
ssid_ask = nmc_readline(&nmc->nmc_config, _("SSID or BSSID: "));
|
2018-04-24 11:20:03 +02:00
|
|
|
param_user = ssid_ask ?: "";
|
2014-07-04 15:59:19 -04:00
|
|
|
bssid1_arr = nm_utils_hwaddr_atoba(param_user, ETH_ALEN);
|
2012-11-22 14:32:45 +01:00
|
|
|
}
|
|
|
|
|
if (!ssid_ask) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: SSID or BSSID are missing."));
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
2016-07-12 09:45:23 +02:00
|
|
|
goto finish;
|
2020-09-28 16:03:33 +02:00
|
|
|
}
|
2012-11-22 14:32:45 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2012-04-28 22:32:21 +01:00
|
|
|
/* Get the rest of the parameters */
|
|
|
|
|
while (argc > 0) {
|
2016-07-12 09:45:23 +02:00
|
|
|
if (argc == 1 && nmc->complete) {
|
|
|
|
|
nmc_complete_strings(*argv,
|
|
|
|
|
"ifname",
|
|
|
|
|
"bssid",
|
|
|
|
|
"password",
|
|
|
|
|
"wep-key-type",
|
2019-04-12 15:40:01 +02:00
|
|
|
"name",
|
|
|
|
|
"private",
|
|
|
|
|
"hidden");
|
2016-07-12 09:45:23 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-04-18 14:54:01 +02:00
|
|
|
if (strcmp(*argv, "ifname") == 0) {
|
2017-03-29 12:02:14 +02:00
|
|
|
argc--;
|
|
|
|
|
argv++;
|
2017-03-24 14:00:25 +01:00
|
|
|
if (!argc) {
|
2012-11-16 22:43:29 +01:00
|
|
|
g_string_printf(nmc->return_text, _("Error: %s argument is missing."), *(argv - 1));
|
2012-04-28 22:32:21 +01:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
2016-07-12 09:45:23 +02:00
|
|
|
goto finish;
|
2012-04-28 22:32:21 +01:00
|
|
|
}
|
2013-04-18 14:54:01 +02:00
|
|
|
ifname = *argv;
|
2017-06-11 22:31:43 +02:00
|
|
|
if (argc == 1 && nmc->complete)
|
|
|
|
|
complete_device(devices, ifname, TRUE);
|
2012-04-28 22:32:21 +01:00
|
|
|
} else if (strcmp(*argv, "bssid") == 0) {
|
2017-03-29 12:02:14 +02:00
|
|
|
argc--;
|
|
|
|
|
argv++;
|
2017-03-24 14:00:25 +01:00
|
|
|
if (!argc) {
|
2012-11-16 22:43:29 +01:00
|
|
|
g_string_printf(nmc->return_text, _("Error: %s argument is missing."), *(argv - 1));
|
2012-04-28 22:32:21 +01:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
2016-07-12 09:45:23 +02:00
|
|
|
goto finish;
|
2012-04-28 22:32:21 +01:00
|
|
|
}
|
|
|
|
|
bssid = *argv;
|
2016-07-12 09:45:23 +02:00
|
|
|
if (argc == 1 && nmc->complete)
|
|
|
|
|
complete_aps(devices, NULL, bssid, NULL);
|
2014-07-04 15:59:19 -04:00
|
|
|
bssid2_arr = nm_utils_hwaddr_atoba(bssid, ETH_ALEN);
|
2012-04-28 22:32:21 +01:00
|
|
|
if (!bssid2_arr) {
|
|
|
|
|
g_string_printf(nmc->return_text,
|
|
|
|
|
_("Error: bssid argument value '%s' is not a valid BSSID."),
|
|
|
|
|
bssid);
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
2016-07-12 09:45:23 +02:00
|
|
|
goto finish;
|
2012-04-28 22:32:21 +01:00
|
|
|
}
|
|
|
|
|
} else if (strcmp(*argv, "password") == 0) {
|
2017-03-29 12:02:14 +02:00
|
|
|
argc--;
|
|
|
|
|
argv++;
|
2017-03-24 14:00:25 +01:00
|
|
|
if (!argc) {
|
2012-11-16 22:43:29 +01:00
|
|
|
g_string_printf(nmc->return_text, _("Error: %s argument is missing."), *(argv - 1));
|
2012-04-28 22:32:21 +01:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
2016-07-12 09:45:23 +02:00
|
|
|
goto finish;
|
2012-04-28 22:32:21 +01:00
|
|
|
}
|
|
|
|
|
password = *argv;
|
|
|
|
|
} else if (strcmp(*argv, "wep-key-type") == 0) {
|
2017-03-29 12:02:14 +02:00
|
|
|
argc--;
|
|
|
|
|
argv++;
|
2017-03-24 14:00:25 +01:00
|
|
|
if (!argc) {
|
2012-11-16 22:43:29 +01:00
|
|
|
g_string_printf(nmc->return_text, _("Error: %s argument is missing."), *(argv - 1));
|
2012-04-28 22:32:21 +01:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
2016-07-12 09:45:23 +02:00
|
|
|
goto finish;
|
2012-04-28 22:32:21 +01:00
|
|
|
}
|
2016-07-12 09:45:23 +02:00
|
|
|
if (argc == 1 && nmc->complete)
|
2019-04-12 15:40:01 +02:00
|
|
|
nmc_complete_strings(*argv, "key", "phrase");
|
2012-04-28 22:32:21 +01:00
|
|
|
if (strcmp(*argv, "key") == 0)
|
|
|
|
|
wep_passphrase = FALSE;
|
|
|
|
|
else if (strcmp(*argv, "phrase") == 0)
|
|
|
|
|
wep_passphrase = TRUE;
|
|
|
|
|
else {
|
|
|
|
|
g_string_printf(
|
|
|
|
|
nmc->return_text,
|
|
|
|
|
_("Error: wep-key-type argument value '%s' is invalid, use 'key' or 'phrase'."),
|
|
|
|
|
*argv);
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
2016-07-12 09:45:23 +02:00
|
|
|
goto finish;
|
2012-04-28 22:32:21 +01:00
|
|
|
}
|
|
|
|
|
} else if (strcmp(*argv, "name") == 0) {
|
2017-03-29 12:02:14 +02:00
|
|
|
argc--;
|
|
|
|
|
argv++;
|
2017-03-24 14:00:25 +01:00
|
|
|
if (!argc) {
|
2012-11-16 22:43:29 +01:00
|
|
|
g_string_printf(nmc->return_text, _("Error: %s argument is missing."), *(argv - 1));
|
2012-04-28 22:32:21 +01:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
2016-07-12 09:45:23 +02:00
|
|
|
goto finish;
|
2012-04-28 22:32:21 +01:00
|
|
|
}
|
|
|
|
|
con_name = *argv;
|
2013-05-14 13:51:06 +02:00
|
|
|
} else if (strcmp(*argv, "private") == 0) {
|
|
|
|
|
GError *err_tmp = NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-29 12:02:14 +02:00
|
|
|
argc--;
|
|
|
|
|
argv++;
|
2017-03-24 14:00:25 +01:00
|
|
|
if (!argc) {
|
2013-05-14 13:51:06 +02:00
|
|
|
g_string_printf(nmc->return_text, _("Error: %s argument is missing."), *(argv - 1));
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
2016-07-12 09:45:23 +02:00
|
|
|
goto finish;
|
2013-05-14 13:51:06 +02:00
|
|
|
}
|
2016-07-12 09:45:23 +02:00
|
|
|
if (argc == 1 && nmc->complete)
|
|
|
|
|
nmc_complete_bool(*argv);
|
2013-05-14 13:51:06 +02:00
|
|
|
if (!nmc_string_to_bool(*argv, &private, &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);
|
2016-07-12 09:45:23 +02:00
|
|
|
goto finish;
|
2013-05-14 13:51:06 +02:00
|
|
|
}
|
2015-07-10 13:16:21 +02:00
|
|
|
} else if (strcmp(*argv, "hidden") == 0) {
|
|
|
|
|
GError *err_tmp = NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-29 12:02:14 +02:00
|
|
|
argc--;
|
|
|
|
|
argv++;
|
2017-03-24 14:00:25 +01:00
|
|
|
if (!argc) {
|
2015-07-10 13:16:21 +02:00
|
|
|
g_string_printf(nmc->return_text, _("Error: %s argument is missing."), *(argv - 1));
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
2016-07-12 09:45:23 +02:00
|
|
|
goto finish;
|
2015-07-10 13:16:21 +02:00
|
|
|
}
|
2016-07-12 09:45:23 +02:00
|
|
|
if (argc == 1 && nmc->complete)
|
|
|
|
|
nmc_complete_bool(*argv);
|
2015-07-10 13:16:21 +02:00
|
|
|
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);
|
2016-07-12 09:45:23 +02:00
|
|
|
goto finish;
|
2015-07-10 13:16:21 +02:00
|
|
|
}
|
2016-07-12 09:45:23 +02:00
|
|
|
} else if (!nmc->complete) {
|
2019-07-30 12:23:03 +02:00
|
|
|
g_string_printf(nmc->return_text, _("Error: invalid extra argument '%s'."), *argv);
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
goto finish;
|
2012-04-28 22:32:21 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg(nmc, &argc, &argv, NULL);
|
2012-04-28 22:32:21 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-07-12 09:45:23 +02:00
|
|
|
if (nmc->complete)
|
|
|
|
|
goto finish;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2012-04-28 22:32:21 +01:00
|
|
|
/* Verify SSID/BSSID parameters */
|
|
|
|
|
if (bssid1_arr && bssid2_arr && memcmp(bssid1_arr->data, bssid2_arr->data, ETH_ALEN)) {
|
|
|
|
|
g_string_printf(nmc->return_text,
|
|
|
|
|
_("Error: BSSID to connect to (%s) differs from bssid argument (%s)."),
|
|
|
|
|
param_user,
|
|
|
|
|
bssid);
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
2016-07-12 09:45:23 +02:00
|
|
|
goto finish;
|
2012-04-28 22:32:21 +01:00
|
|
|
}
|
|
|
|
|
if (!bssid1_arr && strlen(param_user) > 32) {
|
|
|
|
|
g_string_printf(nmc->return_text,
|
|
|
|
|
_("Error: Parameter '%s' is neither SSID nor BSSID."),
|
|
|
|
|
param_user);
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
2016-07-12 09:45:23 +02:00
|
|
|
goto finish;
|
2012-04-28 22:32:21 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2012-04-28 22:32:21 +01:00
|
|
|
/* Find a device to activate the connection on */
|
|
|
|
|
devices_idx = 0;
|
2013-04-18 14:54:01 +02:00
|
|
|
device = find_wifi_device_by_iface(devices, ifname, &devices_idx);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2012-04-28 22:32:21 +01:00
|
|
|
if (!device) {
|
2013-04-18 14:54:01 +02:00
|
|
|
if (ifname)
|
|
|
|
|
g_string_printf(nmc->return_text,
|
|
|
|
|
_("Error: Device '%s' is not a Wi-Fi device."),
|
|
|
|
|
ifname);
|
2012-04-28 22:32:21 +01:00
|
|
|
else
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: No Wi-Fi device found."));
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
|
2016-07-12 09:45:23 +02:00
|
|
|
goto finish;
|
2012-04-28 22:32:21 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-07-10 13:16:21 +02:00
|
|
|
/* For hidden SSID first scan it so that NM learns about the AP */
|
|
|
|
|
if (hidden) {
|
|
|
|
|
GVariantBuilder builder, array_builder;
|
2021-11-09 13:28:54 +01:00
|
|
|
GVariant *options;
|
|
|
|
|
GError *scan_err = NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-07-10 13:16:21 +02:00
|
|
|
g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
|
|
|
|
|
g_variant_builder_init(&array_builder, G_VARIANT_TYPE("aay"));
|
2021-04-15 09:17:47 +02:00
|
|
|
g_variant_builder_add(&array_builder,
|
|
|
|
|
"@ay",
|
|
|
|
|
nm_g_variant_new_ay((const guint8 *) param_user, strlen(param_user)));
|
2015-07-10 13:16:21 +02:00
|
|
|
g_variant_builder_add(&builder, "{sv}", "ssids", g_variant_builder_end(&array_builder));
|
|
|
|
|
options = g_variant_builder_end(&builder);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-07-10 13:16:21 +02:00
|
|
|
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;
|
2016-07-12 09:45:23 +02:00
|
|
|
goto finish;
|
2020-09-28 16:03:33 +02:00
|
|
|
}
|
2015-07-10 13:16:21 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2012-04-28 22:32:21 +01:00
|
|
|
/* Find an AP to connect to */
|
2018-06-22 03:21:25 +02:00
|
|
|
ap = find_ap_on_device(device,
|
|
|
|
|
bssid1_arr ? param_user : bssid,
|
2016-07-12 14:36:53 +02:00
|
|
|
bssid1_arr ? NULL : param_user,
|
|
|
|
|
FALSE);
|
2013-04-18 14:54:01 +02:00
|
|
|
if (!ap && !ifname) {
|
2015-07-10 13:16:21 +02:00
|
|
|
NMDevice *dev;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-07-10 13:16:21 +02:00
|
|
|
/* 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) {
|
2018-06-22 03:21:25 +02:00
|
|
|
ap = find_ap_on_device(dev,
|
|
|
|
|
bssid1_arr ? param_user : bssid,
|
2016-07-12 14:36:53 +02:00
|
|
|
bssid1_arr ? NULL : param_user,
|
|
|
|
|
FALSE);
|
2015-07-10 13:16:21 +02:00
|
|
|
if (ap) {
|
|
|
|
|
device = dev;
|
2012-04-28 22:32:21 +01:00
|
|
|
break;
|
2020-09-28 16:03:33 +02:00
|
|
|
}
|
2015-07-10 13:16:21 +02:00
|
|
|
}
|
2012-04-28 22:32:21 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2012-04-28 22:32:21 +01:00
|
|
|
if (!ap) {
|
|
|
|
|
if (!bssid1_arr)
|
|
|
|
|
g_string_printf(nmc->return_text,
|
|
|
|
|
_("Error: No network with SSID '%s' found."),
|
|
|
|
|
param_user);
|
|
|
|
|
else
|
|
|
|
|
g_string_printf(nmc->return_text,
|
|
|
|
|
_("Error: No access point with BSSID '%s' found."),
|
|
|
|
|
param_user);
|
2013-11-21 09:19:18 -05:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND;
|
2016-07-12 09:45:23 +02:00
|
|
|
goto finish;
|
2012-04-28 22:32:21 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-06-12 06:52:01 +02:00
|
|
|
avail_cons = nm_device_get_available_connections(device);
|
|
|
|
|
for (i = 0; i < avail_cons->len; i++) {
|
2019-10-10 17:59:24 +02:00
|
|
|
NMConnection *avail_con = g_ptr_array_index(avail_cons, i);
|
2021-11-09 13:28:54 +01:00
|
|
|
const char *id = nm_connection_get_id(NM_CONNECTION(avail_con));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-06-12 06:52:01 +02:00
|
|
|
if (con_name) {
|
|
|
|
|
if (!id || strcmp(id, con_name))
|
|
|
|
|
continue;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-06-12 06:52:01 +02:00
|
|
|
name_match = TRUE;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-06-12 06:52:01 +02:00
|
|
|
if (nm_access_point_connection_valid(ap, NM_CONNECTION(avail_con))) {
|
|
|
|
|
/* ap has been checked against bssid1, bssid2 and the ssid
|
|
|
|
|
* and now avail_con has been checked against ap.
|
|
|
|
|
*/
|
2019-10-10 17:59:24 +02:00
|
|
|
connection = g_object_ref(avail_con);
|
2018-06-12 06:52:01 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2012-04-28 22:32:21 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 17:59:24 +02:00
|
|
|
if (name_match && !connection) {
|
2018-06-12 06:52:01 +02:00
|
|
|
g_string_printf(nmc->return_text,
|
|
|
|
|
_("Error: Connection '%s' exists but properties don't match."),
|
|
|
|
|
con_name);
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND;
|
|
|
|
|
goto finish;
|
2012-04-28 22:32:21 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 17:59:24 +02:00
|
|
|
if (!connection) {
|
2018-06-12 06:52:01 +02:00
|
|
|
/* If there are some connection data from user, create a connection and
|
|
|
|
|
* fill them into proper settings. */
|
2019-07-30 13:01:37 +02:00
|
|
|
if (con_name || private || bssid2_arr || hidden)
|
2018-06-12 06:52:01 +02:00
|
|
|
connection = nm_simple_connection_new();
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-06-12 06:52:01 +02:00
|
|
|
if (con_name || private) {
|
|
|
|
|
s_con = (NMSettingConnection *) nm_setting_connection_new();
|
|
|
|
|
nm_connection_add_setting(connection, NM_SETTING(s_con));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-06-12 06:52:01 +02:00
|
|
|
/* Set user provided connection name */
|
|
|
|
|
if (con_name)
|
|
|
|
|
g_object_set(s_con, NM_SETTING_CONNECTION_ID, con_name, NULL);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-06-12 06:52:01 +02:00
|
|
|
/* Connection will only be visible to this user when 'private' is specified */
|
|
|
|
|
if (private)
|
libnm: cleanup handling of "connection.permissions" and improve validation
Previously, both nm_setting_connection_add_permission() and the GObject
property setter would merely assert that the provided values are valid
(and otherwise don't do anything). That is bad for handling errors.
For example, we use the property setter to initialize the setting from
keyfile and GVariant (D-Bus). That means, if a user provides an invalid
permissions value, we would emit a g_critical() assertion failure, but
otherwise ignore the configuration. What we instead need to do is to
accept the value, and afterwards fail verification. That way, a proper error
message can be generated.
$ mcli connection add type ethernet autoconnect no ifname bogus con-name x connection.permissions 'bogus:'
(process:429514): libnm-CRITICAL **: 12:12:00.359: permission_new: assertion 'strchr (uname, ':') == NULL' failed
(process:429514): libnm-CRITICAL **: 12:12:00.359: nm_setting_connection_add_permission: assertion 'p != NULL' failed
Connection 'x' (2802d117-f84e-44d9-925b-bfe26fd85da1) successfully added.
$ $ nmcli -f connection.permissions connection show x
connection.permissions: --
While at it, also don't track the permissions in a GSList. Tracking one
permission in a GSList requires 3 allocations (one for the user string,
one for the Permission struct, and one for the GSList struct). Instead,
use a GArray. That is still not great, because GArray cannot be embedded
inside NMSettingConnectionPrivate, so tracking one permission also
requires 3 allocations (which is really a fault of GArray). So, GArray
is not better in the common case where there is only one permissions. But even
in the worst case (only one entry), GArray is no worse than GSList.
Also change the API of nm_setting_connection_add_permission().
Previously, the function would assert that the arguments are in
a certain form (strcmp (ptype, "user") == 0), but still document
the such behaviors like regular operation ("[returns] %FALSE if @ptype
or @pitem was invalid"). Don't assert against the function arguments.
Also, if you first set the user to "fo:o", then
nm_setting_connection_add_permission() would accept it -- only at
a later phase, the property setter would assert against such values.
Also, the function would return %FALSE both if the input value was
invalid (an error) and if the value already existed. I think the
function should not treat a duplicate entry like a badly formatted
input.
Now the function does much less asserting of the arguments, but will
return %FALSE only if the values are invalid. And it will silently ignore
duplicate entries.
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/636
2020-09-24 20:53:13 +02:00
|
|
|
nm_setting_connection_add_permission(s_con,
|
|
|
|
|
NM_SETTINGS_CONNECTION_PERMISSION_USER,
|
|
|
|
|
g_get_user_name() ?: "",
|
|
|
|
|
NULL);
|
2018-06-12 06:52:01 +02:00
|
|
|
}
|
|
|
|
|
if (bssid2_arr || hidden) {
|
|
|
|
|
s_wifi = (NMSettingWireless *) nm_setting_wireless_new();
|
|
|
|
|
nm_connection_add_setting(connection, NM_SETTING(s_wifi));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-06-12 06:52:01 +02:00
|
|
|
/* '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);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-06-12 06:52:01 +02:00
|
|
|
/* 'hidden' parameter is used to indicate that SSID is not broadcasted */
|
|
|
|
|
if (hidden) {
|
|
|
|
|
GBytes *ssid = g_bytes_new(param_user, strlen(param_user));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-06-12 06:52:01 +02:00
|
|
|
g_object_set(s_wifi,
|
|
|
|
|
NM_SETTING_WIRELESS_SSID,
|
|
|
|
|
ssid,
|
|
|
|
|
NM_SETTING_WIRELESS_HIDDEN,
|
|
|
|
|
hidden,
|
|
|
|
|
NULL);
|
|
|
|
|
g_bytes_unref(ssid);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-06-12 06:52:01 +02:00
|
|
|
/* Warn when the provided AP identifier looks like BSSID instead of SSID */
|
|
|
|
|
if (bssid1_arr)
|
|
|
|
|
g_printerr(_("Warning: '%s' should be SSID for hidden APs; but it looks like a "
|
|
|
|
|
"BSSID.\n"),
|
|
|
|
|
param_user);
|
2012-04-28 22:32:21 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-22 14:32:45 +01:00
|
|
|
/* handle password */
|
|
|
|
|
ap_flags = nm_access_point_get_flags(ap);
|
|
|
|
|
ap_wpa_flags = nm_access_point_get_wpa_flags(ap);
|
|
|
|
|
ap_rsn_flags = nm_access_point_get_rsn_flags(ap);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2012-11-22 14:32:45 +01:00
|
|
|
/* Set password for WEP or WPA-PSK. */
|
2018-06-13 01:04:55 +02:00
|
|
|
if ((ap_flags & NM_802_11_AP_FLAGS_PRIVACY)
|
2020-05-09 03:30:21 +02:00
|
|
|
|| (ap_wpa_flags != NM_802_11_AP_SEC_NONE
|
|
|
|
|
&& !NM_FLAGS_ANY(ap_wpa_flags,
|
|
|
|
|
NM_802_11_AP_SEC_KEY_MGMT_OWE | NM_802_11_AP_SEC_KEY_MGMT_OWE_TM))
|
|
|
|
|
|| (ap_rsn_flags != NM_802_11_AP_SEC_NONE
|
|
|
|
|
&& !NM_FLAGS_ANY(ap_rsn_flags,
|
|
|
|
|
NM_802_11_AP_SEC_KEY_MGMT_OWE | NM_802_11_AP_SEC_KEY_MGMT_OWE_TM))) {
|
2021-11-09 13:28:54 +01:00
|
|
|
const char *con_password = NULL;
|
2018-06-12 06:52:01 +02:00
|
|
|
NMSettingWirelessSecurity *s_wsec = NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-06-12 06:52:01 +02:00
|
|
|
if (connection) {
|
|
|
|
|
s_wsec = nm_connection_get_setting_wireless_security(connection);
|
|
|
|
|
if (s_wsec) {
|
|
|
|
|
if (ap_wpa_flags == NM_802_11_AP_SEC_NONE
|
|
|
|
|
&& ap_rsn_flags == NM_802_11_AP_SEC_NONE) {
|
|
|
|
|
/* WEP */
|
|
|
|
|
con_password = nm_setting_wireless_security_get_wep_key(s_wsec, 0);
|
|
|
|
|
} else if ((ap_wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK)
|
2019-01-22 09:44:26 +01:00
|
|
|
|| (ap_rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK)
|
|
|
|
|
|| (ap_rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_SAE)) {
|
2018-06-12 06:52:01 +02:00
|
|
|
/* WPA PSK */
|
|
|
|
|
con_password = nm_setting_wireless_security_get_psk(s_wsec);
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-22 14:32:45 +01:00
|
|
|
/* Ask for missing password when one is expected and '--ask' is used */
|
2018-06-12 06:52:01 +02:00
|
|
|
if (!password && !con_password && nmc->ask) {
|
2018-10-09 11:50:26 +02:00
|
|
|
password = passwd_ask =
|
|
|
|
|
nmc_readline_echo(&nmc->nmc_config, nmc->nmc_config.show_secrets, _("Password: "));
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2012-11-22 14:32:45 +01:00
|
|
|
if (password) {
|
|
|
|
|
if (!connection)
|
2014-08-13 14:34:29 -04:00
|
|
|
connection = nm_simple_connection_new();
|
2018-06-12 06:52:01 +02:00
|
|
|
if (!s_wsec) {
|
|
|
|
|
s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new();
|
|
|
|
|
nm_connection_add_setting(connection, NM_SETTING(s_wsec));
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2012-11-22 14:32:45 +01:00
|
|
|
if (ap_wpa_flags == NM_802_11_AP_SEC_NONE && ap_rsn_flags == NM_802_11_AP_SEC_NONE) {
|
2012-04-28 22:32:21 +01:00
|
|
|
/* WEP */
|
|
|
|
|
nm_setting_wireless_security_set_wep_key(s_wsec, 0, password);
|
|
|
|
|
g_object_set(G_OBJECT(s_wsec),
|
|
|
|
|
NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE,
|
|
|
|
|
wep_passphrase ? NM_WEP_KEY_TYPE_PASSPHRASE : NM_WEP_KEY_TYPE_KEY,
|
|
|
|
|
NULL);
|
2017-09-16 11:59:46 +02:00
|
|
|
} else if ((ap_wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK)
|
2019-01-22 09:44:26 +01:00
|
|
|
|| (ap_rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK)
|
|
|
|
|
|| (ap_rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_SAE)) {
|
2012-04-28 22:32:21 +01:00
|
|
|
/* WPA PSK */
|
|
|
|
|
g_object_set(s_wsec, NM_SETTING_WIRELESS_SECURITY_PSK, password, NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-06-12 06:52:01 +02:00
|
|
|
// FIXME: Creating WPA-Enterprise connections is not supported yet.
|
2012-11-22 14:32:45 +01:00
|
|
|
// We are not able to determine and fill all the parameters for
|
|
|
|
|
// 802.1X authentication automatically without user providing
|
|
|
|
|
// the data. Adding nmcli options for the 8021x setting would
|
|
|
|
|
// clutter the command. However, that could be solved later by
|
|
|
|
|
// implementing add/edit connections support for nmcli.
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2012-04-28 22:32:21 +01:00
|
|
|
/* nowait_flag indicates user input. should_wait says whether quit in start().
|
|
|
|
|
* We have to delay exit after add_and_activate_cb() is called, even if
|
|
|
|
|
* the user doesn't want to wait, in order to give NM time to check our
|
|
|
|
|
* permissions. */
|
2013-05-14 12:43:43 +02:00
|
|
|
nmc->nowait_flag = (nmc->timeout == 0);
|
2015-03-27 12:39:17 +01:00
|
|
|
nmc->should_wait++;
|
2012-04-28 22:32:21 +01:00
|
|
|
|
2019-10-10 17:59:24 +02:00
|
|
|
save_and_activate_connection(nmc, device, connection, FALSE, nm_object_get_path(NM_OBJECT(ap)));
|
2012-04-28 22:32:21 +01:00
|
|
|
|
2016-07-12 09:45:23 +02:00
|
|
|
finish:
|
2012-04-28 22:32:21 +01:00
|
|
|
if (bssid1_arr)
|
|
|
|
|
g_byte_array_free(bssid1_arr, TRUE);
|
|
|
|
|
if (bssid2_arr)
|
|
|
|
|
g_byte_array_free(bssid2_arr, TRUE);
|
2012-11-22 14:32:45 +01:00
|
|
|
g_free(ssid_ask);
|
2019-12-18 14:46:22 +01:00
|
|
|
nm_free_secret(passwd_ask);
|
2012-04-28 22:32:21 +01:00
|
|
|
}
|
|
|
|
|
|
2015-10-02 22:46:53 +02:00
|
|
|
static GBytes *
|
2019-10-10 18:22:33 +02:00
|
|
|
generate_ssid_for_hotspot(void)
|
2015-10-02 22:46:53 +02:00
|
|
|
{
|
|
|
|
|
GBytes *ssid_bytes;
|
2021-11-09 13:28:54 +01:00
|
|
|
char *ssid = NULL;
|
2015-10-02 22:46:53 +02:00
|
|
|
|
2019-10-10 18:22:33 +02:00
|
|
|
ssid = g_strdup_printf("Hotspot-%s", g_get_host_name());
|
|
|
|
|
if (strlen(ssid) > 32)
|
|
|
|
|
ssid[32] = '\0';
|
2015-10-02 22:46:53 +02:00
|
|
|
ssid_bytes = g_bytes_new(ssid, strlen(ssid));
|
2019-10-10 18:22:33 +02:00
|
|
|
g_free(ssid);
|
|
|
|
|
|
2015-10-02 22:46:53 +02:00
|
|
|
return ssid_bytes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define WPA_PASSKEY_SIZE 8
|
|
|
|
|
static void
|
|
|
|
|
generate_wpa_key(char *key, size_t len)
|
|
|
|
|
{
|
|
|
|
|
guint i;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-10-02 22:46:53 +02:00
|
|
|
g_return_if_fail(key);
|
|
|
|
|
g_return_if_fail(len > WPA_PASSKEY_SIZE);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-10-02 22:46:53 +02:00
|
|
|
/* generate a 8-chars ASCII WPA key */
|
|
|
|
|
for (i = 0; i < WPA_PASSKEY_SIZE; i++) {
|
|
|
|
|
int c;
|
all: use nm_random_*() instead of g_random_*()
g_random_*() is based on GRand, which is not a CSPRNG. Instead, rely on
kernel to give us good random numbers, which is what nm_random_*() does.
Note that nm_random_*() calls getrandom() (or reads /dev/urandom), which
most likely is slower than GRand. It doesn't matter for our uses though.
It is cumbersome to review all uses of g_rand_*() whether their usage of
a non-cryptographically secure generator is appropriate. Instead, just
always use an appropriate function, thereby avoiding this question. Even
glib documentation refers to reading "/dev/urandom" as alternative. Which
is what nm_random_*() does. These days, it seems unnecessary to not use
the best random generator available, unless it's not fast enough or you
need a stable/seedable stream of random numbers.
In particular in nmcli, we used g_random_int_range() to generate
passwords. That is not appropriate. Sure, it's *only* for the hotspot,
but still.
2023-01-27 12:52:20 +01:00
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
c = nm_random_u64_range_full(33, 126, TRUE);
|
|
|
|
|
/* too many non alphanumeric characters are hard to remember for humans */
|
|
|
|
|
} while (g_ascii_isalnum(c));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
all: don't use gchar/gshort/gint/glong but C types
We commonly don't use the glib typedefs for char/short/int/long,
but their C types directly.
$ git grep '\<g\(char\|short\|int\|long\|float\|double\)\>' | wc -l
587
$ git grep '\<\(char\|short\|int\|long\|float\|double\)\>' | wc -l
21114
One could argue that using the glib typedefs is preferable in
public API (of our glib based libnm library) or where it clearly
is related to glib, like during
g_object_set (obj, PROPERTY, (gint) value, NULL);
However, that argument does not seem strong, because in practice we don't
follow that argument today, and seldomly use the glib typedefs.
Also, the style guide for this would be hard to formalize, because
"using them where clearly related to a glib" is a very loose suggestion.
Also note that glib typedefs will always just be typedefs of the
underlying C types. There is no danger of glib changing the meaning
of these typedefs (because that would be a major API break of glib).
A simple style guide is instead: don't use these typedefs.
No manual actions, I only ran the bash script:
FILES=($(git ls-files '*.[hc]'))
sed -i \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>\( [^ ]\)/\1\2/g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\> /\1 /g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>/\1/g' \
"${FILES[@]}"
2018-07-11 07:40:19 +02:00
|
|
|
key[i] = (char) c;
|
2015-10-02 22:46:53 +02:00
|
|
|
}
|
|
|
|
|
key[WPA_PASSKEY_SIZE] = '\0';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
generate_wep_key(char *key, size_t len)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
const char *hexdigits = "0123456789abcdef";
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-10-02 22:46:53 +02:00
|
|
|
g_return_if_fail(key);
|
|
|
|
|
g_return_if_fail(len > 10);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-10-02 22:46:53 +02:00
|
|
|
/* generate a 10-digit hex WEP key */
|
|
|
|
|
for (i = 0; i < 10; i++) {
|
|
|
|
|
int digit;
|
all: use nm_random_*() instead of g_random_*()
g_random_*() is based on GRand, which is not a CSPRNG. Instead, rely on
kernel to give us good random numbers, which is what nm_random_*() does.
Note that nm_random_*() calls getrandom() (or reads /dev/urandom), which
most likely is slower than GRand. It doesn't matter for our uses though.
It is cumbersome to review all uses of g_rand_*() whether their usage of
a non-cryptographically secure generator is appropriate. Instead, just
always use an appropriate function, thereby avoiding this question. Even
glib documentation refers to reading "/dev/urandom" as alternative. Which
is what nm_random_*() does. These days, it seems unnecessary to not use
the best random generator available, unless it's not fast enough or you
need a stable/seedable stream of random numbers.
In particular in nmcli, we used g_random_int_range() to generate
passwords. That is not appropriate. Sure, it's *only* for the hotspot,
but still.
2023-01-27 12:52:20 +01:00
|
|
|
|
|
|
|
|
digit = nm_random_u64_range_full(0, 16, TRUE);
|
2015-10-02 22:46:53 +02:00
|
|
|
key[i] = hexdigits[digit];
|
|
|
|
|
}
|
|
|
|
|
key[10] = '\0';
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-13 17:48:06 +02:00
|
|
|
static gboolean
|
2015-10-02 22:46:53 +02:00
|
|
|
set_wireless_security_for_hotspot(NMSettingWirelessSecurity *s_wsec,
|
2021-11-09 13:28:54 +01:00
|
|
|
const char *wifi_mode,
|
2015-10-13 17:48:06 +02:00
|
|
|
NMDeviceWifiCapabilities caps,
|
2021-11-09 13:28:54 +01:00
|
|
|
const char *password,
|
2015-10-14 12:05:32 +02:00
|
|
|
gboolean show_password,
|
2021-11-09 13:28:54 +01:00
|
|
|
GError **error)
|
2015-10-02 22:46:53 +02:00
|
|
|
{
|
2015-10-13 17:48:06 +02:00
|
|
|
char generated_key[11];
|
|
|
|
|
const char *key;
|
2015-10-02 22:46:53 +02:00
|
|
|
const char *key_mgmt;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-10-02 22:46:53 +02:00
|
|
|
if (g_strcmp0(wifi_mode, NM_SETTING_WIRELESS_MODE_AP) == 0) {
|
|
|
|
|
if (caps & NM_WIFI_DEVICE_CAP_RSN) {
|
|
|
|
|
nm_setting_wireless_security_add_proto(s_wsec, "rsn");
|
|
|
|
|
nm_setting_wireless_security_add_pairwise(s_wsec, "ccmp");
|
|
|
|
|
nm_setting_wireless_security_add_group(s_wsec, "ccmp");
|
|
|
|
|
key_mgmt = "wpa-psk";
|
|
|
|
|
} else if (caps & NM_WIFI_DEVICE_CAP_WPA) {
|
|
|
|
|
nm_setting_wireless_security_add_proto(s_wsec, "wpa");
|
|
|
|
|
nm_setting_wireless_security_add_pairwise(s_wsec, "tkip");
|
|
|
|
|
nm_setting_wireless_security_add_group(s_wsec, "tkip");
|
|
|
|
|
key_mgmt = "wpa-psk";
|
2020-09-28 16:03:33 +02:00
|
|
|
} else
|
2015-10-02 22:46:53 +02:00
|
|
|
key_mgmt = "none";
|
2015-10-13 17:48:06 +02:00
|
|
|
} else
|
2015-10-02 22:46:53 +02:00
|
|
|
key_mgmt = "none";
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-10-02 22:46:53 +02:00
|
|
|
if (g_strcmp0(key_mgmt, "wpa-psk") == 0) {
|
2015-10-13 17:48:06 +02:00
|
|
|
/* use WPA */
|
|
|
|
|
if (password) {
|
|
|
|
|
if (!nm_utils_wpa_psk_valid(password)) {
|
|
|
|
|
g_set_error(error, NMCLI_ERROR, 0, _("'%s' is not valid WPA PSK"), password);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
key = password;
|
|
|
|
|
} else {
|
|
|
|
|
generate_wpa_key(generated_key, sizeof(generated_key));
|
|
|
|
|
key = generated_key;
|
|
|
|
|
}
|
2015-10-02 22:46:53 +02:00
|
|
|
g_object_set(s_wsec,
|
|
|
|
|
NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,
|
|
|
|
|
key_mgmt,
|
|
|
|
|
NM_SETTING_WIRELESS_SECURITY_PSK,
|
|
|
|
|
key,
|
|
|
|
|
NULL);
|
|
|
|
|
} else {
|
2015-10-13 17:48:06 +02:00
|
|
|
/* use WEP */
|
|
|
|
|
if (password) {
|
|
|
|
|
if (!nm_utils_wep_key_valid(password, NM_WEP_KEY_TYPE_KEY)) {
|
|
|
|
|
g_set_error(error,
|
|
|
|
|
NMCLI_ERROR,
|
|
|
|
|
0,
|
|
|
|
|
_("'%s' is not valid WEP key (it should be 5 or 13 ASCII chars)"),
|
|
|
|
|
password);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
key = password;
|
|
|
|
|
} else {
|
|
|
|
|
generate_wep_key(generated_key, sizeof(generated_key));
|
|
|
|
|
key = generated_key;
|
|
|
|
|
}
|
2015-10-02 22:46:53 +02:00
|
|
|
g_object_set(s_wsec,
|
|
|
|
|
NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,
|
|
|
|
|
key_mgmt,
|
|
|
|
|
NM_SETTING_WIRELESS_SECURITY_WEP_KEY0,
|
|
|
|
|
key,
|
|
|
|
|
NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE,
|
|
|
|
|
NM_WEP_KEY_TYPE_KEY,
|
|
|
|
|
NULL);
|
|
|
|
|
}
|
2015-10-14 12:05:32 +02:00
|
|
|
if (show_password)
|
|
|
|
|
g_print(_("Hotspot password: %s\n"), key);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-10-13 17:48:06 +02:00
|
|
|
return TRUE;
|
2015-10-02 22:46:53 +02:00
|
|
|
}
|
|
|
|
|
|
2019-10-10 18:22:33 +02:00
|
|
|
static NMConnection *
|
2021-11-09 13:28:54 +01:00
|
|
|
find_hotspot_conn(NMDevice *device,
|
2019-10-10 18:22:33 +02:00
|
|
|
const GPtrArray *connections,
|
2021-11-09 13:28:54 +01:00
|
|
|
const char *con_name,
|
|
|
|
|
GBytes *ssid_bytes,
|
|
|
|
|
const char *wifi_mode,
|
|
|
|
|
const char *band,
|
2019-10-10 18:22:33 +02:00
|
|
|
gint64 channel_int)
|
|
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NMConnection *connection;
|
2019-10-10 18:22:33 +02:00
|
|
|
NMSettingWireless *s_wifi;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < connections->len; i++) {
|
|
|
|
|
connection = NM_CONNECTION(connections->pdata[i]);
|
|
|
|
|
|
|
|
|
|
s_wifi = nm_connection_get_setting_wireless(connection);
|
|
|
|
|
if (!s_wifi)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (channel_int != -1 && nm_setting_wireless_get_channel(s_wifi) != channel_int)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (g_strcmp0(nm_setting_wireless_get_mode(s_wifi), wifi_mode) != 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (band && g_strcmp0(nm_setting_wireless_get_band(s_wifi), band) != 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (ssid_bytes && !g_bytes_equal(nm_setting_wireless_get_ssid(s_wifi), ssid_bytes))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (!nm_device_connection_compatible(device, connection, NULL))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
return g_object_ref(connection);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static NMConnection *
|
|
|
|
|
create_hotspot_conn(const GPtrArray *connections,
|
2021-11-09 13:28:54 +01:00
|
|
|
const char *con_name,
|
|
|
|
|
GBytes *ssid_bytes,
|
|
|
|
|
const char *wifi_mode,
|
|
|
|
|
const char *band,
|
2019-10-10 18:22:33 +02:00
|
|
|
gint64 channel_int)
|
|
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
char *default_name = NULL;
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
NMSettingWireless *s_wifi;
|
2019-10-10 18:22:33 +02:00
|
|
|
NMSettingWirelessSecurity *s_wsec;
|
2021-11-09 13:28:54 +01:00
|
|
|
NMSettingIPConfig *s_ip4, *s_ip6;
|
|
|
|
|
NMSettingProxy *s_proxy;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 18:22:33 +02:00
|
|
|
connection = nm_simple_connection_new();
|
|
|
|
|
s_con = (NMSettingConnection *) nm_setting_connection_new();
|
|
|
|
|
nm_connection_add_setting(connection, NM_SETTING(s_con));
|
|
|
|
|
if (!con_name)
|
|
|
|
|
con_name = default_name = nmc_unique_connection_name(connections, "Hotspot");
|
|
|
|
|
g_object_set(s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_ID,
|
|
|
|
|
con_name,
|
|
|
|
|
NM_SETTING_CONNECTION_AUTOCONNECT,
|
|
|
|
|
FALSE,
|
|
|
|
|
NULL);
|
|
|
|
|
g_free(default_name);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 18:22:33 +02:00
|
|
|
s_wifi = (NMSettingWireless *) nm_setting_wireless_new();
|
|
|
|
|
nm_connection_add_setting(connection, NM_SETTING(s_wifi));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 18:22:33 +02:00
|
|
|
g_object_set(s_wifi,
|
|
|
|
|
NM_SETTING_WIRELESS_MODE,
|
|
|
|
|
wifi_mode,
|
|
|
|
|
NM_SETTING_WIRELESS_SSID,
|
|
|
|
|
ssid_bytes,
|
|
|
|
|
NULL);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 18:22:33 +02:00
|
|
|
if (channel_int != -1) {
|
|
|
|
|
g_object_set(s_wifi,
|
|
|
|
|
NM_SETTING_WIRELESS_CHANNEL,
|
|
|
|
|
(guint32) channel_int,
|
|
|
|
|
NM_SETTING_WIRELESS_BAND,
|
|
|
|
|
band,
|
|
|
|
|
NULL);
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 18:22:33 +02:00
|
|
|
s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new();
|
|
|
|
|
nm_connection_add_setting(connection, NM_SETTING(s_wsec));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 18:22:33 +02:00
|
|
|
s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new();
|
|
|
|
|
nm_connection_add_setting(connection, NM_SETTING(s_ip4));
|
|
|
|
|
g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_SHARED, NULL);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 18:22:33 +02:00
|
|
|
s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new();
|
|
|
|
|
nm_connection_add_setting(connection, NM_SETTING(s_ip6));
|
|
|
|
|
g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 18:22:33 +02:00
|
|
|
s_proxy = (NMSettingProxy *) nm_setting_proxy_new();
|
|
|
|
|
nm_connection_add_setting(connection, NM_SETTING(s_proxy));
|
|
|
|
|
g_object_set(s_proxy, NM_SETTING_PROXY_METHOD, (int) NM_SETTING_PROXY_METHOD_NONE, NULL);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 18:22:33 +02:00
|
|
|
return connection;
|
|
|
|
|
}
|
|
|
|
|
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
static void
|
2020-04-05 13:05:58 +02:00
|
|
|
do_device_wifi_hotspot(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
|
2015-10-02 22:46:53 +02:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
const char *ifname = NULL;
|
|
|
|
|
const char *con_name = NULL;
|
|
|
|
|
gs_unref_bytes GBytes *ssid_bytes = NULL;
|
|
|
|
|
const char *wifi_mode;
|
|
|
|
|
const char *band = NULL;
|
|
|
|
|
const char *channel = NULL;
|
|
|
|
|
gint64 channel_int = -1;
|
|
|
|
|
const char *password = NULL;
|
|
|
|
|
gboolean show_password = FALSE;
|
|
|
|
|
NMDevice *device = NULL;
|
|
|
|
|
gs_free NMDevice **devices = NULL;
|
|
|
|
|
NMDeviceWifiCapabilities caps;
|
2019-10-10 18:22:33 +02:00
|
|
|
gs_unref_object NMConnection *connection = NULL;
|
2021-11-09 13:28:54 +01:00
|
|
|
const GPtrArray *connections;
|
|
|
|
|
NMSettingWirelessSecurity *s_wsec;
|
|
|
|
|
GError *error = NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-10-02 22:46:53 +02:00
|
|
|
/* Set default timeout waiting for operation completion. */
|
|
|
|
|
if (nmc->timeout == -1)
|
|
|
|
|
nmc->timeout = 60;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-07-12 11:37:18 +02:00
|
|
|
devices = nmc_get_devices_sorted(nmc->client);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg(nmc, &argc, &argv, NULL);
|
2015-10-02 22:46:53 +02:00
|
|
|
while (argc > 0) {
|
2016-07-12 11:37:18 +02:00
|
|
|
if (argc == 1 && nmc->complete) {
|
|
|
|
|
nmc_complete_strings(*argv,
|
|
|
|
|
"ifname",
|
|
|
|
|
"con-name",
|
|
|
|
|
"ssid",
|
|
|
|
|
"band",
|
2019-04-12 15:40:01 +02:00
|
|
|
"channel",
|
|
|
|
|
"password");
|
2016-07-12 11:37:18 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-10-02 22:46:53 +02:00
|
|
|
if (strcmp(*argv, "ifname") == 0) {
|
2017-03-29 12:02:14 +02:00
|
|
|
argc--;
|
|
|
|
|
argv++;
|
2017-03-24 14:00:25 +01:00
|
|
|
if (!argc) {
|
2015-10-02 22:46:53 +02:00
|
|
|
g_string_printf(nmc->return_text, _("Error: %s argument is missing."), *(argv - 1));
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2015-10-02 22:46:53 +02:00
|
|
|
}
|
|
|
|
|
ifname = *argv;
|
2016-07-12 11:37:18 +02:00
|
|
|
if (argc == 1 && nmc->complete)
|
|
|
|
|
complete_device(devices, ifname, TRUE);
|
2015-10-02 22:46:53 +02:00
|
|
|
} else if (strcmp(*argv, "con-name") == 0) {
|
2017-03-29 12:02:14 +02:00
|
|
|
argc--;
|
|
|
|
|
argv++;
|
2017-03-24 14:00:25 +01:00
|
|
|
if (!argc) {
|
2015-10-02 22:46:53 +02:00
|
|
|
g_string_printf(nmc->return_text, _("Error: %s argument is missing."), *(argv - 1));
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2015-10-02 22:46:53 +02:00
|
|
|
}
|
|
|
|
|
con_name = *argv;
|
|
|
|
|
} else if (strcmp(*argv, "ssid") == 0) {
|
2017-03-29 12:02:14 +02:00
|
|
|
argc--;
|
|
|
|
|
argv++;
|
2017-03-24 14:00:25 +01:00
|
|
|
if (!argc) {
|
2015-10-02 22:46:53 +02:00
|
|
|
g_string_printf(nmc->return_text, _("Error: %s argument is missing."), *(argv - 1));
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2015-10-02 22:46:53 +02:00
|
|
|
}
|
2019-10-10 18:22:33 +02:00
|
|
|
if (strlen(*argv) > 32) {
|
2015-10-02 22:46:53 +02:00
|
|
|
g_string_printf(nmc->return_text, _("Error: ssid is too long."));
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2015-10-02 22:46:53 +02:00
|
|
|
}
|
2019-10-10 18:22:33 +02:00
|
|
|
ssid_bytes = g_bytes_new(*argv, strlen(*argv));
|
2015-10-02 22:46:53 +02:00
|
|
|
} else if (strcmp(*argv, "band") == 0) {
|
2017-03-29 12:02:14 +02:00
|
|
|
argc--;
|
|
|
|
|
argv++;
|
2017-03-24 14:00:25 +01:00
|
|
|
if (!argc) {
|
2015-10-02 22:46:53 +02:00
|
|
|
g_string_printf(nmc->return_text, _("Error: %s argument is missing."), *(argv - 1));
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2015-10-02 22:46:53 +02:00
|
|
|
}
|
|
|
|
|
band = *argv;
|
2016-07-12 11:37:18 +02:00
|
|
|
if (argc == 1 && nmc->complete)
|
2019-04-12 15:40:01 +02:00
|
|
|
nmc_complete_strings(band, "a", "bg");
|
2015-10-02 22:46:53 +02:00
|
|
|
if (strcmp(band, "a") && strcmp(band, "bg")) {
|
|
|
|
|
g_string_printf(nmc->return_text,
|
|
|
|
|
_("Error: band argument value '%s' is invalid; use 'a' or 'bg'."),
|
|
|
|
|
band);
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2015-10-02 22:46:53 +02:00
|
|
|
}
|
|
|
|
|
} else if (strcmp(*argv, "channel") == 0) {
|
2017-03-29 12:02:14 +02:00
|
|
|
argc--;
|
|
|
|
|
argv++;
|
2017-03-24 14:00:25 +01:00
|
|
|
if (!argc) {
|
2015-10-02 22:46:53 +02:00
|
|
|
g_string_printf(nmc->return_text, _("Error: %s argument is missing."), *(argv - 1));
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2015-10-02 22:46:53 +02:00
|
|
|
}
|
|
|
|
|
channel = *argv;
|
2015-10-13 17:48:06 +02:00
|
|
|
} else if (strcmp(*argv, "password") == 0) {
|
2017-03-29 12:02:14 +02:00
|
|
|
argc--;
|
|
|
|
|
argv++;
|
2017-03-24 14:00:25 +01:00
|
|
|
if (!argc) {
|
2015-10-13 17:48:06 +02:00
|
|
|
g_string_printf(nmc->return_text, _("Error: %s argument is missing."), *(argv - 1));
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2015-10-13 17:48:06 +02:00
|
|
|
}
|
|
|
|
|
password = *argv;
|
2015-12-04 13:29:42 +01:00
|
|
|
/* --show-password is deprecated in favour of global --show-secrets option */
|
|
|
|
|
/* Keep it here for backwards compatibility */
|
2015-10-14 12:05:32 +02:00
|
|
|
} else if (nmc_arg_is_option(*argv, "show-password")) {
|
|
|
|
|
show_password = TRUE;
|
2015-10-02 22:46:53 +02:00
|
|
|
} else {
|
2019-07-30 12:23:03 +02:00
|
|
|
g_string_printf(nmc->return_text, _("Error: invalid extra argument '%s'."), *argv);
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2015-10-02 22:46:53 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg(nmc, &argc, &argv, NULL);
|
2015-10-02 22:46:53 +02:00
|
|
|
}
|
2017-04-06 15:26:23 +02:00
|
|
|
show_password = nmc->nmc_config.show_secrets || show_password;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-07-12 11:37:18 +02:00
|
|
|
if (nmc->complete)
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
return;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-10-02 22:46:53 +02:00
|
|
|
/* Verify band and channel parameters */
|
|
|
|
|
if (!channel) {
|
|
|
|
|
if (g_strcmp0(band, "bg") == 0)
|
|
|
|
|
channel = "1";
|
|
|
|
|
if (g_strcmp0(band, "a") == 0)
|
|
|
|
|
channel = "7";
|
|
|
|
|
}
|
|
|
|
|
if (channel) {
|
2019-10-10 18:22:33 +02:00
|
|
|
unsigned long int value;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-10-02 22:46:53 +02:00
|
|
|
if (!band) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: channel requires band too."));
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2015-10-02 22:46:53 +02:00
|
|
|
}
|
2019-10-10 18:22:33 +02:00
|
|
|
if (!nmc_string_to_uint(channel, TRUE, 1, 5825, &value)
|
|
|
|
|
|| !nm_utils_wifi_is_channel_valid(value, band)) {
|
2015-10-02 22:46:53 +02:00
|
|
|
g_string_printf(nmc->return_text,
|
|
|
|
|
_("Error: channel '%s' not valid for band '%s'."),
|
|
|
|
|
channel,
|
|
|
|
|
band);
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2015-10-02 22:46:53 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 18:22:33 +02:00
|
|
|
channel_int = value;
|
2015-10-02 22:46:53 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-10-02 22:46:53 +02:00
|
|
|
/* Find Wi-Fi device. When no ifname is provided, the first Wi-Fi is used. */
|
2016-07-12 12:33:31 +02:00
|
|
|
device = find_wifi_device_by_iface(devices, ifname, NULL);
|
2015-10-02 22:46:53 +02:00
|
|
|
if (!device) {
|
|
|
|
|
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."));
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
|
|
|
|
|
return;
|
2015-10-02 22:46:53 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-10-02 22:46:53 +02:00
|
|
|
/* Check device supported mode */
|
|
|
|
|
caps = nm_device_wifi_get_capabilities(NM_DEVICE_WIFI(device));
|
|
|
|
|
if (caps & NM_WIFI_DEVICE_CAP_AP)
|
|
|
|
|
wifi_mode = NM_SETTING_WIRELESS_MODE_AP;
|
|
|
|
|
else if (caps & NM_WIFI_DEVICE_CAP_ADHOC)
|
|
|
|
|
wifi_mode = NM_SETTING_WIRELESS_MODE_ADHOC;
|
|
|
|
|
else {
|
|
|
|
|
g_string_printf(nmc->return_text,
|
|
|
|
|
_("Error: Device '%s' supports neither AP nor Ad-Hoc mode."),
|
|
|
|
|
nm_device_get_iface(device));
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
|
|
|
|
|
return;
|
2015-10-02 22:46:53 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 18:22:33 +02:00
|
|
|
connections = nm_client_get_connections(nmc->client);
|
|
|
|
|
connection =
|
|
|
|
|
find_hotspot_conn(device, connections, con_name, ssid_bytes, wifi_mode, band, channel_int);
|
|
|
|
|
if (!connection) {
|
|
|
|
|
/* Create a connection with appropriate parameters */
|
|
|
|
|
if (!ssid_bytes)
|
|
|
|
|
ssid_bytes = generate_ssid_for_hotspot();
|
|
|
|
|
connection =
|
|
|
|
|
create_hotspot_conn(connections, con_name, ssid_bytes, wifi_mode, band, channel_int);
|
2015-10-13 17:48:06 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 18:22:33 +02:00
|
|
|
if (password || !NM_IS_REMOTE_CONNECTION(connection)) {
|
|
|
|
|
s_wsec = nm_connection_get_setting_wireless_security(connection);
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
g_return_if_fail(s_wsec);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 18:22:33 +02:00
|
|
|
if (!set_wireless_security_for_hotspot(s_wsec,
|
|
|
|
|
wifi_mode,
|
|
|
|
|
caps,
|
|
|
|
|
password,
|
|
|
|
|
show_password,
|
|
|
|
|
&error)) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: Invalid 'password': %s."), error->message);
|
|
|
|
|
g_clear_error(&error);
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
|
|
|
|
|
return;
|
2019-10-10 18:22:33 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
}
|
|
|
|
|
|
2015-10-02 22:46:53 +02:00
|
|
|
/* Activate the connection now */
|
|
|
|
|
nmc->nowait_flag = (nmc->timeout == 0);
|
2016-06-22 17:44:39 +02:00
|
|
|
nmc->should_wait++;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-10-10 18:22:33 +02:00
|
|
|
save_and_activate_connection(nmc, device, connection, TRUE, NULL);
|
2015-10-02 22:46:53 +02:00
|
|
|
}
|
|
|
|
|
|
2012-11-19 17:10:56 +01:00
|
|
|
static void
|
2014-09-11 16:27:13 -04:00
|
|
|
request_rescan_cb(GObject *object, GAsyncResult *result, gpointer user_data)
|
2012-11-19 17:10:56 +01:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NmCli *nmc = (NmCli *) user_data;
|
2014-09-11 16:27:13 -04:00
|
|
|
GError *error = NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2014-09-11 16:27:13 -04:00
|
|
|
nm_device_wifi_request_scan_finish(NM_DEVICE_WIFI(object), result, &error);
|
2012-11-19 17:10:56 +01:00
|
|
|
if (error) {
|
2014-09-11 16:27:13 -04:00
|
|
|
g_string_printf(nmc->return_text, _("Error: %s."), error->message);
|
2012-11-19 17:10:56 +01:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
|
2014-09-11 16:27:13 -04:00
|
|
|
g_error_free(error);
|
2012-11-19 17:10:56 +01:00
|
|
|
}
|
|
|
|
|
quit();
|
|
|
|
|
}
|
|
|
|
|
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
static void
|
2020-04-05 13:05:58 +02:00
|
|
|
do_device_wifi_rescan(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
|
2012-11-19 17:10:56 +01:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NMDevice *device;
|
|
|
|
|
const char *ifname = NULL;
|
|
|
|
|
gs_unref_ptrarray GPtrArray *ssids = NULL;
|
|
|
|
|
gs_free NMDevice **devices = NULL;
|
|
|
|
|
GVariantBuilder builder, array_builder;
|
|
|
|
|
GVariant *options;
|
|
|
|
|
int i;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-07-14 09:50:56 +02:00
|
|
|
ssids = g_ptr_array_new();
|
2016-07-12 10:14:53 +02:00
|
|
|
devices = nmc_get_devices_sorted(nmc->client);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg(nmc, &argc, &argv, NULL);
|
2012-11-19 17:10:56 +01:00
|
|
|
/* Get the parameters */
|
2015-07-14 09:50:56 +02:00
|
|
|
while (argc > 0) {
|
2016-07-12 10:14:53 +02:00
|
|
|
if (argc == 1 && nmc->complete)
|
2019-04-12 15:40:01 +02:00
|
|
|
nmc_complete_strings(*argv, "ifname", "ssid");
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-04-18 14:54:01 +02:00
|
|
|
if (strcmp(*argv, "ifname") == 0) {
|
2015-07-14 09:50:56 +02:00
|
|
|
if (ifname) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: '%s' cannot repeat."), *(argv - 1));
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
return;
|
2015-07-14 09:50:56 +02:00
|
|
|
}
|
2017-03-29 12:02:14 +02:00
|
|
|
argc--;
|
|
|
|
|
argv++;
|
2017-03-24 14:00:25 +01:00
|
|
|
if (!argc) {
|
2012-11-19 17:10:56 +01:00
|
|
|
g_string_printf(nmc->return_text, _("Error: %s argument is missing."), *(argv - 1));
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
return;
|
2012-11-19 17:10:56 +01:00
|
|
|
}
|
2015-07-14 09:50:56 +02:00
|
|
|
ifname = *argv;
|
2016-07-12 10:14:53 +02:00
|
|
|
if (argc == 1 && nmc->complete)
|
|
|
|
|
complete_device(devices, ifname, TRUE);
|
2015-07-14 09:50:56 +02:00
|
|
|
} else if (strcmp(*argv, "ssid") == 0) {
|
2017-03-29 12:02:14 +02:00
|
|
|
argc--;
|
|
|
|
|
argv++;
|
2017-03-24 14:00:25 +01:00
|
|
|
if (!argc) {
|
2015-07-14 09:50:56 +02:00
|
|
|
g_string_printf(nmc->return_text, _("Error: %s argument is missing."), *(argv - 1));
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
return;
|
2015-07-14 09:50:56 +02:00
|
|
|
}
|
2020-04-05 13:05:58 +02:00
|
|
|
g_ptr_array_add(ssids, (gpointer) *argv);
|
2019-07-30 12:23:03 +02:00
|
|
|
} else if (!nmc->complete) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: invalid extra argument '%s'."), *argv);
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
return;
|
2019-07-30 12:23:03 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg(nmc, &argc, &argv, NULL);
|
2012-11-19 17:10:56 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-07-12 10:14:53 +02:00
|
|
|
if (nmc->complete)
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
return;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-04-18 14:54:01 +02:00
|
|
|
/* Find Wi-Fi device to scan on. When no ifname is provided, the first Wi-Fi is used. */
|
2016-07-12 12:33:31 +02:00
|
|
|
device = find_wifi_device_by_iface(devices, ifname, NULL);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2012-11-19 17:10:56 +01:00
|
|
|
if (!device) {
|
2015-08-13 09:48:12 +02:00
|
|
|
if (ifname)
|
|
|
|
|
g_string_printf(nmc->return_text,
|
|
|
|
|
_("Error: Device '%s' is not a Wi-Fi device."),
|
|
|
|
|
ifname);
|
|
|
|
|
else
|
2012-11-19 17:10:56 +01:00
|
|
|
g_string_printf(nmc->return_text, _("Error: No Wi-Fi device found."));
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
return;
|
2012-11-19 17:10:56 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-07-14 09:50:56 +02:00
|
|
|
if (ssids->len) {
|
|
|
|
|
g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
|
|
|
|
|
g_variant_builder_init(&array_builder, G_VARIANT_TYPE("aay"));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-07-14 09:50:56 +02:00
|
|
|
for (i = 0; i < ssids->len; i++) {
|
2020-04-05 13:05:58 +02:00
|
|
|
const char *ssid = g_ptr_array_index(ssids, i);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2021-04-15 09:17:47 +02:00
|
|
|
g_variant_builder_add(&array_builder,
|
|
|
|
|
"@ay",
|
|
|
|
|
nm_g_variant_new_ay((const guint8 *) ssid, strlen(ssid)));
|
2015-07-14 09:50:56 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-07-14 09:50:56 +02:00
|
|
|
g_variant_builder_add(&builder, "{sv}", "ssids", g_variant_builder_end(&array_builder));
|
|
|
|
|
options = g_variant_builder_end(&builder);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-07-14 09:50:56 +02:00
|
|
|
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);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-03-27 12:39:17 +01:00
|
|
|
nmc->should_wait++;
|
2012-11-19 17:10:56 +01:00
|
|
|
}
|
|
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
static void
|
|
|
|
|
string_append_mecard(GString *string, const char *tag, const char *text)
|
|
|
|
|
{
|
|
|
|
|
const char *p;
|
|
|
|
|
bool is_hex = TRUE;
|
|
|
|
|
int start;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
if (!text)
|
|
|
|
|
return;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
g_string_append(string, tag);
|
|
|
|
|
start = string->len;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
for (p = text; *p; p++) {
|
|
|
|
|
if (!g_ascii_isxdigit(*p))
|
|
|
|
|
is_hex = FALSE;
|
|
|
|
|
if (strchr("\\\":;,", *p))
|
|
|
|
|
g_string_append_c(string, '\\');
|
|
|
|
|
g_string_append_c(string, *p);
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
if (is_hex) {
|
|
|
|
|
g_string_insert_c(string, start, '\"');
|
|
|
|
|
g_string_append_c(string, '\"');
|
|
|
|
|
}
|
|
|
|
|
g_string_append_c(string, ';');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
print_wifi_connection(const NmcConfig *nmc_config, NMConnection *connection)
|
|
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NMSettingWireless *s_wireless;
|
|
|
|
|
NMSettingWirelessSecurity *s_wsec;
|
|
|
|
|
const char *key_mgmt = NULL;
|
|
|
|
|
const char *psk = NULL;
|
|
|
|
|
const char *type = NULL;
|
|
|
|
|
GBytes *ssid_bytes;
|
|
|
|
|
gs_free char *ssid = NULL;
|
2021-05-27 10:41:45 +02:00
|
|
|
nm_auto_free_gstring GString *string = NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
s_wireless = nm_connection_get_setting_wireless(connection);
|
|
|
|
|
g_return_if_fail(s_wireless);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
ssid_bytes = nm_setting_wireless_get_ssid(s_wireless);
|
|
|
|
|
g_return_if_fail(ssid_bytes);
|
|
|
|
|
ssid = nm_utils_ssid_to_utf8(g_bytes_get_data(ssid_bytes, NULL), g_bytes_get_size(ssid_bytes));
|
|
|
|
|
g_return_if_fail(ssid);
|
|
|
|
|
g_print("SSID: %s\n", ssid);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
string = g_string_sized_new(64);
|
|
|
|
|
g_string_append(string, "WIFI:");
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
s_wsec = nm_connection_get_setting_wireless_security(connection);
|
|
|
|
|
if (s_wsec) {
|
|
|
|
|
key_mgmt = nm_setting_wireless_security_get_key_mgmt(s_wsec);
|
|
|
|
|
psk = nm_setting_wireless_security_get_psk(s_wsec);
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
if (key_mgmt == NULL) {
|
|
|
|
|
type = "nopass";
|
|
|
|
|
g_print("%s: %s\n", _("Security"), _("None"));
|
|
|
|
|
} else if (strcmp(key_mgmt, "none") == 0 || strcmp(key_mgmt, "ieee8021x") == 0) {
|
|
|
|
|
type = "WEP";
|
|
|
|
|
g_print("%s: WEP\n", _("Security"));
|
|
|
|
|
} else if (strcmp(key_mgmt, "wpa-none") == 0 || strcmp(key_mgmt, "wpa-psk") == 0
|
|
|
|
|
|| strcmp(key_mgmt, "sae") == 0) {
|
|
|
|
|
type = "WPA";
|
|
|
|
|
g_print("%s: WPA\n", _("Security"));
|
2019-11-17 22:24:19 +01:00
|
|
|
} else if (strcmp(key_mgmt, "owe") == 0) {
|
|
|
|
|
type = "nopass";
|
|
|
|
|
g_print("%s: OWE\n", _("Security"));
|
2019-09-11 16:45:12 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
if (psk)
|
|
|
|
|
g_print("%s: %s\n", _("Password"), psk);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
string_append_mecard(string, "T:", type);
|
|
|
|
|
string_append_mecard(string, "S:", ssid);
|
|
|
|
|
string_append_mecard(string, "P:", psk);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
if (nm_setting_wireless_get_hidden(s_wireless))
|
|
|
|
|
g_string_append(string, "H:true;");
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
g_string_append_c(string, ';');
|
|
|
|
|
if (nmc_config->use_colors)
|
|
|
|
|
nmc_print_qrcode(string->str);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
g_print("\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
wifi_show_device(const NmcConfig *nmc_config, NMDevice *device, GError **error)
|
|
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NMActiveConnection *active_conn;
|
2019-09-11 16:45:12 +02:00
|
|
|
gs_unref_object NMConnection *connection = NULL;
|
2021-11-09 13:28:54 +01:00
|
|
|
gs_unref_variant GVariant *secrets = NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
if (!NM_IS_DEVICE_WIFI(device)) {
|
|
|
|
|
g_set_error(error,
|
|
|
|
|
NMCLI_ERROR,
|
|
|
|
|
0,
|
|
|
|
|
_("Error: Device '%s' is not a Wi-Fi device."),
|
|
|
|
|
nm_device_get_iface(device));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
connection = nm_device_get_applied_connection(device, 0, NULL, NULL, error);
|
|
|
|
|
if (!connection)
|
|
|
|
|
return FALSE;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
active_conn = nm_device_get_active_connection(device);
|
|
|
|
|
if (!active_conn) {
|
|
|
|
|
g_set_error(error,
|
|
|
|
|
NMCLI_ERROR,
|
|
|
|
|
0,
|
|
|
|
|
_("no active connection on device '%s'"),
|
|
|
|
|
nm_device_get_iface(device));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
secrets = nm_remote_connection_get_secrets(nm_active_connection_get_connection(active_conn),
|
|
|
|
|
NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL);
|
|
|
|
|
if (secrets
|
|
|
|
|
&& !nm_connection_update_secrets(connection,
|
|
|
|
|
NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
|
|
|
|
|
secrets,
|
|
|
|
|
error)) {
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
print_wifi_connection(nmc_config, connection);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
static void
|
2020-04-05 13:05:58 +02:00
|
|
|
do_device_wifi_show_password(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
|
2019-09-11 16:45:12 +02:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
const char *ifname = NULL;
|
|
|
|
|
gs_free NMDevice **devices = NULL;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
|
|
|
|
gboolean found = FALSE;
|
2019-09-11 16:45:12 +02:00
|
|
|
int i;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
devices = nmc_get_devices_sorted(nmc->client);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
next_arg(nmc, &argc, &argv, NULL);
|
|
|
|
|
while (argc > 0) {
|
|
|
|
|
if (argc == 1 && nmc->complete)
|
|
|
|
|
nmc_complete_strings(*argv, "ifname");
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
if (strcmp(*argv, "ifname") == 0) {
|
|
|
|
|
if (ifname) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: '%s' cannot repeat."), *(argv - 1));
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2019-09-11 16:45:12 +02:00
|
|
|
}
|
|
|
|
|
argc--;
|
|
|
|
|
argv++;
|
|
|
|
|
if (!argc) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: %s argument is missing."), *(argv - 1));
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2019-09-11 16:45:12 +02:00
|
|
|
}
|
|
|
|
|
ifname = *argv;
|
|
|
|
|
if (argc == 1 && nmc->complete)
|
|
|
|
|
complete_device(devices, ifname, TRUE);
|
|
|
|
|
} else if (!nmc->complete) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: invalid extra argument '%s'."), *argv);
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2019-09-11 16:45:12 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
next_arg(nmc, &argc, &argv, NULL);
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
if (nmc->complete)
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
return;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
for (i = 0; devices[i]; i++) {
|
|
|
|
|
if (ifname && g_strcmp0(nm_device_get_iface(devices[i]), ifname) != 0)
|
|
|
|
|
continue;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
if (wifi_show_device(&nmc->nmc_config, devices[i], &error)) {
|
|
|
|
|
found = TRUE;
|
|
|
|
|
} else {
|
|
|
|
|
if (ifname) {
|
2022-08-26 12:52:22 +02:00
|
|
|
g_string_assign(nmc->return_text, error->message);
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
|
|
|
|
|
return;
|
2019-09-11 16:45:12 +02:00
|
|
|
}
|
|
|
|
|
g_clear_error(&error);
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
if (ifname)
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-09-11 16:45:12 +02:00
|
|
|
if (!found) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: No Wi-Fi device found."));
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
|
|
|
|
|
return;
|
2019-09-11 16:45:12 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-24 19:03:33 +02:00
|
|
|
static NMCCommand device_wifi_cmds[] = {
|
2019-09-11 16:45:12 +02:00
|
|
|
{"list", do_device_wifi_list, NULL, TRUE, TRUE},
|
|
|
|
|
{"connect", do_device_wifi_connect, NULL, TRUE, TRUE},
|
|
|
|
|
{"hotspot", do_device_wifi_hotspot, NULL, TRUE, TRUE},
|
|
|
|
|
{"rescan", do_device_wifi_rescan, NULL, TRUE, TRUE},
|
|
|
|
|
{"show-password", do_device_wifi_show_password, NULL, TRUE, TRUE},
|
|
|
|
|
{NULL, do_device_wifi_list, NULL, TRUE, TRUE},
|
2016-06-24 19:03:33 +02:00
|
|
|
};
|
|
|
|
|
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
static void
|
2020-04-05 13:05:58 +02:00
|
|
|
do_device_wifi(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
|
2010-02-25 09:52:30 -08:00
|
|
|
{
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg(nmc, &argc, &argv, NULL);
|
2016-08-31 21:04:33 +02:00
|
|
|
nmc_do_cmd(nmc, device_wifi_cmds, *argv, argc, argv);
|
2010-02-25 09:52:30 -08:00
|
|
|
}
|
|
|
|
|
|
2015-11-10 14:06:02 +01:00
|
|
|
static int
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
show_device_lldp_list(NMDevice *device, NmCli *nmc, const char *fields_str, int *counter)
|
2015-11-10 14:06:02 +01:00
|
|
|
{
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
const NMMetaAbstractInfo *const *tmpl;
|
2021-11-09 13:28:54 +01:00
|
|
|
NmcOutputField *arr;
|
|
|
|
|
GPtrArray *neighbors;
|
|
|
|
|
const char *str;
|
2015-11-10 14:06:02 +01:00
|
|
|
int i;
|
2017-03-30 14:56:19 +02:00
|
|
|
NMC_OUTPUT_DATA_DEFINE_SCOPED(out);
|
2017-03-31 13:21:47 +02:00
|
|
|
gs_free char *header_name = NULL;
|
2015-11-10 14:06:02 +01:00
|
|
|
|
|
|
|
|
neighbors = nm_device_get_lldp_neighbors(device);
|
|
|
|
|
|
|
|
|
|
if (!neighbors || !neighbors->len)
|
|
|
|
|
return 0;
|
|
|
|
|
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
tmpl = (const NMMetaAbstractInfo *const *) nmc_fields_dev_lldp_list;
|
2015-11-10 14:06:02 +01:00
|
|
|
|
|
|
|
|
/* Main header name */
|
2017-03-31 13:21:47 +02:00
|
|
|
header_name = construct_header_name(_("Device LLDP neighbors"), nm_device_get_iface(device));
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
out_indices = parse_output_fields(fields_str,
|
|
|
|
|
(const NMMetaAbstractInfo *const *) nmc_fields_dev_lldp_list,
|
|
|
|
|
FALSE,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL);
|
|
|
|
|
arr = nmc_dup_fields_array(tmpl, NMC_OF_FLAG_MAIN_HEADER_ADD | NMC_OF_FLAG_FIELD_NAMES);
|
2017-03-30 14:56:19 +02:00
|
|
|
g_ptr_array_add(out.output_data, arr);
|
2015-11-10 14:06:02 +01:00
|
|
|
|
|
|
|
|
for (i = 0; i < neighbors->len; i++) {
|
|
|
|
|
NMLldpNeighbor *neighbor = neighbors->pdata[i];
|
|
|
|
|
guint value;
|
|
|
|
|
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
arr = nmc_dup_fields_array(tmpl, NMC_OF_FLAG_SECTION_PREFIX);
|
2015-11-10 14:06:02 +01:00
|
|
|
set_val_str(arr, 0, g_strdup_printf("NEIGHBOR[%d]", (*counter)++));
|
|
|
|
|
|
|
|
|
|
set_val_strc(arr, 1, nm_device_get_iface(device));
|
|
|
|
|
|
|
|
|
|
if (nm_lldp_neighbor_get_attr_string_value(neighbor, NM_LLDP_ATTR_CHASSIS_ID, &str))
|
|
|
|
|
set_val_strc(arr, 2, str);
|
|
|
|
|
|
|
|
|
|
if (nm_lldp_neighbor_get_attr_string_value(neighbor, NM_LLDP_ATTR_PORT_ID, &str))
|
|
|
|
|
set_val_strc(arr, 3, str);
|
|
|
|
|
|
|
|
|
|
if (nm_lldp_neighbor_get_attr_string_value(neighbor, NM_LLDP_ATTR_PORT_DESCRIPTION, &str))
|
|
|
|
|
set_val_strc(arr, 4, str);
|
|
|
|
|
|
|
|
|
|
if (nm_lldp_neighbor_get_attr_string_value(neighbor, NM_LLDP_ATTR_SYSTEM_NAME, &str))
|
|
|
|
|
set_val_strc(arr, 5, str);
|
|
|
|
|
|
|
|
|
|
if (nm_lldp_neighbor_get_attr_string_value(neighbor, NM_LLDP_ATTR_SYSTEM_DESCRIPTION, &str))
|
|
|
|
|
set_val_strc(arr, 6, str);
|
|
|
|
|
|
2020-05-14 12:03:16 +02:00
|
|
|
if (nm_lldp_neighbor_get_attr_uint_value(neighbor,
|
|
|
|
|
NM_LLDP_ATTR_SYSTEM_CAPABILITIES,
|
|
|
|
|
&value)) {
|
|
|
|
|
gs_free char *tmp = NULL;
|
|
|
|
|
|
|
|
|
|
set_val_str(
|
|
|
|
|
arr,
|
|
|
|
|
7,
|
|
|
|
|
g_strdup_printf("%u (%s)", value, (tmp = nmc_parse_lldp_capabilities(value))));
|
|
|
|
|
}
|
2015-11-10 14:06:02 +01:00
|
|
|
|
|
|
|
|
if (nm_lldp_neighbor_get_attr_uint_value(neighbor, NM_LLDP_ATTR_IEEE_802_1_PVID, &value))
|
2020-05-14 11:53:37 +02:00
|
|
|
set_val_str(arr, 8, nm_strdup_int(value));
|
2015-11-10 14:06:02 +01:00
|
|
|
|
|
|
|
|
if (nm_lldp_neighbor_get_attr_uint_value(neighbor, NM_LLDP_ATTR_IEEE_802_1_PPVID, &value))
|
2020-05-14 11:53:37 +02:00
|
|
|
set_val_str(arr, 9, nm_strdup_int(value));
|
2015-11-10 14:06:02 +01:00
|
|
|
|
|
|
|
|
if (nm_lldp_neighbor_get_attr_uint_value(neighbor,
|
|
|
|
|
NM_LLDP_ATTR_IEEE_802_1_PPVID_FLAGS,
|
|
|
|
|
&value))
|
2020-05-14 11:53:37 +02:00
|
|
|
set_val_str(arr, 10, nm_strdup_int(value));
|
2015-11-10 14:06:02 +01:00
|
|
|
|
|
|
|
|
if (nm_lldp_neighbor_get_attr_uint_value(neighbor, NM_LLDP_ATTR_IEEE_802_1_VID, &value))
|
2020-05-14 11:53:37 +02:00
|
|
|
set_val_str(arr, 11, nm_strdup_int(value));
|
2015-11-10 14:06:02 +01:00
|
|
|
|
|
|
|
|
if (nm_lldp_neighbor_get_attr_string_value(neighbor,
|
|
|
|
|
NM_LLDP_ATTR_IEEE_802_1_VLAN_NAME,
|
|
|
|
|
&str))
|
|
|
|
|
set_val_strc(arr, 12, str);
|
|
|
|
|
|
|
|
|
|
if (nm_lldp_neighbor_get_attr_string_value(neighbor, NM_LLDP_ATTR_DESTINATION, &str))
|
|
|
|
|
set_val_strc(arr, 13, str);
|
|
|
|
|
|
|
|
|
|
if (nm_lldp_neighbor_get_attr_uint_value(neighbor, NM_LLDP_ATTR_CHASSIS_ID_TYPE, &value))
|
2020-05-14 11:53:37 +02:00
|
|
|
set_val_str(arr, 14, nm_strdup_int(value));
|
2015-11-10 14:06:02 +01:00
|
|
|
|
|
|
|
|
if (nm_lldp_neighbor_get_attr_uint_value(neighbor, NM_LLDP_ATTR_PORT_ID_TYPE, &value))
|
2020-05-14 11:53:37 +02:00
|
|
|
set_val_str(arr, 15, nm_strdup_int(value));
|
2015-11-10 14:06:02 +01:00
|
|
|
|
2017-03-30 14:56:19 +02:00
|
|
|
g_ptr_array_add(out.output_data, arr);
|
2015-11-10 14:06:02 +01:00
|
|
|
}
|
|
|
|
|
|
2017-03-30 14:56:19 +02:00
|
|
|
print_data_prepare_width(out.output_data);
|
2020-04-02 19:10:15 +02:00
|
|
|
print_data(&nmc->nmc_config, &nmc->pager_data, out_indices, header_name, 0, &out);
|
2015-11-10 14:06:02 +01:00
|
|
|
|
|
|
|
|
return neighbors->len;
|
|
|
|
|
}
|
|
|
|
|
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
static void
|
2020-04-05 13:05:58 +02:00
|
|
|
do_device_lldp_list(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
|
2015-11-10 14:06:02 +01:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
NMDevice *device = NULL;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
|
|
|
|
const char *fields_str = NULL;
|
|
|
|
|
int counter = 0;
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
gs_unref_array GArray *out_indices = NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg(nmc, &argc, &argv, NULL);
|
2015-11-10 14:06:02 +01:00
|
|
|
while (argc > 0) {
|
2016-06-24 19:03:14 +02:00
|
|
|
if (argc == 1 && nmc->complete)
|
2019-04-12 15:40:01 +02:00
|
|
|
nmc_complete_strings(*argv, "ifname");
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-11-10 14:06:02 +01:00
|
|
|
if (strcmp(*argv, "ifname") == 0) {
|
2017-03-29 12:02:14 +02:00
|
|
|
argc--;
|
|
|
|
|
argv++;
|
2017-03-24 14:00:25 +01:00
|
|
|
if (!argc) {
|
2015-11-10 14:06:02 +01:00
|
|
|
g_string_printf(nmc->return_text, _("Error: %s argument is missing."), *(argv - 1));
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2016-06-24 19:22:36 +02:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-24 19:22:36 +02:00
|
|
|
device = get_device(nmc, &argc, &argv, &error);
|
|
|
|
|
if (!device) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: %s."), error->message);
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = error->code;
|
|
|
|
|
return;
|
2015-11-10 14:06:02 +01:00
|
|
|
}
|
|
|
|
|
} else {
|
2016-02-12 15:43:19 +01:00
|
|
|
g_string_printf(nmc->return_text, _("Error: invalid extra argument '%s'."), *argv);
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2015-11-10 14:06:02 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg(nmc, &argc, &argv, NULL);
|
2015-11-10 14:06:02 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-02-11 15:17:03 +01:00
|
|
|
if (!nmc->required_fields || g_ascii_strcasecmp(nmc->required_fields, "common") == 0)
|
2015-11-10 14:06:02 +01:00
|
|
|
fields_str = NMC_FIELDS_DEV_LLDP_LIST_COMMON;
|
2020-02-11 15:17:03 +01:00
|
|
|
else if (!nmc->required_fields || g_ascii_strcasecmp(nmc->required_fields, "all") == 0) {
|
2020-05-06 23:18:54 +02:00
|
|
|
/* pass */
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
} else
|
2015-11-10 14:06:02 +01:00
|
|
|
fields_str = nmc->required_fields;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
cli: split tracking of meta data out of NmcOutputField
When generating output data, nmcli iterates over a list of
property-descriptors (nmc_fields_ip4_config), creates an intermediate
array (output_data) and finally prints it.
However, previously both the meta data (nmc_fields_ip4_config) and
the intermediate format use the same type NmcOutputField. This means,
certain fields are relevant to describe a property, and other fields
are output/formatting fields.
Split this up. Now, the meta data is tracked in form of an NMMetaAbstractInfo
lists. This separates the information about properties from intermediate steps
during creation of the output.
Note that currently functions like print_ip4_config() still have all the
knowledge about how to generate the output. That is wrong, instead, the
meta data (NMMetaAbstractInfo) should describe how to create the output
and then all those functions could be replaced. This means, later we want
to add more knowledge to the NMMetaAbstractInfo, so it is important to
keep them separate from NmcOutputField.
2017-03-31 19:18:16 +02:00
|
|
|
out_indices = parse_output_fields(fields_str,
|
|
|
|
|
(const NMMetaAbstractInfo *const *) nmc_fields_dev_lldp_list,
|
|
|
|
|
FALSE,
|
|
|
|
|
NULL,
|
|
|
|
|
&error);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2015-11-10 14:06:02 +01:00
|
|
|
if (error) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: 'device lldp list': %s"), error->message);
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
2015-11-10 14:06:02 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-24 19:03:14 +02:00
|
|
|
if (nmc->complete)
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
return;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2016-06-24 19:22:36 +02:00
|
|
|
if (device) {
|
2015-11-10 14:06:02 +01:00
|
|
|
show_device_lldp_list(device, nmc, fields_str, &counter);
|
|
|
|
|
} else {
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
gs_free NMDevice **devices = nmc_get_devices_sorted(nmc->client);
|
|
|
|
|
guint i;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 14:56:19 +02:00
|
|
|
for (i = 0; devices[i]; i++)
|
2015-11-10 14:06:02 +01:00
|
|
|
show_device_lldp_list(devices[i], nmc, fields_str, &counter);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-24 19:03:11 +02:00
|
|
|
static NMCCommand device_lldp_cmds[] = {
|
2016-08-31 20:52:48 +02:00
|
|
|
{"list", do_device_lldp_list, NULL, TRUE, TRUE},
|
|
|
|
|
{NULL, do_device_lldp_list, NULL, TRUE, TRUE},
|
2016-06-24 19:03:11 +02:00
|
|
|
};
|
|
|
|
|
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
static void
|
2020-04-05 13:05:58 +02:00
|
|
|
do_device_lldp(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
|
2015-11-10 14:06:02 +01:00
|
|
|
{
|
2016-06-23 12:19:10 +02:00
|
|
|
if (!nmc->mode_specified)
|
2017-03-30 12:45:41 +02:00
|
|
|
nmc->nmc_config_mutable.multiline_output =
|
|
|
|
|
TRUE; /* multiline mode is default for 'device lldp' */
|
2016-06-23 12:19:10 +02:00
|
|
|
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg(nmc, &argc, &argv, NULL);
|
2016-08-31 21:04:33 +02:00
|
|
|
nmc_do_cmd(nmc, device_lldp_cmds, *argv, argc, argv);
|
2015-11-10 14:06:02 +01:00
|
|
|
}
|
|
|
|
|
|
2022-05-04 09:19:01 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
NmCli *nmc;
|
|
|
|
|
NMCheckpoint *checkpoint;
|
|
|
|
|
char **argv;
|
|
|
|
|
guint removed_id;
|
|
|
|
|
guint child_id;
|
|
|
|
|
gboolean removed;
|
|
|
|
|
} CheckpointCbInfo;
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
free_checkpoint_info(CheckpointCbInfo *info)
|
|
|
|
|
{
|
|
|
|
|
g_clear_object(&info->checkpoint);
|
|
|
|
|
g_strfreev(info->argv);
|
|
|
|
|
g_slice_free(CheckpointCbInfo, info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
checkpoints_changed_cb(GObject *object, GParamSpec *pspec, CheckpointCbInfo *info)
|
|
|
|
|
{
|
|
|
|
|
const GPtrArray *checkpoints;
|
|
|
|
|
guint i;
|
|
|
|
|
|
|
|
|
|
checkpoints = nm_client_get_checkpoints(info->nmc->client);
|
|
|
|
|
for (i = 0; i < checkpoints->len; i++) {
|
|
|
|
|
if (checkpoints->pdata[i] == info->checkpoint) {
|
|
|
|
|
/* Our checkpoint still exists. */
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_string_printf(info->nmc->return_text, _("Checkpoint was removed."));
|
|
|
|
|
info->nmc->return_value = NMC_RESULT_ERROR_TIMEOUT_EXPIRED;
|
|
|
|
|
|
|
|
|
|
info->removed = TRUE;
|
|
|
|
|
|
|
|
|
|
if (!info->child_id) {
|
|
|
|
|
/* The command is done, we're in the confirmation prompt. */
|
|
|
|
|
g_print("%s\n", _("No"));
|
|
|
|
|
g_main_loop_quit(loop);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
checkpoint_destroy_cb(GObject *object, GAsyncResult *result, void *user_data)
|
|
|
|
|
{
|
|
|
|
|
NmCli *nmc = (NmCli *) user_data;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
|
|
|
|
|
|
|
|
|
if (!nm_client_checkpoint_destroy_finish(nmc->client, result, &error)) {
|
|
|
|
|
g_string_printf(nmc->return_text,
|
|
|
|
|
_("Error: Destroying a checkpoint failed: %s"),
|
|
|
|
|
error->message);
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_main_loop_quit(loop);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
child_watch_cb(GPid pid, gint wait_status, gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
CheckpointCbInfo *info = (CheckpointCbInfo *) user_data;
|
|
|
|
|
NmCli *nmc = info->nmc;
|
|
|
|
|
char *line;
|
|
|
|
|
|
|
|
|
|
info->child_id = 0;
|
|
|
|
|
if (info->removed) {
|
|
|
|
|
g_main_loop_quit(loop);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (g_main_loop_is_running(loop)) {
|
|
|
|
|
line = nmc_readline(&nmc->nmc_config, "Type \"%s\" to commit the changes: ", _("Yes"));
|
|
|
|
|
if (g_strcmp0(line, _("Yes")) == 0) {
|
|
|
|
|
g_signal_handler_disconnect(nmc->client, info->removed_id);
|
|
|
|
|
nm_client_checkpoint_destroy(nmc->client,
|
|
|
|
|
nm_object_get_path(NM_OBJECT(info->checkpoint)),
|
|
|
|
|
NULL,
|
|
|
|
|
checkpoint_destroy_cb,
|
|
|
|
|
nmc);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
nmc_cleanup_readline();
|
|
|
|
|
out:
|
|
|
|
|
free_checkpoint_info(info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
checkpoint_create_cb(GObject *object, GAsyncResult *result, void *user_data)
|
|
|
|
|
{
|
|
|
|
|
NMClient *client = NM_CLIENT(object);
|
|
|
|
|
CheckpointCbInfo *info = (CheckpointCbInfo *) user_data;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
|
|
|
|
GPid pid;
|
|
|
|
|
|
|
|
|
|
info->checkpoint = nm_client_checkpoint_create_finish(client, result, &error);
|
|
|
|
|
if (!info->checkpoint) {
|
|
|
|
|
g_string_printf(info->nmc->return_text,
|
|
|
|
|
_("Error: Creating a checkpoint failed: %s"),
|
|
|
|
|
error->message);
|
|
|
|
|
info->nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
|
|
|
|
|
g_main_loop_quit(loop);
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!g_spawn_async(NULL,
|
|
|
|
|
info->argv,
|
|
|
|
|
NULL,
|
|
|
|
|
G_SPAWN_LEAVE_DESCRIPTORS_OPEN | G_SPAWN_SEARCH_PATH
|
|
|
|
|
| G_SPAWN_CHILD_INHERITS_STDIN | G_SPAWN_DO_NOT_REAP_CHILD,
|
|
|
|
|
NULL,
|
|
|
|
|
info,
|
|
|
|
|
&pid,
|
|
|
|
|
&error)) {
|
|
|
|
|
g_string_printf(info->nmc->return_text, _("Error: %s"), error->message);
|
|
|
|
|
info->nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
|
|
|
|
|
g_main_loop_quit(loop);
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
info->child_id = g_child_watch_add(pid, child_watch_cb, info);
|
|
|
|
|
info->removed_id = g_signal_connect(client,
|
|
|
|
|
"notify::" NM_CLIENT_CHECKPOINTS,
|
|
|
|
|
G_CALLBACK(checkpoints_changed_cb),
|
|
|
|
|
info);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
err:
|
|
|
|
|
free_checkpoint_info(info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
do_device_checkpoint(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
|
|
|
|
|
{
|
|
|
|
|
NMClient *client = nmc->client;
|
|
|
|
|
long unsigned int timeout = 15;
|
|
|
|
|
int option;
|
|
|
|
|
CheckpointCbInfo *info;
|
|
|
|
|
const GPtrArray *devices = NULL;
|
|
|
|
|
gs_unref_ptrarray GPtrArray *devices_free = NULL;
|
|
|
|
|
|
|
|
|
|
while ((option = next_arg(nmc, &argc, &argv, "--timeout", NULL)) > 0) {
|
|
|
|
|
switch (option) {
|
|
|
|
|
case 1: /* --timeout */
|
|
|
|
|
argc--;
|
|
|
|
|
argv++;
|
|
|
|
|
if (!argc) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: %s argument is missing."), *(argv - 1));
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (!nmc_string_to_uint(*argv, TRUE, 0, G_MAXUINT32, &timeout)) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: '%s' is not a valid timeout."), *argv);
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
nm_assert_not_reached();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (argc) {
|
|
|
|
|
if (strcmp(*argv, "--") == 0) {
|
|
|
|
|
devices = nm_client_get_devices(client);
|
|
|
|
|
argc--;
|
|
|
|
|
argv++;
|
|
|
|
|
} else {
|
|
|
|
|
devices = devices_free = get_device_list(nmc, &argc, &argv);
|
|
|
|
|
if (!devices) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: not all devices found."));
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (argc == 0) {
|
|
|
|
|
g_string_printf(nmc->return_text, _("Error: Expected a command to run after '--'"));
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nmc->complete)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
info = g_slice_new0(CheckpointCbInfo);
|
|
|
|
|
info->nmc = nmc;
|
|
|
|
|
info->argv = nm_strv_dup(argv, argc, TRUE);
|
|
|
|
|
|
|
|
|
|
nmc->should_wait++;
|
|
|
|
|
nm_client_checkpoint_create(client,
|
|
|
|
|
devices,
|
|
|
|
|
(guint32) timeout,
|
|
|
|
|
NM_CHECKPOINT_CREATE_FLAG_NONE,
|
|
|
|
|
NULL,
|
|
|
|
|
checkpoint_create_cb,
|
|
|
|
|
info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2014-05-15 12:52:26 +02:00
|
|
|
static gboolean
|
|
|
|
|
is_single_word(const char *line)
|
|
|
|
|
{
|
|
|
|
|
size_t n1, n2, n3;
|
|
|
|
|
|
|
|
|
|
n1 = strspn(line, " \t");
|
|
|
|
|
n2 = strcspn(line + n1, " \t\0") + n1;
|
|
|
|
|
n3 = strspn(line + n2, " \t");
|
|
|
|
|
|
|
|
|
|
if (n3 == 0)
|
|
|
|
|
return TRUE;
|
|
|
|
|
else
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-14 09:22:50 +02:00
|
|
|
static char **
|
2014-06-06 11:22:24 +02:00
|
|
|
nmcli_device_tab_completion(const char *text, int start, int end)
|
2014-05-14 09:22:50 +02:00
|
|
|
{
|
2021-11-09 13:28:54 +01:00
|
|
|
char **match_array = NULL;
|
2014-06-06 11:22:24 +02:00
|
|
|
rl_compentry_func_t *generator_func = NULL;
|
2014-05-15 12:52:26 +02:00
|
|
|
|
2014-05-14 09:22:50 +02:00
|
|
|
/* Disable readline's default filename completion */
|
|
|
|
|
rl_attempted_completion_over = 1;
|
2014-05-15 12:52:26 +02:00
|
|
|
|
2015-03-11 19:10:58 +01:00
|
|
|
if (g_strcmp0(rl_prompt, PROMPT_INTERFACE) == 0) {
|
|
|
|
|
/* Disable appending space after completion */
|
|
|
|
|
rl_completion_append_character = '\0';
|
2014-05-15 12:52:26 +02:00
|
|
|
|
2015-03-11 19:10:58 +01:00
|
|
|
if (!is_single_word(rl_line_buffer))
|
|
|
|
|
return NULL;
|
2014-05-15 12:52:26 +02:00
|
|
|
|
2016-09-15 01:20:53 +02:00
|
|
|
generator_func = nmc_rl_gen_func_ifnames;
|
2015-03-11 19:10:58 +01:00
|
|
|
} else if (g_strcmp0(rl_prompt, PROMPT_INTERFACES) == 0) {
|
2016-09-15 01:20:53 +02:00
|
|
|
generator_func = nmc_rl_gen_func_ifnames;
|
2015-03-11 19:10:58 +01:00
|
|
|
}
|
2014-05-15 12:52:26 +02:00
|
|
|
|
|
|
|
|
if (generator_func)
|
|
|
|
|
match_array = rl_completion_matches(text, generator_func);
|
|
|
|
|
|
|
|
|
|
return match_array;
|
2014-05-14 09:22:50 +02:00
|
|
|
}
|
|
|
|
|
|
cli: remove redundant return value from NMCCommand funcs
Many func implementations are asynchronous, that means, they
cannot return right away. Instead, they record the return value
in nmc->result_value.
The return value from the command functions was thus redundant.
In the best case, the return value agrees with the cached result
in nmc->result_value, in which it was unnecessary. In the worst case,
they disagree, and overwrite each other.
nmc->result_value is state. Tracking state is hard, and there should
be fewer places where the state gets mutated. Also, the rules how that
happened should be clearer. Drop the redundant, conflicting mechanism.
2020-04-05 15:36:30 +02:00
|
|
|
void
|
2020-04-05 13:05:58 +02:00
|
|
|
nmc_command_func_device(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
|
2010-02-25 09:52:30 -08:00
|
|
|
{
|
2020-04-05 11:47:07 +02:00
|
|
|
static const NMCCommand cmds[] = {
|
2022-05-04 09:19:01 +02:00
|
|
|
{"checkpoint", do_device_checkpoint, usage_device_checkpoint, TRUE, TRUE},
|
2020-04-05 11:47:07 +02:00
|
|
|
{"connect", do_device_connect, usage_device_connect, TRUE, TRUE},
|
|
|
|
|
{"disconnect", do_devices_disconnect, usage_device_disconnect, TRUE, TRUE},
|
|
|
|
|
{"delete", do_devices_delete, usage_device_delete, TRUE, TRUE},
|
2021-07-09 10:50:09 +02:00
|
|
|
{"down", do_devices_disconnect, usage_device_disconnect, TRUE, TRUE},
|
2020-04-05 11:47:07 +02:00
|
|
|
{"lldp", do_device_lldp, usage_device_lldp, FALSE, FALSE},
|
2021-07-09 10:50:09 +02:00
|
|
|
{"monitor", do_devices_monitor, usage_device_monitor, TRUE, TRUE},
|
2020-04-05 11:47:07 +02:00
|
|
|
{"modify", do_device_modify, usage_device_modify, TRUE, TRUE},
|
2021-07-09 10:50:09 +02:00
|
|
|
{"reapply", do_device_reapply, usage_device_reapply, TRUE, TRUE},
|
|
|
|
|
{"status", do_devices_status, usage_device_status, TRUE, TRUE},
|
|
|
|
|
{"set", do_device_set, usage_device_set, TRUE, TRUE},
|
2021-07-09 16:00:17 +02:00
|
|
|
{"show", do_device_show, usage_device_show, TRUE, TRUE},
|
2021-06-23 15:59:10 +02:00
|
|
|
{"up", do_device_connect, usage_device_connect, TRUE, TRUE},
|
2021-07-09 10:50:09 +02:00
|
|
|
{"wifi", do_device_wifi, usage_device_wifi, FALSE, FALSE},
|
2021-07-09 16:01:29 +02:00
|
|
|
{NULL, do_devices_status, usage, TRUE, TRUE},
|
2020-04-05 11:47:07 +02:00
|
|
|
};
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg(nmc, &argc, &argv, NULL);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2014-10-30 15:45:43 +01:00
|
|
|
nmc_start_polkit_agent_start_try(nmc);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2014-06-06 11:22:24 +02:00
|
|
|
rl_attempted_completion_function = (rl_completion_func_t *) nmcli_device_tab_completion;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-04-05 11:47:07 +02:00
|
|
|
nmc_do_cmd(nmc, cmds, *argv, argc, argv);
|
2010-02-25 09:52:30 -08:00
|
|
|
}
|
2015-03-27 13:07:43 +01:00
|
|
|
|
|
|
|
|
void
|
2023-02-06 16:36:47 +01:00
|
|
|
nmc_monitor_devices(NmCli *nmc)
|
2015-03-27 13:07:43 +01:00
|
|
|
{
|
2020-04-05 12:16:08 +02:00
|
|
|
do_devices_monitor(NULL, nmc, 0, NULL);
|
2015-03-27 13:07:43 +01:00
|
|
|
}
|