diff --git a/NetworkMgr/trayicon.py b/NetworkMgr/trayicon.py index 76fcc51..b0690f2 100755 --- a/NetworkMgr/trayicon.py +++ b/NetworkMgr/trayicon.py @@ -25,6 +25,12 @@ ) from NetworkMgr.configuration import network_card_configuration +from NetworkMgr.wg_api import ( + wg_dictionary, + disable_wg, + enable_wg, + wg_status +) gettext.bindtextdomain('networkmgr', '/usr/local/share/locale') gettext.textdomain('networkmgr') @@ -64,6 +70,32 @@ def icon_clicked(self, status_icon, button, time): def nm_menu(self): self.menu = Gtk.Menu() + if len(self.wginfo['configs'])> 0 and self.wginfo['service'] == '"NO"': + wg_title = Gtk.MenuItem() + wg_title.set_label(_("WireGuard VPN")) + wg_title.set_sensitive(False) + self.menu.append(wg_title) + self.menu.append(Gtk.SeparatorMenuItem()) + wg_devices = self.wginfo['configs'] + for wg_dev in wg_devices: + connection_state = wg_devices[wg_dev]['state'] + connection_info = wg_devices[wg_dev]['info'] + if connection_state == "Connected": + wg_item = Gtk.MenuItem(_("%s Connected") % connection_info) + wg_item.set_sensitive(False) + self.menu.append(wg_item) + disconnectwg_item = Gtk.ImageMenuItem(_(f"Disable {wg_dev}")) + disconnectwg_item.connect("activate", self.disconnectWG, wg_dev) + self.menu.append(disconnectwg_item) + else: + notonlinewg = Gtk.MenuItem(_("%s Disconnected") % connection_info) + notonlinewg.set_sensitive(False) + self.menu.append(notonlinewg) + wiredwg_item = Gtk.MenuItem(_("Enable")) + wiredwg_item.connect("activate", self.connectWG, wg_dev) + self.menu.append(wiredwg_item) + self.menu.append(Gtk.SeparatorMenuItem()) + e_title = Gtk.MenuItem() e_title.set_label(_("Ethernet Network")) e_title.set_sensitive(False) @@ -220,6 +252,14 @@ def disconnectcard(self, widget, netcard): stopnetworkcard(netcard) self.updateinfo() + def connectWG(self, widget, wginfo): + enable_wg(wginfo) + self.updateinfo() + + def disconnectWG(self, widget, wginfo): + disable_wg(wginfo) + self.updateinfo() + def closeNetwork(self, widget): stopallnetwork() self.updateinfo() @@ -258,6 +298,7 @@ def updateinfo(self): defaultcard = self.cardinfo['default'] default_type = self.network_type(defaultcard) GLib.idle_add(self.updatetray, defaultcard, default_type) + self.wginfo = wg_dictionary() self.if_running = False def updatetray(self, defaultdev, default_type): diff --git a/NetworkMgr/wg_api.py b/NetworkMgr/wg_api.py new file mode 100644 index 0000000..ea052cf --- /dev/null +++ b/NetworkMgr/wg_api.py @@ -0,0 +1,69 @@ +#!/usr/local/bin/python3.11 + +from platform import system +from subprocess import PIPE, run, os + +PREFIX = '/usr/local' if system() == 'FreeBSD' else sys.prefix +WG_CONFIG_PATH = f'{PREFIX}/etc/wireguard/' + +def wg_service_state(): + """Function returns the WireGuard service status.""" + result = run(['service', 'wireguard', 'rcvar'], stdout=PIPE, stderr=PIPE, check=False) + out = result.stdout.decode('utf-8') + + state = 'Unknown' + + for line in out.splitlines(): + if "wireguard_enable=" in line: + state = line.split('=')[1].strip() + break + + return state + +def wg_dictionary(): + """Function returns the WireGuard configurations.""" + maindictionary = { + 'service': wg_service_state(), + 'default': '', + } + configs = {} + + if os.path.exists(WG_CONFIG_PATH): + wgconfigs = sorted(os.listdir(WG_CONFIG_PATH)) + for wgconfig in wgconfigs: + wg_device = wgconfig.replace('.conf', '') + wg_state = wg_status(wg_device) + wg_name = wg_device + with open(WG_CONFIG_PATH + wgconfig, encoding="utf-8") as content: + for line in content: + if "# Name = " in line: + wg_name = line.split('=')[1].strip() + break + + seconddictionary = { 'state': wg_state, 'info': wg_name } + configs[wg_device] = seconddictionary + + maindictionary['configs'] = configs + + return maindictionary + +def disable_wg(wgconfig): + """Function disable the specified WireGuard configuration (device).""" + run(f'wg-quick down {wgconfig}', shell=True, check=False) + +def enable_wg(wgconfig): + """Function enable the specified WireGuard configuration (device).""" + run(f'wg-quick up {wgconfig}', shell=True, check=False) + +def wg_status(wgconfig): + """Function returning the WireGuard configuration (device) is connected or not.""" + result = run(['wg', 'show', wgconfig], stdout=PIPE, stderr=PIPE, check=False) + out = result.stdout.decode('utf-8') + error = result.stderr.decode('utf-8') + + if len(out) == 0 and 'Unable to access interface: Device not configured' in error: + status = "Disconnected" + else: + status = "Connected" + + return status