Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Wireguard as a VPN connection #338

Merged
merged 5 commits into from
Oct 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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