Skip to content

Commit

Permalink
Support Wireguard as a VPN connection (#338)
Browse files Browse the repository at this point in the history
  • Loading branch information
milouse authored Oct 26, 2023
1 parent 3b69132 commit 4553bda
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 39 deletions.
108 changes: 76 additions & 32 deletions src/Views/VPNPage.vala
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

public class Network.VPNPage : Network.Widgets.Page {
public Network.Widgets.DeviceItem owner { get; construct; }
private Gee.List<NM.VpnConnection> active_connections;
private Gee.List<NM.ActiveConnection> active_connections;

private Gtk.ListBox vpn_list;
private uint timeout_id = 0;
Expand Down Expand Up @@ -125,7 +125,7 @@ public class Network.VPNPage : Network.Widgets.Page {
edit_connection_button.sensitive = row != null;
});

active_connections = new Gee.ArrayList<NM.VpnConnection> ();
active_connections = new Gee.ArrayList<NM.ActiveConnection> ();

update ();
unowned NetworkManager network_manager = NetworkManager.get_default ();
Expand All @@ -138,23 +138,40 @@ public class Network.VPNPage : Network.Widgets.Page {
VPNMenuItem? item = null;
foreach (var ac in active_connections) {
if (ac != null) {
switch (ac.get_vpn_state ()) {
case NM.VpnConnectionState.UNKNOWN:
case NM.VpnConnectionState.DISCONNECTED:
state = NM.DeviceState.DISCONNECTED;
break;
case NM.VpnConnectionState.PREPARE:
case NM.VpnConnectionState.NEED_AUTH:
case NM.VpnConnectionState.IP_CONFIG_GET:
case NM.VpnConnectionState.CONNECT:
state = NM.DeviceState.PREPARE;
break;
case NM.VpnConnectionState.FAILED:
state = NM.DeviceState.FAILED;
break;
case NM.VpnConnectionState.ACTIVATED:
state = NM.DeviceState.ACTIVATED;
break;
unowned string connection_type = ac.get_connection_type ();
if (connection_type == NM.SettingVpn.SETTING_NAME) {
switch (((NM.VpnConnection)ac).vpn_state) {
case NM.VpnConnectionState.UNKNOWN:
case NM.VpnConnectionState.DISCONNECTED:
state = NM.DeviceState.DISCONNECTED;
break;
case NM.VpnConnectionState.PREPARE:
case NM.VpnConnectionState.NEED_AUTH:
case NM.VpnConnectionState.IP_CONFIG_GET:
case NM.VpnConnectionState.CONNECT:
state = NM.DeviceState.PREPARE;
break;
case NM.VpnConnectionState.FAILED:
state = NM.DeviceState.FAILED;
break;
case NM.VpnConnectionState.ACTIVATED:
state = NM.DeviceState.ACTIVATED;
break;
}
} else if (connection_type == NM.SettingWireGuard.SETTING_NAME) {
switch (ac.get_state ()) {
case NM.ActiveConnectionState.UNKNOWN:
case NM.ActiveConnectionState.DEACTIVATED:
case NM.ActiveConnectionState.DEACTIVATING:
state = NM.DeviceState.DISCONNECTED;
break;
case NM.ActiveConnectionState.ACTIVATING:
state = NM.DeviceState.PREPARE;
break;
case NM.ActiveConnectionState.ACTIVATED:
state = NM.DeviceState.ACTIVATED;
break;
}
}

item = get_item_by_uuid (ac.get_uuid ());
Expand Down Expand Up @@ -206,37 +223,64 @@ public class Network.VPNPage : Network.Widgets.Page {

private void update_active_connections () {
active_connections.clear ();

unowned NetworkManager network_manager = NetworkManager.get_default ();
network_manager.client.get_active_connections ().foreach ((ac) => {
if (ac.get_vpn ()) {
active_connections.add ((NM.VpnConnection) ac);
(ac as NM.VpnConnection).vpn_state_changed.connect (update);
unowned string connection_type = ac.get_connection_type ();
/* In both case, make sure to disconnect first any previously
* connected signal to avoid spamming the CPU once you pass several
* time into this function. */
if (connection_type == NM.SettingVpn.SETTING_NAME) {
/* We cannot rely on the sole state_changed signal, as it will
* silently ignore sub-vpn specific states, like tun/tap
* interface connection etc. That's why we keep a separate
* implementation for the signal handlers. */
var _connection = (NM.VpnConnection) ac;
_connection.vpn_state_changed.disconnect (update);
_connection.vpn_state_changed.connect (update);
} else if (connection_type == NM.SettingWireGuard.SETTING_NAME) {
ac.state_changed.disconnect (update);
ac.state_changed.connect (update);
} else {
// Neither a VPN, nor a Wireguard connection, do not add it to
// the active_connection list.
return;
}
// Either a VPN or a Wireguard connection
active_connections.add (ac);
});
}

private void connect_vpn_cb (VPNMenuItem item) {
update_active_connections ();
unowned NetworkManager network_manager = NetworkManager.get_default ();
network_manager.client.activate_connection_async.begin (item.connection, null, null, null, null);
update ();
network_manager.client.activate_connection_async.begin (
item.connection, null, null, null,
(obj, res) => {
try {
network_manager.client.activate_connection_async.end (res);
} catch (Error e) {
warning (e.message);
}
update ();
}
);
}

private void disconnect_vpn_cb (VPNMenuItem item) {
update_active_connections ();
unowned NetworkManager network_manager = NetworkManager.get_default ();
foreach (var ac in active_connections) {
if (ac.get_connection () == item.connection) {
try {
network_manager.client.deactivate_connection (ac);
} catch (Error e) {
warning (e.message);
}
network_manager.client.deactivate_connection_async.begin (ac, null, (obj, res) => {
try {
network_manager.client.deactivate_connection_async.end (res);
} catch (Error e) {
warning (e.message);
}
update ();
});
break;
}
}
update ();
}

private void remove_button_cb () {
Expand Down
2 changes: 2 additions & 0 deletions src/Widgets/DeviceList.vala
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ namespace Network.Widgets {

public void add_connection (NM.RemoteConnection connection) {
switch (connection.get_connection_type ()) {
case NM.SettingWireGuard.SETTING_NAME:
case NM.SettingVpn.SETTING_NAME:
((VPNPage)vpn.page).add_connection (connection);
break;
Expand All @@ -94,6 +95,7 @@ namespace Network.Widgets {

public void remove_connection (NM.RemoteConnection connection) {
switch (connection.get_connection_type ()) {
case NM.SettingWireGuard.SETTING_NAME:
case NM.SettingVpn.SETTING_NAME:
((VPNPage)vpn.page).remove_connection (connection);
break;
Expand Down
32 changes: 25 additions & 7 deletions src/Widgets/VPN/VPNInfoDialog.vala
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,31 @@ public class Network.Widgets.VPNInfoDialog : Granite.MessageDialog {

primary_text = connection.get_id ();

var vpn_settings = connection.get_setting_vpn ();
if (vpn_settings != null) {
service_type = get_service_type (vpn_settings);
vpn_type.label = service_type;

gateway.label = vpn_settings.get_data_item (get_key_gateway ());
username.label = vpn_settings.get_data_item (get_key_group_username ());
switch (connection.get_connection_type ()) {
case NM.SettingWireGuard.SETTING_NAME:
service_type = NM.SettingWireGuard.SETTING_NAME;
vpn_type.label = service_type;

var wireguard_settings = (NM.SettingWireGuard) connection.get_setting (typeof (NM.SettingWireGuard));
if (wireguard_settings != null) {
if (wireguard_settings.get_peers_len () >= 1) {
NM.WireGuardPeer first_peer = wireguard_settings.get_peer (0);
gateway.label = first_peer.get_endpoint ();
username.label = "";
}
}
break;
case NM.SettingVpn.SETTING_NAME:
var vpn_settings = connection.get_setting_vpn ();

if (vpn_settings != null) {
service_type = get_service_type (vpn_settings);
vpn_type.label = service_type;

gateway.label = vpn_settings.get_data_item (get_key_gateway ());
username.label = vpn_settings.get_data_item (get_key_group_username ());
}
break;
}

vpn_type.visible = vpn_type.label != "";
Expand Down

0 comments on commit 4553bda

Please sign in to comment.