2019-09-10 11:19:01 +02:00
|
|
|
// SPDX-License-Identifier: GPL-2.0+
|
2019-09-25 13:13:40 +02:00
|
|
|
/*
|
2019-10-01 09:20:35 +02:00
|
|
|
* Copyright (C) 2010 - 2018 Red Hat, Inc.
|
2010-02-25 09:52:30 -08:00
|
|
|
*/
|
|
|
|
|
|
2016-02-19 14:57:48 +01:00
|
|
|
#include "nm-default.h"
|
2011-03-14 01:00:56 -05:00
|
|
|
|
2017-04-04 13:52:13 +02:00
|
|
|
#include "general.h"
|
|
|
|
|
|
2010-02-25 09:52:30 -08:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
shared: build helper "libnm-libnm-core-{intern|aux}.la" library for libnm-core
"libnm-core" implements common functionality for "NetworkManager" and
"libnm".
Note that clients like "nmcli" cannot access the internal API provided
by "libnm-core". So, if nmcli wants to do something that is also done by
"libnm-core", , "libnm", or "NetworkManager", the code would have to be
duplicated.
Instead, such code can be in "libnm-libnm-core-{intern|aux}.la".
Note that:
0) "libnm-libnm-core-intern.la" is used by libnm-core itsself.
On the other hand, "libnm-libnm-core-aux.la" is not used by
libnm-core, but provides utilities on top of it.
1) they both extend "libnm-core" with utlities that are not public
API of libnm itself. Maybe part of the code should one day become
public API of libnm. On the other hand, this is code for which
we may not want to commit to a stable interface or which we
don't want to provide as part of the API.
2) "libnm-libnm-core-intern.la" is statically linked by "libnm-core"
and thus directly available to "libnm" and "NetworkManager".
On the other hand, "libnm-libnm-core-aux.la" may be used by "libnm"
and "NetworkManager".
Both libraries may be statically linked by libnm clients (like
nmcli).
3) it must only use glib, libnm-glib-aux.la, and the public API
of libnm-core.
This is important: it must not use "libnm-core/nm-core-internal.h"
nor "libnm-core/nm-utils-private.h" so the static library is usable
by nmcli which couldn't access these.
Note that "shared/nm-meta-setting.c" is an entirely different case,
because it behaves differently depending on whether linking against
"libnm-core" or the client programs. As such, this file must be compiled
twice.
2019-04-15 09:26:53 +02:00
|
|
|
#include "nm-libnm-core-intern/nm-common-macros.h"
|
2017-03-28 12:16:31 +02:00
|
|
|
|
|
|
|
|
#include "nm-client-utils.h"
|
|
|
|
|
|
2014-10-30 15:45:43 +01:00
|
|
|
#include "polkit-agent.h"
|
2010-02-25 09:52:30 -08:00
|
|
|
#include "utils.h"
|
2016-07-06 13:34:21 +02:00
|
|
|
#include "common.h"
|
2016-07-01 21:47:01 +02:00
|
|
|
#include "common.h"
|
2015-03-27 13:07:43 +01:00
|
|
|
#include "devices.h"
|
|
|
|
|
#include "connections.h"
|
|
|
|
|
|
2017-04-06 14:43:44 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2018-12-01 15:32:55 +01:00
|
|
|
NM_UTILS_LOOKUP_STR_DEFINE_STATIC (nm_state_to_string, NMState,
|
2017-04-06 14:39:46 +02:00
|
|
|
NM_UTILS_LOOKUP_DEFAULT (N_("unknown")),
|
|
|
|
|
NM_UTILS_LOOKUP_ITEM (NM_STATE_ASLEEP, N_("asleep")),
|
|
|
|
|
NM_UTILS_LOOKUP_ITEM (NM_STATE_CONNECTING, N_("connecting")),
|
|
|
|
|
NM_UTILS_LOOKUP_ITEM (NM_STATE_CONNECTED_LOCAL, N_("connected (local only)")),
|
|
|
|
|
NM_UTILS_LOOKUP_ITEM (NM_STATE_CONNECTED_SITE, N_("connected (site only)")),
|
|
|
|
|
NM_UTILS_LOOKUP_ITEM (NM_STATE_CONNECTED_GLOBAL, N_("connected")),
|
|
|
|
|
NM_UTILS_LOOKUP_ITEM (NM_STATE_DISCONNECTING, N_("disconnecting")),
|
|
|
|
|
NM_UTILS_LOOKUP_ITEM (NM_STATE_DISCONNECTED, N_("disconnected")),
|
|
|
|
|
NM_UTILS_LOOKUP_ITEM_IGNORE (NM_STATE_UNKNOWN),
|
|
|
|
|
);
|
|
|
|
|
|
2018-03-29 12:31:33 +02:00
|
|
|
static NMMetaColor
|
2017-04-06 14:43:44 +02:00
|
|
|
state_to_color (NMState state)
|
|
|
|
|
{
|
|
|
|
|
switch (state) {
|
|
|
|
|
case NM_STATE_CONNECTING:
|
2018-03-29 12:31:33 +02:00
|
|
|
return NM_META_COLOR_STATE_CONNECTING;
|
2017-04-06 14:43:44 +02:00
|
|
|
case NM_STATE_CONNECTED_LOCAL:
|
2018-03-29 12:31:33 +02:00
|
|
|
return NM_META_COLOR_STATE_CONNECTED_LOCAL;
|
2017-04-06 14:43:44 +02:00
|
|
|
case NM_STATE_CONNECTED_SITE:
|
2018-03-29 12:31:33 +02:00
|
|
|
return NM_META_COLOR_STATE_CONNECTED_SITE;
|
2017-04-06 14:43:44 +02:00
|
|
|
case NM_STATE_CONNECTED_GLOBAL:
|
2018-03-29 12:31:33 +02:00
|
|
|
return NM_META_COLOR_STATE_CONNECTED_GLOBAL;
|
2017-04-06 14:43:44 +02:00
|
|
|
case NM_STATE_DISCONNECTING:
|
2018-03-29 12:31:33 +02:00
|
|
|
return NM_META_COLOR_STATE_DISCONNECTING;
|
2017-04-06 14:43:44 +02:00
|
|
|
case NM_STATE_ASLEEP:
|
2018-03-29 12:31:33 +02:00
|
|
|
return NM_META_COLOR_STATE_ASLEEP;
|
2017-04-06 14:43:44 +02:00
|
|
|
case NM_STATE_DISCONNECTED:
|
2018-03-29 12:31:33 +02:00
|
|
|
return NM_META_COLOR_STATE_DISCONNECTED;
|
2017-04-06 14:43:44 +02:00
|
|
|
default:
|
2018-03-29 12:31:33 +02:00
|
|
|
return NM_META_COLOR_STATE_UNKNOWN;
|
2017-04-06 14:43:44 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-29 12:31:33 +02:00
|
|
|
static NMMetaColor
|
2017-04-06 14:43:44 +02:00
|
|
|
connectivity_to_color (NMConnectivityState connectivity)
|
|
|
|
|
{
|
|
|
|
|
switch (connectivity) {
|
|
|
|
|
case NM_CONNECTIVITY_NONE:
|
2018-03-29 12:31:33 +02:00
|
|
|
return NM_META_COLOR_CONNECTIVITY_NONE;
|
2017-04-06 14:43:44 +02:00
|
|
|
case NM_CONNECTIVITY_PORTAL:
|
2018-03-29 12:31:33 +02:00
|
|
|
return NM_META_COLOR_CONNECTIVITY_PORTAL;
|
2017-04-06 14:43:44 +02:00
|
|
|
case NM_CONNECTIVITY_LIMITED:
|
2018-03-29 12:31:33 +02:00
|
|
|
return NM_META_COLOR_CONNECTIVITY_LIMITED;
|
2017-04-06 14:43:44 +02:00
|
|
|
case NM_CONNECTIVITY_FULL:
|
2018-03-29 12:31:33 +02:00
|
|
|
return NM_META_COLOR_CONNECTIVITY_FULL;
|
2017-04-06 14:43:44 +02:00
|
|
|
default:
|
2018-03-29 12:31:33 +02:00
|
|
|
return NM_META_COLOR_CONNECTIVITY_UNKNOWN;
|
2017-04-06 14:43:44 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-06 15:14:23 +02:00
|
|
|
static const char *
|
|
|
|
|
permission_to_string (NMClientPermission perm)
|
|
|
|
|
{
|
|
|
|
|
switch (perm) {
|
|
|
|
|
case NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK:
|
|
|
|
|
return NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK;
|
|
|
|
|
case NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI:
|
|
|
|
|
return NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI;
|
|
|
|
|
case NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN:
|
|
|
|
|
return NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN;
|
|
|
|
|
case NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX:
|
|
|
|
|
return NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX;
|
|
|
|
|
case NM_CLIENT_PERMISSION_SLEEP_WAKE:
|
|
|
|
|
return NM_AUTH_PERMISSION_SLEEP_WAKE;
|
|
|
|
|
case NM_CLIENT_PERMISSION_NETWORK_CONTROL:
|
|
|
|
|
return NM_AUTH_PERMISSION_NETWORK_CONTROL;
|
|
|
|
|
case NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED:
|
|
|
|
|
return NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED;
|
|
|
|
|
case NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN:
|
|
|
|
|
return NM_AUTH_PERMISSION_WIFI_SHARE_OPEN;
|
|
|
|
|
case NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM:
|
|
|
|
|
return NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM;
|
|
|
|
|
case NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN:
|
|
|
|
|
return NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN;
|
|
|
|
|
case NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME:
|
|
|
|
|
return NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME;
|
|
|
|
|
case NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS:
|
|
|
|
|
return NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS;
|
|
|
|
|
case NM_CLIENT_PERMISSION_RELOAD:
|
|
|
|
|
return NM_AUTH_PERMISSION_RELOAD;
|
|
|
|
|
case NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK:
|
|
|
|
|
return NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK;
|
|
|
|
|
case NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS:
|
|
|
|
|
return NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS;
|
2017-08-17 23:09:07 +02:00
|
|
|
case NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK:
|
|
|
|
|
return NM_AUTH_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK;
|
2019-01-25 14:33:11 +08:00
|
|
|
case NM_CLIENT_PERMISSION_WIFI_SCAN:
|
|
|
|
|
return NM_AUTH_PERMISSION_WIFI_SCAN;
|
2017-04-06 15:14:23 +02:00
|
|
|
default:
|
|
|
|
|
return _("unknown");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-01 15:32:55 +01:00
|
|
|
NM_UTILS_LOOKUP_STR_DEFINE_STATIC (permission_result_to_string, NMClientPermissionResult,
|
2017-04-06 15:14:23 +02:00
|
|
|
NM_UTILS_LOOKUP_DEFAULT (N_("unknown")),
|
|
|
|
|
NM_UTILS_LOOKUP_ITEM (NM_CLIENT_PERMISSION_RESULT_YES, N_("yes")),
|
|
|
|
|
NM_UTILS_LOOKUP_ITEM (NM_CLIENT_PERMISSION_RESULT_NO, N_("no")),
|
|
|
|
|
NM_UTILS_LOOKUP_ITEM (NM_CLIENT_PERMISSION_RESULT_AUTH, N_("auth")),
|
|
|
|
|
NM_UTILS_LOOKUP_ITEM_IGNORE (NM_CLIENT_PERMISSION_RESULT_UNKNOWN),
|
|
|
|
|
);
|
|
|
|
|
|
2018-03-29 12:31:33 +02:00
|
|
|
_NM_UTILS_LOOKUP_DEFINE (static, permission_result_to_color, NMClientPermissionResult, NMMetaColor,
|
|
|
|
|
NM_UTILS_LOOKUP_DEFAULT (NM_META_COLOR_PERMISSION_UNKNOWN),
|
|
|
|
|
NM_UTILS_LOOKUP_ITEM (NM_CLIENT_PERMISSION_RESULT_YES, NM_META_COLOR_PERMISSION_YES),
|
|
|
|
|
NM_UTILS_LOOKUP_ITEM (NM_CLIENT_PERMISSION_RESULT_NO, NM_META_COLOR_PERMISSION_NO),
|
|
|
|
|
NM_UTILS_LOOKUP_ITEM (NM_CLIENT_PERMISSION_RESULT_AUTH, NM_META_COLOR_PERMISSION_AUTH),
|
2017-04-06 15:14:23 +02:00
|
|
|
NM_UTILS_LOOKUP_ITEM_IGNORE (NM_CLIENT_PERMISSION_RESULT_UNKNOWN),
|
|
|
|
|
);
|
|
|
|
|
|
2017-04-06 14:43:44 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-04-04 15:23:39 +02:00
|
|
|
static const NmcMetaGenericInfo *const metagen_general_status[];
|
|
|
|
|
|
|
|
|
|
static gconstpointer
|
2018-04-27 11:10:13 +02:00
|
|
|
_metagen_general_status_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS)
|
2017-04-04 15:23:39 +02:00
|
|
|
{
|
|
|
|
|
NmCli *nmc = target;
|
|
|
|
|
const char *value;
|
|
|
|
|
gboolean v_bool;
|
|
|
|
|
NMState state;
|
|
|
|
|
NMConnectivityState connectivity;
|
|
|
|
|
|
|
|
|
|
switch (info->info_type) {
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_RUNNING:
|
2018-03-29 12:31:33 +02:00
|
|
|
NMC_HANDLE_COLOR (NM_META_COLOR_NONE);
|
2017-04-04 15:23:39 +02:00
|
|
|
value = N_("running");
|
|
|
|
|
goto translate_and_out;
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_VERSION:
|
2018-03-29 12:31:33 +02:00
|
|
|
NMC_HANDLE_COLOR (NM_META_COLOR_NONE);
|
2017-04-04 15:23:39 +02:00
|
|
|
value = nm_client_get_version (nmc->client);
|
|
|
|
|
goto clone_and_out;
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_STATE:
|
|
|
|
|
state = nm_client_get_state (nmc->client);
|
2018-03-29 12:31:33 +02:00
|
|
|
NMC_HANDLE_COLOR (state_to_color (state));
|
2018-12-01 15:32:55 +01:00
|
|
|
value = nm_state_to_string (state);
|
2017-04-04 15:23:39 +02:00
|
|
|
goto translate_and_out;
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_STARTUP:
|
|
|
|
|
v_bool = nm_client_get_startup (nmc->client);
|
2018-03-29 12:31:33 +02:00
|
|
|
NMC_HANDLE_COLOR (v_bool ? NM_META_COLOR_MANAGER_STARTING : NM_META_COLOR_MANAGER_RUNNING);
|
2017-04-04 15:23:39 +02:00
|
|
|
value = v_bool ? N_("starting") : N_("started");
|
|
|
|
|
goto translate_and_out;
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_CONNECTIVITY:
|
|
|
|
|
connectivity = nm_client_get_connectivity (nmc->client);
|
2018-03-29 12:31:33 +02:00
|
|
|
NMC_HANDLE_COLOR (connectivity_to_color (connectivity));
|
2018-12-01 15:32:55 +01:00
|
|
|
value = nm_connectivity_to_string (connectivity);
|
2017-04-04 15:23:39 +02:00
|
|
|
goto translate_and_out;
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_NETWORKING:
|
|
|
|
|
v_bool = nm_client_networking_get_enabled (nmc->client);
|
|
|
|
|
goto enabled_out;
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIFI_HW:
|
|
|
|
|
v_bool = nm_client_wireless_hardware_get_enabled (nmc->client);
|
|
|
|
|
goto enabled_out;
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIFI:
|
|
|
|
|
v_bool = nm_client_wireless_get_enabled (nmc->client);
|
|
|
|
|
goto enabled_out;
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WWAN_HW:
|
|
|
|
|
v_bool = nm_client_wwan_hardware_get_enabled (nmc->client);
|
|
|
|
|
goto enabled_out;
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WWAN:
|
|
|
|
|
v_bool = nm_client_wwan_get_enabled (nmc->client);
|
|
|
|
|
goto enabled_out;
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIMAX_HW:
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIMAX:
|
2018-09-14 23:49:20 -04:00
|
|
|
/* deprecated fields. Don't return anything. */
|
2017-04-04 15:23:39 +02:00
|
|
|
return NULL;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_return_val_if_reached (NULL);
|
|
|
|
|
|
|
|
|
|
enabled_out:
|
2018-03-29 12:31:33 +02:00
|
|
|
NMC_HANDLE_COLOR (v_bool ? NM_META_COLOR_ENABLED : NM_META_COLOR_DISABLED);
|
2017-04-04 15:23:39 +02:00
|
|
|
value = v_bool ? N_("enabled") : N_("disabled");
|
|
|
|
|
goto translate_and_out;
|
|
|
|
|
|
|
|
|
|
clone_and_out:
|
|
|
|
|
return (*out_to_free = g_strdup (value));
|
|
|
|
|
|
|
|
|
|
translate_and_out:
|
|
|
|
|
if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY)
|
|
|
|
|
return _(value);
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const NmcMetaGenericInfo *const metagen_general_status[_NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_NUM + 1] = {
|
|
|
|
|
#define _METAGEN_GENERAL_STATUS(type, name) \
|
|
|
|
|
[type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_general_status_get_fcn)
|
|
|
|
|
_METAGEN_GENERAL_STATUS (NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_RUNNING, "RUNNING"),
|
|
|
|
|
_METAGEN_GENERAL_STATUS (NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_VERSION, "VERSION"),
|
|
|
|
|
_METAGEN_GENERAL_STATUS (NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_STATE, "STATE"),
|
|
|
|
|
_METAGEN_GENERAL_STATUS (NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_STARTUP, "STARTUP"),
|
|
|
|
|
_METAGEN_GENERAL_STATUS (NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_CONNECTIVITY, "CONNECTIVITY"),
|
|
|
|
|
_METAGEN_GENERAL_STATUS (NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_NETWORKING, "NETWORKING"),
|
|
|
|
|
_METAGEN_GENERAL_STATUS (NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIFI_HW, "WIFI-HW"),
|
|
|
|
|
_METAGEN_GENERAL_STATUS (NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIFI, "WIFI"),
|
|
|
|
|
_METAGEN_GENERAL_STATUS (NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WWAN_HW, "WWAN-HW"),
|
|
|
|
|
_METAGEN_GENERAL_STATUS (NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WWAN, "WWAN"),
|
|
|
|
|
_METAGEN_GENERAL_STATUS (NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIMAX_HW, "WIMAX-HW"),
|
|
|
|
|
_METAGEN_GENERAL_STATUS (NMC_GENERIC_INFO_TYPE_GENERAL_STATUS_WIMAX, "WIMAX"),
|
2010-03-19 14:53:08 +01:00
|
|
|
};
|
2013-09-12 16:23:15 +02:00
|
|
|
#define NMC_FIELDS_NM_STATUS_ALL "RUNNING,VERSION,STATE,STARTUP,CONNECTIVITY,NETWORKING,WIFI-HW,WIFI,WWAN-HW,WWAN"
|
2012-12-12 13:03:12 +01:00
|
|
|
#define NMC_FIELDS_NM_STATUS_SWITCH "NETWORKING,WIFI-HW,WIFI,WWAN-HW,WWAN"
|
2013-02-28 14:53:11 +01:00
|
|
|
#define NMC_FIELDS_NM_STATUS_RADIO "WIFI-HW,WIFI,WWAN-HW,WWAN"
|
2013-08-28 10:06:54 -04:00
|
|
|
#define NMC_FIELDS_NM_STATUS_COMMON "STATE,CONNECTIVITY,WIFI-HW,WIFI,WWAN-HW,WWAN"
|
2012-12-10 19:11:04 +01:00
|
|
|
#define NMC_FIELDS_NM_NETWORKING "NETWORKING"
|
2010-03-19 14:53:08 +01:00
|
|
|
#define NMC_FIELDS_NM_WIFI "WIFI"
|
|
|
|
|
#define NMC_FIELDS_NM_WWAN "WWAN"
|
2011-01-06 17:01:55 -06:00
|
|
|
#define NMC_FIELDS_NM_WIMAX "WIMAX"
|
2013-08-28 10:06:54 -04:00
|
|
|
#define NMC_FIELDS_NM_CONNECTIVITY "CONNECTIVITY"
|
2010-03-19 14:53:08 +01:00
|
|
|
|
2017-04-06 15:14:23 +02:00
|
|
|
/*****************************************************************************/
|
2012-12-10 19:11:04 +01:00
|
|
|
|
2017-04-06 15:14:23 +02:00
|
|
|
static gconstpointer
|
2018-04-27 11:10:13 +02:00
|
|
|
_metagen_general_permissions_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS)
|
2017-04-06 15:14:23 +02:00
|
|
|
{
|
|
|
|
|
NMClientPermission perm = GPOINTER_TO_UINT (target);
|
|
|
|
|
NmCli *nmc = environment_user_data;
|
|
|
|
|
NMClientPermissionResult perm_result;
|
|
|
|
|
const char *s;
|
|
|
|
|
|
|
|
|
|
switch (info->info_type) {
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_GENERAL_PERMISSIONS_PERMISSION:
|
2018-03-29 12:31:33 +02:00
|
|
|
NMC_HANDLE_COLOR (NM_META_COLOR_NONE);
|
2017-04-06 15:14:23 +02:00
|
|
|
return permission_to_string (perm);
|
|
|
|
|
case NMC_GENERIC_INFO_TYPE_GENERAL_PERMISSIONS_VALUE:
|
|
|
|
|
perm_result = nm_client_get_permission_result (nmc->client, perm);
|
2018-03-29 12:31:33 +02:00
|
|
|
NMC_HANDLE_COLOR (permission_result_to_color (perm_result));
|
2018-12-01 15:32:55 +01:00
|
|
|
s = permission_result_to_string (perm_result);
|
2017-04-06 15:14:23 +02:00
|
|
|
if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY)
|
|
|
|
|
return _(s);
|
|
|
|
|
return s;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_return_val_if_reached (NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const NmcMetaGenericInfo *const metagen_general_permissions[_NMC_GENERIC_INFO_TYPE_GENERAL_PERMISSIONS_NUM + 1] = {
|
|
|
|
|
#define _METAGEN_GENERAL_PERMISSIONS(type, name) \
|
|
|
|
|
[type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_general_permissions_get_fcn)
|
|
|
|
|
_METAGEN_GENERAL_PERMISSIONS (NMC_GENERIC_INFO_TYPE_GENERAL_PERMISSIONS_PERMISSION, "PERMISSION"),
|
|
|
|
|
_METAGEN_GENERAL_PERMISSIONS (NMC_GENERIC_INFO_TYPE_GENERAL_PERMISSIONS_VALUE, "VALUE"),
|
2012-04-30 11:50:26 +02:00
|
|
|
};
|
2017-04-06 15:14:23 +02:00
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
2012-04-30 11:50:26 +02:00
|
|
|
|
2017-04-06 15:14:23 +02:00
|
|
|
typedef struct {
|
|
|
|
|
bool initialized;
|
|
|
|
|
char **level;
|
|
|
|
|
char **domains;
|
|
|
|
|
} GetGeneralLoggingData;
|
|
|
|
|
|
|
|
|
|
static gconstpointer
|
2018-04-27 11:10:13 +02:00
|
|
|
_metagen_general_logging_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS)
|
2017-04-06 15:14:23 +02:00
|
|
|
{
|
|
|
|
|
NmCli *nmc = environment_user_data;
|
|
|
|
|
GetGeneralLoggingData *d = target;
|
|
|
|
|
|
|
|
|
|
nm_assert (info->info_type < _NMC_GENERIC_INFO_TYPE_GENERAL_LOGGING_NUM);
|
|
|
|
|
|
2018-03-29 12:31:33 +02:00
|
|
|
NMC_HANDLE_COLOR (NM_META_COLOR_NONE);
|
2017-04-06 15:14:23 +02:00
|
|
|
|
|
|
|
|
if (!d->initialized) {
|
|
|
|
|
d->initialized = TRUE;
|
|
|
|
|
if (!nm_client_get_logging (nmc->client,
|
|
|
|
|
d->level,
|
|
|
|
|
d->domains,
|
|
|
|
|
NULL))
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (info->info_type == NMC_GENERIC_INFO_TYPE_GENERAL_LOGGING_LEVEL)
|
|
|
|
|
return *d->level;
|
|
|
|
|
else
|
|
|
|
|
return *d->domains;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const NmcMetaGenericInfo *const metagen_general_logging[_NMC_GENERIC_INFO_TYPE_GENERAL_LOGGING_NUM + 1] = {
|
|
|
|
|
#define _METAGEN_GENERAL_LOGGING(type, name) \
|
|
|
|
|
[type] = NMC_META_GENERIC(name, .info_type = type, .get_fcn = _metagen_general_logging_get_fcn)
|
|
|
|
|
_METAGEN_GENERAL_LOGGING (NMC_GENERIC_INFO_TYPE_GENERAL_LOGGING_LEVEL, "LEVEL"),
|
|
|
|
|
_METAGEN_GENERAL_LOGGING (NMC_GENERIC_INFO_TYPE_GENERAL_LOGGING_DOMAINS, "DOMAINS"),
|
2012-12-12 14:23:54 +01:00
|
|
|
};
|
|
|
|
|
|
2017-04-06 15:14:23 +02:00
|
|
|
/*****************************************************************************/
|
2012-04-30 11:50:26 +02:00
|
|
|
|
2010-02-25 09:52:30 -08:00
|
|
|
static void
|
2012-12-10 19:11:04 +01:00
|
|
|
usage_general (void)
|
2010-02-25 09:52:30 -08:00
|
|
|
{
|
2014-09-19 16:04:40 -04:00
|
|
|
g_printerr (_("Usage: nmcli general { COMMAND | help }\n\n"
|
|
|
|
|
"COMMAND := { status | hostname | permissions | logging }\n\n"
|
|
|
|
|
" status\n\n"
|
|
|
|
|
" hostname [<hostname>]\n\n"
|
|
|
|
|
" permissions\n\n"
|
|
|
|
|
" logging [level <log level>] [domains <log domains>]\n\n"));
|
2013-12-18 14:49:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
usage_general_status (void)
|
|
|
|
|
{
|
2014-09-19 16:04:40 -04:00
|
|
|
g_printerr (_("Usage: nmcli general status { help }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Show overall status of NetworkManager.\n"
|
|
|
|
|
"'status' is the default action, which means 'nmcli gen' calls 'nmcli gen status'\n\n"));
|
2013-12-18 14:49:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
usage_general_hostname (void)
|
|
|
|
|
{
|
2014-09-19 16:04:40 -04:00
|
|
|
g_printerr (_("Usage: nmcli general hostname { ARGUMENTS | help }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"ARGUMENTS := [<hostname>]\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Get or change persistent system hostname.\n"
|
|
|
|
|
"With no arguments, this prints currently configured hostname. When you pass\n"
|
|
|
|
|
"a hostname, NetworkManager will set it as the new persistent system hostname.\n\n"));
|
2013-12-18 14:49:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
usage_general_permissions (void)
|
|
|
|
|
{
|
2014-09-19 16:04:40 -04:00
|
|
|
g_printerr (_("Usage: nmcli general permissions { help }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Show caller permissions for authenticated operations.\n\n"));
|
2013-12-18 14:49:06 +01:00
|
|
|
}
|
|
|
|
|
|
2019-09-05 18:32:57 +02:00
|
|
|
static void
|
|
|
|
|
usage_general_reload (void)
|
|
|
|
|
{
|
|
|
|
|
g_printerr (_("Usage: nmcli general reload { ARGUMENTS | help }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"ARGUMENTS := [<flag>[,<flag>...]]\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Reload NetworkManager's configuration and perform certain updates, like\n"
|
|
|
|
|
"flushing caches or rewriting external state to disk. This is similar to\n"
|
|
|
|
|
"sending SIGHUP to NetworkManager but it allows for more fine-grained\n"
|
|
|
|
|
"control over what to reload through the flags argument. It also allows\n"
|
|
|
|
|
"non-root access via PolicyKit and contrary to signals it is synchronous.\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Available flags are:\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" 'conf' Reload the NetworkManager.conf configuration from\n"
|
|
|
|
|
" disk. Note that this does not include connections, which\n"
|
|
|
|
|
" can be reloaded through 'nmcli connection reload' instead.\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" 'dns-rc' Update DNS configuration, which usually involves writing\n"
|
|
|
|
|
" /etc/resolv.conf anew.\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" 'dns-full' Restart the DNS plugin. This is for example useful when\n"
|
|
|
|
|
" using dnsmasq plugin, which uses additional configuration\n"
|
|
|
|
|
" in /etc/NetworkManager/dnsmasq.d. If you edit those files,\n"
|
|
|
|
|
" you can restart the DNS plugin. This action shortly\n"
|
|
|
|
|
" interrupts name resolution.\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"With no flags, everything that is supported is reloaded, which is\n"
|
|
|
|
|
"identical to sending a SIGHUP.\n"));
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-18 14:49:06 +01:00
|
|
|
static void
|
|
|
|
|
usage_general_logging (void)
|
|
|
|
|
{
|
2014-09-19 16:04:40 -04:00
|
|
|
g_printerr (_("Usage: nmcli general logging { ARGUMENTS | help }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"ARGUMENTS := [level <log level>] [domains <log domains>]\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Get or change NetworkManager logging level and domains.\n"
|
|
|
|
|
"Without any argument current logging level and domains are shown. In order to\n"
|
|
|
|
|
"change logging state, provide level and/or domain. Please refer to the man page\n"
|
|
|
|
|
"for the list of possible logging domains.\n\n"));
|
2012-12-10 19:11:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2013-02-28 14:53:11 +01:00
|
|
|
usage_networking (void)
|
2012-12-10 19:11:04 +01:00
|
|
|
{
|
2014-09-19 16:04:40 -04:00
|
|
|
g_printerr (_("Usage: nmcli networking { COMMAND | help }\n\n"
|
|
|
|
|
"COMMAND := { [ on | off | connectivity ] }\n\n"
|
|
|
|
|
" on\n\n"
|
|
|
|
|
" off\n\n"
|
|
|
|
|
" connectivity [check]\n\n"));
|
2013-12-18 14:49:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
usage_networking_on (void)
|
|
|
|
|
{
|
2014-09-19 16:04:40 -04:00
|
|
|
g_printerr (_("Usage: nmcli networking on { help }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Switch networking on.\n\n"));
|
2013-12-18 14:49:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
usage_networking_off (void)
|
|
|
|
|
{
|
2014-09-19 16:04:40 -04:00
|
|
|
g_printerr (_("Usage: nmcli networking off { help }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Switch networking off.\n\n"));
|
2013-12-18 14:49:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
usage_networking_connectivity (void)
|
|
|
|
|
{
|
2014-09-19 16:04:40 -04:00
|
|
|
g_printerr (_("Usage: nmcli networking connectivity { ARGUMENTS | help }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"ARGUMENTS := [check]\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Get network connectivity state.\n"
|
|
|
|
|
"The optional 'check' argument makes NetworkManager re-check the connectivity.\n\n"));
|
2013-12-18 14:49:06 +01:00
|
|
|
|
2013-02-28 14:53:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
usage_radio (void)
|
|
|
|
|
{
|
2014-09-19 16:04:40 -04:00
|
|
|
g_printerr (_("Usage: nmcli radio { COMMAND | help }\n\n"
|
|
|
|
|
"COMMAND := { all | wifi | wwan }\n\n"
|
|
|
|
|
" all | wifi | wwan [ on | off ]\n\n"
|
|
|
|
|
));
|
2010-02-25 09:52:30 -08:00
|
|
|
}
|
|
|
|
|
|
2013-12-18 14:49:06 +01:00
|
|
|
static void
|
|
|
|
|
usage_radio_all (void)
|
|
|
|
|
{
|
2014-09-19 16:04:40 -04:00
|
|
|
g_printerr (_("Usage: nmcli radio all { ARGUMENTS | help }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"ARGUMENTS := [on | off]\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Get status of all radio switches, or turn them on/off.\n\n"));
|
2013-12-18 14:49:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
usage_radio_wifi (void)
|
|
|
|
|
{
|
2014-09-19 16:04:40 -04:00
|
|
|
g_printerr (_("Usage: nmcli radio wifi { ARGUMENTS | help }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"ARGUMENTS := [on | off]\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Get status of Wi-Fi radio switch, or turn it on/off.\n\n"));
|
2013-12-18 14:49:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
usage_radio_wwan (void)
|
|
|
|
|
{
|
2014-09-19 16:04:40 -04:00
|
|
|
g_printerr (_("Usage: nmcli radio wwan { ARGUMENTS | help }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"ARGUMENTS := [on | off]\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Get status of mobile broadband radio switch, or turn it on/off.\n\n"));
|
2013-12-18 14:49:06 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-27 13:07:43 +01:00
|
|
|
static void
|
|
|
|
|
usage_monitor (void)
|
|
|
|
|
{
|
|
|
|
|
g_printerr (_("Usage: nmcli monitor\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Monitor NetworkManager changes.\n"
|
|
|
|
|
"Prints a line whenever a change occurs in NetworkManager\n\n"));
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-25 09:52:30 -08:00
|
|
|
static void
|
|
|
|
|
quit (void)
|
|
|
|
|
{
|
2017-04-06 19:39:36 +02:00
|
|
|
g_main_loop_quit (loop);
|
2010-02-25 09:52:30 -08:00
|
|
|
}
|
|
|
|
|
|
2012-12-10 19:11:04 +01:00
|
|
|
static gboolean
|
2013-04-18 15:07:21 +02:00
|
|
|
show_nm_status (NmCli *nmc, const char *pretty_header_name, const char *print_flds)
|
2010-02-25 09:52:30 -08:00
|
|
|
{
|
2017-04-04 15:23:39 +02:00
|
|
|
gs_free_error GError *error = NULL;
|
2010-03-19 14:53:08 +01:00
|
|
|
const char *fields_str;
|
2018-04-24 11:20:03 +02:00
|
|
|
const char *fields_all = print_flds ?: NMC_FIELDS_NM_STATUS_ALL;
|
|
|
|
|
const char *fields_common = print_flds ?: NMC_FIELDS_NM_STATUS_COMMON;
|
2010-02-25 09:52:30 -08:00
|
|
|
|
2010-03-19 14:53:08 +01:00
|
|
|
if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0)
|
|
|
|
|
fields_str = fields_common;
|
|
|
|
|
else if (!nmc->required_fields || strcasecmp (nmc->required_fields, "all") == 0)
|
|
|
|
|
fields_str = fields_all;
|
2012-04-28 22:54:02 +02:00
|
|
|
else
|
2010-03-19 14:53:08 +01:00
|
|
|
fields_str = nmc->required_fields;
|
|
|
|
|
|
2017-04-04 15:23:39 +02:00
|
|
|
if (!nmc_print (&nmc->nmc_config,
|
|
|
|
|
(gpointer[]) { nmc, NULL },
|
2018-04-30 13:01:20 +02:00
|
|
|
NULL,
|
2017-04-04 15:23:39 +02:00
|
|
|
pretty_header_name ?: N_("NetworkManager status"),
|
|
|
|
|
(const NMMetaAbstractInfo *const*) metagen_general_status,
|
|
|
|
|
fields_str,
|
|
|
|
|
&error)) {
|
2013-12-10 12:00:53 +01:00
|
|
|
g_string_printf (nmc->return_text, _("Error: only these fields are allowed: %s"), fields_all);
|
2010-03-24 13:42:47 +01:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
2012-12-10 19:11:04 +01:00
|
|
|
return FALSE;
|
2010-03-19 14:53:08 +01:00
|
|
|
}
|
2012-12-10 19:11:04 +01:00
|
|
|
return TRUE;
|
2010-02-25 09:52:30 -08:00
|
|
|
}
|
|
|
|
|
|
2016-07-06 13:34:21 +02:00
|
|
|
static NMCResultCode
|
|
|
|
|
do_general_status (NmCli *nmc, int argc, char **argv)
|
|
|
|
|
{
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg (nmc, &argc, &argv, NULL);
|
2016-07-06 14:43:13 +02:00
|
|
|
if (nmc->complete)
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
|
2016-07-06 13:34:21 +02:00
|
|
|
show_nm_status (nmc, NULL, NULL);
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-10 19:11:04 +01:00
|
|
|
static gboolean
|
2016-10-19 10:08:46 +02:00
|
|
|
timeout_cb (gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
print_permissions (void *user_data)
|
2012-04-30 11:50:26 +02:00
|
|
|
{
|
2016-10-19 10:08:46 +02:00
|
|
|
NmCli *nmc = user_data;
|
2017-04-06 15:14:23 +02:00
|
|
|
gs_free_error GError *error = NULL;
|
|
|
|
|
const char *fields_str = NULL;
|
2012-04-30 11:50:26 +02:00
|
|
|
NMClientPermission perm;
|
2017-04-06 15:14:23 +02:00
|
|
|
guint i;
|
|
|
|
|
gpointer permissions[NM_CLIENT_PERMISSION_LAST + 1];
|
2012-04-30 11:50:26 +02:00
|
|
|
|
2017-04-06 15:14:23 +02:00
|
|
|
if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0) {
|
|
|
|
|
} else if (strcasecmp (nmc->required_fields, "all") == 0) {
|
|
|
|
|
} else
|
2012-04-30 11:50:26 +02:00
|
|
|
fields_str = nmc->required_fields;
|
|
|
|
|
|
2017-04-06 15:14:23 +02:00
|
|
|
for (i = 0, perm = NM_CLIENT_PERMISSION_NONE + 1; perm <= NM_CLIENT_PERMISSION_LAST; perm++)
|
|
|
|
|
permissions[i++] = GINT_TO_POINTER (perm);
|
|
|
|
|
permissions[i++] = NULL;
|
2012-04-30 11:50:26 +02:00
|
|
|
|
2018-10-09 13:08:24 +02:00
|
|
|
nm_cli_spawn_pager (nmc);
|
2018-06-11 10:16:37 +02:00
|
|
|
|
2017-04-06 15:14:23 +02:00
|
|
|
if (!nmc_print (&nmc->nmc_config,
|
|
|
|
|
permissions,
|
2018-04-30 13:01:20 +02:00
|
|
|
NULL,
|
2017-04-06 15:14:23 +02:00
|
|
|
_("NetworkManager permissions"),
|
|
|
|
|
(const NMMetaAbstractInfo *const*) metagen_general_permissions,
|
|
|
|
|
fields_str,
|
|
|
|
|
&error)) {
|
2013-12-10 12:00:53 +01:00
|
|
|
g_string_printf (nmc->return_text, _("Error: 'general permissions': %s"), error->message);
|
2012-04-30 11:50:26 +02:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-19 10:08:46 +02:00
|
|
|
quit ();
|
|
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
got_permissions (NmCli *nmc)
|
|
|
|
|
{
|
|
|
|
|
NMClientPermission perm;
|
|
|
|
|
|
|
|
|
|
/* The server returns all the permissions at once, so if at least one is there
|
core: also return unknown permission check result
For example with
mount -o remount,rw,hidepid=1 /proc/
all permission checks will fail with an error. Internally, we map the
failure to NM_AUTH_CALL_RESULT_UNKNOWN.
<trace> [1575645672.5958] auth: call[1069]: CheckAuthorization(org.freedesktop.NetworkManager.enable-disable-connectivity-check), subject=unix-process[pid=468316, uid=1000, start=1912881]
<trace> [1575645672.6295] auth: call[1069]: completed: failed: GDBus.Error:org.gtk.GDBus.UnmappedGError.Quark._g_2dfile_2derror_2dquark.Code4: Failed to open file “/proc/468316/status”: No such file or directory
<debug> [1575645672.6296] manager: unknown auth chain result 0
First of all, we should not log a debug message about that (we already log the
result of permission checks separately).
Also, we should include the unknown result in the response. The permission was
checked, and omitting it from GetPermissions() result seems wrong (even if we
failed to get the result).
Note that "unknown" is now a new possible return value on D-Bus. But
see how nm_permission_result_to_client() would map such a value to
"unknown" as well. So, it's probably a fine extension of the D-Bus API.
Note that NMClient API is currently quite limited. The user won't know
whether permissions were received (and if they were received, they
could not distinguish between UNKNOWN and absent). Hence, returning
all permissions as unknown (or not at all) causes `nmcli general permissions`
to hang. The solution here is to improve NMClient API to allow the user
to know when the permissions are received. But this patch doesn't
fix the hanging of nmcli nor the limitation of NMClient's API.
2019-12-05 13:54:27 +01:00
|
|
|
* we already received the reply.
|
|
|
|
|
*
|
|
|
|
|
* FIXME: this is wrong, because all permissions could be unknown. We should instead
|
|
|
|
|
* have a signal in NMClient to indicate when permissions are received. */
|
2016-10-19 10:08:46 +02:00
|
|
|
for (perm = NM_CLIENT_PERMISSION_NONE + 1; perm <= NM_CLIENT_PERMISSION_LAST; perm++) {
|
|
|
|
|
if (nm_client_get_permission_result (nmc->client, perm) != NM_CLIENT_PERMISSION_RESULT_UNKNOWN)
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
permission_changed (NMClient *client,
|
|
|
|
|
NMClientPermission permission,
|
|
|
|
|
NMClientPermissionResult result,
|
|
|
|
|
NmCli *nmc)
|
|
|
|
|
{
|
|
|
|
|
if (got_permissions (nmc)) {
|
|
|
|
|
/* Defer the printing, so that we have a chance to process the other
|
|
|
|
|
* permission-changed signals. */
|
cli: unsubscribe permission signal from NMClient on exit
During the libnm rework, we might still emit permissions changed
signal while destructing the instance. That triggers an assertion.
Backtrace, with a different libnm:
#0 _g_log_abort (breakpoint=1) at ../glib/gmessages.c:554
#1 0x00007ffff77d09b6 in g_logv (log_domain=0x7ffff7f511cd "libnm", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=args@entry=0x7fffffffcb80) at ../glib/gmessages.c:1373
#2 0x00007ffff77d0b83 in g_log
(log_domain=log_domain@entry=0x7ffff7f511cd "libnm", log_level=log_level@entry=G_LOG_LEVEL_CRITICAL, format=format@entry=0x7ffff78215df "%s: assertion '%s' failed")
at ../glib/gmessages.c:1415
#3 0x00007ffff77d137d in g_return_if_fail_warning
(log_domain=log_domain@entry=0x7ffff7f511cd "libnm", pretty_function=pretty_function@entry=0x7ffff7f58aa0 <__func__.40223> "nm_client_get_permission_result", expression=expression@entry=0x7ffff7f54830 "NM_IS_CLIENT (client)") at ../glib/gmessages.c:2771
#4 0x00007ffff7e9de9a in nm_client_get_permission_result (client=0x0, permission=permission@entry=NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK) at libnm/nm-client.c:3816
#5 0x0000555555593ba3 in got_permissions (nmc=nmc@entry=0x55555562ec20 <nm_cli>) at clients/cli/general.c:587
#6 0x0000555555593bcb in permission_changed (client=<optimized out>, permission=<optimized out>, result=<optimized out>, nmc=0x55555562ec20 <nm_cli>) at clients/cli/general.c:600
#7 0x00007ffff73b1aa8 in ffi_call_unix64 () at ../src/x86/unix64.S:76
#8 0x00007ffff73b12a4 in ffi_call (cif=cif@entry=0x7fffffffced0, fn=fn@entry=0x555555593bbf <permission_changed>, rvalue=<optimized out>, avalue=avalue@entry=0x7fffffffcde0)
at ../src/x86/ffi64.c:525
#9 0x00007ffff78b4746 in g_cclosure_marshal_generic_va
(closure=<optimized out>, return_value=<optimized out>, instance=<optimized out>, args_list=<optimized out>, marshal_data=<optimized out>, n_params=<optimized out>, param_types=<optimized out>) at ../gobject/gclosure.c:1614
#10 0x00007ffff78b3996 in _g_closure_invoke_va (closure=0x5555556f4330, return_value=0x0, instance=0x55555565a020, args=0x7fffffffd180, n_params=2, param_types=0x555555656f00)
at ../gobject/gclosure.c:873
#11 0x00007ffff78d0228 in g_signal_emit_valist (instance=0x55555565a020, signal_id=<optimized out>, detail=0, var_args=var_args@entry=0x7fffffffd180) at ../gobject/gsignal.c:3306
#12 0x00007ffff78d09d3 in g_signal_emit (instance=instance@entry=0x55555565a020, signal_id=<optimized out>, detail=detail@entry=0) at ../gobject/gsignal.c:3453
#13 0x00007ffff7e8989a in _emit_permissions_changed (self=self@entry=0x55555565a020, permissions=permissions@entry=0x555555690e40 = {...}, force_unknown=force_unknown@entry=1)
at libnm/nm-client.c:2874
#14 0x00007ffff7e9a0c9 in _init_release_all (self=self@entry=0x55555565a020) at libnm/nm-client.c:6092
#15 0x00007ffff7e9bcde in dispose (object=0x55555565a020 [NMClient]) at libnm/nm-client.c:6838
#16 0x00007ffff78b8c28 in g_object_unref (_object=<optimized out>) at ../gobject/gobject.c:3344
#17 g_object_unref (_object=0x55555565a020) at ../gobject/gobject.c:3274
#18 0x00005555555badcf in nmc_cleanup (nmc=0x55555562ec20 <nm_cli>) at clients/cli/nmcli.c:924
#19 0x00005555555bbea7 in main (argc=<optimized out>, argv=0x7fffffffd498) at clients/cli/nmcli.c:987
2019-11-01 12:59:03 +01:00
|
|
|
g_signal_handlers_disconnect_by_func (nmc->client,
|
|
|
|
|
G_CALLBACK (permission_changed),
|
|
|
|
|
nmc);
|
2016-10-19 10:08:46 +02:00
|
|
|
g_idle_remove_by_data (nmc);
|
|
|
|
|
g_idle_add (print_permissions, nmc);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
show_nm_permissions (NmCli *nmc)
|
|
|
|
|
{
|
|
|
|
|
/* The permissions are available now, just print them. */
|
|
|
|
|
if (got_permissions (nmc)) {
|
|
|
|
|
print_permissions (nmc);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The client didn't get the permissions reply yet. Subscribe to changes. */
|
|
|
|
|
g_signal_connect (nmc->client, NM_CLIENT_PERMISSION_CHANGED,
|
cli: unsubscribe permission signal from NMClient on exit
During the libnm rework, we might still emit permissions changed
signal while destructing the instance. That triggers an assertion.
Backtrace, with a different libnm:
#0 _g_log_abort (breakpoint=1) at ../glib/gmessages.c:554
#1 0x00007ffff77d09b6 in g_logv (log_domain=0x7ffff7f511cd "libnm", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=args@entry=0x7fffffffcb80) at ../glib/gmessages.c:1373
#2 0x00007ffff77d0b83 in g_log
(log_domain=log_domain@entry=0x7ffff7f511cd "libnm", log_level=log_level@entry=G_LOG_LEVEL_CRITICAL, format=format@entry=0x7ffff78215df "%s: assertion '%s' failed")
at ../glib/gmessages.c:1415
#3 0x00007ffff77d137d in g_return_if_fail_warning
(log_domain=log_domain@entry=0x7ffff7f511cd "libnm", pretty_function=pretty_function@entry=0x7ffff7f58aa0 <__func__.40223> "nm_client_get_permission_result", expression=expression@entry=0x7ffff7f54830 "NM_IS_CLIENT (client)") at ../glib/gmessages.c:2771
#4 0x00007ffff7e9de9a in nm_client_get_permission_result (client=0x0, permission=permission@entry=NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK) at libnm/nm-client.c:3816
#5 0x0000555555593ba3 in got_permissions (nmc=nmc@entry=0x55555562ec20 <nm_cli>) at clients/cli/general.c:587
#6 0x0000555555593bcb in permission_changed (client=<optimized out>, permission=<optimized out>, result=<optimized out>, nmc=0x55555562ec20 <nm_cli>) at clients/cli/general.c:600
#7 0x00007ffff73b1aa8 in ffi_call_unix64 () at ../src/x86/unix64.S:76
#8 0x00007ffff73b12a4 in ffi_call (cif=cif@entry=0x7fffffffced0, fn=fn@entry=0x555555593bbf <permission_changed>, rvalue=<optimized out>, avalue=avalue@entry=0x7fffffffcde0)
at ../src/x86/ffi64.c:525
#9 0x00007ffff78b4746 in g_cclosure_marshal_generic_va
(closure=<optimized out>, return_value=<optimized out>, instance=<optimized out>, args_list=<optimized out>, marshal_data=<optimized out>, n_params=<optimized out>, param_types=<optimized out>) at ../gobject/gclosure.c:1614
#10 0x00007ffff78b3996 in _g_closure_invoke_va (closure=0x5555556f4330, return_value=0x0, instance=0x55555565a020, args=0x7fffffffd180, n_params=2, param_types=0x555555656f00)
at ../gobject/gclosure.c:873
#11 0x00007ffff78d0228 in g_signal_emit_valist (instance=0x55555565a020, signal_id=<optimized out>, detail=0, var_args=var_args@entry=0x7fffffffd180) at ../gobject/gsignal.c:3306
#12 0x00007ffff78d09d3 in g_signal_emit (instance=instance@entry=0x55555565a020, signal_id=<optimized out>, detail=detail@entry=0) at ../gobject/gsignal.c:3453
#13 0x00007ffff7e8989a in _emit_permissions_changed (self=self@entry=0x55555565a020, permissions=permissions@entry=0x555555690e40 = {...}, force_unknown=force_unknown@entry=1)
at libnm/nm-client.c:2874
#14 0x00007ffff7e9a0c9 in _init_release_all (self=self@entry=0x55555565a020) at libnm/nm-client.c:6092
#15 0x00007ffff7e9bcde in dispose (object=0x55555565a020 [NMClient]) at libnm/nm-client.c:6838
#16 0x00007ffff78b8c28 in g_object_unref (_object=<optimized out>) at ../gobject/gobject.c:3344
#17 g_object_unref (_object=0x55555565a020) at ../gobject/gobject.c:3274
#18 0x00005555555badcf in nmc_cleanup (nmc=0x55555562ec20 <nm_cli>) at clients/cli/nmcli.c:924
#19 0x00005555555bbea7 in main (argc=<optimized out>, argv=0x7fffffffd498) at clients/cli/nmcli.c:987
2019-11-01 12:59:03 +01:00
|
|
|
G_CALLBACK (permission_changed), nmc);
|
2016-10-19 10:08:46 +02:00
|
|
|
|
|
|
|
|
if (nmc->timeout == -1)
|
|
|
|
|
nmc->timeout = 10;
|
|
|
|
|
g_timeout_add_seconds (nmc->timeout, timeout_cb, nmc);
|
|
|
|
|
|
|
|
|
|
nmc->should_wait++;
|
2012-12-10 19:11:04 +01:00
|
|
|
return TRUE;
|
2012-04-30 11:50:26 +02:00
|
|
|
}
|
|
|
|
|
|
2019-09-05 18:32:57 +02:00
|
|
|
static NMCResultCode
|
|
|
|
|
do_general_reload (NmCli *nmc, int argc, char **argv)
|
|
|
|
|
{
|
|
|
|
|
gs_unref_variant GVariant *result = NULL;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
|
|
|
|
gs_free const char **values = NULL;
|
|
|
|
|
gs_free char *err_token = NULL;
|
|
|
|
|
gs_free char *joined = NULL;
|
|
|
|
|
int flags = 0;
|
|
|
|
|
|
|
|
|
|
next_arg (nmc, &argc, &argv, NULL);
|
|
|
|
|
|
|
|
|
|
if (nmc->complete) {
|
|
|
|
|
if (argc == 0)
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
|
|
|
|
|
if (argc == 1) {
|
|
|
|
|
values = nm_utils_enum_get_values (nm_manager_reload_flags_get_type (),
|
|
|
|
|
NM_MANAGER_RELOAD_FLAG_CONF,
|
|
|
|
|
NM_MANAGER_RELOAD_FLAG_ALL);
|
|
|
|
|
nmc_complete_strv (*argv, -1, values);
|
|
|
|
|
}
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (argc > 0) {
|
|
|
|
|
if (!nm_utils_enum_from_str (nm_manager_reload_flags_get_type (), *argv, &flags, &err_token)) {
|
|
|
|
|
values = nm_utils_enum_get_values (nm_manager_reload_flags_get_type (),
|
|
|
|
|
NM_MANAGER_RELOAD_FLAG_CONF,
|
|
|
|
|
NM_MANAGER_RELOAD_FLAG_ALL);
|
|
|
|
|
joined = g_strjoinv (",", (char **) values);
|
|
|
|
|
g_string_printf (nmc->return_text,
|
|
|
|
|
_("Error: invalid reload flag '%s'. Allowed flags are: %s"),
|
|
|
|
|
err_token,
|
|
|
|
|
joined);
|
|
|
|
|
return NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
}
|
|
|
|
|
argc--;
|
|
|
|
|
argv++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (argc > 0) {
|
|
|
|
|
g_string_printf (nmc->return_text, _("Error: extra argument '%s'"), *argv);
|
|
|
|
|
return NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result = nmc_dbus_call_sync (nmc,
|
|
|
|
|
"/org/freedesktop/NetworkManager",
|
|
|
|
|
"org.freedesktop.NetworkManager",
|
|
|
|
|
"Reload",
|
|
|
|
|
g_variant_new ("(u)", flags),
|
|
|
|
|
G_VARIANT_TYPE("()"),
|
|
|
|
|
&error);
|
|
|
|
|
|
|
|
|
|
if (error) {
|
|
|
|
|
g_string_printf (nmc->return_text,
|
|
|
|
|
_("Error: failed to reload: %s"),
|
|
|
|
|
nmc_error_get_simple_message (error));
|
|
|
|
|
return NMC_RESULT_ERROR_UNKNOWN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-06 13:34:21 +02:00
|
|
|
static NMCResultCode
|
|
|
|
|
do_general_permissions (NmCli *nmc, int argc, char **argv)
|
|
|
|
|
{
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg (nmc, &argc, &argv, NULL);
|
2016-07-06 14:43:13 +02:00
|
|
|
if (nmc->complete)
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
|
2016-07-06 13:34:21 +02:00
|
|
|
show_nm_permissions (nmc);
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-06 15:14:23 +02:00
|
|
|
static void
|
2012-12-12 14:23:54 +01:00
|
|
|
show_general_logging (NmCli *nmc)
|
|
|
|
|
{
|
2017-04-06 15:14:23 +02:00
|
|
|
gs_free char *level_cache = NULL;
|
|
|
|
|
gs_free char *domains_cache = NULL;
|
2017-06-27 09:29:18 +02:00
|
|
|
gs_free_error GError *error = NULL;
|
2017-04-06 15:14:23 +02:00
|
|
|
const char *fields_str = NULL;
|
|
|
|
|
GetGeneralLoggingData d = {
|
|
|
|
|
.level = &level_cache,
|
|
|
|
|
.domains = &domains_cache,
|
|
|
|
|
};
|
2012-12-12 14:23:54 +01:00
|
|
|
|
2017-04-06 15:14:23 +02:00
|
|
|
if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0) {
|
|
|
|
|
} else if (strcasecmp (nmc->required_fields, "all") == 0) {
|
|
|
|
|
} else
|
2012-12-12 14:23:54 +01:00
|
|
|
fields_str = nmc->required_fields;
|
|
|
|
|
|
2017-04-06 15:14:23 +02:00
|
|
|
if (!nmc_print (&nmc->nmc_config,
|
|
|
|
|
(gpointer const []) { &d, NULL },
|
2018-04-30 13:01:20 +02:00
|
|
|
NULL,
|
2017-04-06 15:14:23 +02:00
|
|
|
_("NetworkManager logging"),
|
|
|
|
|
(const NMMetaAbstractInfo *const*) metagen_general_logging,
|
|
|
|
|
fields_str,
|
|
|
|
|
&error)) {
|
2013-12-10 12:00:53 +01:00
|
|
|
g_string_printf (nmc->return_text, _("Error: 'general logging': %s"), error->message);
|
2012-12-12 14:23:54 +01:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-14 16:38:16 +01:00
|
|
|
static void
|
|
|
|
|
nmc_complete_strings_nocase (const char *prefix, ...)
|
|
|
|
|
{
|
|
|
|
|
va_list args;
|
|
|
|
|
const char *candidate;
|
|
|
|
|
int len;
|
|
|
|
|
|
|
|
|
|
len = strlen (prefix);
|
|
|
|
|
|
|
|
|
|
va_start (args, prefix);
|
|
|
|
|
while ((candidate = va_arg (args, const char *))) {
|
|
|
|
|
if (strncasecmp (prefix, candidate, len) == 0)
|
|
|
|
|
g_print ("%s\n", candidate);
|
|
|
|
|
}
|
|
|
|
|
va_end (args);
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-06 13:34:21 +02:00
|
|
|
static NMCResultCode
|
|
|
|
|
do_general_logging (NmCli *nmc, int argc, char **argv)
|
|
|
|
|
{
|
|
|
|
|
gs_free_error GError *error = NULL;
|
|
|
|
|
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg (nmc, &argc, &argv, NULL);
|
2016-07-06 13:34:21 +02:00
|
|
|
if (argc == 0) {
|
2016-07-06 14:43:13 +02:00
|
|
|
if (nmc->complete)
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
|
2016-07-06 13:34:21 +02:00
|
|
|
show_general_logging (nmc);
|
|
|
|
|
} else {
|
|
|
|
|
/* arguments provided -> set logging level and domains */
|
|
|
|
|
const char *level = NULL;
|
|
|
|
|
const char *domains = NULL;
|
|
|
|
|
|
2017-02-14 16:38:16 +01:00
|
|
|
do {
|
|
|
|
|
if (argc == 1 && nmc->complete)
|
2019-04-12 15:40:01 +02:00
|
|
|
nmc_complete_strings (*argv, "level", "domains");
|
2017-02-14 16:38:16 +01: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, "level")) {
|
2017-03-29 12:02:14 +02:00
|
|
|
argc--;
|
|
|
|
|
argv++;
|
2017-03-24 14:00:25 +01:00
|
|
|
if (!argc) {
|
2017-02-14 16:38:16 +01:00
|
|
|
g_string_printf (nmc->return_text, _("Error: '%s' argument is missing."), *(argv-1));
|
|
|
|
|
return NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
}
|
|
|
|
|
if (argc == 1 && nmc->complete) {
|
|
|
|
|
nmc_complete_strings_nocase (*argv, "TRACE", "DEBUG", "INFO", "WARN",
|
|
|
|
|
"ERR", "OFF", "KEEP", NULL);
|
|
|
|
|
}
|
|
|
|
|
level = *argv;
|
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, "domains")) {
|
2017-03-29 12:02:14 +02:00
|
|
|
argc--;
|
|
|
|
|
argv++;
|
2017-03-24 14:00:25 +01:00
|
|
|
if (!argc) {
|
2017-02-14 16:38:16 +01:00
|
|
|
g_string_printf (nmc->return_text, _("Error: '%s' argument is missing."), *(argv-1));
|
|
|
|
|
return NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
}
|
|
|
|
|
if (argc == 1 && nmc->complete) {
|
|
|
|
|
nmc_complete_strings_nocase (*argv, "PLATFORM", "RFKILL", "ETHER", "WIFI", "BT",
|
|
|
|
|
"MB", "DHCP4", "DHCP6", "PPP", "WIFI_SCAN", "IP4",
|
|
|
|
|
"IP6", "AUTOIP4", "DNS", "VPN", "SHARING", "SUPPLICANT",
|
|
|
|
|
"AGENTS", "SETTINGS", "SUSPEND", "CORE", "DEVICE", "OLPC",
|
|
|
|
|
"INFINIBAND", "FIREWALL", "ADSL", "BOND", "VLAN", "BRIDGE",
|
|
|
|
|
"DBUS_PROPS", "TEAM", "CONCHECK", "DCB", "DISPATCH", "AUDIT",
|
2017-11-16 19:19:37 +01:00
|
|
|
"SYSTEMD", "VPN_PLUGIN", "PROXY", "TC", NULL);
|
2017-02-14 16:38:16 +01:00
|
|
|
}
|
|
|
|
|
domains = *argv;
|
|
|
|
|
} else {
|
|
|
|
|
g_string_printf (nmc->return_text, _("Error: property '%s' is not known."), *argv);
|
|
|
|
|
return NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
}
|
2017-03-30 16:09:46 +02:00
|
|
|
} while (next_arg (nmc, &argc, &argv, NULL) == 0);
|
2017-02-14 16:38:16 +01:00
|
|
|
|
2016-07-06 14:43:13 +02:00
|
|
|
if (nmc->complete)
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
|
2016-07-06 13:34:21 +02:00
|
|
|
nm_client_set_logging (nmc->client, level, domains, &error);
|
|
|
|
|
if (error) {
|
|
|
|
|
g_string_printf (nmc->return_text, _("Error: failed to set logging: %s"),
|
2016-08-19 11:56:58 +02:00
|
|
|
nmc_error_get_simple_message (error));
|
2016-07-06 13:34:21 +02:00
|
|
|
return NMC_RESULT_ERROR_UNKNOWN;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-07 11:30:54 +01:00
|
|
|
static void
|
2014-09-11 16:27:13 -04:00
|
|
|
save_hostname_cb (GObject *object, GAsyncResult *result, gpointer user_data)
|
2013-11-07 11:30:54 +01:00
|
|
|
{
|
|
|
|
|
NmCli *nmc = (NmCli *) user_data;
|
2014-09-11 16:27:13 -04:00
|
|
|
GError *error = NULL;
|
2013-11-07 11:30:54 +01:00
|
|
|
|
2014-09-29 10:58:16 -04:00
|
|
|
nm_client_save_hostname_finish (NM_CLIENT (object), result, &error);
|
2013-11-07 11:30:54 +01:00
|
|
|
if (error) {
|
2014-10-01 10:31:03 +02:00
|
|
|
g_string_printf (nmc->return_text, _("Error: failed to set hostname: %s"),
|
|
|
|
|
error->message);
|
2013-11-07 11:30:54 +01:00
|
|
|
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
|
2014-09-11 16:27:13 -04:00
|
|
|
g_error_free (error);
|
2013-11-07 11:30:54 +01:00
|
|
|
}
|
|
|
|
|
quit ();
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-06 13:34:21 +02:00
|
|
|
static NMCResultCode
|
|
|
|
|
do_general_hostname (NmCli *nmc, int argc, char **argv)
|
|
|
|
|
{
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg (nmc, &argc, &argv, NULL);
|
2016-07-06 14:43:13 +02:00
|
|
|
if (nmc->complete)
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
|
2016-07-06 13:34:21 +02:00
|
|
|
if (argc == 0) {
|
|
|
|
|
/* no arguments -> get hostname */
|
|
|
|
|
char *hostname = NULL;
|
|
|
|
|
|
|
|
|
|
g_object_get (nmc->client, NM_CLIENT_HOSTNAME, &hostname, NULL);
|
|
|
|
|
if (hostname)
|
|
|
|
|
g_print ("%s\n", hostname);
|
|
|
|
|
g_free (hostname);
|
|
|
|
|
} else {
|
|
|
|
|
/* hostname provided -> set it */
|
|
|
|
|
const char *hostname = *argv;
|
|
|
|
|
|
2017-03-30 16:09:46 +02:00
|
|
|
if (next_arg (nmc, &argc, &argv, NULL) == 0)
|
2016-07-06 13:34:21 +02:00
|
|
|
g_print ("Warning: ignoring extra garbage after '%s' hostname\n", hostname);
|
|
|
|
|
|
|
|
|
|
nmc->should_wait++;
|
|
|
|
|
nm_client_save_hostname_async (nmc->client, hostname, NULL, save_hostname_cb, nmc);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const NMCCommand general_cmds[] = {
|
2016-08-31 20:52:48 +02:00
|
|
|
{ "status", do_general_status, usage_general_status, TRUE, TRUE },
|
|
|
|
|
{ "hostname", do_general_hostname, usage_general_hostname, TRUE, TRUE },
|
|
|
|
|
{ "permissions", do_general_permissions, usage_general_permissions, TRUE, TRUE },
|
|
|
|
|
{ "logging", do_general_logging, usage_general_logging, TRUE, TRUE },
|
2019-09-05 18:32:57 +02:00
|
|
|
{ "reload", do_general_reload, usage_general_reload, FALSE, FALSE },
|
2016-08-31 20:52:48 +02:00
|
|
|
{ NULL, do_general_status, usage_general, TRUE, TRUE },
|
2016-07-06 13:34:21 +02:00
|
|
|
};
|
|
|
|
|
|
2012-12-10 19:11:04 +01:00
|
|
|
/*
|
|
|
|
|
* Entry point function for general operations 'nmcli general'
|
|
|
|
|
*/
|
|
|
|
|
NMCResultCode
|
|
|
|
|
do_general (NmCli *nmc, int argc, char **argv)
|
|
|
|
|
{
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg (nmc, &argc, &argv, NULL);
|
|
|
|
|
|
2014-10-30 15:45:43 +01:00
|
|
|
/* Register polkit agent */
|
|
|
|
|
nmc_start_polkit_agent_start_try (nmc);
|
|
|
|
|
|
2016-08-31 21:04:33 +02:00
|
|
|
nmc_do_cmd (nmc, general_cmds, *argv, argc, argv);
|
|
|
|
|
|
|
|
|
|
return nmc->return_value;
|
2012-12-10 19:11:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
nmc_switch_show (NmCli *nmc, const char *switch_name, const char *header)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (nmc != NULL, FALSE);
|
|
|
|
|
g_return_val_if_fail (switch_name != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
if (nmc->required_fields && strcasecmp (nmc->required_fields, switch_name) != 0) {
|
2013-09-12 14:45:08 +02:00
|
|
|
g_string_printf (nmc->return_text, _("Error: '--fields' value '%s' is not valid here (allowed field: %s)"),
|
2012-12-10 19:11:04 +01:00
|
|
|
nmc->required_fields, switch_name);
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2017-03-30 12:45:41 +02:00
|
|
|
if (nmc->nmc_config.print_output == NMC_PRINT_NORMAL)
|
|
|
|
|
nmc->nmc_config_mutable.print_output = NMC_PRINT_TERSE;
|
2012-12-10 19:11:04 +01:00
|
|
|
|
2013-09-12 14:45:08 +02:00
|
|
|
if (!nmc->required_fields)
|
|
|
|
|
nmc->required_fields = g_strdup (switch_name);
|
|
|
|
|
return show_nm_status (nmc, header, NULL);
|
2012-12-10 19:11:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
nmc_switch_parse_on_off (NmCli *nmc, const char *arg1, const char *arg2, gboolean *res)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (nmc != NULL, FALSE);
|
|
|
|
|
g_return_val_if_fail (arg1 && arg2, FALSE);
|
|
|
|
|
g_return_val_if_fail (res != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
if (!strcmp (arg2, "on"))
|
|
|
|
|
*res = TRUE;
|
|
|
|
|
else if (!strcmp (arg2, "off"))
|
|
|
|
|
*res = FALSE;
|
|
|
|
|
else {
|
|
|
|
|
g_string_printf (nmc->return_text, _("Error: invalid '%s' argument: '%s' (use on/off)."), arg1, arg2);
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-09 13:21:41 +01:00
|
|
|
static NMCResultCode
|
|
|
|
|
do_networking_on_off (NmCli *nmc, int argc, char **argv, gboolean enable)
|
2013-08-28 10:06:54 -04:00
|
|
|
{
|
2016-12-09 13:21:41 +01:00
|
|
|
if (nmc->complete)
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
|
|
|
|
|
/* Register polkit agent */
|
|
|
|
|
nmc_start_polkit_agent_start_try (nmc);
|
|
|
|
|
|
|
|
|
|
nm_client_networking_set_enabled (nmc->client, enable, NULL);
|
|
|
|
|
|
|
|
|
|
return nmc->return_value;
|
2013-08-28 10:06:54 -04:00
|
|
|
}
|
|
|
|
|
|
2016-12-09 13:21:41 +01:00
|
|
|
static NMCResultCode
|
|
|
|
|
do_networking_on (NmCli *nmc, int argc, char **argv)
|
2013-02-28 14:53:11 +01:00
|
|
|
{
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg (nmc, &argc, &argv, NULL);
|
2016-12-09 13:21:41 +01:00
|
|
|
return do_networking_on_off (nmc, argc, argv, TRUE);
|
|
|
|
|
}
|
2013-02-28 14:53:11 +01:00
|
|
|
|
2016-12-09 13:21:41 +01:00
|
|
|
static NMCResultCode
|
|
|
|
|
do_networking_off (NmCli *nmc, int argc, char **argv)
|
|
|
|
|
{
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg (nmc, &argc, &argv, NULL);
|
2016-12-09 13:21:41 +01:00
|
|
|
return do_networking_on_off (nmc, argc, argv, FALSE);
|
|
|
|
|
}
|
2014-10-30 15:45:43 +01:00
|
|
|
|
2016-12-09 13:21:41 +01:00
|
|
|
static NMCResultCode
|
|
|
|
|
do_networking_connectivity (NmCli *nmc, int argc, char **argv)
|
|
|
|
|
{
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg (nmc, &argc, &argv, NULL);
|
2016-12-09 13:21:41 +01:00
|
|
|
if (nmc->complete) {
|
|
|
|
|
if (argc == 1)
|
2019-04-12 15:40:01 +02:00
|
|
|
nmc_complete_strings (*argv, "check");
|
2016-12-09 13:21:41 +01:00
|
|
|
return nmc->return_value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!argc) {
|
|
|
|
|
/* no arguments -> get current state */
|
2017-04-04 15:23:39 +02:00
|
|
|
nmc_switch_show (nmc, NMC_FIELDS_NM_CONNECTIVITY, N_("Connectivity"));
|
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, "check")) {
|
2016-12-09 13:21:41 +01:00
|
|
|
gs_free_error GError *error = NULL;
|
|
|
|
|
|
|
|
|
|
/* Register polkit agent */
|
|
|
|
|
nmc_start_polkit_agent_start_try (nmc);
|
|
|
|
|
|
|
|
|
|
nm_client_check_connectivity (nmc->client, NULL, &error);
|
|
|
|
|
if (error) {
|
|
|
|
|
g_string_printf (nmc->return_text, _("Error: %s."), error->message);
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
|
|
|
|
|
} else
|
2017-04-04 15:23:39 +02:00
|
|
|
nmc_switch_show (nmc, NMC_FIELDS_NM_CONNECTIVITY, N_("Connectivity"));
|
2016-12-09 13:21:41 +01:00
|
|
|
} else {
|
|
|
|
|
usage_networking ();
|
|
|
|
|
g_string_printf (nmc->return_text, _("Error: 'networking' command '%s' is not valid."), *argv);
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
}
|
2016-07-06 14:52:25 +02:00
|
|
|
|
2016-12-09 13:21:41 +01:00
|
|
|
return nmc->return_value;
|
|
|
|
|
}
|
2016-07-06 14:52:25 +02:00
|
|
|
|
2016-12-09 13:21:41 +01:00
|
|
|
static NMCResultCode
|
|
|
|
|
do_networking_show (NmCli *nmc, int argc, char **argv)
|
|
|
|
|
{
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg (nmc, &argc, &argv, NULL);
|
2016-12-09 13:21:41 +01:00
|
|
|
if (nmc->complete)
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
|
2017-04-04 15:23:39 +02:00
|
|
|
nmc_switch_show (nmc, NMC_FIELDS_NM_NETWORKING, N_("Networking"));
|
2016-12-09 13:21:41 +01:00
|
|
|
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const NMCCommand networking_cmds[] = {
|
|
|
|
|
{ "on", do_networking_on, usage_networking_on, TRUE, TRUE },
|
|
|
|
|
{ "off", do_networking_off, usage_networking_off, TRUE, TRUE },
|
|
|
|
|
{ "connectivity", do_networking_connectivity, usage_networking_connectivity, TRUE, TRUE },
|
|
|
|
|
{ NULL, do_networking_show, usage_networking, TRUE, TRUE },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Entry point function for networking commands 'nmcli networking'
|
|
|
|
|
*/
|
|
|
|
|
NMCResultCode
|
|
|
|
|
do_networking (NmCli *nmc, int argc, char **argv)
|
|
|
|
|
{
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg (nmc, &argc, &argv, NULL);
|
2016-12-09 13:21:41 +01:00
|
|
|
nmc_do_cmd (nmc, networking_cmds, *argv, argc, argv);
|
2013-02-28 14:53:11 +01:00
|
|
|
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-06 14:33:16 +02:00
|
|
|
static NMCResultCode
|
|
|
|
|
do_radio_all (NmCli *nmc, int argc, char **argv)
|
2012-12-10 19:11:04 +01:00
|
|
|
{
|
|
|
|
|
gboolean enable_flag;
|
2014-10-30 15:45:43 +01:00
|
|
|
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg (nmc, &argc, &argv, NULL);
|
2012-12-10 19:11:04 +01:00
|
|
|
if (argc == 0) {
|
2016-07-06 14:54:58 +02:00
|
|
|
if (nmc->complete)
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
|
2016-07-06 14:33:16 +02:00
|
|
|
/* no argument, show all radio switches */
|
2017-04-04 15:23:39 +02:00
|
|
|
show_nm_status (nmc, N_("Radio switches"), NMC_FIELDS_NM_STATUS_RADIO);
|
2016-07-06 14:33:16 +02:00
|
|
|
} else {
|
2016-07-06 14:54:58 +02:00
|
|
|
if (nmc->complete) {
|
|
|
|
|
if (argc == 1)
|
|
|
|
|
nmc_complete_bool (*argv);
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-06 14:33:16 +02:00
|
|
|
if (!nmc_switch_parse_on_off (nmc, *(argv-1), *argv, &enable_flag))
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
|
|
|
|
|
nm_client_wireless_set_enabled (nmc->client, enable_flag);
|
|
|
|
|
nm_client_wimax_set_enabled (nmc->client, enable_flag);
|
|
|
|
|
nm_client_wwan_set_enabled (nmc->client, enable_flag);
|
2012-12-10 19:11:04 +01:00
|
|
|
}
|
|
|
|
|
|
2016-07-06 14:33:16 +02:00
|
|
|
return nmc->return_value;
|
|
|
|
|
}
|
2012-12-10 19:11:04 +01:00
|
|
|
|
2016-07-06 14:33:16 +02:00
|
|
|
static NMCResultCode
|
|
|
|
|
do_radio_wifi (NmCli *nmc, int argc, char **argv)
|
|
|
|
|
{
|
|
|
|
|
gboolean enable_flag;
|
2012-12-10 19:11:04 +01:00
|
|
|
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg (nmc, &argc, &argv, NULL);
|
2016-07-06 14:33:16 +02:00
|
|
|
if (argc == 0) {
|
2016-07-06 14:54:58 +02:00
|
|
|
if (nmc->complete)
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
|
2018-11-21 11:32:38 +01:00
|
|
|
/* no argument, show current Wi-Fi state */
|
2017-04-04 15:23:39 +02:00
|
|
|
nmc_switch_show (nmc, NMC_FIELDS_NM_WIFI, N_("Wi-Fi radio switch"));
|
2016-07-06 14:33:16 +02:00
|
|
|
} else {
|
2016-07-06 14:54:58 +02:00
|
|
|
if (nmc->complete) {
|
|
|
|
|
if (argc == 1)
|
|
|
|
|
nmc_complete_bool (*argv);
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
}
|
2016-07-06 14:33:16 +02:00
|
|
|
if (!nmc_switch_parse_on_off (nmc, *(argv-1), *argv, &enable_flag))
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
|
|
|
|
|
nm_client_wireless_set_enabled (nmc->client, enable_flag);
|
2012-12-10 19:11:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-06 14:33:16 +02:00
|
|
|
static NMCResultCode
|
|
|
|
|
do_radio_wwan (NmCli *nmc, int argc, char **argv)
|
|
|
|
|
{
|
|
|
|
|
gboolean enable_flag;
|
|
|
|
|
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg (nmc, &argc, &argv, NULL);
|
2016-07-06 14:33:16 +02:00
|
|
|
if (argc == 0) {
|
2016-07-06 14:54:58 +02:00
|
|
|
if (nmc->complete)
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
|
2016-07-06 14:33:16 +02:00
|
|
|
/* no argument, show current WWAN (mobile broadband) state */
|
2017-04-04 15:23:39 +02:00
|
|
|
nmc_switch_show (nmc, NMC_FIELDS_NM_WWAN, N_("WWAN radio switch"));
|
2016-07-06 14:33:16 +02:00
|
|
|
} else {
|
2016-07-06 14:54:58 +02:00
|
|
|
if (nmc->complete) {
|
|
|
|
|
if (argc == 1)
|
|
|
|
|
nmc_complete_bool (*argv);
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
}
|
2016-07-06 14:33:16 +02:00
|
|
|
if (!nmc_switch_parse_on_off (nmc, *(argv-1), *argv, &enable_flag))
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
|
|
|
|
|
nm_client_wwan_set_enabled (nmc->client, enable_flag);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const NMCCommand radio_cmds[] = {
|
2016-08-31 20:52:48 +02:00
|
|
|
{ "all", do_radio_all, usage_radio_all, TRUE, TRUE },
|
|
|
|
|
{ "wifi", do_radio_wifi, usage_radio_wifi, TRUE, TRUE },
|
|
|
|
|
{ "wwan", do_radio_wwan, usage_radio_wwan, TRUE, TRUE },
|
|
|
|
|
{ NULL, do_radio_all, usage_radio, TRUE, TRUE },
|
2016-07-06 14:33:16 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Entry point function for radio switch commands 'nmcli radio'
|
|
|
|
|
*/
|
|
|
|
|
NMCResultCode
|
|
|
|
|
do_radio (NmCli *nmc, int argc, char **argv)
|
|
|
|
|
{
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg (nmc, &argc, &argv, NULL);
|
|
|
|
|
|
2016-07-06 14:33:16 +02:00
|
|
|
/* Register polkit agent */
|
|
|
|
|
nmc_start_polkit_agent_start_try (nmc);
|
|
|
|
|
|
2016-08-31 21:04:33 +02:00
|
|
|
nmc_do_cmd (nmc, radio_cmds, *argv, argc, argv);
|
|
|
|
|
|
|
|
|
|
return nmc->return_value;
|
2016-07-06 14:33:16 +02:00
|
|
|
}
|
|
|
|
|
|
2015-12-14 16:37:57 +01:00
|
|
|
static void
|
|
|
|
|
networkmanager_running (NMClient *client, GParamSpec *param, NmCli *nmc)
|
|
|
|
|
{
|
|
|
|
|
gboolean running;
|
|
|
|
|
char *str;
|
|
|
|
|
|
|
|
|
|
running = nm_client_get_nm_running (client);
|
2018-03-29 12:25:14 +02:00
|
|
|
str = nmc_colorize (&nmc->nmc_config,
|
2018-03-29 12:31:33 +02:00
|
|
|
running ? NM_META_COLOR_MANAGER_RUNNING : NM_META_COLOR_MANAGER_STOPPED,
|
2016-06-05 11:46:06 +02:00
|
|
|
running ? _("NetworkManager has started") : _("NetworkManager has stopped"));
|
2015-12-14 16:37:57 +01:00
|
|
|
g_print ("%s\n", str);
|
|
|
|
|
g_free (str);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-27 13:07:43 +01:00
|
|
|
static void
|
|
|
|
|
client_hostname (NMClient *client, GParamSpec *param, NmCli *nmc)
|
|
|
|
|
{
|
|
|
|
|
const char *hostname;
|
|
|
|
|
|
|
|
|
|
g_object_get (client, NM_CLIENT_HOSTNAME, &hostname, NULL);
|
|
|
|
|
g_print (_("Hostname set to '%s'\n"), hostname);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
client_primary_connection (NMClient *client, GParamSpec *param, NmCli *nmc)
|
|
|
|
|
{
|
2015-12-14 16:04:49 +01:00
|
|
|
NMActiveConnection *primary;
|
2015-03-27 13:07:43 +01:00
|
|
|
const char *id;
|
|
|
|
|
|
2015-12-14 16:04:49 +01:00
|
|
|
primary = nm_client_get_primary_connection (client);
|
2015-03-27 13:07:43 +01:00
|
|
|
if (primary) {
|
2015-12-14 16:04:49 +01:00
|
|
|
id = nm_active_connection_get_id (primary);
|
2015-03-27 13:07:43 +01:00
|
|
|
if (!id)
|
2015-12-14 16:04:49 +01:00
|
|
|
id = nm_active_connection_get_uuid (primary);
|
2015-03-27 13:07:43 +01:00
|
|
|
|
|
|
|
|
g_print (_("'%s' is now the primary connection\n"), id);
|
|
|
|
|
} else {
|
|
|
|
|
g_print (_("There's no primary connection\n"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
client_connectivity (NMClient *client, GParamSpec *param, NmCli *nmc)
|
|
|
|
|
{
|
|
|
|
|
NMConnectivityState connectivity;
|
|
|
|
|
char *str;
|
|
|
|
|
|
|
|
|
|
g_object_get (client, NM_CLIENT_CONNECTIVITY, &connectivity, NULL);
|
2018-03-29 12:31:33 +02:00
|
|
|
str = nmc_colorize (&nmc->nmc_config, connectivity_to_color (connectivity),
|
2018-12-01 15:32:55 +01:00
|
|
|
_("Connectivity is now '%s'\n"),
|
|
|
|
|
gettext (nm_connectivity_to_string (connectivity)));
|
2015-03-27 13:07:43 +01:00
|
|
|
g_print ("%s", str);
|
|
|
|
|
g_free (str);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
client_state (NMClient *client, GParamSpec *param, NmCli *nmc)
|
|
|
|
|
{
|
|
|
|
|
NMState state;
|
|
|
|
|
char *str;
|
|
|
|
|
|
|
|
|
|
g_object_get (client, NM_CLIENT_STATE, &state, NULL);
|
2018-03-29 12:31:33 +02:00
|
|
|
str = nmc_colorize (&nmc->nmc_config, state_to_color (state),
|
2015-03-27 13:07:43 +01:00
|
|
|
_("Networkmanager is now in the '%s' state\n"),
|
2018-12-01 15:32:55 +01:00
|
|
|
gettext (nm_state_to_string (state)));
|
2015-03-27 13:07:43 +01:00
|
|
|
g_print ("%s", str);
|
|
|
|
|
g_free (str);
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-01 21:47:01 +02:00
|
|
|
static void
|
|
|
|
|
device_overview (NmCli *nmc, NMDevice *device)
|
|
|
|
|
{
|
|
|
|
|
GString *outbuf = g_string_sized_new (80);
|
|
|
|
|
char *tmp;
|
|
|
|
|
const GPtrArray *activatable;
|
|
|
|
|
|
|
|
|
|
activatable = nm_device_get_available_connections (device);
|
|
|
|
|
|
|
|
|
|
g_string_append_printf (outbuf, "%s", nm_device_get_type_description (device));
|
|
|
|
|
|
|
|
|
|
if (nm_device_get_state (device) == NM_DEVICE_STATE_DISCONNECTED) {
|
|
|
|
|
if (activatable) {
|
|
|
|
|
if (activatable->len == 1)
|
|
|
|
|
g_print ("\t%d %s\n", activatable->len, _("connection available"));
|
|
|
|
|
else if (activatable->len > 1)
|
|
|
|
|
g_print ("\t%d %s\n", activatable->len, _("connections available"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( nm_device_get_driver (device)
|
|
|
|
|
&& strcmp (nm_device_get_driver (device), "")
|
|
|
|
|
&& strcmp (nm_device_get_driver (device), nm_device_get_type_description (device))) {
|
|
|
|
|
g_string_append_printf (outbuf, " (%s)", nm_device_get_driver (device));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_string_append_printf (outbuf, ", ");
|
|
|
|
|
|
|
|
|
|
if ( nm_device_get_hw_address (device)
|
|
|
|
|
&& strcmp (nm_device_get_hw_address (device), "")) {
|
|
|
|
|
g_string_append_printf (outbuf, "%s, ", nm_device_get_hw_address (device));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!nm_device_get_autoconnect (device))
|
|
|
|
|
g_string_append_printf (outbuf, "%s, ", _("autoconnect"));
|
|
|
|
|
if (nm_device_get_firmware_missing (device)) {
|
2018-03-29 12:31:33 +02:00
|
|
|
tmp = nmc_colorize (&nmc->nmc_config, NM_META_COLOR_DEVICE_FIRMWARE_MISSING, _("fw missing"));
|
2016-07-01 21:47:01 +02:00
|
|
|
g_string_append_printf (outbuf, "%s, ", tmp);
|
|
|
|
|
g_free (tmp);
|
|
|
|
|
}
|
|
|
|
|
if (nm_device_get_nm_plugin_missing (device)) {
|
2018-03-29 12:31:33 +02:00
|
|
|
tmp = nmc_colorize (&nmc->nmc_config, NM_META_COLOR_DEVICE_PLUGIN_MISSING, _("plugin missing"));
|
2016-07-01 21:47:01 +02:00
|
|
|
g_string_append_printf (outbuf, "%s, ", tmp);
|
|
|
|
|
g_free (tmp);
|
|
|
|
|
}
|
2019-09-12 09:51:06 +02:00
|
|
|
|
|
|
|
|
switch (nm_device_get_device_type (device)) {
|
|
|
|
|
case NM_DEVICE_TYPE_WIFI:
|
|
|
|
|
case NM_DEVICE_TYPE_OLPC_MESH:
|
|
|
|
|
case NM_DEVICE_TYPE_WIFI_P2P:
|
|
|
|
|
if (!nm_client_wireless_get_enabled (nmc->client)) {
|
|
|
|
|
tmp = nmc_colorize (&nmc->nmc_config, NM_META_COLOR_DEVICE_DISABLED, _("sw disabled"));
|
|
|
|
|
g_string_append_printf (outbuf, "%s, ", tmp);
|
|
|
|
|
g_free (tmp);
|
|
|
|
|
}
|
|
|
|
|
if (!nm_client_wireless_hardware_get_enabled (nmc->client)) {
|
|
|
|
|
tmp = nmc_colorize (&nmc->nmc_config, NM_META_COLOR_DEVICE_DISABLED, _("hw disabled"));
|
|
|
|
|
g_string_append_printf (outbuf, "%s, ", tmp);
|
|
|
|
|
g_free (tmp);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case NM_DEVICE_TYPE_MODEM:
|
|
|
|
|
if ( nm_device_modem_get_current_capabilities (NM_DEVICE_MODEM (device))
|
|
|
|
|
& (NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS | NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO)) {
|
|
|
|
|
if (!nm_client_wwan_get_enabled (nmc->client)) {
|
|
|
|
|
tmp = nmc_colorize (&nmc->nmc_config, NM_META_COLOR_DEVICE_DISABLED, _("sw disabled"));
|
|
|
|
|
g_string_append_printf (outbuf, "%s, ", tmp);
|
|
|
|
|
g_free (tmp);
|
|
|
|
|
}
|
|
|
|
|
if (!nm_client_wwan_hardware_get_enabled (nmc->client)) {
|
|
|
|
|
tmp = nmc_colorize (&nmc->nmc_config, NM_META_COLOR_DEVICE_DISABLED, _("hw disabled"));
|
|
|
|
|
g_string_append_printf (outbuf, "%s, ", tmp);
|
|
|
|
|
g_free (tmp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-01 21:47:01 +02:00
|
|
|
if (nm_device_is_software (device))
|
|
|
|
|
g_string_append_printf (outbuf, "%s, ", _("sw"));
|
|
|
|
|
else
|
|
|
|
|
g_string_append_printf (outbuf, "%s, ", _("hw"));
|
|
|
|
|
|
2017-06-09 15:23:44 +02:00
|
|
|
if (!NM_IN_STRSET (nm_device_get_ip_iface (device),
|
|
|
|
|
NULL,
|
|
|
|
|
nm_device_get_iface (device)))
|
2017-06-09 15:18:20 +02:00
|
|
|
g_string_append_printf (outbuf, "%s %s, ", _("iface"), nm_device_get_ip_iface (device));
|
2016-07-01 21:47:01 +02:00
|
|
|
|
|
|
|
|
if (nm_device_get_physical_port_id (device))
|
|
|
|
|
g_string_append_printf (outbuf, "%s %s, ", _("port"), nm_device_get_physical_port_id (device));
|
|
|
|
|
|
|
|
|
|
if (nm_device_get_mtu (device))
|
|
|
|
|
g_string_append_printf (outbuf, "%s %d, ", _("mtu"), nm_device_get_mtu (device));
|
|
|
|
|
|
|
|
|
|
if (outbuf->len >= 2) {
|
|
|
|
|
g_string_truncate (outbuf, outbuf->len - 2);
|
|
|
|
|
g_print ("\t%s\n", outbuf->str);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_string_free (outbuf, TRUE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
ac_overview (NmCli *nmc, NMActiveConnection *ac)
|
|
|
|
|
{
|
|
|
|
|
GString *outbuf = g_string_sized_new (80);
|
|
|
|
|
NMIPConfig *ip;
|
|
|
|
|
|
|
|
|
|
if (nm_active_connection_get_master (ac)) {
|
2017-03-16 13:16:57 +00:00
|
|
|
g_string_append_printf (outbuf, "%s %s, ", _("master"),
|
2016-07-01 21:47:01 +02:00
|
|
|
nm_device_get_iface (nm_active_connection_get_master (ac)));
|
|
|
|
|
}
|
|
|
|
|
if (nm_active_connection_get_vpn (ac))
|
|
|
|
|
g_string_append_printf (outbuf, "%s, ", _("VPN"));
|
|
|
|
|
if (nm_active_connection_get_default (ac))
|
|
|
|
|
g_string_append_printf (outbuf, "%s, ", _("ip4 default"));
|
|
|
|
|
if (nm_active_connection_get_default6 (ac))
|
|
|
|
|
g_string_append_printf (outbuf, "%s, ", _("ip6 default"));
|
|
|
|
|
if (outbuf->len >= 2) {
|
|
|
|
|
g_string_truncate (outbuf, outbuf->len - 2);
|
|
|
|
|
g_print ("\t%s\n", outbuf->str);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ip = nm_active_connection_get_ip4_config (ac);
|
|
|
|
|
if (ip) {
|
|
|
|
|
const GPtrArray *p;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
p = nm_ip_config_get_addresses (ip);
|
|
|
|
|
for (i = 0; i < p->len; i++) {
|
|
|
|
|
NMIPAddress *a = p->pdata[i];
|
|
|
|
|
g_print ("\tinet4 %s/%d\n", nm_ip_address_get_address (a),
|
|
|
|
|
nm_ip_address_get_prefix (a));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p = nm_ip_config_get_routes (ip);
|
|
|
|
|
for (i = 0; i < p->len; i++) {
|
|
|
|
|
NMIPRoute *a = p->pdata[i];
|
|
|
|
|
g_print ("\troute4 %s/%d\n", nm_ip_route_get_dest (a),
|
|
|
|
|
nm_ip_route_get_prefix (a));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ip = nm_active_connection_get_ip6_config (ac);
|
|
|
|
|
if (ip) {
|
|
|
|
|
const GPtrArray *p;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
p = nm_ip_config_get_addresses (ip);
|
|
|
|
|
for (i = 0; i < p->len; i++) {
|
|
|
|
|
NMIPAddress *a = p->pdata[i];
|
|
|
|
|
g_print ("\tinet6 %s/%d\n", nm_ip_address_get_address (a),
|
|
|
|
|
nm_ip_address_get_prefix (a));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p = nm_ip_config_get_routes (ip);
|
|
|
|
|
for (i = 0; i < p->len; i++) {
|
|
|
|
|
NMIPRoute *a = p->pdata[i];
|
|
|
|
|
g_print ("\troute6 %s/%d\n", nm_ip_route_get_dest (a),
|
|
|
|
|
nm_ip_route_get_prefix (a));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_string_free (outbuf, TRUE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Entry point function for 'nmcli' without arguments.
|
|
|
|
|
*/
|
|
|
|
|
NMCResultCode
|
|
|
|
|
do_overview (NmCli *nmc, int argc, char **argv)
|
|
|
|
|
{
|
|
|
|
|
NMDevice **devices;
|
|
|
|
|
const GPtrArray *p;
|
|
|
|
|
NMActiveConnection *ac;
|
2018-03-29 12:31:33 +02:00
|
|
|
NMMetaColor color;
|
2016-10-27 09:09:13 +02:00
|
|
|
NMDnsEntry *dns;
|
2016-07-01 21:47:01 +02:00
|
|
|
char *tmp;
|
|
|
|
|
int i;
|
|
|
|
|
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg (nmc, &argc, &argv, NULL);
|
|
|
|
|
|
2016-07-01 21:47:01 +02:00
|
|
|
/* Register polkit agent */
|
|
|
|
|
nmc_start_polkit_agent_start_try (nmc);
|
2017-05-15 17:23:51 +02:00
|
|
|
|
2018-10-09 13:08:24 +02:00
|
|
|
nm_cli_spawn_pager (nmc);
|
2016-07-01 21:47:01 +02:00
|
|
|
|
|
|
|
|
/* The VPN connections don't have devices (yet?). */
|
|
|
|
|
p = nm_client_get_active_connections (nmc->client);
|
|
|
|
|
for (i = 0; i < p->len; i++) {
|
|
|
|
|
NMActiveConnectionState state;
|
|
|
|
|
|
|
|
|
|
ac = p->pdata[i];
|
|
|
|
|
|
|
|
|
|
if (!nm_active_connection_get_vpn (ac))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
state = nm_active_connection_get_state (ac);
|
2018-03-29 12:31:33 +02:00
|
|
|
color = nmc_active_connection_state_to_color (state);
|
|
|
|
|
tmp = nmc_colorize (&nmc->nmc_config, color, _("%s VPN connection"),
|
2016-07-01 21:47:01 +02:00
|
|
|
nm_active_connection_get_id (ac));
|
|
|
|
|
g_print ("%s\n", tmp);
|
|
|
|
|
g_free (tmp);
|
|
|
|
|
|
|
|
|
|
ac_overview (nmc, ac);
|
|
|
|
|
g_print ("\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
devices = nmc_get_devices_sorted (nmc->client);
|
|
|
|
|
for (i = 0; devices[i]; i++) {
|
|
|
|
|
NMDeviceState state;
|
|
|
|
|
|
|
|
|
|
ac = nm_device_get_active_connection (devices[i]);
|
|
|
|
|
|
|
|
|
|
state = nm_device_get_state (devices[i]);
|
2018-03-29 12:31:33 +02:00
|
|
|
color = nmc_device_state_to_color (state);
|
2019-10-01 16:17:48 +02:00
|
|
|
if (ac) {
|
|
|
|
|
/* TRANSLATORS: prints header line for activated device in plain `nmcli` overview output as
|
|
|
|
|
* "<interface-name>: <device-state> to <connection-id>" */
|
|
|
|
|
tmp = nmc_colorize (&nmc->nmc_config, color, C_("nmcli-overview", "%s: %s to %s"),
|
|
|
|
|
nm_device_get_iface (devices[i]),
|
|
|
|
|
gettext (nmc_device_state_to_string (state)),
|
|
|
|
|
nm_active_connection_get_id (ac));
|
|
|
|
|
} else {
|
|
|
|
|
/* TRANSLATORS: prints header line for not active device in plain `nmcli` overview output as
|
|
|
|
|
* "<interface-name>: <device-state>" */
|
|
|
|
|
tmp = nmc_colorize (&nmc->nmc_config, color, C_("nmcli-overview", "%s: %s"),
|
|
|
|
|
nm_device_get_iface (devices[i]),
|
|
|
|
|
gettext (nmc_device_state_to_string (state)));
|
|
|
|
|
}
|
2016-07-01 21:47:01 +02:00
|
|
|
g_print ("%s\n", tmp);
|
|
|
|
|
g_free (tmp);
|
|
|
|
|
|
|
|
|
|
if (nm_device_get_description (devices[i]) && strcmp (nm_device_get_description (devices[i]), ""))
|
|
|
|
|
g_print ("\t\"%s\"\n", nm_device_get_description (devices[i]));
|
|
|
|
|
|
|
|
|
|
device_overview (nmc, devices[i]);
|
|
|
|
|
if (ac)
|
|
|
|
|
ac_overview (nmc, ac);
|
|
|
|
|
g_print ("\n");
|
|
|
|
|
}
|
|
|
|
|
g_free (devices);
|
|
|
|
|
|
2016-10-27 09:09:13 +02:00
|
|
|
p = nm_client_get_dns_configuration (nmc->client);
|
|
|
|
|
for (i = 0; p && i < p->len; i++) {
|
|
|
|
|
const char * const *strv;
|
|
|
|
|
|
|
|
|
|
dns = p->pdata[i];
|
|
|
|
|
strv = nm_dns_entry_get_nameservers (dns);
|
|
|
|
|
if (!strv || !strv[0]) {
|
|
|
|
|
/* Invalid entry */
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (i == 0)
|
|
|
|
|
g_print ("DNS configuration:\n");
|
|
|
|
|
|
|
|
|
|
tmp = g_strjoinv (" ", (char **) strv);
|
|
|
|
|
g_print ("\tservers: %s\n", tmp);
|
|
|
|
|
g_free (tmp);
|
|
|
|
|
|
|
|
|
|
strv = nm_dns_entry_get_domains (dns);
|
|
|
|
|
if (strv && strv[0]) {
|
|
|
|
|
tmp = g_strjoinv (" ", (char **) strv);
|
|
|
|
|
g_print ("\tdomains: %s\n", tmp);
|
|
|
|
|
g_free (tmp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nm_dns_entry_get_interface (dns))
|
|
|
|
|
g_print ("\tinterface: %s\n", nm_dns_entry_get_interface (dns));
|
|
|
|
|
|
|
|
|
|
if (nm_dns_entry_get_vpn (dns))
|
|
|
|
|
g_print ("\ttype: vpn\n");
|
|
|
|
|
g_print ("\n");
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-01 21:47:01 +02:00
|
|
|
g_print (_("Use \"nmcli device show\" to get complete information about known devices and\n"
|
|
|
|
|
"\"nmcli connection show\" to get an overview on active connection profiles.\n"
|
|
|
|
|
"\n"
|
2019-04-12 09:54:56 +02:00
|
|
|
"Consult nmcli(1) and nmcli-examples(7) manual pages for complete usage details.\n"));
|
2016-07-01 21:47:01 +02:00
|
|
|
|
|
|
|
|
return NMC_RESULT_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Entry point function for 'nmcli monitor'
|
|
|
|
|
*/
|
2015-03-27 13:07:43 +01:00
|
|
|
NMCResultCode
|
|
|
|
|
do_monitor (NmCli *nmc, int argc, char **argv)
|
|
|
|
|
{
|
2017-03-30 16:09:46 +02:00
|
|
|
next_arg (nmc, &argc, &argv, NULL);
|
|
|
|
|
|
2016-07-06 14:39:58 +02:00
|
|
|
if (nmc->complete)
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
|
2015-03-27 13:07:43 +01:00
|
|
|
if (argc > 0) {
|
|
|
|
|
if (!nmc_arg_is_help (*argv)) {
|
|
|
|
|
g_string_printf (nmc->return_text, _("Error: 'monitor' command '%s' is not valid."), *argv);
|
|
|
|
|
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
usage_monitor ();
|
|
|
|
|
return nmc->return_value;
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-14 16:37:57 +01:00
|
|
|
if (!nm_client_get_nm_running (nmc->client)) {
|
|
|
|
|
char *str;
|
|
|
|
|
|
2018-03-29 12:31:33 +02:00
|
|
|
str = nmc_colorize (&nmc->nmc_config, NM_META_COLOR_MANAGER_STOPPED,
|
2015-12-14 16:37:57 +01:00
|
|
|
_("Networkmanager is not running (waiting for it)\n"));
|
|
|
|
|
g_print ("%s", str);
|
|
|
|
|
g_free (str);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_signal_connect (nmc->client, "notify::" NM_CLIENT_NM_RUNNING,
|
|
|
|
|
G_CALLBACK (networkmanager_running), nmc);
|
2015-03-27 13:07:43 +01:00
|
|
|
g_signal_connect (nmc->client, "notify::" NM_CLIENT_HOSTNAME,
|
|
|
|
|
G_CALLBACK (client_hostname), nmc);
|
|
|
|
|
g_signal_connect (nmc->client, "notify::" NM_CLIENT_PRIMARY_CONNECTION,
|
|
|
|
|
G_CALLBACK (client_primary_connection), nmc);
|
|
|
|
|
g_signal_connect (nmc->client, "notify::" NM_CLIENT_CONNECTIVITY,
|
|
|
|
|
G_CALLBACK (client_connectivity), nmc);
|
|
|
|
|
g_signal_connect (nmc->client, "notify::" NM_CLIENT_STATE,
|
|
|
|
|
G_CALLBACK (client_state), nmc);
|
|
|
|
|
|
|
|
|
|
nmc->should_wait++;
|
|
|
|
|
|
|
|
|
|
monitor_devices (nmc);
|
|
|
|
|
monitor_connections (nmc);
|
|
|
|
|
|
|
|
|
|
return NMC_RESULT_SUCCESS;
|
|
|
|
|
}
|