2020-12-23 22:21:36 +01:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
2019-09-25 13:13:40 +02:00
|
|
|
/*
|
2019-10-01 09:20:35 +02:00
|
|
|
* Copyright (C) 2010 - 2015 Red Hat, Inc.
|
2010-03-31 17:14:35 +02:00
|
|
|
*/
|
|
|
|
|
|
2021-02-19 15:23:34 +01:00
|
|
|
#include "libnm-client-aux-extern/nm-default-client.h"
|
2016-02-19 14:57:48 +01:00
|
|
|
|
2016-02-12 14:44:52 +01:00
|
|
|
#include "settings.h"
|
|
|
|
|
|
2014-05-30 16:45:02 -04:00
|
|
|
#include <stdlib.h>
|
2014-10-19 17:30:10 -04:00
|
|
|
#include <arpa/inet.h>
|
2011-12-09 13:20:36 +01:00
|
|
|
|
2021-02-12 15:01:09 +01:00
|
|
|
#include "libnm-core-aux-intern/nm-common-macros.h"
|
2017-03-28 12:16:31 +02:00
|
|
|
|
2021-03-01 12:42:48 +01:00
|
|
|
#include "libnmc-base/nm-client-utils.h"
|
|
|
|
|
#include "libnmc-base/nm-vpn-helpers.h"
|
|
|
|
|
#include "libnmc-setting/nm-meta-setting-access.h"
|
2017-03-28 12:16:31 +02:00
|
|
|
|
2010-03-31 17:14:35 +02:00
|
|
|
#include "utils.h"
|
2013-01-18 15:21:00 +01:00
|
|
|
#include "common.h"
|
2010-03-31 17:14:35 +02:00
|
|
|
|
2017-03-24 17:32:04 +01:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2013-11-06 08:16:40 -06:00
|
|
|
static gboolean
|
2017-01-21 00:17:03 +01:00
|
|
|
get_answer(const char *prop, const char *value)
|
2013-11-06 08:16:40 -06:00
|
|
|
{
|
2017-01-21 00:17:03 +01:00
|
|
|
char * tmp_str;
|
|
|
|
|
char * question;
|
|
|
|
|
gboolean answer = FALSE;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
if (value)
|
|
|
|
|
question = g_strdup_printf(_("Do you also want to set '%s' to '%s'? [yes]: "), prop, value);
|
|
|
|
|
else
|
|
|
|
|
question = g_strdup_printf(_("Do you also want to clear '%s'? [yes]: "), prop);
|
|
|
|
|
tmp_str = nmc_get_user_input(question);
|
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 (!tmp_str || matches(tmp_str, "yes"))
|
2017-01-21 00:17:03 +01:00
|
|
|
answer = TRUE;
|
|
|
|
|
g_free(tmp_str);
|
|
|
|
|
g_free(question);
|
|
|
|
|
return answer;
|
|
|
|
|
}
|
2013-11-06 08:16:40 -06:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
static void ipv4_method_changed_cb(GObject *object, GParamSpec *pspec, gpointer user_data);
|
|
|
|
|
static void ipv6_method_changed_cb(GObject *object, GParamSpec *pspec, gpointer user_data);
|
2013-11-06 08:16:40 -06:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
static void
|
|
|
|
|
ipv4_addresses_changed_cb(GObject *object, GParamSpec *pspec, gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
static gboolean answered = FALSE;
|
|
|
|
|
static gboolean answer = FALSE;
|
2013-11-06 08:16:40 -06:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
g_signal_handlers_block_by_func(object, G_CALLBACK(ipv4_method_changed_cb), NULL);
|
2013-11-06 08:16:40 -06:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
/* If we have some IP addresses set method to 'manual'.
|
|
|
|
|
* Else if the method was 'manual', change it back to 'auto'.
|
|
|
|
|
*/
|
|
|
|
|
if (nm_setting_ip_config_get_num_addresses(NM_SETTING_IP_CONFIG(object))) {
|
|
|
|
|
if (g_strcmp0(nm_setting_ip_config_get_method(NM_SETTING_IP_CONFIG(object)),
|
|
|
|
|
NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) {
|
|
|
|
|
if (!answered) {
|
|
|
|
|
answered = TRUE;
|
|
|
|
|
answer = get_answer("ipv4.method", "manual");
|
2013-11-06 08:16:40 -06:00
|
|
|
}
|
2017-01-21 00:17:03 +01:00
|
|
|
if (answer)
|
|
|
|
|
g_object_set(object,
|
|
|
|
|
NM_SETTING_IP_CONFIG_METHOD,
|
|
|
|
|
NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
|
|
|
|
|
NULL);
|
2013-11-06 08:16:40 -06:00
|
|
|
}
|
2017-01-21 00:17:03 +01:00
|
|
|
} else {
|
|
|
|
|
answered = FALSE;
|
|
|
|
|
if (!g_strcmp0(nm_setting_ip_config_get_method(NM_SETTING_IP_CONFIG(object)),
|
|
|
|
|
NM_SETTING_IP4_CONFIG_METHOD_MANUAL))
|
|
|
|
|
g_object_set(object,
|
|
|
|
|
NM_SETTING_IP_CONFIG_METHOD,
|
|
|
|
|
NM_SETTING_IP4_CONFIG_METHOD_AUTO,
|
|
|
|
|
NULL);
|
2013-11-06 08:16:40 -06:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
g_signal_handlers_unblock_by_func(object, G_CALLBACK(ipv4_method_changed_cb), NULL);
|
2013-11-06 08:16:40 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2017-01-21 00:17:03 +01:00
|
|
|
ipv4_method_changed_cb(GObject *object, GParamSpec *pspec, gpointer user_data)
|
2013-11-06 08:16:40 -06:00
|
|
|
{
|
2019-03-18 11:19:05 +01:00
|
|
|
static GPtrArray *old_value = NULL;
|
2017-01-21 00:17:03 +01:00
|
|
|
static gboolean answered = FALSE;
|
|
|
|
|
static gboolean answer = FALSE;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
g_signal_handlers_block_by_func(object, G_CALLBACK(ipv4_addresses_changed_cb), NULL);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
/* If method != manual, remove addresses (save them for restoring them later when method becomes 'manual' */
|
|
|
|
|
if (g_strcmp0(nm_setting_ip_config_get_method(NM_SETTING_IP_CONFIG(object)),
|
|
|
|
|
NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) {
|
|
|
|
|
if (nm_setting_ip_config_get_num_addresses(NM_SETTING_IP_CONFIG(object))) {
|
|
|
|
|
if (!answered) {
|
|
|
|
|
answered = TRUE;
|
|
|
|
|
answer = get_answer("ipv4.addresses", NULL);
|
|
|
|
|
}
|
|
|
|
|
if (answer) {
|
2019-03-18 11:19:05 +01:00
|
|
|
nm_clear_pointer(&old_value, g_ptr_array_unref);
|
|
|
|
|
g_object_get(object, NM_SETTING_IP_CONFIG_ADDRESSES, &old_value, NULL);
|
2017-01-21 00:17:03 +01:00
|
|
|
g_object_set(object, NM_SETTING_IP_CONFIG_ADDRESSES, NULL, NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
answered = FALSE;
|
2019-03-18 11:19:05 +01:00
|
|
|
if (old_value) {
|
|
|
|
|
gs_unref_ptrarray GPtrArray *v = g_steal_pointer(&old_value);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-03-18 11:19:05 +01:00
|
|
|
g_object_set(object, NM_SETTING_IP_CONFIG_ADDRESSES, v, NULL);
|
2017-01-21 00:17:03 +01:00
|
|
|
}
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
g_signal_handlers_unblock_by_func(object, G_CALLBACK(ipv4_addresses_changed_cb), NULL);
|
2013-11-06 08:16:40 -06:00
|
|
|
}
|
|
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
static void
|
|
|
|
|
ipv6_addresses_changed_cb(GObject *object, GParamSpec *pspec, gpointer user_data)
|
2013-11-06 08:16:40 -06:00
|
|
|
{
|
2017-01-21 00:17:03 +01:00
|
|
|
static gboolean answered = FALSE;
|
|
|
|
|
static gboolean answer = FALSE;
|
2013-11-06 08:16:40 -06:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
g_signal_handlers_block_by_func(object, G_CALLBACK(ipv6_method_changed_cb), NULL);
|
2013-11-06 08:16:40 -06:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
/* If we have some IP addresses set method to 'manual'.
|
|
|
|
|
* Else if the method was 'manual', change it back to 'auto'.
|
|
|
|
|
*/
|
|
|
|
|
if (nm_setting_ip_config_get_num_addresses(NM_SETTING_IP_CONFIG(object))) {
|
|
|
|
|
if (g_strcmp0(nm_setting_ip_config_get_method(NM_SETTING_IP_CONFIG(object)),
|
|
|
|
|
NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
|
|
|
|
|
if (!answered) {
|
|
|
|
|
answered = TRUE;
|
|
|
|
|
answer = get_answer("ipv6.method", "manual");
|
|
|
|
|
}
|
|
|
|
|
if (answer)
|
|
|
|
|
g_object_set(object,
|
|
|
|
|
NM_SETTING_IP_CONFIG_METHOD,
|
|
|
|
|
NM_SETTING_IP6_CONFIG_METHOD_MANUAL,
|
|
|
|
|
NULL);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
answered = FALSE;
|
2019-03-22 13:11:59 +01:00
|
|
|
/* FIXME: editor_init_existing_connection() and registering handlers is not the
|
|
|
|
|
* right approach.
|
|
|
|
|
*
|
|
|
|
|
* This only happens to work because in nmcli's edit mode
|
|
|
|
|
* tends to append addresses -- instead of setting them.
|
|
|
|
|
* If we would change that (to behavior I'd expect), we'd get:
|
|
|
|
|
*
|
|
|
|
|
* nmcli> set ipv6.addresses fc01::1:5/68
|
|
|
|
|
* Do you also want to set 'ipv6.method' to 'manual'? [yes]: y
|
|
|
|
|
* nmcli> set ipv6.addresses fc01::1:6/68
|
|
|
|
|
* Do you also want to set 'ipv6.method' to 'manual'? [yes]:
|
|
|
|
|
*
|
|
|
|
|
* That's because nmc_setting_set_property() calls set_fcn(). With modifier '\0'
|
|
|
|
|
* (set), it would first clear all addresses before adding the address. Thereby
|
|
|
|
|
* emitting multiple property changed signals.
|
|
|
|
|
*
|
|
|
|
|
* That can be avoided by freezing/thawing the signals, but this solution
|
|
|
|
|
* here is ugly in general.
|
|
|
|
|
*/
|
2017-01-21 00:17:03 +01:00
|
|
|
if (!g_strcmp0(nm_setting_ip_config_get_method(NM_SETTING_IP_CONFIG(object)),
|
|
|
|
|
NM_SETTING_IP6_CONFIG_METHOD_MANUAL))
|
|
|
|
|
g_object_set(object,
|
|
|
|
|
NM_SETTING_IP_CONFIG_METHOD,
|
|
|
|
|
NM_SETTING_IP6_CONFIG_METHOD_AUTO,
|
|
|
|
|
NULL);
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
g_signal_handlers_unblock_by_func(object, G_CALLBACK(ipv6_method_changed_cb), NULL);
|
2013-11-06 08:16:40 -06:00
|
|
|
}
|
|
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
static void
|
|
|
|
|
ipv6_method_changed_cb(GObject *object, GParamSpec *pspec, gpointer user_data)
|
2013-11-06 08:16:40 -06:00
|
|
|
{
|
2019-03-18 11:19:05 +01:00
|
|
|
static GPtrArray *old_value = NULL;
|
2017-01-21 00:17:03 +01:00
|
|
|
static gboolean answered = FALSE;
|
|
|
|
|
static gboolean answer = FALSE;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
g_signal_handlers_block_by_func(object, G_CALLBACK(ipv6_addresses_changed_cb), NULL);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
/* If method != manual, remove addresses (save them for restoring them later when method becomes 'manual' */
|
|
|
|
|
if (g_strcmp0(nm_setting_ip_config_get_method(NM_SETTING_IP_CONFIG(object)),
|
|
|
|
|
NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
|
|
|
|
|
if (nm_setting_ip_config_get_num_addresses(NM_SETTING_IP_CONFIG(object))) {
|
|
|
|
|
if (!answered) {
|
|
|
|
|
answered = TRUE;
|
|
|
|
|
answer = get_answer("ipv6.addresses", NULL);
|
|
|
|
|
}
|
|
|
|
|
if (answer) {
|
2019-03-18 11:19:05 +01:00
|
|
|
nm_clear_pointer(&old_value, g_ptr_array_unref);
|
|
|
|
|
g_object_get(object, NM_SETTING_IP_CONFIG_ADDRESSES, &old_value, NULL);
|
2017-01-21 00:17:03 +01:00
|
|
|
g_object_set(object, NM_SETTING_IP_CONFIG_ADDRESSES, NULL, NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
answered = FALSE;
|
2019-03-18 11:19:05 +01:00
|
|
|
if (old_value) {
|
|
|
|
|
gs_unref_ptrarray GPtrArray *v = g_steal_pointer(&old_value);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-03-18 11:19:05 +01:00
|
|
|
g_object_set(object, NM_SETTING_IP_CONFIG_ADDRESSES, v, NULL);
|
2017-01-21 00:17:03 +01:00
|
|
|
}
|
2013-11-06 08:16:40 -06:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
g_signal_handlers_unblock_by_func(object, G_CALLBACK(ipv6_addresses_changed_cb), NULL);
|
2013-11-06 08:16:40 -06:00
|
|
|
}
|
|
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
static void
|
|
|
|
|
proxy_method_changed_cb(GObject *object, GParamSpec *pspec, gpointer user_data)
|
2013-11-06 08:16:40 -06:00
|
|
|
{
|
2017-01-21 00:17:03 +01:00
|
|
|
NMSettingProxyMethod method;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
method = nm_setting_proxy_get_method(NM_SETTING_PROXY(object));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
if (method == NM_SETTING_PROXY_METHOD_NONE) {
|
|
|
|
|
g_object_set(object,
|
|
|
|
|
NM_SETTING_PROXY_PAC_URL,
|
|
|
|
|
NULL,
|
|
|
|
|
NM_SETTING_PROXY_PAC_SCRIPT,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL);
|
|
|
|
|
}
|
2013-11-06 08:16:40 -06:00
|
|
|
}
|
|
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
static void
|
|
|
|
|
wireless_band_channel_changed_cb(GObject *object, GParamSpec *pspec, gpointer user_data)
|
2013-11-06 08:16:40 -06:00
|
|
|
{
|
2017-01-21 00:17:03 +01:00
|
|
|
const char * value = NULL, *mode;
|
|
|
|
|
char str[16];
|
|
|
|
|
NMSettingWireless *s_wireless = NM_SETTING_WIRELESS(object);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
if (strcmp(g_param_spec_get_name(pspec), NM_SETTING_WIRELESS_BAND) == 0) {
|
|
|
|
|
value = nm_setting_wireless_get_band(s_wireless);
|
|
|
|
|
if (!value)
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
guint32 channel = nm_setting_wireless_get_channel(s_wireless);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
if (channel == 0)
|
|
|
|
|
return;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
g_snprintf(str, sizeof(str), "%d", nm_setting_wireless_get_channel(s_wireless));
|
|
|
|
|
value = str;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
mode = nm_setting_wireless_get_mode(NM_SETTING_WIRELESS(object));
|
|
|
|
|
if (!mode || !*mode || strcmp(mode, NM_SETTING_WIRELESS_MODE_INFRA) == 0) {
|
|
|
|
|
g_print(_("Warning: %s.%s set to '%s', but it might be ignored in infrastructure mode\n"),
|
|
|
|
|
nm_setting_get_name(NM_SETTING(s_wireless)),
|
|
|
|
|
g_param_spec_get_name(pspec),
|
|
|
|
|
value);
|
|
|
|
|
}
|
2013-11-06 08:16:40 -06:00
|
|
|
}
|
|
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
static void
|
|
|
|
|
connection_master_changed_cb(GObject *object, GParamSpec *pspec, gpointer user_data)
|
2013-11-06 08:16:40 -06:00
|
|
|
{
|
2017-01-21 00:17:03 +01:00
|
|
|
NMSettingConnection *s_con = NM_SETTING_CONNECTION(object);
|
|
|
|
|
NMConnection * connection = NM_CONNECTION(user_data);
|
|
|
|
|
NMSetting * s_ipv4, *s_ipv6;
|
|
|
|
|
const char * value, *tmp_str;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
value = nm_setting_connection_get_master(s_con);
|
|
|
|
|
if (value) {
|
|
|
|
|
s_ipv4 = nm_connection_get_setting_by_name(connection, NM_SETTING_IP4_CONFIG_SETTING_NAME);
|
|
|
|
|
s_ipv6 = nm_connection_get_setting_by_name(connection, NM_SETTING_IP6_CONFIG_SETTING_NAME);
|
|
|
|
|
if (s_ipv4 || s_ipv6) {
|
|
|
|
|
g_print(_("Warning: setting %s.%s requires removing ipv4 and ipv6 settings\n"),
|
|
|
|
|
nm_setting_get_name(NM_SETTING(s_con)),
|
|
|
|
|
g_param_spec_get_name(pspec));
|
|
|
|
|
tmp_str = nmc_get_user_input(_("Do you want to remove them? [yes] "));
|
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 (!tmp_str || matches(tmp_str, "yes")) {
|
2017-01-21 00:17:03 +01:00
|
|
|
if (s_ipv4)
|
|
|
|
|
nm_connection_remove_setting(connection, G_OBJECT_TYPE(s_ipv4));
|
|
|
|
|
if (s_ipv6)
|
|
|
|
|
nm_connection_remove_setting(connection, G_OBJECT_TYPE(s_ipv6));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-11-06 08:16:40 -06:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
void
|
|
|
|
|
nmc_setting_ip4_connect_handlers(NMSettingIPConfig *setting)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail(NM_IS_SETTING_IP4_CONFIG(setting));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
g_signal_connect(setting,
|
|
|
|
|
"notify::" NM_SETTING_IP_CONFIG_ADDRESSES,
|
|
|
|
|
G_CALLBACK(ipv4_addresses_changed_cb),
|
|
|
|
|
NULL);
|
|
|
|
|
g_signal_connect(setting,
|
|
|
|
|
"notify::" NM_SETTING_IP_CONFIG_METHOD,
|
|
|
|
|
G_CALLBACK(ipv4_method_changed_cb),
|
|
|
|
|
NULL);
|
2013-11-06 08:16:40 -06:00
|
|
|
}
|
|
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
void
|
|
|
|
|
nmc_setting_ip6_connect_handlers(NMSettingIPConfig *setting)
|
2013-11-06 08:16:40 -06:00
|
|
|
{
|
2017-01-21 00:17:03 +01:00
|
|
|
g_return_if_fail(NM_IS_SETTING_IP6_CONFIG(setting));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
g_signal_connect(setting,
|
|
|
|
|
"notify::" NM_SETTING_IP_CONFIG_ADDRESSES,
|
|
|
|
|
G_CALLBACK(ipv6_addresses_changed_cb),
|
|
|
|
|
NULL);
|
|
|
|
|
g_signal_connect(setting,
|
|
|
|
|
"notify::" NM_SETTING_IP_CONFIG_METHOD,
|
|
|
|
|
G_CALLBACK(ipv6_method_changed_cb),
|
|
|
|
|
NULL);
|
|
|
|
|
}
|
2013-11-06 08:16:40 -06:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
void
|
|
|
|
|
nmc_setting_proxy_connect_handlers(NMSettingProxy *setting)
|
2015-10-20 18:35:16 -05:00
|
|
|
{
|
2017-01-21 00:17:03 +01:00
|
|
|
g_return_if_fail(NM_IS_SETTING_PROXY(setting));
|
2015-10-20 18:35:16 -05:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
g_signal_connect(setting,
|
|
|
|
|
"notify::" NM_SETTING_PROXY_METHOD,
|
|
|
|
|
G_CALLBACK(proxy_method_changed_cb),
|
|
|
|
|
NULL);
|
|
|
|
|
}
|
2015-10-20 18:35:16 -05:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
void
|
|
|
|
|
nmc_setting_wireless_connect_handlers(NMSettingWireless *setting)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail(NM_IS_SETTING_WIRELESS(setting));
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
g_signal_connect(setting,
|
|
|
|
|
"notify::" NM_SETTING_WIRELESS_BAND,
|
|
|
|
|
G_CALLBACK(wireless_band_channel_changed_cb),
|
|
|
|
|
NULL);
|
|
|
|
|
g_signal_connect(setting,
|
|
|
|
|
"notify::" NM_SETTING_WIRELESS_CHANNEL,
|
|
|
|
|
G_CALLBACK(wireless_band_channel_changed_cb),
|
|
|
|
|
NULL);
|
2015-10-20 18:35:16 -05:00
|
|
|
}
|
|
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
void
|
|
|
|
|
nmc_setting_connection_connect_handlers(NMSettingConnection *setting, NMConnection *connection)
|
2015-09-01 15:14:03 +02:00
|
|
|
{
|
2017-01-21 00:17:03 +01:00
|
|
|
g_return_if_fail(NM_IS_SETTING_CONNECTION(setting));
|
2015-09-01 15:14:03 +02:00
|
|
|
|
2017-01-21 00:17:03 +01:00
|
|
|
g_signal_connect(setting,
|
|
|
|
|
"notify::" NM_SETTING_CONNECTION_MASTER,
|
|
|
|
|
G_CALLBACK(connection_master_changed_cb),
|
|
|
|
|
connection);
|
2015-09-01 15:14:03 +02:00
|
|
|
}
|
|
|
|
|
|
2017-03-25 15:52:03 +01:00
|
|
|
/*****************************************************************************/
|
2013-01-18 15:21:00 +01:00
|
|
|
|
2017-03-30 17:26:17 +02:00
|
|
|
static gboolean
|
2018-10-09 13:21:02 +02:00
|
|
|
_set_fcn_precheck_connection_secondaries(NMClient * client,
|
|
|
|
|
const char *value,
|
2017-03-30 17:26:17 +02:00
|
|
|
char ** value_coerced,
|
|
|
|
|
GError ** error)
|
|
|
|
|
{
|
|
|
|
|
const GPtrArray * connections;
|
|
|
|
|
NMConnection * con;
|
2017-12-08 10:44:36 +01:00
|
|
|
gs_free const char **strv0 = NULL;
|
2017-03-30 17:26:17 +02:00
|
|
|
gs_strfreev char ** strv = NULL;
|
|
|
|
|
char ** iter;
|
2017-12-08 10:44:36 +01:00
|
|
|
gboolean modified = FALSE;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-04-03 15:44:19 +02:00
|
|
|
strv0 = nm_utils_strsplit_set(value, " \t,");
|
2017-12-08 10:44:36 +01:00
|
|
|
if (!strv0)
|
2017-03-30 17:26:17 +02:00
|
|
|
return TRUE;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2018-10-09 13:21:02 +02:00
|
|
|
connections = nm_client_get_connections(client);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-12-08 10:44:36 +01:00
|
|
|
strv = g_strdupv((char **) strv0);
|
2017-03-30 17:26:17 +02:00
|
|
|
for (iter = strv; *iter; iter++) {
|
|
|
|
|
if (nm_utils_is_uuid(*iter)) {
|
|
|
|
|
con = nmc_find_connection(connections, "uuid", *iter, NULL, FALSE);
|
|
|
|
|
if (!con) {
|
|
|
|
|
g_print(_("Warning: %s is not an UUID of any existing connection profile\n"),
|
|
|
|
|
*iter);
|
|
|
|
|
} else {
|
2020-07-01 17:20:40 -04:00
|
|
|
/* Currently, NM only supports VPN connections as secondaries */
|
2017-03-30 17:26:17 +02:00
|
|
|
if (!nm_connection_is_type(con, NM_SETTING_VPN_SETTING_NAME)) {
|
|
|
|
|
g_set_error(error, 1, 0, _("'%s' is not a VPN connection profile"), *iter);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
con = nmc_find_connection(connections, "id", *iter, NULL, FALSE);
|
|
|
|
|
if (!con) {
|
|
|
|
|
g_set_error(error, 1, 0, _("'%s' is not a name of any exiting profile"), *iter);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2020-07-01 17:20:40 -04:00
|
|
|
/* Currently, NM only supports VPN connections as secondaries */
|
2017-03-30 17:26:17 +02:00
|
|
|
if (!nm_connection_is_type(con, NM_SETTING_VPN_SETTING_NAME)) {
|
|
|
|
|
g_set_error(error, 1, 0, _("'%s' is not a VPN connection profile"), *iter);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 17:26:17 +02:00
|
|
|
/* translate id to uuid */
|
|
|
|
|
g_free(*iter);
|
|
|
|
|
*iter = g_strdup(nm_connection_get_uuid(con));
|
|
|
|
|
modified = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 17:26:17 +02:00
|
|
|
if (modified)
|
|
|
|
|
*value_coerced = g_strjoinv(" ", strv);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 17:26:17 +02:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-03-30 18:07:26 +02:00
|
|
|
static void
|
|
|
|
|
_env_warn_fcn_handle(
|
|
|
|
|
const NMMetaEnvironment *environment,
|
|
|
|
|
gpointer environment_user_data,
|
|
|
|
|
NMMetaEnvWarnLevel warn_level,
|
|
|
|
|
const char *
|
|
|
|
|
fmt_l10n, /* the untranslated format string, but it is marked for translation using N_(). */
|
|
|
|
|
va_list ap)
|
|
|
|
|
{
|
2017-12-01 14:14:24 +01:00
|
|
|
NmCli * nmc = environment_user_data;
|
2017-03-30 18:07:26 +02:00
|
|
|
gs_free char *m = NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-12-01 14:14:24 +01:00
|
|
|
if (nmc->complete)
|
|
|
|
|
return;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 18:07:26 +02:00
|
|
|
NM_PRAGMA_WARNING_DISABLE("-Wformat-nonliteral")
|
|
|
|
|
m = g_strdup_vprintf(_(fmt_l10n), ap);
|
|
|
|
|
NM_PRAGMA_WARNING_REENABLE
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-30 18:07:26 +02:00
|
|
|
switch (warn_level) {
|
|
|
|
|
case NM_META_ENV_WARN_LEVEL_WARN:
|
|
|
|
|
g_print(_("Warning: %s\n"), m);
|
|
|
|
|
return;
|
|
|
|
|
case NM_META_ENV_WARN_LEVEL_INFO:
|
|
|
|
|
g_print(_("Info: %s\n"), m);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
g_print(_("Error: %s\n"), m);
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-11 15:48:04 +02:00
|
|
|
static NMDevice *const *
|
|
|
|
|
_env_get_nm_devices(const NMMetaEnvironment *environment,
|
|
|
|
|
gpointer environment_user_data,
|
|
|
|
|
guint * out_len)
|
|
|
|
|
{
|
|
|
|
|
NmCli * nmc = environment_user_data;
|
|
|
|
|
const GPtrArray *devices;
|
|
|
|
|
|
|
|
|
|
nm_assert(nmc);
|
|
|
|
|
|
|
|
|
|
/* the returned list is *not* NULL terminated. Need to
|
|
|
|
|
* provide and honor the out_len argument. */
|
|
|
|
|
nm_assert(out_len);
|
|
|
|
|
|
|
|
|
|
devices = nm_client_get_devices(nmc->client);
|
|
|
|
|
if (!devices) {
|
|
|
|
|
*out_len = 0;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*out_len = devices->len;
|
|
|
|
|
return (NMDevice *const *) devices->pdata;
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-11 15:48:04 +02:00
|
|
|
static NMRemoteConnection *const *
|
|
|
|
|
_env_get_nm_connections(const NMMetaEnvironment *environment,
|
|
|
|
|
gpointer environment_user_data,
|
|
|
|
|
guint * out_len)
|
|
|
|
|
{
|
|
|
|
|
NmCli * nmc = environment_user_data;
|
|
|
|
|
const GPtrArray *values;
|
|
|
|
|
|
|
|
|
|
nm_assert(nmc);
|
|
|
|
|
|
|
|
|
|
/* the returned list is *not* NULL terminated. Need to
|
|
|
|
|
* provide and honor the out_len argument. */
|
|
|
|
|
nm_assert(out_len);
|
|
|
|
|
|
|
|
|
|
values = nm_client_get_connections(nmc->client);
|
|
|
|
|
if (!values) {
|
|
|
|
|
*out_len = 0;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*out_len = values->len;
|
|
|
|
|
return (NMRemoteConnection *const *) values->pdata;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-30 18:07:26 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-04-07 12:58:13 +02:00
|
|
|
const NMMetaEnvironment *const nmc_meta_environment = &((NMMetaEnvironment){
|
2017-03-30 18:07:26 +02:00
|
|
|
.warn_fcn = _env_warn_fcn_handle,
|
2017-04-11 15:48:04 +02:00
|
|
|
.get_nm_devices = _env_get_nm_devices,
|
2017-04-11 15:48:04 +02:00
|
|
|
.get_nm_connections = _env_get_nm_connections,
|
2017-04-07 12:58:13 +02:00
|
|
|
});
|
|
|
|
|
|
2013-09-11 17:32:00 +02:00
|
|
|
static char *
|
2017-03-28 11:02:03 +02:00
|
|
|
get_property_val(NMSetting * setting,
|
|
|
|
|
const char * prop,
|
|
|
|
|
NMMetaAccessorGetType get_type,
|
|
|
|
|
gboolean show_secrets,
|
|
|
|
|
GError ** error)
|
2013-09-11 17:32:00 +02:00
|
|
|
{
|
2017-03-28 11:02:03 +02:00
|
|
|
const NMMetaPropertyInfo *property_info;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-04-07 13:23:31 +02:00
|
|
|
g_return_val_if_fail(NM_IS_SETTING(setting), NULL);
|
|
|
|
|
g_return_val_if_fail(!error || !*error, NULL);
|
|
|
|
|
g_return_val_if_fail(
|
|
|
|
|
NM_IN_SET(get_type, NM_META_ACCESSOR_GET_TYPE_PARSABLE, NM_META_ACCESSOR_GET_TYPE_PRETTY),
|
|
|
|
|
NULL);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-03-31 16:16:06 +02:00
|
|
|
if ((property_info = nm_meta_property_info_find_by_setting(setting, prop))) {
|
2017-04-06 15:14:23 +02:00
|
|
|
if (property_info->property_type->get_fcn) {
|
2017-04-07 13:23:31 +02:00
|
|
|
NMMetaAccessorGetOutFlags out_flags = NM_META_ACCESSOR_GET_OUT_FLAGS_NONE;
|
|
|
|
|
char * to_free = NULL;
|
|
|
|
|
const char * value;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-04-07 13:23:31 +02:00
|
|
|
value = property_info->property_type->get_fcn(
|
|
|
|
|
property_info,
|
|
|
|
|
nmc_meta_environment,
|
2020-04-02 13:39:39 +02:00
|
|
|
(gpointer) nmc_meta_environment_arg,
|
2017-04-07 13:23:31 +02:00
|
|
|
setting,
|
|
|
|
|
get_type,
|
|
|
|
|
show_secrets ? NM_META_ACCESSOR_GET_FLAGS_SHOW_SECRETS : 0,
|
|
|
|
|
&out_flags,
|
2018-02-27 15:34:49 +01:00
|
|
|
NULL,
|
2017-04-07 13:23:31 +02:00
|
|
|
(gpointer *) &to_free);
|
|
|
|
|
nm_assert(!out_flags);
|
|
|
|
|
return to_free ?: g_strdup(value);
|
2017-03-25 12:56:10 +01:00
|
|
|
}
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-09-11 17:32:00 +02:00
|
|
|
g_set_error_literal(error, 1, 0, _("don't know how to get the property value"));
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-18 15:21:00 +01:00
|
|
|
/*
|
|
|
|
|
* Generic function for getting property value.
|
|
|
|
|
*
|
|
|
|
|
* Gets property value as a string by calling specialized functions.
|
|
|
|
|
*
|
|
|
|
|
* Returns: current property value. The caller must free the returned string.
|
|
|
|
|
*/
|
|
|
|
|
char *
|
|
|
|
|
nmc_setting_get_property(NMSetting *setting, const char *prop, GError **error)
|
|
|
|
|
{
|
2017-03-28 11:02:03 +02:00
|
|
|
return get_property_val(setting, prop, NM_META_ACCESSOR_GET_TYPE_PRETTY, TRUE, error);
|
2013-09-11 17:32:00 +02:00
|
|
|
}
|
2013-01-18 15:21:00 +01:00
|
|
|
|
2013-09-11 17:32:00 +02:00
|
|
|
/*
|
2015-05-21 13:00:40 +02:00
|
|
|
* Similar to nmc_setting_get_property(), but returns the property in a string
|
|
|
|
|
* format that can be parsed via nmc_setting_set_property().
|
2013-09-11 17:32:00 +02:00
|
|
|
*/
|
|
|
|
|
char *
|
2015-05-21 13:00:40 +02:00
|
|
|
nmc_setting_get_property_parsable(NMSetting *setting, const char *prop, GError **error)
|
2013-09-11 17:32:00 +02:00
|
|
|
{
|
2017-03-28 11:02:03 +02:00
|
|
|
return get_property_val(setting, prop, NM_META_ACCESSOR_GET_TYPE_PARSABLE, TRUE, error);
|
2013-01-18 15:21:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
2019-03-18 11:08:41 +01:00
|
|
|
nmc_setting_set_property(NMClient * client,
|
|
|
|
|
NMSetting * setting,
|
|
|
|
|
const char * prop,
|
2019-08-09 09:43:15 +02:00
|
|
|
NMMetaAccessorModifier modifier,
|
2019-03-18 11:08:41 +01:00
|
|
|
const char * value,
|
|
|
|
|
GError ** error)
|
2013-01-18 15:21:00 +01:00
|
|
|
{
|
2017-03-28 11:02:03 +02:00
|
|
|
const NMMetaPropertyInfo *property_info;
|
2019-03-18 11:08:41 +01:00
|
|
|
gs_free char * value_to_free = NULL;
|
2019-03-22 13:26:49 +01:00
|
|
|
gboolean success;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-01-18 15:21:00 +01:00
|
|
|
g_return_val_if_fail(NM_IS_SETTING(setting), FALSE);
|
|
|
|
|
g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
|
2019-08-09 09:43:15 +02:00
|
|
|
g_return_val_if_fail(NM_IN_SET(modifier,
|
|
|
|
|
NM_META_ACCESSOR_MODIFIER_SET,
|
|
|
|
|
NM_META_ACCESSOR_MODIFIER_DEL,
|
|
|
|
|
NM_META_ACCESSOR_MODIFIER_ADD),
|
|
|
|
|
FALSE);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-03-18 10:09:24 +01:00
|
|
|
if (!(property_info = nm_meta_property_info_find_by_setting(setting, prop)))
|
|
|
|
|
goto out_fail_read_only;
|
2019-03-18 11:08:41 +01:00
|
|
|
if (!property_info->property_type->set_fcn)
|
|
|
|
|
goto out_fail_read_only;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-08-09 09:43:15 +02:00
|
|
|
if (modifier == NM_META_ACCESSOR_MODIFIER_DEL
|
2019-03-19 20:39:10 +01:00
|
|
|
&& !property_info->property_type->set_supports_remove) {
|
|
|
|
|
/* The property is a plain property. It does not support '-'.
|
|
|
|
|
*
|
|
|
|
|
* Maybe we should fail, but just return silently. */
|
2019-03-18 11:08:41 +01:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-03-18 15:27:49 +01:00
|
|
|
if (value) {
|
|
|
|
|
switch (property_info->setting_info->general->meta_type) {
|
|
|
|
|
case NM_META_SETTING_TYPE_CONNECTION:
|
|
|
|
|
if (nm_streq(property_info->property_name, NM_SETTING_CONNECTION_SECONDARIES)) {
|
|
|
|
|
if (!_set_fcn_precheck_connection_secondaries(client, value, &value_to_free, error))
|
|
|
|
|
return FALSE;
|
|
|
|
|
if (value_to_free)
|
|
|
|
|
value = value_to_free;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
2019-03-18 11:08:41 +01:00
|
|
|
}
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-08-09 09:43:15 +02:00
|
|
|
if (NM_IN_SET(modifier, NM_META_ACCESSOR_MODIFIER_ADD, NM_META_ACCESSOR_MODIFIER_DEL)
|
2019-08-09 09:21:13 +02:00
|
|
|
&& (!value || !value[0])) {
|
|
|
|
|
/* nothing to do. */
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2019-03-22 13:26:49 +01:00
|
|
|
g_object_freeze_notify(G_OBJECT(setting));
|
|
|
|
|
success = property_info->property_type->set_fcn(property_info,
|
|
|
|
|
nmc_meta_environment,
|
2020-04-02 13:39:39 +02:00
|
|
|
(gpointer) nmc_meta_environment_arg,
|
2019-03-22 13:26:49 +01:00
|
|
|
setting,
|
|
|
|
|
modifier,
|
|
|
|
|
value,
|
|
|
|
|
error);
|
|
|
|
|
g_object_thaw_notify(G_OBJECT(setting));
|
|
|
|
|
return success;
|
2019-03-18 11:08:41 +01:00
|
|
|
|
|
|
|
|
out_fail_read_only:
|
|
|
|
|
nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, _("the property can't be changed"));
|
|
|
|
|
return FALSE;
|
2013-01-18 15:21:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Get valid property names for a setting.
|
|
|
|
|
*
|
|
|
|
|
* Returns: string array with the properties or NULL on failure.
|
|
|
|
|
* The returned value should be freed with g_strfreev()
|
|
|
|
|
*/
|
|
|
|
|
char **
|
|
|
|
|
nmc_setting_get_valid_properties(NMSetting *setting)
|
|
|
|
|
{
|
2018-08-01 17:24:16 +02:00
|
|
|
const NMMetaSettingInfoEditor *setting_info;
|
|
|
|
|
char ** valid_props;
|
|
|
|
|
guint i, num;
|
|
|
|
|
|
|
|
|
|
setting_info = nm_meta_setting_info_editor_find_by_setting(setting);
|
|
|
|
|
|
|
|
|
|
num = setting_info ? setting_info->properties_num : 0;
|
|
|
|
|
|
|
|
|
|
valid_props = g_new(char *, num + 1);
|
|
|
|
|
for (i = 0; i < num; i++)
|
|
|
|
|
valid_props[i] = g_strdup(setting_info->properties[i]->property_name);
|
2013-01-18 15:21:00 +01:00
|
|
|
|
2018-08-01 17:24:16 +02:00
|
|
|
valid_props[num] = NULL;
|
2013-01-18 15:21:00 +01:00
|
|
|
return valid_props;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-25 13:20:11 +01:00
|
|
|
const char *const *
|
2017-03-27 23:11:11 +02:00
|
|
|
nmc_setting_get_property_allowed_values(NMSetting *setting, const char *prop, char ***out_to_free)
|
2013-01-18 15:21:00 +01:00
|
|
|
{
|
2017-03-28 11:02:03 +02:00
|
|
|
const NMMetaPropertyInfo *property_info;
|
2013-01-18 15:21:00 +01:00
|
|
|
|
|
|
|
|
g_return_val_if_fail(NM_IS_SETTING(setting), FALSE);
|
2017-03-27 23:11:11 +02:00
|
|
|
g_return_val_if_fail(out_to_free, FALSE);
|
|
|
|
|
|
|
|
|
|
*out_to_free = NULL;
|
2013-01-18 15:21:00 +01:00
|
|
|
|
2017-03-31 16:16:06 +02:00
|
|
|
if ((property_info = nm_meta_property_info_find_by_setting(setting, prop))) {
|
2017-04-06 15:14:23 +02:00
|
|
|
if (property_info->property_type->values_fcn) {
|
2017-03-31 16:16:06 +02:00
|
|
|
return property_info->property_type->values_fcn(property_info, out_to_free);
|
2017-03-26 09:57:02 +02:00
|
|
|
} else if (property_info->property_typ_data
|
|
|
|
|
&& property_info->property_typ_data->values_static)
|
|
|
|
|
return property_info->property_typ_data->values_static;
|
2017-03-25 13:20:11 +01:00
|
|
|
}
|
|
|
|
|
|
2017-03-26 14:30:17 +02:00
|
|
|
return NULL;
|
2013-01-18 15:21:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Create a description string for a property.
|
|
|
|
|
*
|
2014-05-30 16:45:02 -04:00
|
|
|
* It returns a description got from property documentation, concatenated with
|
2013-01-18 15:21:00 +01:00
|
|
|
* nmcli specific description (if it exists).
|
|
|
|
|
*
|
|
|
|
|
* Returns: property description or NULL on failure. The caller must free the string.
|
|
|
|
|
*/
|
|
|
|
|
char *
|
|
|
|
|
nmc_setting_get_property_desc(NMSetting *setting, const char *prop)
|
|
|
|
|
{
|
2017-03-27 23:11:11 +02:00
|
|
|
gs_free char * desc_to_free = NULL;
|
2014-05-30 16:45:02 -04:00
|
|
|
const char * setting_desc = NULL;
|
2013-01-18 15:21:00 +01:00
|
|
|
const char * setting_desc_title = "";
|
|
|
|
|
const char * nmcli_desc = NULL;
|
|
|
|
|
const char * nmcli_desc_title = "";
|
|
|
|
|
const char * nmcli_nl = "";
|
2017-03-28 11:02:03 +02:00
|
|
|
const NMMetaPropertyInfo *property_info;
|
2017-04-12 09:17:51 +02:00
|
|
|
const char * desc = NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-01-18 15:21:00 +01:00
|
|
|
g_return_val_if_fail(NM_IS_SETTING(setting), FALSE);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-04-12 09:17:51 +02:00
|
|
|
property_info = nm_meta_property_info_find_by_setting(setting, prop);
|
|
|
|
|
if (!property_info)
|
|
|
|
|
return NULL;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-04-12 09:17:51 +02:00
|
|
|
if (property_info->describe_doc) {
|
|
|
|
|
setting_desc = _(property_info->describe_doc);
|
|
|
|
|
setting_desc_title = _("[NM property description]");
|
2013-01-18 15:21:00 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-04-06 15:14:23 +02:00
|
|
|
if (property_info->property_type->describe_fcn) {
|
2017-04-12 09:17:51 +02:00
|
|
|
desc = property_info->property_type->describe_fcn(property_info, &desc_to_free);
|
|
|
|
|
} else
|
2017-04-20 10:22:52 +02:00
|
|
|
desc = _(property_info->describe_message);
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-04-12 09:17:51 +02:00
|
|
|
if (desc) {
|
2017-04-20 10:22:52 +02:00
|
|
|
nmcli_desc = desc;
|
2017-04-12 09:17:51 +02:00
|
|
|
nmcli_desc_title = _("[nmcli specific description]");
|
|
|
|
|
nmcli_nl = "\n";
|
|
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2013-01-18 15:21:00 +01:00
|
|
|
return g_strdup_printf("%s\n%s\n%s%s%s%s",
|
2014-05-30 16:45:02 -04:00
|
|
|
setting_desc_title,
|
2018-04-24 11:20:03 +02:00
|
|
|
setting_desc ?: "",
|
2013-01-18 15:21:00 +01:00
|
|
|
nmcli_nl,
|
|
|
|
|
nmcli_desc_title,
|
|
|
|
|
nmcli_nl,
|
2018-04-24 11:20:03 +02:00
|
|
|
nmcli_desc ?: "");
|
2013-01-18 15:21:00 +01:00
|
|
|
}
|
|
|
|
|
|
2017-03-25 15:52:03 +01:00
|
|
|
/*****************************************************************************/
|
2012-03-05 07:50:28 +01:00
|
|
|
|
2017-03-26 14:30:17 +02:00
|
|
|
gboolean
|
2017-04-06 15:14:23 +02:00
|
|
|
setting_details(const NmcConfig *nmc_config, NMSetting *setting, const char *one_prop)
|
2010-03-31 17:14:35 +02:00
|
|
|
{
|
2017-03-28 11:02:03 +02:00
|
|
|
const NMMetaSettingInfoEditor *setting_info;
|
2017-04-06 15:14:23 +02:00
|
|
|
gs_free_error GError *error = NULL;
|
|
|
|
|
gs_free char * fields_str = NULL;
|
2010-03-31 17:14:35 +02:00
|
|
|
|
2017-03-26 14:30:17 +02:00
|
|
|
g_return_val_if_fail(NM_IS_SETTING(setting), FALSE);
|
|
|
|
|
|
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
|
|
|
setting_info = nm_meta_setting_info_editor_find_by_setting(setting);
|
2017-04-03 14:04:28 +02:00
|
|
|
if (!setting_info)
|
|
|
|
|
return FALSE;
|
2017-03-26 14:30:17 +02:00
|
|
|
|
2017-04-06 15:14:23 +02:00
|
|
|
if (one_prop) {
|
|
|
|
|
/* hack around setting-details being called for one setting. Must prefix the
|
|
|
|
|
* property name with the setting name. Later we should remove setting_details()
|
|
|
|
|
* and merge it into the caller. */
|
|
|
|
|
fields_str = g_strdup_printf("%s.%s", nm_setting_get_name(setting), one_prop);
|
2017-03-24 17:32:04 +01:00
|
|
|
}
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2017-04-06 15:14:23 +02:00
|
|
|
if (!nmc_print(
|
|
|
|
|
nmc_config,
|
|
|
|
|
(gpointer[]){setting, NULL},
|
2018-04-30 13:01:20 +02:00
|
|
|
NULL,
|
2020-09-28 16:03:33 +02:00
|
|
|
NULL,
|
2017-04-06 15:14:23 +02:00
|
|
|
(const NMMetaAbstractInfo *const[]){(const NMMetaAbstractInfo *) setting_info, NULL},
|
|
|
|
|
fields_str,
|
|
|
|
|
&error))
|
|
|
|
|
return FALSE;
|
2020-09-28 16:03:33 +02:00
|
|
|
|
2010-03-31 17:14:35 +02:00
|
|
|
return TRUE;
|
|
|
|
|
}
|