summaryrefslogtreecommitdiff
path: root/src/conf_mode
diff options
context:
space:
mode:
authorDaniil Baturin <daniil@baturin.org>2018-11-12 16:57:22 +0100
committerDaniil Baturin <daniil@baturin.org>2018-11-12 16:57:22 +0100
commit559ac84addd27c135f5799304434ad3ef872555d (patch)
tree5d06f61b62ff69760d83f63ca42927f7f61d1d1f /src/conf_mode
parent7e6e5a211325b8f00e58a01a67ad2c01d073ff2a (diff)
parent718d9a123c2ba72b87d7f6e48a5e6d83fa86d494 (diff)
downloadvyos-1x-559ac84addd27c135f5799304434ad3ef872555d.tar.gz
vyos-1x-559ac84addd27c135f5799304434ad3ef872555d.zip
Merge branch 'current' into crux
Diffstat (limited to 'src/conf_mode')
-rwxr-xr-xsrc/conf_mode/accel_pppoe.py363
-rwxr-xr-xsrc/conf_mode/dhcp_server.py19
-rwxr-xr-xsrc/conf_mode/dns_forwarding.py14
-rwxr-xr-xsrc/conf_mode/dynamic_dns.py4
-rwxr-xr-xsrc/conf_mode/igmp_proxy.py179
-rwxr-xr-xsrc/conf_mode/wireguard.py33
6 files changed, 597 insertions, 15 deletions
diff --git a/src/conf_mode/accel_pppoe.py b/src/conf_mode/accel_pppoe.py
new file mode 100755
index 000000000..4aea84c44
--- /dev/null
+++ b/src/conf_mode/accel_pppoe.py
@@ -0,0 +1,363 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2018 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+#
+
+import sys
+import os
+import re
+import subprocess
+import jinja2
+import socket
+import time
+import syslog as sl
+
+from vyos.config import Config
+from vyos import ConfigError
+
+pidfile = r'/var/run/accel_pppoe.pid'
+pppoe_cnf_dir = r'/etc/accel-ppp/pppoe'
+chap_secrets = pppoe_cnf_dir + '/chap-secrets'
+pppoe_conf = pppoe_cnf_dir + '/pppoe.config'
+# accel-pppd -d -c /etc/accel-ppp/pppoe/pppoe.config -p /var/run/accel_pppoe.pid
+
+### config path creation
+if not os.path.exists(pppoe_cnf_dir):
+ os.makedirs(pppoe_cnf_dir)
+ sl.syslog(sl.LOG_NOTICE, pppoe_cnf_dir + " created")
+
+pppoe_config = '''
+### generated by accel_pppoe.py ###
+[modules]
+log_syslog
+pppoe
+ippool
+chap-secrets
+auth_pap
+auth_chap_md5
+auth_mschap_v1
+auth_mschap_v2
+pppd_compat
+shaper
+net-snmp
+connlimit
+{% if authentication['mode'] == 'radius' %}
+radius
+{% endif %}
+
+[core]
+thread-count={{thread_cnt}}
+
+[log]
+syslog=accel-pppoe,daemon
+copy=1
+level=5
+
+[snmp]
+master=1
+
+[client-ip-range]
+disable
+
+[ip-pool]
+{% if client_ip_pool %}
+{{client_ip_pool}}
+{% endif %}
+gw-ip-address={{ppp_gw}}
+
+{% if dns %}
+[dns]
+{% if dns[0] %}
+dns1={{dns[0]}}
+{% endif %}
+{% if dns[1] %}
+dns2={{dns[1]}}
+{% endif %}
+{% endif %}
+
+{% if wins %}
+[wins]
+{% if wins[0] %}
+wins1={{wins[0]}}
+{% endif %}
+{% if wins[1] %}
+wins2={{wins[1]}}
+{% endif %}
+{% endif %}
+
+{% if authentication['mode'] == 'local' %}
+[chap-secrets]
+chap-secrets=/etc/accel-ppp/pppoe/chap-secrets
+{% endif %}
+
+{% if authentication['mode'] == 'radius' %}
+[radius]
+{% for rsrv in authentication['radiussrv']: %}
+server={{rsrv}},{{authentication['radiussrv'][rsrv]}}
+{% endfor %}
+timeout=10
+acct-timeout=3
+gw-ip-address={{ppp_gw}}
+verbose=1
+{% endif %}
+
+[ppp]
+verbose=1
+min-mtu={{mtu}}
+mtu={{mtu}}
+mru=1400
+check-ip=1
+mppe=prefer
+ipv4=require
+check-ip=1
+single-session=replace
+mppe=prefer
+lcp-echo-interval=30
+lcp-echo-failure=3
+
+[pppoe]
+verbose=1
+{% if concentrator %}
+ac-name={{concentrator}}
+{% endif %}
+{% if interface %}
+{% for int in interface %}
+interface={{int}}
+{% endfor %}
+{% endif %}
+{% if svc_name %}
+service-name={{svc_name}}
+{% endif %}
+
+
+[connlimit]
+limit=10/min
+burst=3
+timeout=60
+
+[cli]
+tcp=127.0.0.1:2001
+'''
+
+### pppoe chap secrets
+chap_secrets_conf = '''
+# username server password acceptable local IP addresses
+{% for user in authentication['local-users'] %}
+{% if authentication['local-users'][user]['state'] == 'enabled' %}
+{{user}}\t*\t{{authentication['local-users'][user]['passwd']}}\t{{authentication['local-users'][user]['ip']}}
+{% endif %}
+{% endfor %}
+'''
+###
+# inline helper functions
+###
+# depending on hw and threads, daemon needs a little to start
+# if it takes longer than 100 * 0.5 secs, exception is being raised
+# not sure if that's the best way to check it, but it worked so far quite well
+###
+def chk_con():
+ cnt = 0
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ while True:
+ try:
+ s.connect(("127.0.0.1", 2001))
+ break
+ except ConnectionRefusedError:
+ time.sleep(0.5)
+ cnt +=1
+ if cnt == 100:
+ raise("failed to start pppoe server")
+ break
+
+### chap_secrets file if auth mode local
+def write_chap_secrets(c):
+ tmpl = jinja2.Template(chap_secrets_conf, trim_blocks=True)
+ chap_secrets_txt = tmpl.render(c)
+ old_umask = os.umask(0o077)
+ open(chap_secrets,'w').write(chap_secrets_txt)
+ os.umask(old_umask)
+ sl.syslog(sl.LOG_NOTICE, chap_secrets + ' written')
+
+def accel_cmd(cmd=''):
+ if not cmd:
+ return None
+ try:
+ ret = subprocess.check_output(['/usr/bin/accel-cmd',cmd]).decode().strip()
+ return ret
+ except:
+ return 1
+
+###
+# inline helper functions end
+###
+
+def get_config():
+ c = Config()
+ if not c.exists('service pppoe-server'):
+ return None
+
+ config_data = {
+ 'concentrator' : 'vyos-ac',
+ 'authentication' : {
+ 'local-users' : {
+ },
+ 'mode' : 'local',
+ 'radiussrv' : {}
+ },
+ 'client_ip_pool' : '',
+ 'interface' : [],
+ 'ppp_gw' : '',
+ 'svc_name' : '',
+ 'dns' : [],
+ 'wins' : [],
+ 'mtu' : '1492'
+ }
+
+ c.set_level('service pppoe-server')
+
+ if c.exists('access-concentrator'):
+ config_data['concentrator'] = c.return_value('access-concentrator')
+ if c.exists('service-name'):
+ config_data['svc_name'] = c.return_value('service-name')
+ if c.exists('interface'):
+ config_data['interface'] = c.return_values('interface')
+ if c.exists('local-ip'):
+ config_data['ppp_gw'] = c.return_value('local-ip')
+ if c.exists('dns-servers'):
+ if c.return_value('dns-servers server-1'):
+ config_data['dns'].append(c.return_value('dns-servers server-1'))
+ if c.return_value('dns-servers server-2'):
+ config_data['dns'].append(c.return_value('dns-servers server-2'))
+ if c.exists('wins-servers'):
+ if c.return_value('wins-servers server-1'):
+ config_data['wins'].append(c.return_value('wins-servers server-1'))
+ if c.return_value('wins-servers server-2'):
+ config_data['wins'].append(c.return_value('wins-servers server-2'))
+ if c.exists('client-ip-pool'):
+ if c.exists('client-ip-pool start'):
+ config_data['client_ip_pool'] = c.return_value('client-ip-pool start')
+ if c.exists('client-ip-pool stop'):
+ config_data['client_ip_pool'] += '-' + re.search('[0-9]+$', c.return_value('client-ip-pool stop')).group(0)
+ else:
+ raise ConfigError('client ip pool stop required')
+
+ #### authentication mode local
+ if c.exists('authentication'):
+ if c.return_value('authentication mode') == 'local':
+ if c.exists('authentication local-users username'):
+ for usr in c.list_nodes('authentication local-users username'):
+ config_data['authentication']['local-users'].update(
+ {
+ usr : {
+ 'passwd' : '',
+ 'state' : 'enabled',
+ 'ip' : '*'
+ }
+ }
+ )
+ if c.exists('authentication local-users username ' + usr + ' password'):
+ config_data['authentication']['local-users'][usr]['passwd'] = c.return_value('authentication local-users username ' + usr + ' password')
+ if c.exists('authentication local-users username ' + usr + ' disable'):
+ config_data['authentication']['local-users'][usr]['state'] = 'disable'
+ if c.exists('authentication local-users username ' + usr + ' static-ip'):
+ config_data['authentication']['local-users'][usr]['ip'] = c.return_value('authentication local-users username ' + usr + ' static-ip')
+
+ ### authentication mode radius
+ if c.return_value('authentication mode') == 'radius':
+ config_data['authentication']['mode'] = 'radius'
+ rsrvs = c.list_nodes('authentication radius-server')
+ for rsrv in rsrvs:
+ config_data['authentication']['radiussrv'].update(
+ {
+ rsrv : str(c.return_value('authentication radius-server ' + rsrv + ' key'))
+ }
+ )
+
+ if c.exists('mtu'):
+ config_data['mtu'] = c.return_value('mtu')
+
+ return config_data
+
+def verify(c):
+ if c == None:
+ return None
+
+ for usr in c['authentication']['local-users']:
+ if not c['authentication']['local-users'][usr]:
+ raise ConfigError('user ' + usr + ' has no password set')
+
+ if not c['ppp_gw']:
+ raise ConfigError('pppoe gateway-ip required')
+
+ if c['authentication']['mode'] == 'radius':
+ if len(c['authentication']['radiussrv']) == 0:
+ raise ConfigError('radius server required')
+
+def generate(c):
+ if c == None:
+ return None
+
+ ### accel-cmd reload doesn't work so any change results in a restart of the daemon
+ try:
+ if os.cpu_count() == 1:
+ c['thread_cnt'] = 1
+ else:
+ c['thread_cnt'] = int(os.cpu_count()/2)
+ except KeyError:
+ if os.cpu_count() == 1:
+ c['thread_cnt'] = 1
+ else:
+ c['thread_cnt'] = int(os.cpu_count()/2)
+
+ tmpl = jinja2.Template(pppoe_config, trim_blocks=True)
+ config_text = tmpl.render(c)
+ open(pppoe_conf,'w').write(config_text)
+ sl.syslog(sl.LOG_NOTICE, pppoe_config + ' written')
+
+ return c
+
+def apply(c):
+ if c == None:
+ if os.path.exists(pidfile):
+ accel_cmd('shutdown hard')
+ if os.path.exists(pidfile):
+ os.remove(pidfile)
+ return None
+
+ if not os.path.exists(pidfile):
+ ret = subprocess.call(['/usr/sbin/accel-pppd','-c',pppoe_conf,'-p',pidfile,'-d'])
+ chk_con()
+ if ret !=0 and os.path.exists(pidfile):
+ os.remove(pidfile)
+ raise ConfigError('accel-pppd failed to start')
+ else:
+ accel_cmd('restart')
+ sl.syslog(sl.LOG_NOTICE, "reloading config via daemon restart")
+
+ #if c['state'] == 'update':
+ # accel_cmd('restart')
+ # sl.syslog(sl.LOG_NOTICE, "reloading config via daemon restart")
+ # ## check that config reload actually works
+
+if __name__ == '__main__':
+ try:
+ c = get_config()
+ verify(c)
+ generate(c)
+ apply(c)
+ except ConfigError as e:
+ print(e)
+ sys.exit(1)
diff --git a/src/conf_mode/dhcp_server.py b/src/conf_mode/dhcp_server.py
index 2a2b1fe6c..560c80e7f 100755
--- a/src/conf_mode/dhcp_server.py
+++ b/src/conf_mode/dhcp_server.py
@@ -42,14 +42,6 @@ config_tmpl = """
# log-facility local7;
{% if hostfile_update %}
-on commit {
- set ClientName = pick-first-value(host-decl-name, option fqdn.hostname, option host-name);
- set ClientIp = binary-to-ascii(10, 8, ".", leased-address);
- set ClientMac = binary-to-ascii(16, 8, ":", substring(hardware, 1, 6));
- set ClientDomain = pick-first-value(config-option domain-name, "..YYZ!");
- execute("/usr/libexec/vyos/system/on-dhcp-event.sh", "commit", ClientName, ClientIp, ClientMac, ClientDomain);
-}
-
on release {
set ClientName = pick-first-value(host-decl-name, option fqdn.hostname, option host-name);
set ClientIp = binary-to-ascii(10, 8, ".",leased-address);
@@ -210,7 +202,16 @@ shared-network {{ network.name }} {
{%- endif %}
}
{%- endfor %}
- on commit { set shared-networkname = "{{ network.name }}"; }
+ on commit {
+ set shared-networkname = "{{ network.name }}";
+ {% if hostfile_update -%}
+ set ClientName = pick-first-value(host-decl-name, option fqdn.hostname, option host-name);
+ set ClientIp = binary-to-ascii(10, 8, ".", leased-address);
+ set ClientMac = binary-to-ascii(16, 8, ":", substring(hardware, 1, 6));
+ set ClientDomain = pick-first-value(config-option domain-name, "..YYZ!");
+ execute("/usr/libexec/vyos/system/on-dhcp-event.sh", "commit", ClientName, ClientIp, ClientMac, ClientDomain);
+ {% endif -%}
+ }
}
{%- endif %}
{% endfor %}
diff --git a/src/conf_mode/dns_forwarding.py b/src/conf_mode/dns_forwarding.py
index 43be9d526..c21a91a30 100755
--- a/src/conf_mode/dns_forwarding.py
+++ b/src/conf_mode/dns_forwarding.py
@@ -36,9 +36,11 @@ config_tmpl = """
# Non-configurable defaults
daemon=yes
threads=1
-allow-from=0.0.0.0/0
+allow-from=0.0.0.0/0, ::/0
log-common-errors=yes
non-local-bind=yes
+query-local-address=0.0.0.0
+query-local-address6=::
# cache-size
max-cache-entries={{ cache_size }}
@@ -114,10 +116,10 @@ def get_config():
if conf.exists('domain'):
for node in conf.list_nodes('domain'):
- server = conf.return_values("domain {0} server".format(node))
+ servers = conf.return_values("domain {0} server".format(node))
domain = {
"name": node,
- "servers": server
+ "servers": bracketize_ipv6_addrs(servers)
}
dns['domains'].append(domain)
@@ -138,6 +140,8 @@ def get_config():
dns['name_servers'] = dns['name_servers'] + system_name_servers
conf.set_level('service dns forwarding')
+ dns['name_servers'] = bracketize_ipv6_addrs(dns['name_servers'])
+
if conf.exists('listen-address'):
dns['listen_on'] = conf.return_values('listen-address')
@@ -193,6 +197,10 @@ def get_config():
return dns
+def bracketize_ipv6_addrs(addrs):
+ """Wraps each IPv6 addr in addrs in [], leaving IPv4 addrs untouched."""
+ return ['[{0}]'.format(a) if a.count(':') > 1 else a for a in addrs]
+
def verify(dns):
# bail out early - looks like removal from running config
if dns is None:
diff --git a/src/conf_mode/dynamic_dns.py b/src/conf_mode/dynamic_dns.py
index 60efcaae2..afebc5d0e 100755
--- a/src/conf_mode/dynamic_dns.py
+++ b/src/conf_mode/dynamic_dns.py
@@ -38,8 +38,8 @@ cache=/var/cache/ddclient/ddclient.cache
#
# ddclient configuration for interface "{{ interface.interface }}":
#
-{% if interface.web_url and interface.web_skip -%}
-use=web, web={{ interface.web_url}}, web-skip={{ interface.web_skip }}
+{% if interface.web_url -%}
+use=web, web={{ interface.web_url}} {%- if interface.web_skip %}, web-skip={{ interface.web_skip }}{% endif %}
{% else -%}
use=if, if={{ interface.interface }}
{% endif -%}
diff --git a/src/conf_mode/igmp_proxy.py b/src/conf_mode/igmp_proxy.py
new file mode 100755
index 000000000..b994369af
--- /dev/null
+++ b/src/conf_mode/igmp_proxy.py
@@ -0,0 +1,179 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2018 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+#
+
+import sys
+import os
+import jinja2
+
+from vyos.config import Config
+from vyos import ConfigError
+
+config_file = r'/etc/igmpproxy.conf'
+
+# Please be careful if you edit the template.
+config_tmpl = """
+########################################################
+#
+# autogenerated by igmp_proxy.py
+#
+# The configuration file must define one upstream
+# interface, and one or more downstream interfaces.
+#
+# If multicast traffic originates outside the
+# upstream subnet, the "altnet" option can be
+# used in order to define legal multicast sources.
+# (Se example...)
+#
+# The "quickleave" should be used to avoid saturation
+# of the upstream link. The option should only
+# be used if it's absolutely nessecary to
+# accurately imitate just one Client.
+#
+########################################################
+
+{% if not disable_quickleave -%}
+quickleave
+{% endif -%}
+
+{% for i in interface %}
+# Configuration for {{ i.interface }} ({{ i.role }} interface)
+{% if i.role == 'disabled' -%}
+phyint {{ i.interface }} disabled
+{%- else -%}
+phyint {{ i.interface }} {{ i.role }} ratelimit 0 threshold {{ i.threshold }}
+{%- endif -%}
+{%- for subnet in i.alt_subnet %}
+ altnet {{ subnet }}
+{%- endfor %}
+{%- for subnet in i.whitelist %}
+ whitelist {{ subnet }}
+{%- endfor %}
+{% endfor %}
+"""
+
+default_config_data = {
+ 'disable': False,
+ 'disable_quickleave': False,
+ 'interface': [],
+}
+
+def get_config():
+ igmp_proxy = default_config_data
+ conf = Config()
+ if not conf.exists('protocols igmp-proxy'):
+ return None
+ else:
+ conf.set_level('protocols igmp-proxy')
+
+ # Network interfaces to listen on
+ if conf.exists('disable'):
+ igmp_proxy['disable'] = True
+
+ # Option to disable "quickleave"
+ if conf.exists('disable-quickleave'):
+ igmp_proxy['disable_quickleave'] = True
+
+ for intf in conf.list_nodes('interface'):
+ conf.set_level('protocols igmp-proxy interface {0}'.format(intf))
+ interface = {
+ 'interface': intf,
+ 'alt_subnet': [],
+ 'role': 'downstream',
+ 'threshold': '1',
+ 'whitelist': []
+ }
+
+ if conf.exists('alt-subnet'):
+ interface['alt_subnet'] = conf.return_values('alt-subnet')
+
+ if conf.exists('role'):
+ interface['role'] = conf.return_value('role')
+
+ if conf.exists('threshold'):
+ interface['threshold'] = conf.return_value('threshold')
+
+ if conf.exists('whitelist'):
+ interface['whitelist'] = conf.return_values('whitelist')
+
+ # Append interface configuration to global configuration list
+ igmp_proxy['interface'].append(interface)
+
+ return igmp_proxy
+
+def verify(igmp_proxy):
+ # bail out early - looks like removal from running config
+ if igmp_proxy is None:
+ return None
+
+ # bail out early - service is disabled
+ if igmp_proxy['disable']:
+ return None
+
+ # at least two interfaces are required, one upstream and one downstream
+ if len(igmp_proxy['interface']) < 2:
+ raise ConfigError('Must define an upstream and at least 1 downstream interface!')
+
+ upstream = 0
+ for i in igmp_proxy['interface']:
+ if "upstream" == i['role']:
+ upstream += 1
+
+ if upstream == 0:
+ raise ConfigError('At least 1 upstream interface is required!')
+ elif upstream > 1:
+ raise ConfigError('Only 1 upstream interface allowed!')
+
+ return None
+
+def generate(igmp_proxy):
+ # bail out early - looks like removal from running config
+ if igmp_proxy is None:
+ return None
+
+ # bail out early - service is disabled, but inform user
+ if igmp_proxy['disable']:
+ print('Warning: IGMP Proxy will be deactivated because it is disabled')
+ return None
+
+ tmpl = jinja2.Template(config_tmpl)
+ config_text = tmpl.render(igmp_proxy)
+ with open(config_file, 'w') as f:
+ f.write(config_text)
+
+ return None
+
+def apply(igmp_proxy):
+ if igmp_proxy is None or igmp_proxy['disable']:
+ # IGMP Proxy support is removed in the commit
+ os.system('sudo systemctl stop igmpproxy.service')
+ if os.path.exists(config_file):
+ os.unlink(config_file)
+ else:
+ os.system('sudo systemctl restart igmpproxy.service')
+
+ return None
+
+if __name__ == '__main__':
+ try:
+ c = get_config()
+ verify(c)
+ generate(c)
+ apply(c)
+ except ConfigError as e:
+ print(e)
+ sys.exit(1)
diff --git a/src/conf_mode/wireguard.py b/src/conf_mode/wireguard.py
index 5d390f39f..353528aba 100755
--- a/src/conf_mode/wireguard.py
+++ b/src/conf_mode/wireguard.py
@@ -159,11 +159,37 @@ def apply(c):
c_eff = Config()
c_eff.set_level('interfaces wireguard')
- ### deletion of specific interface
+ ### deletion of a specific interface
for intf in c['interfaces']:
if c['interfaces'][intf]['status'] == 'delete':
sl.syslog(sl.LOG_NOTICE, "removing interface " + intf)
subprocess.call(['ip l d dev ' + intf + ' &>/dev/null'], shell=True)
+
+
+ ### peer deletion
+ peer_eff = c_eff.list_effective_nodes( intf + ' peer')
+ peer_cnf = []
+ try:
+ for p in c['interfaces'][intf]['peer']:
+ peer_cnf.append(p)
+ except KeyError:
+ pass
+
+ peer_rem = list(set(peer_eff) - set(peer_cnf))
+ for p in peer_rem:
+ pkey = c_eff.return_effective_value( intf + ' peer ' + p +' pubkey')
+ remove_peer(intf, pkey)
+
+ ### peer pubkey update
+ ### wg identifies peers by its pubky, so we have to remove the peer first
+ ### it will recreated it then below with the new key from the cli config
+ for p in peer_eff:
+ if p in peer_cnf:
+ ekey = c_eff.return_effective_value( intf + ' peer ' + p +' pubkey')
+ nkey = c['interfaces'][intf]['peer'][p]['pubkey']
+ if nkey != ekey:
+ sl.syslog(sl.LOG_NOTICE, "peer " + p + ' changed pubkey from ' + ekey + 'to key ' + nkey + ' on interface ' + intf)
+ remove_peer(intf, ekey)
### new config
if c['interfaces'][intf]['status'] == 'create':
@@ -304,6 +330,11 @@ def del_addr(intf, addr):
ret = subprocess.call(['ip a d dev ' + intf + ' ' + addr + ' &>/dev/null'], shell=True)
sl.syslog(sl.LOG_NOTICE, "ip a d dev " + intf + " " + addr)
+def remove_peer(intf, peer_key):
+ cmd = 'sudo wg set ' + str(intf) + ' peer ' + peer_key + ' remove &>/dev/null'
+ ret = subprocess.call([cmd], shell=True)
+ sl.syslog(sl.LOG_NOTICE, "peer " + peer_key + " removed from " + intf)
+
if __name__ == '__main__':
try:
check_kmod()