[network-manager-applet/bg/wireguard: 11/11] editor: add wireguard support



commit 0dd5d2ed8139c3c618d1be1b7dda194b90312df7
Author: Beniamino Galvani <bgalvani redhat com>
Date:   Thu Feb 20 22:08:40 2020 +0100

    editor: add wireguard support

 Makefile.am                                  |   3 +
 src/connection-editor/ce-page-wireguard.ui   | 684 +++++++++++++++++++++++++++
 src/connection-editor/ce.gresource.xml       |   1 +
 src/connection-editor/connection-helpers.c   |   2 +
 src/connection-editor/meson.build            |   2 +
 src/connection-editor/nm-connection-editor.c |   4 +
 src/connection-editor/page-wireguard.c       | 644 +++++++++++++++++++++++++
 src/connection-editor/page-wireguard.h       |  48 ++
 8 files changed, 1388 insertions(+)
---
diff --git a/Makefile.am b/Makefile.am
index 495594e5..5576391e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -361,6 +361,8 @@ connection_editor_hc_real = \
        src/connection-editor/page-vlan.c \
        src/connection-editor/page-dcb.c \
        src/connection-editor/page-dcb.h \
+       src/connection-editor/page-wireguard.h \
+       src/connection-editor/page-wireguard.c \
        src/connection-editor/vpn-helpers.h \
        src/connection-editor/vpn-helpers.c \
        src/connection-editor/ip4-routes-dialog.h \
@@ -445,6 +447,7 @@ EXTRA_DIST += \
        src/connection-editor/ce-page-vlan.ui \
        src/connection-editor/ce-page-wifi-security.ui \
        src/connection-editor/ce-page-wifi.ui \
+       src/connection-editor/ce-page-wireguard.ui \
        src/connection-editor/ce-ppp-auth-methods.ui \
        src/connection-editor/gtk/menus.ui \
        src/connection-editor/nm-connection-editor.ui \
diff --git a/src/connection-editor/ce-page-wireguard.ui b/src/connection-editor/ce-page-wireguard.ui
new file mode 100644
index 00000000..f6cbf0b5
--- /dev/null
+++ b/src/connection-editor/ce-page-wireguard.ui
@@ -0,0 +1,684 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="nm-applet">
+  <requires lib="gtk+" version="3.10"/>
+  <object class="GtkAdjustment" id="adj_fwmark">
+    <property name="upper">4294967295</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkAdjustment" id="adj_listen_port">
+    <property name="upper">65535</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkAdjustment" id="adj_mtu">
+    <property name="upper">65535</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkDialog" id="PeerDialog">
+    <property name="width_request">400</property>
+    <property name="can_focus">False</property>
+    <property name="title" translatable="yes">Edit Wireguard peer</property>
+    <property name="type_hint">dialog</property>
+    <child>
+      <placeholder/>
+    </child>
+    <child internal-child="vbox">
+      <object class="GtkBox">
+        <property name="can_focus">False</property>
+        <property name="vexpand">True</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <property name="baseline_position">top</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox">
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="button_cancel">
+                <property name="label" translatable="yes">_Cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="button_apply">
+                <property name="label" translatable="yes">_Apply</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox" id="box_info">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="orientation">vertical</property>
+            <property name="baseline_position">top</property>
+            <child>
+              <object class="GtkInfoBar" id="info_bar">
+                <property name="can_focus">False</property>
+                <property name="vexpand">True</property>
+                <property name="message_type">error</property>
+                <child internal-child="action_area">
+                  <object class="GtkButtonBox">
+                    <property name="can_focus">False</property>
+                    <property name="spacing">6</property>
+                    <property name="layout_style">end</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <child>
+                      <placeholder/>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child internal-child="content_area">
+                  <object class="GtkBox">
+                    <property name="can_focus">False</property>
+                    <property name="spacing">16</property>
+                    <child>
+                      <object class="GtkLabel" id="label_info">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="vexpand">True</property>
+                        <property name="wrap">True</property>
+                        <property name="track_visited_links">False</property>
+                        <attributes>
+                          <attribute name="weight" value="bold"/>
+                        </attributes>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkGrid" id="grid">
+                <property name="name">grid</property>
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="margin_left">6</property>
+                <property name="margin_right">6</property>
+                <property name="margin_top">6</property>
+                <property name="row_spacing">6</property>
+                <property name="column_spacing">6</property>
+                <child>
+                  <object class="GtkLabel">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="halign">end</property>
+                    <property name="label" translatable="yes">_Public key</property>
+                    <property name="use_underline">True</property>
+                    <property name="mnemonic_widget">entry_public_key</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="halign">end</property>
+                    <property name="label" translatable="yes">_Allowed IPs</property>
+                    <property name="use_underline">True</property>
+                    <property name="mnemonic_widget">entry_allowed_ips</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="halign">end</property>
+                    <property name="label" translatable="yes">_Endpoint</property>
+                    <property name="use_underline">True</property>
+                    <property name="mnemonic_widget">entry_endpoint</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="halign">end</property>
+                    <property name="label" translatable="yes">Pre-_shared key</property>
+                    <property name="use_underline">True</property>
+                    <property name="mnemonic_widget">entry_psk</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">3</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="halign">end</property>
+                    <property name="label" translatable="yes">_Keep-alive</property>
+                    <property name="use_underline">True</property>
+                    <property name="mnemonic_widget">spin_keepalive</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">5</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkEntry" id="entry_public_key">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="tooltip_text" translatable="yes">A base64 public key calculated by 'wg 
pubkey' from a private key.</property>
+                    <property name="hexpand">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkEntry" id="entry_allowed_ips">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="tooltip_text" translatable="yes">Comma-separated list of IP (v4 or v6) 
addresses with CIDR masks from which incoming traffic for this peer is allowed and to which outgoing traffic 
for this peer is directed.</property>
+                    <property name="hexpand">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkEntry" id="entry_endpoint">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="tooltip_text" translatable="yes">An endpoint IP or hostname, followed by 
a colon, and then a port number.</property>
+                    <property name="hexpand">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkEntry" id="entry_psk">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="tooltip_text" translatable="yes">A base64 preshared key generated by 'wg 
genpsk'. Optional, and may be omitted. Adds an additional layer of symmetric-key cryptography to be mixed 
into the already existing public-key cryptography, for post-quantum resistance.</property>
+                    <property name="hexpand">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">3</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkBox">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkSpinButton" id="spin_keepalive">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="tooltip_text" translatable="yes">How often to send an authenticated 
empty packet to the peer for the purpose of keeping a stateful firewall or NAT mapping valid. Set to zero to 
disable.</property>
+                        <property name="hexpand">True</property>
+                        <property name="text" translatable="yes">0</property>
+                        <property name="adjustment">adj_mtu</property>
+                        <property name="climb_rate">1</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="margin_left">6</property>
+                        <property name="label" translatable="yes">seconds</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">5</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkCheckButton" id="toggle_show_psk">
+                    <property name="label" translatable="yes">Sho_w pre-shared key</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="use_underline">True</property>
+                    <property name="draw_indicator">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">4</property>
+                  </packing>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-6">button_cancel</action-widget>
+    </action-widgets>
+  </object>
+  <object class="GtkBox" id="WireGuardPage">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="orientation">vertical</property>
+    <child>
+      <object class="GtkGrid">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="margin_left">12</property>
+        <property name="margin_right">12</property>
+        <property name="margin_start">12</property>
+        <property name="margin_end">12</property>
+        <property name="margin_top">12</property>
+        <property name="margin_bottom">12</property>
+        <property name="hexpand">False</property>
+        <property name="orientation">vertical</property>
+        <property name="row_spacing">6</property>
+        <property name="column_spacing">6</property>
+        <property name="row_homogeneous">True</property>
+        <child>
+          <object class="GtkLabel" id="label_interface">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="halign">end</property>
+            <property name="hexpand">False</property>
+            <property name="label" translatable="yes">_Interface name</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">entry_ifname</property>
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="entry_ifname">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="tooltip_text" translatable="yes">The name of the wireguard interface to 
create.</property>
+            <property name="hexpand">True</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">0</property>
+            <property name="width">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label_private_key">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="halign">end</property>
+            <property name="label" translatable="yes">Private _key</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">entry_private_key</property>
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="entry_private_key">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="tooltip_text" translatable="yes">The 256 bit private-key in base64 
encoding</property>
+            <property name="hexpand">True</property>
+            <property name="input_purpose">password</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">1</property>
+            <property name="width">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label_listen_port">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="halign">end</property>
+            <property name="hexpand">False</property>
+            <property name="label" translatable="yes">_Listen port</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">spin_listen_port</property>
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">3</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkSpinButton" id="spin_listen_port">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="tooltip_text" translatable="yes">A port to listen to. If set to 'automatic', the 
port will be chosen randomly when the interface comes up.</property>
+            <property name="hexpand">True</property>
+            <property name="text" translatable="yes">0</property>
+            <property name="adjustment">adj_listen_port</property>
+            <property name="climb_rate">1</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">3</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label_fwmark">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="halign">end</property>
+            <property name="hexpand">False</property>
+            <property name="label" translatable="yes">_fwmark</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">spin_fwmark</property>
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">4</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label_mtu">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="halign">end</property>
+            <property name="hexpand">False</property>
+            <property name="label" translatable="yes">_MTU</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">spin_mtu</property>
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">5</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label_peer_routes">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="halign">end</property>
+            <property name="hexpand">False</property>
+            <property name="label" translatable="yes">Add peer _routes</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">toggle_peer_routes</property>
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">6</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkCheckButton" id="toggle_peer_routes">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">False</property>
+            <property name="tooltip_text" translatable="yes">Whether to automatically add routes for the 
AllowedIPs ranges of the peers</property>
+            <property name="use_underline">True</property>
+            <property name="use_stock">True</property>
+            <property name="draw_indicator">True</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">6</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="halign">start</property>
+            <property name="label" translatable="yes">bytes</property>
+          </object>
+          <packing>
+            <property name="left_attach">2</property>
+            <property name="top_attach">5</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkSpinButton" id="spin_mtu">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="hexpand">True</property>
+            <property name="text" translatable="yes">0</property>
+            <property name="adjustment">adj_mtu</property>
+            <property name="climb_rate">1</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">5</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkSpinButton" id="spin_fwmark">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="tooltip_text" translatable="yes">A 32-bit fwmark for outgoing packets. Leave it 
to zero to disable fwmark.</property>
+            <property name="text" translatable="yes">0</property>
+            <property name="adjustment">adj_fwmark</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">4</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkCheckButton" id="toggle_show_private_key">
+            <property name="label" translatable="yes">_Show private key</property>
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">False</property>
+            <property name="use_underline">True</property>
+            <property name="draw_indicator">True</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">2</property>
+            <property name="width">2</property>
+          </packing>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkGrid">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="margin_left">4</property>
+        <property name="margin_right">4</property>
+        <property name="row_spacing">2</property>
+        <child>
+          <object class="GtkButtonBox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="margin_left">6</property>
+            <property name="margin_right">6</property>
+            <property name="orientation">vertical</property>
+            <property name="layout_style">start</property>
+            <child>
+              <object class="GtkButton" id="button_add">
+                <property name="label" translatable="yes">_Add</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="button_delete">
+                <property name="label" translatable="yes">_Delete</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="margin_top">6</property>
+            <property name="margin_bottom">6</property>
+            <property name="label" translatable="yes">&lt;b&gt;_Peers&lt;/b&gt;</property>
+            <property name="use_markup">True</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">tree_peers</property>
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="hexpand">True</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkTreeView" id="tree_peers">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="reorderable">True</property>
+                <child internal-child="selection">
+                  <object class="GtkTreeSelection"/>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">1</property>
+          </packing>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/src/connection-editor/ce.gresource.xml b/src/connection-editor/ce.gresource.xml
index 75e89d31..b11dfb74 100644
--- a/src/connection-editor/ce.gresource.xml
+++ b/src/connection-editor/ce.gresource.xml
@@ -27,6 +27,7 @@
                <file preprocess="xml-stripblanks">ce-page-vlan.ui</file>
                <file preprocess="xml-stripblanks">ce-page-wifi-security.ui</file>
                <file preprocess="xml-stripblanks">ce-page-wifi.ui</file>
+               <file preprocess="xml-stripblanks">ce-page-wireguard.ui</file>
                <file preprocess="xml-stripblanks">ce-ppp-auth-methods.ui</file>
                <file preprocess="xml-stripblanks">gtk/menus.ui</file>
        </gresource>
diff --git a/src/connection-editor/connection-helpers.c b/src/connection-editor/connection-helpers.c
index bb9dfb31..0d29f20a 100644
--- a/src/connection-editor/connection-helpers.c
+++ b/src/connection-editor/connection-helpers.c
@@ -23,6 +23,7 @@
 #include "page-bridge.h"
 #include "page-vlan.h"
 #include "page-vpn.h"
+#include "page-wireguard.h"
 #include "vpn-helpers.h"
 #include "nm-utils/nm-vpn-editor-plugin-call.h"
 
@@ -106,6 +107,7 @@ get_connection_type_list (void)
        add_type_data_virtual (array, _("VLAN"), vlan_connection_new, NM_TYPE_SETTING_VLAN);
        add_type_data_virtual (array, _("IP tunnel"), ip_tunnel_connection_new, NM_TYPE_SETTING_IP_TUNNEL);
        add_type_data_virtual (array, _("MACsec"), macsec_connection_new, NM_TYPE_SETTING_MACSEC);
+       add_type_data_virtual (array, _("WireGuard"), wireguard_connection_new, NM_TYPE_SETTING_WIREGUARD);
 
        add_type_data_virtual (array, _("VPN"), vpn_connection_new, NM_TYPE_SETTING_VPN);
 
diff --git a/src/connection-editor/meson.build b/src/connection-editor/meson.build
index 9f354ce1..f36e0709 100644
--- a/src/connection-editor/meson.build
+++ b/src/connection-editor/meson.build
@@ -33,6 +33,7 @@ sources = files(
   'page-vpn.c',
   'page-wifi.c',
   'page-wifi-security.c',
+  'page-wireguard.c',
   'ppp-auth-methods-dialog.c',
   'vpn-helpers.c'
 )
@@ -62,6 +63,7 @@ resource_data = files(
   'ce-page-vlan.ui',
   'ce-page-wifi-security.ui',
   'ce-page-wifi.ui',
+  'ce-page-wireguard.ui',
   'ce-ppp-auth-methods.ui',
   'gtk/menus.ui',
   'nm-connection-editor.ui',
diff --git a/src/connection-editor/nm-connection-editor.c b/src/connection-editor/nm-connection-editor.c
index 4c49c770..3c30528b 100644
--- a/src/connection-editor/nm-connection-editor.c
+++ b/src/connection-editor/nm-connection-editor.c
@@ -48,6 +48,7 @@
 #include "page-vlan.h"
 #include "page-dcb.h"
 #include "page-macsec.h"
+#include "page-wireguard.h"
 #include "ce-polkit-button.h"
 #include "vpn-helpers.h"
 #include "eap-method.h"
@@ -1037,6 +1038,9 @@ nm_connection_editor_set_connection (NMConnectionEditor *editor,
                        goto out;
                if (!add_page (editor, ce_page_8021x_security_new, editor->connection, error))
                        goto out;
+       } else if (!strcmp (connection_type, NM_SETTING_WIREGUARD_SETTING_NAME)) {
+               if (!add_page (editor, ce_page_wireguard_new, editor->connection, error))
+                       goto out;
        } else {
                g_warning ("Unhandled setting type '%s'", connection_type);
        }
diff --git a/src/connection-editor/page-wireguard.c b/src/connection-editor/page-wireguard.c
new file mode 100644
index 00000000..4bb7dc0a
--- /dev/null
+++ b/src/connection-editor/page-wireguard.c
@@ -0,0 +1,644 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* NetworkManager Connection editor -- Connection editor for NetworkManager
+ *
+ * Copyright 2020 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+
+#include <string.h>
+
+#include "page-wireguard.h"
+#include "nm-connection-editor.h"
+#include "nma-ui-utils.h"
+
+G_DEFINE_TYPE (CEPageWireGuard, ce_page_wireguard, CE_TYPE_PAGE)
+
+#define CE_PAGE_WIREGUARD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CE_TYPE_PAGE_WIREGUARD, 
CEPageWireGuardPrivate))
+
+typedef struct {
+       NMWireGuardPeer *peer;
+       GtkInfoBar *info_bar;
+       GtkLabel *label_info;
+       GtkButton *button_apply;
+       GtkBuilder *builder;
+       GtkEntry *entry_public_key;
+       GtkEntry *entry_allowed_ips;
+       GtkEntry *entry_endpoint;
+       GtkEntry *entry_psk;
+       GtkSpinButton *spin_keepalive;
+       GtkToggleButton *toggle_show_psk;
+} PeerDialogData;
+
+typedef struct {
+       NMSettingWireGuard *setting;
+
+       NMWireGuardPeer *dialog_peer;
+       int dialog_peer_index;
+
+       GtkEntry *entry_ifname;
+       GtkEntry *entry_pk;
+       GtkSpinButton *spin_mtu;
+       GtkSpinButton *spin_fwmark;
+       GtkSpinButton *spin_listen_port;
+       GtkToggleButton *toggle_peer_routes;
+       GtkToggleButton *toggle_show_pk;
+       GtkButton *button_add;
+       GtkButton *button_delete;
+
+       GtkTreeView *tree;
+       GtkTreeStore *store;
+} CEPageWireGuardPrivate;
+
+enum {
+       COL_PUBLIC_KEY,
+       COL_ALLOWED_IPS,
+       COL_PEER,
+       N_COLUMNS,
+};
+
+static void
+peer_dialog_data_destroy (PeerDialogData *data)
+{
+       g_object_unref (data->builder);
+       nm_wireguard_peer_unref (data->peer);
+       g_free (data);
+}
+
+static char *
+format_allowed_ips (NMWireGuardPeer *peer)
+{
+       guint i, len;
+       GString *string = NULL;
+
+       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));
+       }
+
+       return string ? g_string_free (string, FALSE) : NULL;
+}
+
+static void
+peer_dialog_update_ui (GtkWidget *dialog)
+{
+       PeerDialogData *data;
+       gs_free char *allowed_ips = NULL;
+
+       data = g_object_get_data (G_OBJECT (dialog), "data");
+       g_return_if_fail (data && data->peer);
+
+       allowed_ips = format_allowed_ips (data->peer);
+
+       gtk_entry_set_text (data->entry_public_key, nm_wireguard_peer_get_public_key (data->peer) ?: "");
+       gtk_entry_set_text (data->entry_allowed_ips, allowed_ips ?: "");
+       gtk_entry_set_text (data->entry_endpoint, nm_wireguard_peer_get_endpoint (data->peer) ?: "");
+       gtk_spin_button_set_value (data->spin_keepalive, nm_wireguard_peer_get_persistent_keepalive 
(data->peer));
+       gtk_entry_set_text (data->entry_psk, nm_wireguard_peer_get_preshared_key (data->peer) ?: "");
+
+       nma_utils_update_password_storage (GTK_WIDGET (data->entry_psk),
+                                          nm_wireguard_peer_get_preshared_key_flags (data->peer),
+                                          NULL,
+                                          NULL);
+}
+
+static void
+peer_dialog_update_peer (GtkWidget *dialog)
+{
+       PeerDialogData *data;
+       const char *pk;
+       const char *allowed_ips;
+       const char *endpoint;
+       const char *psk;
+       char **strv;
+       guint i;
+       int keepalive;
+       NMSettingSecretFlags secret_flags;
+
+       data = g_object_get_data (G_OBJECT (dialog), "data");
+       g_return_if_fail (data && data->peer);
+
+       pk = gtk_entry_get_text (data->entry_public_key);
+       nm_wireguard_peer_set_public_key (data->peer, pk && pk[0] ? pk : NULL, TRUE);
+
+       nm_wireguard_peer_clear_allowed_ips (data->peer);
+       allowed_ips = gtk_entry_get_text (data->entry_allowed_ips);
+       strv = g_strsplit (allowed_ips, ",", -1);
+       for (i = 0; strv && strv[i]; i++)
+               nm_wireguard_peer_append_allowed_ip (data->peer, g_strstrip (strv[i]), TRUE);
+       g_strfreev (strv);
+
+       endpoint = gtk_entry_get_text (data->entry_endpoint);
+       nm_wireguard_peer_set_endpoint (data->peer, endpoint && endpoint[0] ? endpoint : NULL, TRUE);
+
+       keepalive = gtk_spin_button_get_value_as_int (data->spin_keepalive);
+       nm_wireguard_peer_set_persistent_keepalive (data->peer, keepalive);
+
+       psk = gtk_entry_get_text (data->entry_psk);
+       if (psk && !psk[0])
+               psk = NULL;
+       nm_wireguard_peer_set_preshared_key (data->peer, psk, TRUE);
+
+       secret_flags = nma_utils_menu_to_secret_flags ((GtkWidget *) data->entry_psk);
+       nm_wireguard_peer_set_preshared_key_flags (data->peer, secret_flags);
+}
+
+static void
+peer_dialog_apply_clicked (GtkWidget *dialog)
+{
+       PeerDialogData *data;
+       gs_free_error GError *error = NULL;
+       gs_free char *reason = NULL;
+
+       data = g_object_get_data (G_OBJECT (dialog), "data");
+
+       if (!nm_wireguard_peer_is_valid (data->peer, TRUE, TRUE, &error)) {
+               reason = g_strdup_printf ("Error: %s", error->message);
+               gtk_label_set_text (data->label_info, reason);
+               gtk_widget_set_visible (GTK_WIDGET (data->info_bar), TRUE);
+       } else {
+               gtk_label_set_text (data->label_info, "");
+               gtk_widget_set_visible (GTK_WIDGET (data->info_bar), FALSE);
+               gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_APPLY);
+       }
+}
+
+static void
+peer_dialog_show_psk (GtkDialog *dialog)
+{
+       PeerDialogData *data;
+
+       data = g_object_get_data (G_OBJECT (dialog), "data");
+       gtk_entry_set_visibility (data->entry_psk,
+                                 gtk_toggle_button_get_active (data->toggle_show_psk));
+}
+
+static GtkWidget *
+peer_dialog_create (GtkWidget *toplevel, NMWireGuardPeer *peer)
+{
+       GtkWidget *dialog;
+       gs_free_error GError *error = NULL;
+       PeerDialogData *data;
+       GtkBuilder *builder;
+
+       builder = gtk_builder_new ();
+
+       if (!gtk_builder_add_from_resource (builder,
+                                           "/org/gnome/nm_connection_editor/ce-page-wireguard.ui",
+                                           &error)) {
+               g_warning ("Couldn't load builder resource: %s", error->message);
+               g_error_free (error);
+               return NULL;
+       }
+
+       dialog = GTK_WIDGET (gtk_builder_get_object (builder, "PeerDialog"));
+
+       data = g_new0 (PeerDialogData, 1);
+       data->peer = nm_wireguard_peer_ref (peer);
+       data->builder = builder;
+       data->button_apply = GTK_BUTTON (gtk_builder_get_object (builder, "button_apply"));
+       data->entry_public_key = GTK_ENTRY (gtk_builder_get_object (builder, "entry_public_key"));
+       data->entry_allowed_ips = GTK_ENTRY (gtk_builder_get_object (builder, "entry_allowed_ips"));
+       data->entry_endpoint = GTK_ENTRY (gtk_builder_get_object (builder, "entry_endpoint"));
+       data->entry_psk = GTK_ENTRY (gtk_builder_get_object (builder, "entry_psk"));
+       data->spin_keepalive = GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "spin_keepalive"));
+       data->info_bar = GTK_INFO_BAR (gtk_builder_get_object (builder, "info_bar"));
+       data->label_info = GTK_LABEL (gtk_builder_get_object (builder, "label_info"));
+       data->toggle_show_psk = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "toggle_show_psk"));
+
+       g_object_set_data_full (G_OBJECT (dialog), "data",
+                               data,
+                               (GDestroyNotify) peer_dialog_data_destroy);
+
+       nma_utils_setup_password_storage ((GtkWidget *) data->entry_psk, 0,
+                                         NULL, NULL, TRUE, FALSE);
+
+       gtk_entry_set_visibility (data->entry_psk, FALSE);
+
+       peer_dialog_update_ui (dialog);
+
+       g_signal_connect_swapped (data->button_apply, "clicked", G_CALLBACK (peer_dialog_apply_clicked), 
dialog);
+       g_signal_connect_swapped (data->entry_public_key, "changed", G_CALLBACK (peer_dialog_update_peer), 
dialog);
+       g_signal_connect_swapped (data->entry_allowed_ips, "changed", G_CALLBACK (peer_dialog_update_peer), 
dialog);
+       g_signal_connect_swapped (data->entry_endpoint, "changed", G_CALLBACK (peer_dialog_update_peer), 
dialog);
+       g_signal_connect_swapped (data->entry_psk, "changed", G_CALLBACK (peer_dialog_update_peer), dialog);
+       g_signal_connect_swapped (data->toggle_show_psk, "toggled", G_CALLBACK (peer_dialog_show_psk), 
dialog);
+
+       gtk_label_set_text (data->label_info, "");
+       gtk_widget_set_visible (GTK_WIDGET (data->info_bar), FALSE);
+
+       gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+       gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (toplevel));
+
+       return dialog;
+}
+
+static void
+wireguard_private_init (CEPageWireGuard *self)
+{
+       CEPageWireGuardPrivate *priv = CE_PAGE_WIREGUARD_GET_PRIVATE (self);
+       GtkBuilder *builder;
+       GtkTreeViewColumn *column;
+
+       builder = CE_PAGE (self)->builder;
+
+       priv->entry_ifname = GTK_ENTRY (gtk_builder_get_object (builder, "entry_ifname"));
+       priv->entry_pk = GTK_ENTRY (gtk_builder_get_object (builder, "entry_private_key"));
+       priv->spin_mtu = GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "spin_mtu"));
+       priv->spin_fwmark = GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "spin_fwmark"));
+       priv->spin_listen_port = GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "spin_listen_port"));
+       priv->toggle_peer_routes = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "toggle_peer_routes"));
+       priv->toggle_show_pk = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, 
"toggle_show_private_key"));
+       priv->tree = GTK_TREE_VIEW (gtk_builder_get_object (builder, "tree_peers"));
+       priv->button_add = GTK_BUTTON (gtk_builder_get_object (builder, "button_add"));
+       priv->button_delete = GTK_BUTTON (gtk_builder_get_object (builder, "button_delete"));
+
+       gtk_entry_set_visibility (priv->entry_pk, FALSE);
+
+       priv->store = gtk_tree_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
+       column = gtk_tree_view_column_new_with_attributes (_("Public key"),
+                                                          gtk_cell_renderer_text_new (),
+                                                          "text", COL_PUBLIC_KEY,
+                                                          NULL);
+       gtk_tree_view_column_set_resizable (column, TRUE);
+       gtk_tree_view_append_column (priv->tree, column);
+
+       column = gtk_tree_view_column_new_with_attributes (_("Allowed IPs"),
+                                                          gtk_cell_renderer_text_new (),
+                                                          "text", COL_ALLOWED_IPS,
+                                                          NULL);
+       gtk_tree_view_column_set_resizable (column, TRUE);
+       gtk_tree_view_append_column (priv->tree, column);
+
+       gtk_tree_view_set_model (priv->tree, GTK_TREE_MODEL (priv->store));
+}
+
+static void
+update_peers_table (CEPageWireGuard *self)
+{
+       CEPageWireGuardPrivate *priv = CE_PAGE_WIREGUARD_GET_PRIVATE (self);
+       NMSettingWireGuard *setting = priv->setting;
+       guint i, num;
+
+       gtk_tree_store_clear (priv->store);
+
+       num = nm_setting_wireguard_get_peers_len (setting);
+       for (i = 0; i < num; i++) {
+               NMWireGuardPeer *peer;
+               GtkTreeIter iter;
+               gs_free char *ips = NULL;
+
+               peer = nm_setting_wireguard_get_peer (setting, i);
+               ips = format_allowed_ips (peer);
+               gtk_tree_store_append (priv->store, &iter, NULL);
+
+               gtk_tree_store_set (priv->store, &iter,
+                                   COL_PUBLIC_KEY, nm_wireguard_peer_get_public_key (peer),
+                                   COL_ALLOWED_IPS, ips,
+                                   COL_PEER, peer,
+                                   -1);
+       }
+}
+
+static int
+get_selected_index (CEPageWireGuard *self)
+{
+       CEPageWireGuardPrivate *priv = CE_PAGE_WIREGUARD_GET_PRIVATE (self);
+       GtkTreeSelection *selection;
+       GtkTreeModel *model;
+       GList *list;
+       int *indices;
+       int ret = -1;
+
+       selection = gtk_tree_view_get_selection (priv->tree);
+       nm_assert (selection);
+
+       list = gtk_tree_selection_get_selected_rows (selection, &model);
+       if (!list)
+               goto done;
+
+       indices = gtk_tree_path_get_indices ((GtkTreePath *) list->data);
+       if (!indices)
+               goto done;
+
+       ret = indices[0];
+done:
+       g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free);
+       return ret;
+}
+
+static void
+tree_selection_changed (CEPageWireGuard *self)
+{
+       CEPageWireGuardPrivate *priv = CE_PAGE_WIREGUARD_GET_PRIVATE (self);
+       int index;
+
+       index = get_selected_index (self);
+       gtk_widget_set_sensitive (GTK_WIDGET (priv->button_delete), index >= 0);
+}
+
+static void
+populate_ui (CEPageWireGuard *self)
+{
+       CEPageWireGuardPrivate *priv = CE_PAGE_WIREGUARD_GET_PRIVATE (self);
+       NMSettingWireGuard *setting = priv->setting;
+       NMConnection *connection;
+       const char *str;
+
+       connection = CE_PAGE (self)->connection;
+       str = nm_connection_get_interface_name (connection);
+       if (str)
+               gtk_entry_set_text (priv->entry_ifname, str);
+
+       gtk_entry_set_text (priv->entry_pk, nm_setting_wireguard_get_private_key (setting) ?: "");
+       nma_utils_setup_password_storage ((GtkWidget *) priv->entry_pk, 0,
+                                         (NMSetting *) priv->setting,
+                                         NM_SETTING_WIREGUARD_PRIVATE_KEY,
+                                         FALSE, FALSE);
+
+       ce_spin_automatic_val (priv->spin_mtu, 0);
+       ce_spin_automatic_val (priv->spin_listen_port, 0);
+       gtk_spin_button_set_value (priv->spin_mtu, nm_setting_wireguard_get_mtu (setting));
+       gtk_spin_button_set_value (priv->spin_fwmark, nm_setting_wireguard_get_fwmark (setting));
+       gtk_spin_button_set_value (priv->spin_listen_port, nm_setting_wireguard_get_listen_port (setting));
+
+       gtk_toggle_button_set_active (priv->toggle_peer_routes,
+                                     nm_setting_wireguard_get_peer_routes (setting));
+
+       update_peers_table (self);
+       tree_selection_changed (self);
+}
+
+static void
+stuff_changed (GtkEditable *editable, gpointer user_data)
+{
+       ce_page_changed (CE_PAGE (user_data));
+}
+
+static void
+peer_dialog_response_cb (GtkWidget *dialog, gint response, gpointer user_data)
+{
+       CEPageWireGuard *self = CE_PAGE_WIREGUARD (user_data);
+       CEPageWireGuardPrivate *priv = CE_PAGE_WIREGUARD_GET_PRIVATE (self);
+
+       if (response == GTK_RESPONSE_APPLY) {
+               peer_dialog_update_peer (dialog);
+               if (priv->dialog_peer_index >= 0) {
+                       nm_setting_wireguard_set_peer (priv->setting,
+                                                      priv->dialog_peer,
+                                                      priv->dialog_peer_index);
+               } else {
+                       nm_setting_wireguard_append_peer (priv->setting,
+                                                         priv->dialog_peer);
+               }
+               update_peers_table (self);
+       }
+
+       nm_wireguard_peer_unref (priv->dialog_peer);
+       priv->dialog_peer = NULL;
+       priv->dialog_peer_index = -1;
+
+       gtk_widget_hide (dialog);
+       gtk_widget_destroy (dialog);
+}
+
+static void
+add_delete_clicked (GtkButton *button, CEPageWireGuard *self)
+{
+       CEPageWireGuardPrivate *priv = CE_PAGE_WIREGUARD_GET_PRIVATE (self);
+       GtkWidget *dialog;
+       int index;
+
+       g_return_if_fail (NM_IN_SET (button, priv->button_add, priv->button_delete));
+
+       if (button == priv->button_add) {
+               priv->dialog_peer = nm_wireguard_peer_new ();
+               priv->dialog_peer_index = -1;
+               dialog = peer_dialog_create (gtk_widget_get_toplevel (CE_PAGE (self)->page),
+                                            priv->dialog_peer);
+               if (!dialog)
+                       return;
+               g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (peer_dialog_response_cb), self);
+               gtk_widget_show (dialog);
+       } else {
+               index = get_selected_index (self);
+               if (index >= 0) {
+                       nm_setting_wireguard_remove_peer (priv->setting, (guint) index);
+                       update_peers_table (self);
+               }
+       }
+}
+
+static void
+row_activated (GtkTreeView       *tree_view,
+               GtkTreePath       *path,
+               GtkTreeViewColumn *column,
+               CEPageWireGuard   *self)
+{
+       CEPageWireGuardPrivate *priv = CE_PAGE_WIREGUARD_GET_PRIVATE (self);
+       NMWireGuardPeer *peer;
+       GtkWidget *dialog;
+       int index;
+
+       index = get_selected_index (self);
+       if (index < 0)
+               return;
+
+       peer = nm_setting_wireguard_get_peer (priv->setting, index);
+       priv->dialog_peer = nm_wireguard_peer_new_clone (peer, TRUE);
+       priv->dialog_peer_index = index;
+
+       dialog = peer_dialog_create (gtk_widget_get_toplevel (CE_PAGE (self)->page),
+                                    priv->dialog_peer);
+       if (!dialog)
+               return;
+
+       g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (peer_dialog_response_cb), self);
+       gtk_widget_show (dialog);
+}
+
+static void
+show_private_key (GtkToggleButton *button, gpointer user_data)
+{
+       CEPageWireGuardPrivate *priv = CE_PAGE_WIREGUARD_GET_PRIVATE (user_data);
+
+       gtk_entry_set_visibility (priv->entry_pk, gtk_toggle_button_get_active (button));
+}
+
+static void
+finish_setup (CEPageWireGuard *self, gpointer user_data)
+{
+       CEPageWireGuardPrivate *priv = CE_PAGE_WIREGUARD_GET_PRIVATE (self);
+       GtkTreeSelection *selection;
+
+       selection = gtk_tree_view_get_selection (priv->tree);
+       populate_ui (self);
+
+       g_signal_connect (priv->entry_ifname,      "changed",       G_CALLBACK (stuff_changed), self);
+       g_signal_connect (priv->entry_pk,          "changed",       G_CALLBACK (stuff_changed), self);
+       g_signal_connect (priv->spin_mtu,          "value-changed", G_CALLBACK (stuff_changed), self);
+       g_signal_connect (priv->spin_listen_port,  "value-changed", G_CALLBACK (stuff_changed), self);
+       g_signal_connect (priv->button_add,        "clicked",       G_CALLBACK (add_delete_clicked), self);
+       g_signal_connect (priv->button_delete,     "clicked",       G_CALLBACK (add_delete_clicked), self);
+       g_signal_connect (priv->tree,              "row-activated", G_CALLBACK (row_activated), self);
+       g_signal_connect (priv->toggle_show_pk,    "toggled",       G_CALLBACK (show_private_key), self);
+
+       g_signal_connect_swapped (selection,       "changed",       G_CALLBACK (tree_selection_changed), 
self);
+}
+
+CEPage *
+ce_page_wireguard_new (NMConnectionEditor *editor,
+                       NMConnection *connection,
+                       GtkWindow *parent_window,
+                       NMClient *client,
+                       const char **out_secrets_setting_name,
+                       GError **error)
+{
+       CEPageWireGuard *self;
+       CEPageWireGuardPrivate *priv;
+
+       self = CE_PAGE_WIREGUARD (ce_page_new (CE_TYPE_PAGE_WIREGUARD,
+                                              editor,
+                                              connection,
+                                              parent_window,
+                                              client,
+                                              "/org/gnome/nm_connection_editor/ce-page-wireguard.ui",
+                                              "WireGuardPage",
+                                             _("WireGuard")));
+       if (!self) {
+               g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("Could not load WireGuard user 
interface."));
+               return NULL;
+       }
+
+       wireguard_private_init (self);
+       priv = CE_PAGE_WIREGUARD_GET_PRIVATE (self);
+
+       priv->setting = (NMSettingWireGuard *) nm_connection_get_setting (connection, 
NM_TYPE_SETTING_WIREGUARD);
+       if (!priv->setting) {
+               priv->setting = NM_SETTING_WIREGUARD (nm_setting_wireguard_new ());
+               nm_connection_add_setting (connection, NM_SETTING (priv->setting));
+       }
+
+       g_signal_connect (self, CE_PAGE_INITIALIZED, G_CALLBACK (finish_setup), NULL);
+
+       *out_secrets_setting_name = NM_SETTING_WIREGUARD_SETTING_NAME;
+
+       return CE_PAGE (self);
+}
+
+static void
+ui_to_setting (CEPageWireGuard *self)
+{
+       CEPageWireGuardPrivate *priv = CE_PAGE_WIREGUARD_GET_PRIVATE (self);
+       NMSettingConnection *s_con;
+       guint32 mtu;
+       guint32 fwmark;
+       guint16 listen_port;
+       const char *private_key;
+       const char *ifname;
+       NMSettingSecretFlags secret_flags;
+       gboolean peer_routes;
+
+       s_con = nm_connection_get_setting_connection (CE_PAGE (self)->connection);
+       g_return_if_fail (s_con != NULL);
+
+       ifname = gtk_entry_get_text (priv->entry_ifname);
+       if (ifname && ifname[0] == '\0')
+               ifname = NULL;
+       g_object_set (s_con,
+                     NM_SETTING_CONNECTION_INTERFACE_NAME,
+                     ifname,
+                     NULL);
+
+       private_key = gtk_entry_get_text (priv->entry_pk);
+       if (private_key && private_key[0] == '\0')
+               private_key = NULL;
+       mtu = gtk_spin_button_get_value_as_int (priv->spin_mtu);
+       fwmark = gtk_spin_button_get_value_as_int (priv->spin_fwmark);
+       listen_port = gtk_spin_button_get_value_as_int (priv->spin_listen_port);
+       peer_routes = gtk_toggle_button_get_active (priv->toggle_peer_routes);
+
+       g_object_set (priv->setting,
+                     NM_SETTING_WIREGUARD_PRIVATE_KEY, private_key,
+                     NM_SETTING_WIREGUARD_LISTEN_PORT, listen_port,
+                     NM_SETTING_WIREGUARD_FWMARK, fwmark,
+                     NM_SETTING_WIREGUARD_MTU, mtu,
+                     NM_SETTING_WIREGUARD_PEER_ROUTES, peer_routes,
+                     NULL);
+
+       /* Save private key flags to the connection */
+       secret_flags = nma_utils_menu_to_secret_flags ((GtkWidget *) priv->entry_pk);
+       nm_setting_set_secret_flags (NM_SETTING (priv->setting),
+                                    NM_SETTING_WIREGUARD_PRIVATE_KEY,
+                                    secret_flags, NULL);
+
+       /* Update secret flags and popup when editing the connection */
+       nma_utils_update_password_storage ((GtkWidget *) priv->entry_pk,
+                                          secret_flags,
+                                          NM_SETTING (priv->setting),
+                                          NM_SETTING_WIREGUARD_PRIVATE_KEY);
+}
+
+static gboolean
+ce_page_validate_v (CEPage *page, NMConnection *connection, GError **error)
+{
+       CEPageWireGuard *self = CE_PAGE_WIREGUARD (page);
+       CEPageWireGuardPrivate *priv = CE_PAGE_WIREGUARD_GET_PRIVATE (self);
+
+       ui_to_setting (self);
+
+       return    nm_setting_verify (NM_SETTING (priv->setting), connection, error)
+              && nm_setting_verify_secrets (NM_SETTING (priv->setting), connection, error);
+}
+
+static void
+ce_page_wireguard_init (CEPageWireGuard *self)
+{
+}
+
+static void
+ce_page_wireguard_class_init (CEPageWireGuardClass *wireguard_class)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (wireguard_class);
+       CEPageClass *parent_class = CE_PAGE_CLASS (wireguard_class);
+
+       g_type_class_add_private (object_class, sizeof (CEPageWireGuardPrivate));
+
+       parent_class->ce_page_validate_v = ce_page_validate_v;
+}
+
+void
+wireguard_connection_new (FUNC_TAG_PAGE_NEW_CONNECTION_IMPL,
+                          GtkWindow *parent,
+                          const char *detail,
+                          gpointer detail_data,
+                          NMConnection *connection,
+                          NMClient *client,
+                          PageNewConnectionResultFunc result_func,
+                          gpointer user_data)
+{
+       gs_unref_object NMConnection *connection_tmp = NULL;
+       NMSettingIPConfig *s_ip;
+
+       connection = _ensure_connection_other (connection, &connection_tmp);
+       ce_page_complete_connection (connection,
+                                    _("WireGuard connection %d"),
+                                    NM_SETTING_WIREGUARD_SETTING_NAME,
+                                    FALSE,
+                                    client);
+       nm_connection_add_setting (connection, nm_setting_wireguard_new ());
+
+       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_IGNORE, NULL);
+       nm_connection_add_setting (connection, (NMSetting *) s_ip);
+
+       (*result_func) (FUNC_TAG_PAGE_NEW_CONNECTION_RESULT_CALL, connection, FALSE, NULL, user_data);
+}
diff --git a/src/connection-editor/page-wireguard.h b/src/connection-editor/page-wireguard.h
new file mode 100644
index 00000000..d3e945e0
--- /dev/null
+++ b/src/connection-editor/page-wireguard.h
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* NetworkManager Connection editor -- Connection editor for NetworkManager
+ *
+ * Copyright 2020 Red Hat, Inc.
+ */
+
+#ifndef __PAGE_WIREGUARD_H__
+#define __PAGE_WIREGUARD_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "ce-page.h"
+
+#define CE_TYPE_PAGE_WIREGUARD            (ce_page_wireguard_get_type ())
+#define CE_PAGE_WIREGUARD(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), CE_TYPE_PAGE_WIREGUARD, 
CEPageWireGuard))
+#define CE_PAGE_WIREGUARD_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), CE_TYPE_PAGE_WIREGUARD, 
CEPageWireGuardClass))
+#define CE_IS_PAGE_WIREGUARD(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CE_TYPE_PAGE_WIREGUARD))
+#define CE_IS_PAGE_WIREGUARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CE_TYPE_PAGE_WIREGUARD))
+#define CE_PAGE_WIREGUARD_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), CE_TYPE_PAGE_WIREGUARD, 
CEPageWireGuardClass))
+
+typedef struct {
+       CEPage parent;
+} CEPageWireGuard;
+
+typedef struct {
+       CEPageClass parent;
+} CEPageWireGuardClass;
+
+GType ce_page_wireguard_get_type (void);
+
+CEPage *ce_page_wireguard_new (NMConnectionEditor *editor,
+                               NMConnection *connection,
+                               GtkWindow *parent,
+                               NMClient *client,
+                               const char **out_secrets_setting_name,
+                               GError **error);
+
+void wireguard_connection_new (FUNC_TAG_PAGE_NEW_CONNECTION_IMPL,
+                               GtkWindow *parent,
+                               const char *detail,
+                               gpointer detail_data,
+                               NMConnection *connection,
+                               NMClient *client,
+                               PageNewConnectionResultFunc callback,
+                               gpointer user_data);
+
+#endif  /* __PAGE_WIREGUARD_H__ */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]