diff options
| author | Michael Biebl <biebl@debian.org> | 2022-01-13 22:30:39 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2022-01-13 22:30:39 +0100 |
| commit | 88c227d90a6b7b388c5c85d72802a0ca8f05ed5c (patch) | |
| tree | 71f32df6617802270e8a78574bd8e1637dc532f4 /src/nmtui | |
| parent | e74c568b07b50b97873fb4ee1d776dedefbd54d6 (diff) | |
New upstream version 1.34.0 upstream/1.34.0
Diffstat (limited to 'src/nmtui')
29 files changed, 1390 insertions, 88 deletions
diff --git a/src/nmtui/meson.build b/src/nmtui/meson.build index fe440175..e6cac268 100644 --- a/src/nmtui/meson.build +++ b/src/nmtui/meson.build @@ -18,6 +18,7 @@ executable( 'nmt-mac-entry.c', 'nmt-mtu-entry.c', 'nmt-page-bond.c', + 'nmt-page-bond-port.c', 'nmt-page-bridge.c', 'nmt-page-bridge-port.c', 'nmt-page-dsl.c', @@ -31,12 +32,15 @@ executable( 'nmt-page-team-port.c', 'nmt-page-vlan.c', 'nmt-page-wifi.c', + 'nmt-page-wireguard.c', 'nmt-password-dialog.c', 'nmt-password-fields.c', 'nmt-route-editor.c', 'nmt-route-entry.c', 'nmt-route-table.c', 'nmt-slave-list.c', + 'nmt-wireguard-peer-list.c', + 'nmt-wireguard-peer-editor.c', 'nmtui.c', 'nmtui-connect.c', 'nmtui-edit.c', diff --git a/src/nmtui/nm-editor-bindings.c b/src/nmtui/nm-editor-bindings.c index 2b1c4748..59474fba 100644 --- a/src/nmtui/nm-editor-bindings.c +++ b/src/nmtui/nm-editor-bindings.c @@ -576,6 +576,229 @@ nm_editor_bind_ip_route_to_strings(int addr_family, NULL); } +gboolean +peer_transform_to_public_key_string(GBinding * binding, + const GValue *source_value, + GValue * target_value, + gpointer user_data) +{ + NMWireGuardPeer *peer; + char * string; + + peer = g_value_get_boxed(source_value); + if (peer && nm_wireguard_peer_get_public_key(peer)) { + string = g_strdup(nm_wireguard_peer_get_public_key(peer)); + g_value_take_string(target_value, string); + } else + g_value_set_string(target_value, ""); + return TRUE; +} + +gboolean +peer_transform_to_allowed_ips_string(GBinding * binding, + const GValue *source_value, + GValue * target_value, + gpointer user_data) +{ + NMWireGuardPeer *peer; + GString * string = NULL; + guint i, len; + + peer = g_value_get_boxed(source_value); + if (!peer) + return TRUE; + + len = nm_wireguard_peer_get_allowed_ips_len(peer); + for (i = 0; i < len; i++) { + if (!string) + string = g_string_new(""); + else + g_string_append_c(string, ','); + g_string_append(string, nm_wireguard_peer_get_allowed_ip(peer, i, NULL)); + } + if (string) + g_value_take_string(target_value, g_string_free(string, FALSE)); + + return TRUE; +} + +gboolean +peer_transform_to_endpoint_string(GBinding * binding, + const GValue *source_value, + GValue * target_value, + gpointer user_data) +{ + NMWireGuardPeer *peer; + char * string; + + peer = g_value_get_boxed(source_value); + if (peer && nm_wireguard_peer_get_endpoint(peer)) { + string = g_strdup_printf("%s", nm_wireguard_peer_get_endpoint(peer)); + g_value_take_string(target_value, string); + } else + g_value_set_string(target_value, ""); + return TRUE; +} + +gboolean +peer_transform_to_preshared_key_string(GBinding * binding, + const GValue *source_value, + GValue * target_value, + gpointer user_data) +{ + NMWireGuardPeer *peer; + char * string; + + peer = g_value_get_boxed(source_value); + if (peer && nm_wireguard_peer_get_preshared_key(peer)) { + string = g_strdup_printf("%s", nm_wireguard_peer_get_preshared_key(peer)); + g_value_take_string(target_value, string); + } else + g_value_set_string(target_value, ""); + return TRUE; +} + +gboolean +peer_transform_to_persistent_keepalive_string(GBinding * binding, + const GValue *source_value, + GValue * target_value, + gpointer user_data) +{ + NMWireGuardPeer *peer; + char * string; + + peer = g_value_get_boxed(source_value); + if (peer && nm_wireguard_peer_get_persistent_keepalive(peer)) { + string = g_strdup_printf("%d", nm_wireguard_peer_get_persistent_keepalive(peer)); + g_value_take_string(target_value, string); + } else + g_value_set_string(target_value, ""); + return TRUE; +} + +gboolean +peer_transform_from_public_key_string(GBinding * binding, + const GValue *source_value, + GValue * target_value, + gpointer user_data) +{ + NMWireGuardPeer *peer; + const char * text; + + text = g_value_get_string(source_value); + + /* Fetch the original property value */ + g_object_get(g_binding_get_source(binding), + g_binding_get_source_property(binding), + &peer, + NULL); + + nm_wireguard_peer_set_public_key(peer, text, TRUE); + + g_value_take_boxed(target_value, peer); + return TRUE; +} + +gboolean +peer_transform_from_allowed_ips_string(GBinding * binding, + const GValue *source_value, + GValue * target_value, + gpointer user_data) +{ + NMWireGuardPeer *peer; + const char * text; + char ** strv; + guint i; + + text = g_value_get_string(source_value); + + /* Fetch the original property value */ + g_object_get(g_binding_get_source(binding), + g_binding_get_source_property(binding), + &peer, + NULL); + + nm_wireguard_peer_clear_allowed_ips(peer); + + strv = g_strsplit(text, ",", -1); + for (i = 0; strv && strv[i]; i++) + nm_wireguard_peer_append_allowed_ip(peer, g_strstrip(strv[i]), TRUE); + g_strfreev(strv); + + g_value_take_boxed(target_value, peer); + return TRUE; +} + +gboolean +peer_transform_from_endpoint_string(GBinding * binding, + const GValue *source_value, + GValue * target_value, + gpointer user_data) +{ + NMWireGuardPeer *peer; + const char * text; + + text = g_value_get_string(source_value); + + /* Fetch the original property value */ + g_object_get(g_binding_get_source(binding), + g_binding_get_source_property(binding), + &peer, + NULL); + + nm_wireguard_peer_set_endpoint(peer, text, TRUE); + + g_value_take_boxed(target_value, peer); + return TRUE; +} + +gboolean +peer_transform_from_preshared_key_string(GBinding * binding, + const GValue *source_value, + GValue * target_value, + gpointer user_data) +{ + NMWireGuardPeer *peer; + const char * text; + + text = g_value_get_string(source_value); + + /* Fetch the original property value */ + g_object_get(g_binding_get_source(binding), + g_binding_get_source_property(binding), + &peer, + NULL); + + nm_wireguard_peer_set_preshared_key(peer, text && text[0] ? text : NULL, TRUE); + nm_wireguard_peer_set_preshared_key_flags(peer, NM_SETTING_SECRET_FLAG_NONE); + + g_value_take_boxed(target_value, peer); + return TRUE; +} + +gboolean +peer_transform_from_persistent_keepalive_string(GBinding * binding, + const GValue *source_value, + GValue * target_value, + gpointer user_data) +{ + NMWireGuardPeer *peer; + const char * text; + + text = g_value_get_string(source_value); + + /* Fetch the original property value */ + g_object_get(g_binding_get_source(binding), + g_binding_get_source_property(binding), + &peer, + NULL); + + nm_wireguard_peer_set_persistent_keepalive(peer, atoi(text)); + + g_value_take_boxed(target_value, peer); + return TRUE; +} + /* Wireless security method binding */ typedef struct { NMConnection * connection; diff --git a/src/nmtui/nm-editor-bindings.h b/src/nmtui/nm-editor-bindings.h index 027a59a9..a9bf51ed 100644 --- a/src/nmtui/nm-editor-bindings.h +++ b/src/nmtui/nm-editor-bindings.h @@ -53,4 +53,54 @@ void nm_editor_bind_wireless_security_wep_key(NMSettingWirelessSecurity *s_wsec, void nm_editor_bind_vlan_name(NMSettingVlan *s_vlan, NMSettingConnection *s_con); +gboolean peer_transform_to_public_key_string(GBinding * binding, + const GValue *source_value, + GValue * target_value, + gpointer user_data); + +gboolean peer_transform_to_allowed_ips_string(GBinding * binding, + const GValue *source_value, + GValue * target_value, + gpointer user_data); + +gboolean peer_transform_to_endpoint_string(GBinding * binding, + const GValue *source_value, + GValue * target_value, + gpointer user_data); + +gboolean peer_transform_to_preshared_key_string(GBinding * binding, + const GValue *source_value, + GValue * target_value, + gpointer user_data); + +gboolean peer_transform_to_persistent_keepalive_string(GBinding * binding, + const GValue *source_value, + GValue * target_value, + gpointer user_data); + +gboolean peer_transform_from_public_key_string(GBinding * binding, + const GValue *source_value, + GValue * target_value, + gpointer user_data); + +gboolean peer_transform_from_allowed_ips_string(GBinding * binding, + const GValue *source_value, + GValue * target_value, + gpointer user_data); + +gboolean peer_transform_from_endpoint_string(GBinding * binding, + const GValue *source_value, + GValue * target_value, + gpointer user_data); + +gboolean peer_transform_from_preshared_key_string(GBinding * binding, + const GValue *source_value, + GValue * target_value, + gpointer user_data); + +gboolean peer_transform_from_persistent_keepalive_string(GBinding * binding, + const GValue *source_value, + GValue * target_value, + gpointer user_data); + #endif /* NM_EDITOR_BINDINGS_H */ diff --git a/src/nmtui/nm-editor-utils.c b/src/nmtui/nm-editor-utils.c index c6b03bd8..2b6acbbe 100644 --- a/src/nmtui/nm-editor-utils.c +++ b/src/nmtui/nm-editor-utils.c @@ -16,7 +16,7 @@ #include "nm-editor-utils.h" #if 0 - #include "libnmc-base/nm-vpn-helpers.h" +#include "libnmc-base/nm-vpn-helpers.h" static GSList *vpn_plugins; @@ -66,6 +66,22 @@ bond_connection_setup_func(NMConnection *connection, NMSettingConnection *s_con, } } +static void +wireguard_connection_setup_func(NMConnection * connection, + NMSettingConnection *s_con, + NMSetting * s_hw) +{ + NMSettingIPConfig *s_ip; + + s_ip = (NMSettingIPConfig *) nm_setting_ip4_config_new(); + g_object_set(s_ip, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_DISABLED, NULL); + nm_connection_add_setting(connection, (NMSetting *) s_ip); + + s_ip = (NMSettingIPConfig *) nm_setting_ip6_config_new(); + g_object_set(s_ip, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_DISABLED, NULL); + nm_connection_add_setting(connection, (NMSetting *) s_ip); +} + typedef void (*NMEditorNewConnectionSetupFunc)(NMConnection * connection, NMSettingConnection *s_con, NMSetting * s_hw); @@ -243,6 +259,15 @@ nm_editor_utils_get_connection_type_list(void) } #endif + item = g_new0(NMEditorConnectionTypeDataReal, 1); + item->data.name = _("WireGuard"); + item->data.setting_type = NM_TYPE_SETTING_WIREGUARD; + item->data.device_type = NM_TYPE_DEVICE_WIREGUARD; + item->data.virtual = TRUE; + item->id_format = _("WireGuard connection %d"); + item->connection_setup_func = wireguard_connection_setup_func; + g_ptr_array_add(array, item); + g_ptr_array_sort(array, sort_types); g_ptr_array_add(array, NULL); diff --git a/src/nmtui/nmt-connect-connection-list.c b/src/nmtui/nmt-connect-connection-list.c index 4503dc92..486e1400 100644 --- a/src/nmtui/nmt-connect-connection-list.c +++ b/src/nmtui/nmt-connect-connection-list.c @@ -100,6 +100,7 @@ static const char *device_sort_order[] = {"NMDeviceEthernet", NM_SETTING_TEAM_SETTING_NAME, NM_SETTING_BRIDGE_SETTING_NAME, NM_SETTING_IP_TUNNEL_SETTING_NAME, + NM_SETTING_WIREGUARD_SETTING_NAME, "NMDeviceModem", "NMDeviceBt"}; static const int device_sort_order_len = G_N_ELEMENTS(device_sort_order); diff --git a/src/nmtui/nmt-editor.c b/src/nmtui/nmt-editor.c index 0ef23693..94e9b7a8 100644 --- a/src/nmtui/nmt-editor.c +++ b/src/nmtui/nmt-editor.c @@ -26,6 +26,7 @@ #include "nmt-mtu-entry.h" #include "nmt-page-bond.h" +#include "nmt-page-bond-port.h" #include "nmt-page-bridge.h" #include "nmt-page-bridge-port.h" #include "nmt-page-dsl.h" @@ -39,6 +40,7 @@ #include "nmt-page-team-port.h" #include "nmt-page-vlan.h" #include "nmt-page-wifi.h" +#include "nmt-page-wireguard.h" #include "libnmc-setting/nm-meta-setting-access.h" @@ -372,6 +374,8 @@ nmt_editor_constructed(GObject *object) page = nmt_page_wifi_new(priv->edit_connection, deventry); else if (nm_connection_is_type(priv->edit_connection, NM_SETTING_IP_TUNNEL_SETTING_NAME)) page = nmt_page_ip_tunnel_new(priv->edit_connection, deventry); + else if (nm_connection_is_type(priv->edit_connection, NM_SETTING_WIREGUARD_SETTING_NAME)) + page = nmt_page_wireguard_new(priv->edit_connection, deventry); else g_assert_not_reached(); @@ -384,6 +388,8 @@ nmt_editor_constructed(GObject *object) add_sections_for_page(editor, grid, nmt_page_bridge_port_new(priv->edit_connection)); else if (!strcmp(slave_type, NM_SETTING_TEAM_SETTING_NAME)) add_sections_for_page(editor, grid, nmt_page_team_port_new(priv->edit_connection)); + else if (nm_streq(slave_type, NM_SETTING_BOND_SETTING_NAME)) + add_sections_for_page(editor, grid, nmt_page_bond_port_new(priv->edit_connection)); } else { NmtNewtWidget *section; diff --git a/src/nmtui/nmt-editor.h b/src/nmtui/nmt-editor.h index 49fe89d3..602a61ae 100644 --- a/src/nmtui/nmt-editor.h +++ b/src/nmtui/nmt-editor.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2013 Red Hat, Inc. */ diff --git a/src/nmtui/nmt-page-bond-port.c b/src/nmtui/nmt-page-bond-port.c new file mode 100644 index 00000000..156553c2 --- /dev/null +++ b/src/nmtui/nmt-page-bond-port.c @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021 Red Hat, Inc. + */ + +/** + * SECTION:nmt-page-bond-port + * @short_description: The editor page for Bond ports + */ + +#include "libnm-client-aux-extern/nm-default-client.h" + +#include "nmt-page-bond-port.h" + +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" + +G_DEFINE_TYPE(NmtPageBondPort, nmt_page_bond_port, NMT_TYPE_EDITOR_PAGE) + +static void +nmt_page_bond_port_init(NmtPageBondPort *bond) +{} + +NmtEditorPage * +nmt_page_bond_port_new(NMConnection *conn) +{ + return g_object_new(NMT_TYPE_PAGE_BOND_PORT, "connection", conn, NULL); +} + +static void +nmt_page_bond_port_constructed(GObject *object) +{ + NmtPageBondPort * bond = NMT_PAGE_BOND_PORT(object); + NmtEditorSection * section; + NmtEditorGrid * grid; + NMSettingBondPort *s_port; + NmtNewtWidget * widget; + NMConnection * conn; + + conn = nmt_editor_page_get_connection(NMT_EDITOR_PAGE(bond)); + s_port = _nm_connection_ensure_setting(conn, NM_TYPE_SETTING_BOND_PORT); + + section = nmt_editor_section_new(_("BOND PORT"), NULL, TRUE); + grid = nmt_editor_section_get_body(section); + + widget = nmt_newt_entry_numeric_new(10, 0, 63); + g_object_bind_property(s_port, + NM_SETTING_BOND_PORT_QUEUE_ID, + widget, + "text", + G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); + nmt_editor_grid_append(grid, _("Queue ID"), widget, NULL); + + nmt_editor_page_add_section(NMT_EDITOR_PAGE(bond), section); + + G_OBJECT_CLASS(nmt_page_bond_port_parent_class)->constructed(object); +} + +static void +nmt_page_bond_port_class_init(NmtPageBondPortClass *bond_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS(bond_class); + + object_class->constructed = nmt_page_bond_port_constructed; +} diff --git a/src/nmtui/nmt-page-bond-port.h b/src/nmtui/nmt-page-bond-port.h new file mode 100644 index 00000000..387acf4c --- /dev/null +++ b/src/nmtui/nmt-page-bond-port.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021 Red Hat, Inc. + */ + +#ifndef NMT_PAGE_BOND_PORT_H +#define NMT_PAGE_BOND_PORT_H + +#include "nmt-editor-page-device.h" + +#define NMT_TYPE_PAGE_BOND_PORT (nmt_page_bond_port_get_type()) +#define NMT_PAGE_BOND_PORT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_BOND_PORT, NmtPageBondPort)) +#define NMT_PAGE_BOND_PORT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_PAGE_BOND_PORT, NmtPageBondPortClass)) +#define NMT_IS_PAGE_BOND_PORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_PAGE_BOND_PORT)) +#define NMT_IS_PAGE_BOND_PORT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NMT_TYPE_PAGE_BOND_PORT)) +#define NMT_PAGE_BOND_PORT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NMT_TYPE_PAGE_BOND_PORT, NmtPageBondPortClass)) + +typedef struct { + NmtEditorPage parent; + +} NmtPageBondPort; + +typedef struct { + NmtEditorPageClass parent; + +} NmtPageBondPortClass; + +GType nmt_page_bond_port_get_type(void); + +NmtEditorPage *nmt_page_bond_port_new(NMConnection *conn); + +#endif /* NMT_PAGE_BOND_PORT_H */ diff --git a/src/nmtui/nmt-page-bond.c b/src/nmtui/nmt-page-bond.c index d3fab1ff..aea7949e 100644 --- a/src/nmtui/nmt-page-bond.c +++ b/src/nmtui/nmt-page-bond.c @@ -334,20 +334,11 @@ nmt_page_bond_constructed(GObject *object) NmtNewtWidget * widget, *label; NMConnection * conn; - conn = nmt_editor_page_get_connection(NMT_EDITOR_PAGE(bond)); - s_bond = nm_connection_get_setting_bond(conn); - if (!s_bond) { - nm_connection_add_setting(conn, nm_setting_bond_new()); - s_bond = nm_connection_get_setting_bond(conn); - } + conn = nmt_editor_page_get_connection(NMT_EDITOR_PAGE(bond)); + s_bond = _nm_connection_ensure_setting(conn, NM_TYPE_SETTING_BOND); priv->s_bond = s_bond; - s_wired = nm_connection_get_setting_wired(conn); - if (!s_wired) { - nm_connection_add_setting(conn, nm_setting_wired_new()); - s_wired = nm_connection_get_setting_wired(conn); - } - + s_wired = _nm_connection_ensure_setting(conn, NM_TYPE_SETTING_WIRED); section = nmt_editor_section_new(_("BOND"), NULL, TRUE); grid = nmt_editor_section_get_body(section); diff --git a/src/nmtui/nmt-page-bridge-port.c b/src/nmtui/nmt-page-bridge-port.c index 30163d15..f6c18d7c 100644 --- a/src/nmtui/nmt-page-bridge-port.c +++ b/src/nmtui/nmt-page-bridge-port.c @@ -12,6 +12,8 @@ #include "nmt-page-bridge-port.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" + G_DEFINE_TYPE(NmtPageBridgePort, nmt_page_bridge_port, NMT_TYPE_EDITOR_PAGE) NmtEditorPage * @@ -35,11 +37,7 @@ nmt_page_bridge_port_constructed(GObject *object) NMConnection * conn; conn = nmt_editor_page_get_connection(NMT_EDITOR_PAGE(bridge)); - s_port = nm_connection_get_setting_bridge_port(conn); - if (!s_port) { - nm_connection_add_setting(conn, nm_setting_bridge_port_new()); - s_port = nm_connection_get_setting_bridge_port(conn); - } + s_port = _nm_connection_ensure_setting(conn, NM_TYPE_SETTING_BRIDGE_PORT); section = nmt_editor_section_new(_("BRIDGE PORT"), NULL, TRUE); grid = nmt_editor_section_get_body(section); diff --git a/src/nmtui/nmt-page-bridge.c b/src/nmtui/nmt-page-bridge.c index 52af8db1..684b17bd 100644 --- a/src/nmtui/nmt-page-bridge.c +++ b/src/nmtui/nmt-page-bridge.c @@ -12,6 +12,7 @@ #include "nmt-page-bridge.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "nmt-address-list.h" #include "nmt-slave-list.h" @@ -53,11 +54,7 @@ nmt_page_bridge_constructed(GObject *object) NMConnection * conn; conn = nmt_editor_page_get_connection(NMT_EDITOR_PAGE(bridge)); - s_bridge = nm_connection_get_setting_bridge(conn); - if (!s_bridge) { - nm_connection_add_setting(conn, nm_setting_bridge_new()); - s_bridge = nm_connection_get_setting_bridge(conn); - } + s_bridge = _nm_connection_ensure_setting(conn, NM_TYPE_SETTING_BRIDGE); section = nmt_editor_section_new(_("BRIDGE"), NULL, TRUE); grid = nmt_editor_section_get_body(section); diff --git a/src/nmtui/nmt-page-dsl.c b/src/nmtui/nmt-page-dsl.c index d7e0d144..a0d8cdf4 100644 --- a/src/nmtui/nmt-page-dsl.c +++ b/src/nmtui/nmt-page-dsl.c @@ -11,6 +11,8 @@ #include "libnm-client-aux-extern/nm-default-client.h" #include "nmt-page-dsl.h" + +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "nmt-page-ethernet.h" #include "nmt-page-ppp.h" #include "nmt-password-fields.h" @@ -83,11 +85,7 @@ nmt_page_dsl_constructed(GObject *object) const GSList * sections, *iter; conn = nmt_editor_page_get_connection(NMT_EDITOR_PAGE(dsl)); - s_pppoe = nm_connection_get_setting_pppoe(conn); - if (!s_pppoe) { - nm_connection_add_setting(conn, nm_setting_pppoe_new()); - s_pppoe = nm_connection_get_setting_pppoe(conn); - } + s_pppoe = _nm_connection_ensure_setting(conn, NM_TYPE_SETTING_PPPOE); section = build_dsl_section(dsl, s_pppoe); nmt_editor_page_add_section(NMT_EDITOR_PAGE(dsl), section); diff --git a/src/nmtui/nmt-page-ethernet.c b/src/nmtui/nmt-page-ethernet.c index f5dc9119..addbd3f3 100644 --- a/src/nmtui/nmt-page-ethernet.c +++ b/src/nmtui/nmt-page-ethernet.c @@ -15,6 +15,7 @@ #include <linux/if_ether.h> #include <linux/if_infiniband.h> +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "nmt-mac-entry.h" #include "nmt-mtu-entry.h" @@ -42,11 +43,7 @@ nmt_page_ethernet_constructed(GObject *object) NMConnection * conn; conn = nmt_editor_page_get_connection(NMT_EDITOR_PAGE(ethernet)); - s_wired = nm_connection_get_setting_wired(conn); - if (!s_wired) { - nm_connection_add_setting(conn, nm_setting_wired_new()); - s_wired = nm_connection_get_setting_wired(conn); - } + s_wired = _nm_connection_ensure_setting(conn, NM_TYPE_SETTING_WIRED); deventry = nmt_editor_page_device_get_device_entry(NMT_EDITOR_PAGE_DEVICE(object)); g_object_bind_property(s_wired, diff --git a/src/nmtui/nmt-page-infiniband.c b/src/nmtui/nmt-page-infiniband.c index c0e3611b..1216208f 100644 --- a/src/nmtui/nmt-page-infiniband.c +++ b/src/nmtui/nmt-page-infiniband.c @@ -11,6 +11,8 @@ #include "libnm-client-aux-extern/nm-default-client.h" #include "nmt-page-infiniband.h" + +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "nmt-mtu-entry.h" G_DEFINE_TYPE(NmtPageInfiniband, nmt_page_infiniband, NMT_TYPE_EDITOR_PAGE_DEVICE) @@ -46,11 +48,7 @@ nmt_page_infiniband_constructed(GObject *object) NMConnection * conn; conn = nmt_editor_page_get_connection(NMT_EDITOR_PAGE(infiniband)); - s_ib = nm_connection_get_setting_infiniband(conn); - if (!s_ib) { - nm_connection_add_setting(conn, nm_setting_infiniband_new()); - s_ib = nm_connection_get_setting_infiniband(conn); - } + s_ib = _nm_connection_ensure_setting(conn, NM_TYPE_SETTING_INFINIBAND); /* initialize 'transport-mode' if it is NULL */ if (!nm_setting_infiniband_get_transport_mode(s_ib)) { g_object_set(G_OBJECT(s_ib), NM_SETTING_INFINIBAND_TRANSPORT_MODE, "datagram", NULL); diff --git a/src/nmtui/nmt-page-ip-tunnel.c b/src/nmtui/nmt-page-ip-tunnel.c index da6d12b9..96864919 100644 --- a/src/nmtui/nmt-page-ip-tunnel.c +++ b/src/nmtui/nmt-page-ip-tunnel.c @@ -11,6 +11,7 @@ #include "nmt-page-ip-tunnel.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "nmt-device-entry.h" #include "nmt-mtu-entry.h" @@ -102,11 +103,7 @@ nmt_page_ip_tunnel_constructed(GObject *object) GClosure * s2w, *w2s; conn = nmt_editor_page_get_connection(NMT_EDITOR_PAGE(ip_tunnel)); - s_ip_tunnel = nm_connection_get_setting_ip_tunnel(conn); - if (!s_ip_tunnel) { - nm_connection_add_setting(conn, nm_setting_ip_tunnel_new()); - s_ip_tunnel = nm_connection_get_setting_ip_tunnel(conn); - } + s_ip_tunnel = _nm_connection_ensure_setting(conn, NM_TYPE_SETTING_IP_TUNNEL); /* Initialize the mode for new connections */ if (nm_setting_ip_tunnel_get_mode(s_ip_tunnel) == NM_IP_TUNNEL_MODE_UNKNOWN) { diff --git a/src/nmtui/nmt-page-ip4.c b/src/nmtui/nmt-page-ip4.c index ecd71447..a7e4bdae 100644 --- a/src/nmtui/nmt-page-ip4.c +++ b/src/nmtui/nmt-page-ip4.c @@ -10,9 +10,11 @@ #include "libnm-client-aux-extern/nm-default-client.h" +#include "nmt-page-ip4.h" + #include <stdlib.h> -#include "nmt-page-ip4.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "nmt-ip-entry.h" #include "nmt-address-list.h" #include "nmt-route-editor.h" @@ -84,14 +86,13 @@ nmt_page_ip4_constructed(GObject *object) NMConnection * conn; conn = nmt_editor_page_get_connection(NMT_EDITOR_PAGE(ip4)); - s_ip4 = nm_connection_get_setting_ip4_config(conn); - if (!s_ip4) { - s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); + s_ip4 = _nm_connection_ensure_setting(conn, NM_TYPE_SETTING_IP4_CONFIG); + /* initialize 'method' to auto if it is NULL */ + if (!nm_setting_ip_config_get_method(s_ip4)) { g_object_set(G_OBJECT(s_ip4), NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); - nm_connection_add_setting(conn, (NMSetting *) s_ip4); } widget = nmt_newt_popup_new(ip4methods); diff --git a/src/nmtui/nmt-page-ip6.c b/src/nmtui/nmt-page-ip6.c index f79c553d..0d4de65a 100644 --- a/src/nmtui/nmt-page-ip6.c +++ b/src/nmtui/nmt-page-ip6.c @@ -10,9 +10,11 @@ #include "libnm-client-aux-extern/nm-default-client.h" +#include "nmt-page-ip6.h" + #include <stdlib.h> -#include "nmt-page-ip6.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "nmt-ip-entry.h" #include "nmt-address-list.h" #include "nmt-route-editor.h" @@ -85,14 +87,13 @@ nmt_page_ip6_constructed(GObject *object) NMConnection * conn; conn = nmt_editor_page_get_connection(NMT_EDITOR_PAGE(ip6)); - s_ip6 = nm_connection_get_setting_ip6_config(conn); - if (!s_ip6) { - s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); + s_ip6 = _nm_connection_ensure_setting(conn, NM_TYPE_SETTING_IP6_CONFIG); + /* initialize 'method' to auto if it is NULL */ + if (!nm_setting_ip_config_get_method(s_ip6)) { g_object_set(G_OBJECT(s_ip6), NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL); - nm_connection_add_setting(conn, (NMSetting *) s_ip6); } widget = nmt_newt_popup_new(ip6methods); diff --git a/src/nmtui/nmt-page-team-port.c b/src/nmtui/nmt-page-team-port.c index 13bb84f0..c1f3cbc6 100644 --- a/src/nmtui/nmt-page-team-port.c +++ b/src/nmtui/nmt-page-team-port.c @@ -12,6 +12,8 @@ #include "nmt-page-team-port.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" + G_DEFINE_TYPE(NmtPageTeamPort, nmt_page_team_port, NMT_TYPE_EDITOR_PAGE) #define NMT_PAGE_TEAM_PORT_GET_PRIVATE(o) \ @@ -63,12 +65,8 @@ nmt_page_team_port_constructed(GObject *object) NmtNewtWidget * widget; NMConnection * conn; - conn = nmt_editor_page_get_connection(NMT_EDITOR_PAGE(team)); - s_port = nm_connection_get_setting_team_port(conn); - if (!s_port) { - nm_connection_add_setting(conn, nm_setting_team_port_new()); - s_port = nm_connection_get_setting_team_port(conn); - } + conn = nmt_editor_page_get_connection(NMT_EDITOR_PAGE(team)); + s_port = _nm_connection_ensure_setting(conn, NM_TYPE_SETTING_TEAM_PORT); priv->s_port = s_port; section = nmt_editor_section_new(_("TEAM PORT"), NULL, TRUE); diff --git a/src/nmtui/nmt-page-team.c b/src/nmtui/nmt-page-team.c index 3cda1257..d61c06c5 100644 --- a/src/nmtui/nmt-page-team.c +++ b/src/nmtui/nmt-page-team.c @@ -12,6 +12,7 @@ #include "nmt-page-team.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "nmt-slave-list.h" G_DEFINE_TYPE(NmtPageTeam, nmt_page_team, NMT_TYPE_EDITOR_PAGE_DEVICE) @@ -111,12 +112,8 @@ nmt_page_team_constructed(GObject *object) NmtNewtWidget * widget; NMConnection * conn; - conn = nmt_editor_page_get_connection(NMT_EDITOR_PAGE(team)); - s_team = nm_connection_get_setting_team(conn); - if (!s_team) { - nm_connection_add_setting(conn, nm_setting_team_new()); - s_team = nm_connection_get_setting_team(conn); - } + conn = nmt_editor_page_get_connection(NMT_EDITOR_PAGE(team)); + s_team = _nm_connection_ensure_setting(conn, NM_TYPE_SETTING_TEAM); priv->s_team = s_team; section = nmt_editor_section_new(_("TEAM"), NULL, TRUE); diff --git a/src/nmtui/nmt-page-vlan.c b/src/nmtui/nmt-page-vlan.c index 299a7267..5baf9756 100644 --- a/src/nmtui/nmt-page-vlan.c +++ b/src/nmtui/nmt-page-vlan.c @@ -10,11 +10,12 @@ #include "libnm-client-aux-extern/nm-default-client.h" -#include "nm-editor-bindings.h" +#include "nmt-page-vlan.h" #include <linux/if_ether.h> -#include "nmt-page-vlan.h" +#include "nm-editor-bindings.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "nmt-device-entry.h" #include "nmt-mac-entry.h" #include "nmt-mtu-entry.h" @@ -49,17 +50,9 @@ nmt_page_vlan_constructed(GObject *object) NmtNewtWidget * widget, *parent, *id_entry; NMConnection * conn; - conn = nmt_editor_page_get_connection(NMT_EDITOR_PAGE(vlan)); - s_vlan = nm_connection_get_setting_vlan(conn); - if (!s_vlan) { - nm_connection_add_setting(conn, nm_setting_vlan_new()); - s_vlan = nm_connection_get_setting_vlan(conn); - } - s_wired = nm_connection_get_setting_wired(conn); - if (!s_wired) { - nm_connection_add_setting(conn, nm_setting_wired_new()); - s_wired = nm_connection_get_setting_wired(conn); - } + conn = nmt_editor_page_get_connection(NMT_EDITOR_PAGE(vlan)); + s_vlan = _nm_connection_ensure_setting(conn, NM_TYPE_SETTING_VLAN); + s_wired = _nm_connection_ensure_setting(conn, NM_TYPE_SETTING_WIRED); section = nmt_editor_section_new(_("VLAN"), NULL, TRUE); grid = nmt_editor_section_get_body(section); diff --git a/src/nmtui/nmt-page-wifi.c b/src/nmtui/nmt-page-wifi.c index 247a0e4e..1a476b02 100644 --- a/src/nmtui/nmt-page-wifi.c +++ b/src/nmtui/nmt-page-wifi.c @@ -14,10 +14,12 @@ #include "libnm-client-aux-extern/nm-default-client.h" +#include "nmt-page-wifi.h" + #include <stdlib.h> #include <linux/if_ether.h> -#include "nmt-page-wifi.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "nmt-mac-entry.h" #include "nmt-mtu-entry.h" #include "nmt-password-fields.h" @@ -164,13 +166,8 @@ nmt_page_wifi_constructed(GObject *object) NMConnection * conn; conn = nmt_editor_page_get_connection(NMT_EDITOR_PAGE(wifi)); - s_wireless = nm_connection_get_setting_wireless(conn); - if (!s_wireless) { - nm_connection_add_setting(conn, nm_setting_wireless_new()); - s_wireless = nm_connection_get_setting_wireless(conn); - } - - s_wsec = nm_connection_get_setting_wireless_security(conn); + s_wireless = _nm_connection_ensure_setting(conn, NM_TYPE_SETTING_WIRELESS); + s_wsec = nm_connection_get_setting_wireless_security(conn); if (!s_wsec) { /* It makes things simpler if we always have a * NMSettingWirelessSecurity; we'll hold a ref on one, and add diff --git a/src/nmtui/nmt-page-wireguard.c b/src/nmtui/nmt-page-wireguard.c new file mode 100644 index 00000000..30a984e0 --- /dev/null +++ b/src/nmtui/nmt-page-wireguard.c @@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2021 Red Hat, Inc. + */ +/** + * SECTION:nmt-page-wireguard + * @short_description: The editor page for WireGuard connections + */ + +#include "libnm-client-aux-extern/nm-default-client.h" + +#include "nmt-page-wireguard.h" + +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" +#include "nmt-device-entry.h" +#include "nmt-mtu-entry.h" +#include "nmt-wireguard-peer-list.h" + +G_DEFINE_TYPE(NmtPageWireGuard, nmt_page_wireguard, NMT_TYPE_EDITOR_PAGE_DEVICE) + +#define NMT_PAGE_WIREGUARD_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NMT_TYPE_PAGE_WIREGUARD, NmtPageWireGuardPrivate)) + +typedef struct { + NmtWireguardPeerList *peers; +} NmtPageWireGuardPrivate; + +NmtEditorPage * +nmt_page_wireguard_new(NMConnection *conn, NmtDeviceEntry *deventry) +{ + return g_object_new(NMT_TYPE_PAGE_WIREGUARD, + "connection", + conn, + "device-entry", + deventry, + NULL); +} + +static void +nmt_page_wireguard_init(NmtPageWireGuard *wireguard) +{} + +static void +nmt_page_wireguard_constructed(GObject *object) +{ + NmtPageWireGuard * wireguard = NMT_PAGE_WIREGUARD(object); + NmtPageWireGuardPrivate *priv = NMT_PAGE_WIREGUARD_GET_PRIVATE(wireguard); + NmtEditorSection * section; + NmtEditorGrid * grid; + NMSettingWireGuard * s_wireguard; + NmtNewtWidget * widget; + NMConnection * conn; + + conn = nmt_editor_page_get_connection(NMT_EDITOR_PAGE(wireguard)); + s_wireguard = _nm_connection_ensure_setting(conn, NM_TYPE_SETTING_WIREGUARD); + + section = nmt_editor_section_new(_("WireGuard"), NULL, TRUE); + grid = nmt_editor_section_get_body(section); + + widget = nmt_newt_entry_new(40, 0); + nmt_editor_grid_append(grid, _("Private key"), widget, NULL); + g_object_bind_property(s_wireguard, + NM_SETTING_WIREGUARD_PRIVATE_KEY, + widget, + "text", + G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL); + + widget = nmt_newt_entry_new(40, 0); + nmt_editor_grid_append(grid, _("Listen port"), widget, NULL); + g_object_bind_property(s_wireguard, + NM_SETTING_WIREGUARD_LISTEN_PORT, + widget, + "text", + G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL); + + widget = nmt_newt_entry_new(40, 0); + nmt_editor_grid_append(grid, _("Fwmark"), widget, NULL); + g_object_bind_property(s_wireguard, + NM_SETTING_WIREGUARD_FWMARK, + widget, + "text", + G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL); + + widget = nmt_mtu_entry_new(); + nmt_editor_grid_append(grid, _("MTU"), widget, NULL); + g_object_bind_property(s_wireguard, + NM_SETTING_WIREGUARD_MTU, + widget, + "mtu", + G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL); + + widget = nmt_newt_checkbox_new(_("Add peer routes")); + nmt_editor_grid_append(grid, NULL, widget, NULL); + g_object_bind_property(s_wireguard, + NM_SETTING_WIREGUARD_PEER_ROUTES, + widget, + "active", + G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL); + + widget = nmt_newt_separator_new(); + nmt_editor_grid_append(grid, _("Peers"), widget, NULL); + nmt_editor_grid_set_row_flags(grid, widget, NMT_EDITOR_GRID_ROW_LABEL_ALIGN_LEFT); + + widget = nmt_wireguard_peer_list_new(s_wireguard); + nmt_editor_grid_append(grid, NULL, widget, NULL); + priv->peers = NMT_WIREGUARD_PEER_LIST(widget); + + nmt_editor_page_add_section(NMT_EDITOR_PAGE(wireguard), section); + + G_OBJECT_CLASS(nmt_page_wireguard_parent_class)->constructed(object); +} + +static void +nmt_page_wireguard_class_init(NmtPageWireGuardClass *wireguard_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS(wireguard_class); + + g_type_class_add_private(wireguard_class, sizeof(NmtPageWireGuardPrivate)); + + object_class->constructed = nmt_page_wireguard_constructed; +} diff --git a/src/nmtui/nmt-page-wireguard.h b/src/nmtui/nmt-page-wireguard.h new file mode 100644 index 00000000..8e39139c --- /dev/null +++ b/src/nmtui/nmt-page-wireguard.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2021 Red Hat, Inc. + */ + +#ifndef NMT_PAGE_WIREGUARD_H +#define NMT_PAGE_WIREGUARD_H + +#include "nmt-editor-page-device.h" + +#define NMT_TYPE_PAGE_WIREGUARD (nmt_page_wireguard_get_type()) +#define NMT_PAGE_WIREGUARD(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_WIREGUARD, NmtPageWireGuard)) +#define NMT_PAGE_WIREGUARD_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_PAGE_WIREGUARD, NmtPageWireGuardClass)) +#define NMT_IS_PAGE_WIREGUARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_PAGE_WIREGUARD)) +#define NMT_IS_PAGE_WIREGUARD_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NMT_TYPE_PAGE_WIREGUARD)) +#define NMT_PAGE_WIREGUARD_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NMT_TYPE_PAGE_WIREGUARD, NmtPageWireGuardClass)) + +typedef struct { + NmtEditorPageDevice parent; +} NmtPageWireGuard; + +typedef struct { + NmtEditorPageDeviceClass parent; +} NmtPageWireGuardClass; + +GType nmt_page_wireguard_get_type(void); + +NmtEditorPage *nmt_page_wireguard_new(NMConnection *conn, NmtDeviceEntry *deventry); + +#endif /* NMT_PAGE_WIREGUARD_H */ diff --git a/src/nmtui/nmt-wireguard-peer-editor.c b/src/nmtui/nmt-wireguard-peer-editor.c new file mode 100644 index 00000000..810bdf69 --- /dev/null +++ b/src/nmtui/nmt-wireguard-peer-editor.c @@ -0,0 +1,247 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2021 Red Hat, Inc. + */ +/** + * SECTION:nmt-wireguard-peer-editor + * @short_description: The editor page for Peer connections + */ + +#include "libnm-client-aux-extern/nm-default-client.h" + +#include "nmt-wireguard-peer-editor.h" +#include "nmt-page-wireguard.h" + +#include "nmt-device-entry.h" +#include "nmt-mtu-entry.h" +#include "nmt-wireguard-peer-list.h" + +#include "nm-editor-bindings.h" + +G_DEFINE_TYPE(NmtWireguardPeerEditor, nmt_wireguard_peer_editor, NMT_TYPE_NEWT_FORM) + +#define NMT_WIREGUARD_PEER_EDITOR_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), \ + NMT_TYPE_WIREGUARD_PEER_EDITOR, \ + NmtWireguardPeerEditorPrivate)) + +typedef struct { + NMSettingWireGuard *orig_setting; + NMSettingWireGuard *edit_setting; + NMWireGuardPeer * peer; + NmtNewtEntry * private_key; +} NmtWireguardPeerEditorPrivate; + +enum { + PROP_0, + + PROP_SETTING, + PROP_PEER, + PROP_PUBLIC_KEY, + + LAST_PROP +}; + +NmtNewtForm * +nmt_wireguard_peer_editor_new(NMSettingWireGuard *setting, NMWireGuardPeer *peer) +{ + return g_object_new(NMT_TYPE_WIREGUARD_PEER_EDITOR, "setting", setting, "peer", peer, NULL); +} + +static void +nmt_wireguard_peer_editor_init(NmtWireguardPeerEditor *peer) +{} + +static void +save_peer_and_exit(NmtNewtButton *button, gpointer user_data) +{ + NmtWireguardPeerEditor * editor = user_data; + NmtWireguardPeerEditorPrivate *priv = NMT_WIREGUARD_PEER_EDITOR_GET_PRIVATE(editor); + + nm_setting_wireguard_append_peer(priv->orig_setting, priv->peer); + + nmt_newt_form_quit(NMT_NEWT_FORM(editor)); +} + +static void +nmt_wireguard_peer_editor_constructed(GObject *object) +{ + NmtWireguardPeerEditor *peer = NMT_WIREGUARD_PEER_EDITOR(object); + NmtEditorSection * section; + NmtEditorGrid * grid; + NmtNewtWidget * widget, *label; + NmtNewtWidget * buttons, *ok, *cancel; + + if (G_OBJECT_CLASS(nmt_wireguard_peer_editor_parent_class)->constructed) + G_OBJECT_CLASS(nmt_wireguard_peer_editor_parent_class)->constructed(object); + + section = nmt_editor_section_new(_("Peer"), NULL, TRUE); + grid = nmt_editor_section_get_body(section); + + widget = nmt_newt_entry_new(40, 0); + nmt_editor_grid_append(grid, _("Public key"), widget, NULL); + g_object_bind_property_full(object, + "peer", + widget, + "text", + G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL, + peer_transform_to_public_key_string, + peer_transform_from_public_key_string, + NULL, + NULL); + + widget = nmt_newt_entry_new(40, 0); + nmt_editor_grid_append(grid, _("Allowed IPs"), widget, NULL); + g_object_bind_property_full(peer, + "peer", + widget, + "text", + G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL, + peer_transform_to_allowed_ips_string, + peer_transform_from_allowed_ips_string, + NULL, + NULL); + + widget = nmt_newt_entry_new(40, 0); + nmt_editor_grid_append(grid, _("Endpoint"), widget, NULL); + g_object_bind_property_full(peer, + "peer", + widget, + "text", + G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL, + peer_transform_to_endpoint_string, + peer_transform_from_endpoint_string, + NULL, + NULL); + + widget = nmt_newt_entry_new(40, 0); + nmt_editor_grid_append(grid, _("Preshared key"), widget, NULL); + g_object_bind_property_full(peer, + "peer", + widget, + "text", + G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL, + peer_transform_to_preshared_key_string, + peer_transform_from_preshared_key_string, + NULL, + NULL); + + widget = nmt_newt_entry_numeric_new(10, 0, G_MAXINT); + label = nmt_newt_label_new(C_("seconds", "seconds")); + nmt_editor_grid_append(grid, _("Persistent keepalive"), widget, label); + g_object_bind_property_full(peer, + "peer", + widget, + "text", + G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL, + peer_transform_to_persistent_keepalive_string, + peer_transform_from_persistent_keepalive_string, + NULL, + NULL); + + buttons = nmt_newt_grid_new(); + nmt_editor_grid_append(grid, NULL, buttons, NULL); + nmt_newt_widget_set_padding(buttons, 0, 1, 0, 0); + + cancel = g_object_ref_sink(nmt_newt_button_new(_("Cancel"))); + nmt_newt_widget_set_exit_on_activate(cancel, TRUE); + nmt_newt_grid_add(NMT_NEWT_GRID(buttons), cancel, 0, 0); + nmt_newt_grid_set_flags(NMT_NEWT_GRID(buttons), + cancel, + NMT_NEWT_GRID_EXPAND_X | NMT_NEWT_GRID_ANCHOR_RIGHT + | NMT_NEWT_GRID_FILL_Y); + + ok = g_object_ref_sink(nmt_newt_button_new(_("OK"))); + g_signal_connect(ok, "clicked", G_CALLBACK(save_peer_and_exit), peer); + nmt_newt_grid_add(NMT_NEWT_GRID(buttons), ok, 1, 0); + nmt_newt_widget_set_padding(ok, 1, 0, 0, 0); + g_object_bind_property(NMT_NEWT_GRID(buttons), "valid", ok, "sensitive", G_BINDING_SYNC_CREATE); + + nmt_newt_form_set_content(NMT_NEWT_FORM(peer), NMT_NEWT_WIDGET(section)); +} + +static void +nmt_wireguard_peer_editor_set_property(GObject * object, + guint prop_id, + const GValue *value, + GParamSpec * pspec) +{ + NmtWireguardPeerEditorPrivate *priv = NMT_WIREGUARD_PEER_EDITOR_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_SETTING: + priv->orig_setting = g_value_dup_object(value); + priv->edit_setting = + NM_SETTING_WIREGUARD(nm_setting_duplicate(NM_SETTING(priv->orig_setting))); + break; + case PROP_PEER: + priv->peer = g_value_dup_boxed(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +nmt_wireguard_peer_editor_get_property(GObject * object, + guint prop_id, + GValue * value, + GParamSpec *pspec) +{ + NmtWireguardPeerEditorPrivate *priv = NMT_WIREGUARD_PEER_EDITOR_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_SETTING: + g_value_set_object(value, priv->edit_setting); + break; + case PROP_PEER: + g_value_set_boxed(value, priv->peer); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +nmt_wireguard_peer_editor_class_init(NmtWireguardPeerEditorClass *peer_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS(peer_class); + + g_type_class_add_private(peer_class, sizeof(NmtWireguardPeerEditorPrivate)); + + /* virtual methods */ + object_class->constructed = nmt_wireguard_peer_editor_constructed; + object_class->set_property = nmt_wireguard_peer_editor_set_property; + object_class->get_property = nmt_wireguard_peer_editor_get_property; + + /* properties */ + + /** + * NmtPeerPage:setting: + * + * The page's #NMSettingWireGuard. + */ + g_object_class_install_property( + object_class, + PROP_SETTING, + g_param_spec_object("setting", + "", + "", + NM_TYPE_SETTING_WIREGUARD, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + /** + * NmtPeerPage:peer: + * + * The page's #NMWireGuardPeer. + */ + g_object_class_install_property(object_class, + PROP_PEER, + g_param_spec_boxed("peer", + "", + "", + nm_wireguard_peer_get_type(), + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +} diff --git a/src/nmtui/nmt-wireguard-peer-editor.h b/src/nmtui/nmt-wireguard-peer-editor.h new file mode 100644 index 00000000..ffe76c8c --- /dev/null +++ b/src/nmtui/nmt-wireguard-peer-editor.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2021 Red Hat, Inc. + */ + +#ifndef NMT_WIREGUARD_PEER_EDITOR_H +#define NMT_WIREGUARD_PEER_EDITOR_H + +#include "libnmt-newt/nmt-newt.h" + +#define NMT_TYPE_WIREGUARD_PEER_EDITOR (nmt_wireguard_peer_editor_get_type()) +#define NMT_WIREGUARD_PEER_EDITOR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_WIREGUARD_PEER_EDITOR, NmtWireguardPeerEditor)) +#define NMT_WIREGUARD_PEER_EDITOR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_WIREGUARD_PEER_EDITOR, NmtWireguardPeerEditorClass)) +#define NMT_IS_WIREGUARD_PEER_EDITOR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_WIREGUARD_PEER_EDITOR)) +#define NMT_IS_WIREGUARD_PEER_EDITOR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NMT_TYPE_WIREGUARD_PEER_EDITOR)) +#define NMT_WIREGUARD_PEER_EDITOR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NMT_TYPE_WIREGUARD_PEER_EDITOR, NmtWireguardPeerEditorClass)) + +typedef struct { + NmtNewtForm parent; +} NmtWireguardPeerEditor; + +typedef struct { + NmtNewtFormClass parent; +} NmtWireguardPeerEditorClass; + +GType nmt_wireguard_peer_editor_get_type(void); + +NmtNewtForm *nmt_wireguard_peer_editor_new(NMSettingWireGuard *setting, NMWireGuardPeer *peer); + +#endif /* NMT_WIREGUARD_PEER_EDITOR_H */ diff --git a/src/nmtui/nmt-wireguard-peer-list.c b/src/nmtui/nmt-wireguard-peer-list.c new file mode 100644 index 00000000..03f3ef9a --- /dev/null +++ b/src/nmtui/nmt-wireguard-peer-list.c @@ -0,0 +1,451 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2021 Red Hat, Inc. + */ + +/** + * SECTION:nmt-wireguard-peer-list: + * @short_description: An editable list of a connection's peers + * + * #NmtWireguardPeerList implements an #NmtNewtGrid for the + * peers of a connection. + */ + +#include "libnm-client-aux-extern/nm-default-client.h" + +#include "nmtui.h" +#include "nmt-wireguard-peer-list.h" +#include "nmt-wireguard-peer-editor.h" + +G_DEFINE_TYPE(NmtWireguardPeerList, nmt_wireguard_peer_list, NMT_TYPE_NEWT_GRID) + +#define NMT_WIREGUARD_PEER_LIST_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), NMT_TYPE_WIREGUARD_PEER_LIST, NmtWireguardPeerListPrivate)) + +typedef struct { + NMSettingWireGuard *setting; + GSList * peers; + + NmtNewtListbox * listbox; + NmtNewtButtonBox *buttons; + + NmtNewtWidget *add; + NmtNewtWidget *edit; + NmtNewtWidget *delete; +} NmtWireguardPeerListPrivate; + +enum { + PROP_0, + + PROP_SETTING, + PROP_PEERS, + PROP_NUM_PEERS, + + LAST_PROP +}; + +enum { + ADD_PEER, + EDIT_PEER, + REMOVE_PEER, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = {0}; + +/** + * nmt_wireguard_peer_list_new: + * @master: the master #NMSettingWireGuard whose peers are being listed + * + * Creates a new #NmtWireguardPeerList. + * + * Returns: a new #NmtWireguardPeerList. + */ +NmtNewtWidget * +nmt_wireguard_peer_list_new(NMSettingWireGuard *setting) +{ + return g_object_new(NMT_TYPE_WIREGUARD_PEER_LIST, "setting", setting, NULL); +} + +static void +add_clicked(NmtNewtButton *button, gpointer list) +{ + g_signal_emit(list, signals[ADD_PEER], 0); +} + +static void +edit_clicked(NmtNewtButton *button, gpointer list) +{ + g_signal_emit(list, signals[EDIT_PEER], 0); +} + +static void +delete_clicked(NmtNewtButton *button, gpointer list) +{ + g_signal_emit(list, signals[REMOVE_PEER], 0); +} + +static void +listbox_activated(NmtNewtWidget *listbox, gpointer list) +{ + NmtWireguardPeerListPrivate *priv = NMT_WIREGUARD_PEER_LIST_GET_PRIVATE(list); + + edit_clicked(NMT_NEWT_BUTTON(priv->edit), list); +} + +static void +nmt_wireguard_peer_list_init(NmtWireguardPeerList *list) +{ + NmtWireguardPeerListPrivate *priv = NMT_WIREGUARD_PEER_LIST_GET_PRIVATE(list); + NmtNewtWidget * listbox, *buttons; + NmtNewtGrid * grid = NMT_NEWT_GRID(list); + + listbox = g_object_new(NMT_TYPE_NEWT_LISTBOX, + "flags", + NMT_NEWT_LISTBOX_SCROLL | NMT_NEWT_LISTBOX_BORDER, + "skip-null-keys", + TRUE, + NULL); + priv->listbox = NMT_NEWT_LISTBOX(listbox); + nmt_newt_grid_add(grid, listbox, 0, 0); + nmt_newt_grid_set_flags(grid, + listbox, + NMT_NEWT_GRID_FILL_X | NMT_NEWT_GRID_FILL_Y | NMT_NEWT_GRID_EXPAND_X + | NMT_NEWT_GRID_EXPAND_Y); + g_signal_connect(priv->listbox, "activated", G_CALLBACK(listbox_activated), list); + + buttons = nmt_newt_button_box_new(NMT_NEWT_BUTTON_BOX_VERTICAL); + priv->buttons = NMT_NEWT_BUTTON_BOX(buttons); + nmt_newt_grid_add(grid, buttons, 1, 0); + nmt_newt_widget_set_padding(buttons, 1, 1, 0, 1); + nmt_newt_grid_set_flags(grid, + buttons, + NMT_NEWT_GRID_FILL_X | NMT_NEWT_GRID_FILL_Y | NMT_NEWT_GRID_EXPAND_Y); + + priv->add = nmt_newt_button_box_add_start(priv->buttons, _("Add")); + g_signal_connect(priv->add, "clicked", G_CALLBACK(add_clicked), list); + + priv->edit = nmt_newt_button_box_add_start(priv->buttons, _("Edit...")); + g_signal_connect(priv->edit, "clicked", G_CALLBACK(edit_clicked), list); + + priv->delete = nmt_newt_button_box_add_start(priv->buttons, _("Delete")); + g_signal_connect(priv->delete, "clicked", G_CALLBACK(delete_clicked), list); +} + +static void nmt_wireguard_peer_list_rebuild(NmtWireguardPeerList *list); + +static void +rebuild_on_peer_changed(gpointer list) +{ + nmt_wireguard_peer_list_rebuild(list); +} + +static void +free_peers(NmtWireguardPeerList *list) +{ + NmtWireguardPeerListPrivate *priv = NMT_WIREGUARD_PEER_LIST_GET_PRIVATE(list); + + g_slist_free(priv->peers); + priv->peers = NULL; +} + +static void +nmt_wireguard_peer_list_finalize(GObject *object) +{ + NmtWireguardPeerListPrivate *priv = NMT_WIREGUARD_PEER_LIST_GET_PRIVATE(object); + + free_peers(NMT_WIREGUARD_PEER_LIST(object)); + g_object_unref(priv->setting); + g_object_unref(priv->peers); + + G_OBJECT_CLASS(nmt_wireguard_peer_list_parent_class)->finalize(object); +} + +static void +nmt_wireguard_peer_list_add_peer(NmtWireguardPeerList *list) +{ + NmtWireguardPeerListPrivate *priv = NMT_WIREGUARD_PEER_LIST_GET_PRIVATE(list); + NMWireGuardPeer * peer = nm_wireguard_peer_new(); + NmtNewtForm * editor; + + editor = nmt_wireguard_peer_editor_new(priv->setting, peer); + + if (!editor) + return; + + nmt_newt_form_run_sync(editor); + g_object_unref(editor); + rebuild_on_peer_changed(list); +} + +static void +nmt_wireguard_peer_list_edit_peer(NmtWireguardPeerList *list) +{ + NmtWireguardPeerListPrivate *priv = NMT_WIREGUARD_PEER_LIST_GET_PRIVATE(list); + NMWireGuardPeer * orig_peer, *edit_peer; + NmtNewtForm * editor; + int selected_row; + + selected_row = nmt_newt_listbox_get_active(priv->listbox); + + if (selected_row >= 0) { + orig_peer = nm_setting_wireguard_get_peer(priv->setting, (guint) selected_row); + edit_peer = nm_wireguard_peer_new_clone(orig_peer, TRUE); + editor = nmt_wireguard_peer_editor_new(priv->setting, edit_peer); + if (!editor) + return; + nmt_newt_form_run_sync(editor); + g_object_unref(editor); + rebuild_on_peer_changed(list); + } +} + +static void +nmt_wireguard_peer_list_remove_peer(NmtWireguardPeerList *list) +{ + NmtWireguardPeerListPrivate *priv = NMT_WIREGUARD_PEER_LIST_GET_PRIVATE(list); + int selected_row; + + selected_row = nmt_newt_listbox_get_active(priv->listbox); + + if (selected_row >= 0) { + nm_setting_wireguard_remove_peer(priv->setting, (guint) selected_row); + rebuild_on_peer_changed(list); + } +} + +static void +nmt_wireguard_peer_list_set_property(GObject * object, + guint prop_id, + const GValue *value, + GParamSpec * pspec) +{ + NmtWireguardPeerListPrivate *priv = NMT_WIREGUARD_PEER_LIST_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_SETTING: + priv->setting = g_value_get_pointer(value); + break; + case PROP_PEERS: + priv->peers = g_value_get_pointer(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +nmt_wireguard_peer_list_get_property(GObject * object, + guint prop_id, + GValue * value, + GParamSpec *pspec) +{ + NmtWireguardPeerListPrivate *priv = NMT_WIREGUARD_PEER_LIST_GET_PRIVATE(object); + GPtrArray * peers; + GSList * iter; + + switch (prop_id) { + case PROP_SETTING: + g_value_set_pointer(value, priv->setting); + break; + case PROP_PEERS: + peers = g_ptr_array_new_with_free_func(g_object_unref); + for (iter = priv->peers; iter; iter = iter->next) + g_ptr_array_add(peers, g_object_ref(iter->data)); + g_value_take_boxed(value, peers); + break; + case PROP_NUM_PEERS: + g_value_set_int(value, g_slist_length(priv->peers)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +nmt_wireguard_peer_list_rebuild(NmtWireguardPeerList *list) +{ + NmtWireguardPeerListPrivate *priv = NMT_WIREGUARD_PEER_LIST_GET_PRIVATE(list); + GSList * iter; + NMWireGuardPeer * peer, *selected_peer; + int i, row, selected_row, num; + NMSettingWireGuard * setting = priv->setting; + + selected_row = nmt_newt_listbox_get_active(priv->listbox); + selected_peer = nmt_newt_listbox_get_active_key(priv->listbox); + + free_peers(list); + num = nm_setting_wireguard_get_peers_len(setting); + for (i = 0; i < num; i++) { + peer = nm_setting_wireguard_get_peer(setting, i); + priv->peers = g_slist_append(priv->peers, peer); + } + g_object_notify(G_OBJECT(list), "peers"); + g_object_notify(G_OBJECT(list), "num-peers"); + + nmt_newt_component_set_sensitive(NMT_NEWT_COMPONENT(priv->edit), priv->peers != NULL); + nmt_newt_component_set_sensitive(NMT_NEWT_COMPONENT(priv->delete), priv->peers != NULL); + + nmt_newt_listbox_clear(priv->listbox); + + for (iter = priv->peers, row = 0; iter; iter = iter->next, row++) { + peer = iter->data; + nmt_newt_listbox_append(priv->listbox, nm_wireguard_peer_get_public_key(peer), peer); + if (peer == selected_peer) + selected_row = row; + } + if (selected_row >= row) + selected_row = row - 1; + nmt_newt_listbox_set_active(priv->listbox, selected_row); +} + +static void +rebuild_on_peers_changed(GObject *object, GParamSpec *pspec, gpointer list) +{ + nmt_wireguard_peer_list_rebuild(list); +} + +static void +nmt_wireguard_peer_list_constructed(GObject *object) +{ + NmtWireguardPeerList *list = NMT_WIREGUARD_PEER_LIST(object); + + g_signal_connect(nm_client, + "notify::" NM_CLIENT_CONNECTIONS, + G_CALLBACK(rebuild_on_peers_changed), + list); + + nmt_wireguard_peer_list_rebuild(list); + + G_OBJECT_CLASS(nmt_wireguard_peer_list_parent_class)->constructed(object); +} + +static void +nmt_wireguard_peer_list_class_init(NmtWireguardPeerListClass *list_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS(list_class); + + g_type_class_add_private(list_class, sizeof(NmtWireguardPeerListPrivate)); + + /* virtual methods */ + object_class->constructed = nmt_wireguard_peer_list_constructed; + object_class->set_property = nmt_wireguard_peer_list_set_property; + object_class->get_property = nmt_wireguard_peer_list_get_property; + object_class->finalize = nmt_wireguard_peer_list_finalize; + + list_class->add_peer = nmt_wireguard_peer_list_add_peer; + list_class->edit_peer = nmt_wireguard_peer_list_edit_peer; + list_class->remove_peer = nmt_wireguard_peer_list_remove_peer; + + /* signals */ + + /** + * NmtWireguardPeerList::add-connection: + * @list: the #NmtWireguardPeerList + * + * Emitted when the user clicks the list's "Add" button. + */ + signals[ADD_PEER] = g_signal_new("add-peer", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(NmtWireguardPeerListClass, add_peer), + NULL, + NULL, + NULL, + G_TYPE_NONE, + 0); + + /** + * NmtWireguardPeerList::edit-connection: + * @list: the #NmtWireguardPeerList + * @connection: the connection to edit + * + * Emitted when the user clicks the list's "Edit" button, or + * hits "Return" on the listbox. + */ + signals[EDIT_PEER] = g_signal_new("edit-peer", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(NmtWireguardPeerListClass, edit_peer), + NULL, + NULL, + NULL, + G_TYPE_NONE, + 0); + + /** + * NmtWireguardPeerList::remove-connection: + * @list: the #NmtWireguardPeerList + * @connection: the connection to remove + * + * Emitted when the user clicks the list's "Delete" button. + */ + signals[REMOVE_PEER] = g_signal_new("remove-peer", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(NmtWireguardPeerListClass, remove_peer), + NULL, + NULL, + NULL, + G_TYPE_NONE, + 0); + + /* properties */ + + /** + * NmtWireguardPeerListFilter: + * @list: the #NmtWireguardPeerList + * @connection: an #NMConnection + * @user_data: the user data + * + * Decides whether @connection should be displayed in @list. + * + * Returns: %TRUE or %FALSE + */ + /** + * NmtWireguardPeerList:connection-filter: + * + * A callback function for filtering which connections appear in + * the list. + */ + g_object_class_install_property( + object_class, + PROP_SETTING, + g_param_spec_pointer("setting", + "", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + /** + * NmtWireguardPeerList:connections: + * + * The list of connections in the widget. + * + * Element-Type: #NMConnection + */ + g_object_class_install_property(object_class, + PROP_PEERS, + g_param_spec_boxed("peers", + "", + "", + G_TYPE_PTR_ARRAY, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * NmtWireguardPeerList:num-connections: + * + * The number of connections in the widget. + */ + g_object_class_install_property(object_class, + PROP_NUM_PEERS, + g_param_spec_int("num-peers", + "", + "", + 0, + G_MAXINT, + 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); +} diff --git a/src/nmtui/nmt-wireguard-peer-list.h b/src/nmtui/nmt-wireguard-peer-list.h new file mode 100644 index 00000000..de3faf12 --- /dev/null +++ b/src/nmtui/nmt-wireguard-peer-list.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2021 Red Hat, Inc. + */ + +#ifndef NMT_WIREGUARD_PEER_LIST_H +#define NMT_WIREGUARD_PEER_LIST_H + +#include "libnmt-newt/nmt-newt.h" +#include "nmtui-edit.h" + +#define NMT_TYPE_WIREGUARD_PEER_LIST (nmt_wireguard_peer_list_get_type()) +#define NMT_WIREGUARD_PEER_LIST(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_WIREGUARD_PEER_LIST, NmtWireguardPeerList)) +#define NMT_WIREGUARD_PEER_LIST_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_WIREGUARD_PEER_LIST, NmtWireguardPeerListClass)) +#define NMT_IS_WIREGUARD_PEER_LIST(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_WIREGUARD_PEER_LIST)) +#define NMT_IS_WIREGUARD_PEER_LIST_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NMT_TYPE_WIREGUARD_PEER_LIST)) +#define NMT_WIREGUARD_PEER_LIST_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NMT_TYPE_WIREGUARD_PEER_LIST, NmtWireguardPeerListClass)) + +typedef struct { + NmtNewtGrid parent; + +} NmtWireguardPeerList; + +typedef struct { + NmtNewtGridClass parent; + + /* signals */ + void (*add_peer)(NmtWireguardPeerList *list); + void (*edit_peer)(NmtWireguardPeerList *list); + void (*remove_peer)(NmtWireguardPeerList *list); +} NmtWireguardPeerListClass; + +GType nmt_wireguard_peer_list_get_type(void); + +NmtNewtWidget *nmt_wireguard_peer_list_new(NMSettingWireGuard *setting); + +#endif /* NMT_WIREGUARD_PEER_LIST_H */ diff --git a/src/nmtui/nmtui.c b/src/nmtui/nmtui.c index 5edf70e5..897e0911 100644 --- a/src/nmtui/nmtui.c +++ b/src/nmtui/nmtui.c @@ -283,7 +283,7 @@ main(int argc, char **argv) startup_data.argc = argc; startup_data.argv = argv; - g_idle_add(idle_run_subprogram, &startup_data); + nm_g_idle_add(idle_run_subprogram, &startup_data); loop = g_main_loop_new(NULL, FALSE); g_main_loop_run(loop); g_main_loop_unref(loop); |