summaryrefslogtreecommitdiff
path: root/src/op_mode
diff options
context:
space:
mode:
authorMarcus Hoff <marcus.hoff@ring2.dk>2020-09-05 09:58:03 +0200
committerMarcus Hoff <marcus.hoff@ring2.dk>2020-09-05 09:58:03 +0200
commit46fb580fa0131f6815bbcfc95631654f6fe999a8 (patch)
tree73ae9fcaa97d5cfab7883bc6fbf3ea036677c2a3 /src/op_mode
parent0377b8e40b0d3e424da11194e97659c5066c0a1d (diff)
parentb6b61bc9ecf1328e67a0c15934f8bf3966a6b66d (diff)
downloadvyos-1x-46fb580fa0131f6815bbcfc95631654f6fe999a8.tar.gz
vyos-1x-46fb580fa0131f6815bbcfc95631654f6fe999a8.zip
Merge remote-tracking branch 'upstream/current' into current
Diffstat (limited to 'src/op_mode')
-rwxr-xr-xsrc/op_mode/anyconnect-control.py67
-rwxr-xr-xsrc/op_mode/lldp_op.py185
-rwxr-xr-xsrc/op_mode/ping.py8
-rwxr-xr-xsrc/op_mode/show_system_integrity.py70
-rwxr-xr-xsrc/op_mode/system_integrity.py70
-rwxr-xr-xsrc/op_mode/wireguard.py17
6 files changed, 220 insertions, 197 deletions
diff --git a/src/op_mode/anyconnect-control.py b/src/op_mode/anyconnect-control.py
new file mode 100755
index 000000000..6382016b7
--- /dev/null
+++ b/src/op_mode/anyconnect-control.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2020 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 argparse
+import json
+
+from vyos.config import Config
+from vyos.util import popen, run, DEVNULL
+from tabulate import tabulate
+
+occtl = '/usr/bin/occtl'
+occtl_socket = '/run/ocserv/occtl.socket'
+
+def show_sessions():
+ out, code = popen("sudo {0} -j -s {1} show users".format(occtl, occtl_socket),stderr=DEVNULL)
+ if code:
+ sys.exit('Cannot get anyconnect users information')
+ else:
+ headers = ["interface", "username", "ip", "remote IP", "RX", "TX", "state", "uptime"]
+ sessions = json.loads(out)
+ ses_list = []
+ for ses in sessions:
+ ses_list.append([ses["Device"], ses["Username"], ses["IPv4"], ses["Remote IP"], ses["_RX"], ses["_TX"], ses["State"], ses["_Connected at"]])
+ if len(ses_list) > 0:
+ print(tabulate(ses_list, headers))
+ else:
+ print("No active anyconnect sessions")
+
+def is_ocserv_configured():
+ if not Config().exists_effective('vpn anyconnect'):
+ print("vpn anyconnect server is not configured")
+ sys.exit(1)
+
+def main():
+ #parese args
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--action', help='Control action', required=True)
+ parser.add_argument('--selector', help='Selector username|ifname|sid', required=False)
+ parser.add_argument('--target', help='Target must contain username|ifname|sid', required=False)
+ args = parser.parse_args()
+
+
+ # Check is IPoE configured
+ is_ocserv_configured()
+
+ if args.action == "restart":
+ run("systemctl restart ocserv")
+ sys.exit(0)
+ elif args.action == "show_sessions":
+ show_sessions()
+
+if __name__ == '__main__':
+ main()
diff --git a/src/op_mode/lldp_op.py b/src/op_mode/lldp_op.py
index 5d48e3210..06958c605 100755
--- a/src/op_mode/lldp_op.py
+++ b/src/op_mode/lldp_op.py
@@ -14,19 +14,19 @@
# 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 argparse
import jinja2
+import json
-from xml.dom import minidom
from sys import exit
from tabulate import tabulate
-from vyos.util import popen
+from vyos.util import cmd
from vyos.config import Config
parser = argparse.ArgumentParser()
parser.add_argument("-a", "--all", action="store_true", help="Show LLDP neighbors on all interfaces")
+parser.add_argument("-d", "--detail", action="store_true", help="Show detailes LLDP neighbor information on all interfaces")
parser.add_argument("-i", "--interface", action="store", help="Show LLDP neighbors on specific interface")
# Please be careful if you edit the template.
@@ -35,108 +35,61 @@ lldp_out = """Capability Codes: R - Router, B - Bridge, W - Wlan r - Repeater, S
Device ID Local Proto Cap Platform Port ID
--------- ----- ----- --- -------- -------
-{% for n in neighbors -%}
-{{ "%-25s" | format(n.chassis) }} {{ "%-9s" | format(n.interface) }} {{ "%-6s" | format(n.proto) }} {{ "%-5s" | format(n.cap) }} {{ "%-20s" | format(n.platform) }} {{ n.port }}
-{% endfor -%}
+{% for neighbor in neighbors %}
+{% for local_if, info in neighbor.items() %}
+{{ "%-25s" | format(info.chassis) }} {{ "%-9s" | format(local_if) }} {{ "%-6s" | format(info.proto) }} {{ "%-5s" | format(info.capabilities) }} {{ "%-20s" | format(info.platform[:18]) }} {{ info.remote_if }}
+{% endfor %}
+{% endfor %}
"""
-def _get_neighbors():
- command = '/usr/sbin/lldpcli -f xml show neighbors'
- out,_ = popen(command)
- return out
-
-def extract_neighbor(neighbor):
- """
- Extract LLDP neighbor information from XML document passed as param neighbor
-
- <lldp>
- <interface label="Interface" name="eth0" via="LLDP" rid="3" age="0 day, 00:17:42">
- <chassis label="Chassis">
- <id label="ChassisID" type="mac">00:50:56:9d:a6:11</id>
- <name label="SysName">VyOS</name>
- <descr label="SysDescr">VyOS unknown</descr>
- <mgmt-ip label="MgmtIP">172.18.254.203</mgmt-ip>
- <mgmt-ip label="MgmtIP">fe80::250:56ff:fe9d:a611</mgmt-ip>
- <capability label="Capability" type="Bridge" enabled="off"/>
- <capability label="Capability" type="Router" enabled="on"/>
- <capability label="Capability" type="Wlan" enabled="off"/>
- <capability label="Capability" type="Station" enabled="off"/>
- </chassis>
- <port label="Port">
- <id label="PortID" type="mac">00:50:56:9d:a6:11</id>
- <descr label="PortDescr">eth0</descr>
- <ttl label="TTL">120</ttl>
- <auto-negotiation label="PMD autoneg" supported="no" enabled="no">
- <current label="MAU oper type">10GigBaseCX4 - X copper over 8 pair 100-Ohm balanced cable</current>
- </auto-negotiation>
- </port>
- <vlan label="VLAN" vlan-id="203">eth0.203</vlan>
- <lldp-med label="LLDP-MED">
- <device-type label="Device Type">Network Connectivity Device</device-type>
- <capability label="Capability" type="Capabilities" available="yes"/>
- <capability label="Capability" type="Policy" available="yes"/>
- <capability label="Capability" type="Location" available="yes"/>
- <capability label="Capability" type="MDI/PSE" available="yes"/>
- <capability label="Capability" type="MDI/PD" available="yes"/>
- <capability label="Capability" type="Inventory" available="yes"/>
- <inventory label="Inventory">
- <hardware label="Hardware Revision">None</hardware>
- <software label="Software Revision">4.19.54-amd64-vyos</software>
- <firmware label="Firmware Revision">6.00</firmware>
- <serial label="Serial Number">VMware-42 1d cf 87 ab 7f da 7e-3</serial>
- <manufacturer label="Manufacturer">VMware, Inc.</manufacturer>
- <model label="Model">VMware Virtual Platform</model>
- <asset label="Asset ID">No Asset Tag</asset>
- </inventory>
- </lldp-med>
- </interface>
- </lldp>
- """
-
- device = {
- 'interface' : neighbor.getAttribute('name'),
- 'chassis' : '',
- 'proto' : neighbor.getAttribute('via'),
- 'descr' : '',
- 'cap' : '',
- 'platform' : '',
- 'port' : ''
- }
-
- # first change to <chassis> node and then retrieve <name> and <descr>
- chassis = neighbor.getElementsByTagName('chassis')
- device['chassis'] = chassis[0].getElementsByTagName('name')[0].firstChild.data
- # Cisco IOS comes with a ',' remove character ....
- device['platform'] = chassis[0].getElementsByTagName('descr')[0].firstChild.data[:20].replace(',',' ')
-
- # extract capabilities
- for capability in chassis[0].getElementsByTagName('capability'):
- # we are only interested in enabled capabilities ...
- if capability.getAttribute('enabled') == "on":
- if capability.getAttribute('type') == "Router":
- device['cap'] += 'R'
- elif capability.getAttribute('type') == "Bridge":
- device['cap'] += 'B'
- elif capability.getAttribute('type') == "Wlan":
- device['cap'] += 'W'
- elif capability.getAttribute('type') == "Station":
- device['cap'] += 'S'
- elif capability.getAttribute('type') == "Repeater":
- device['cap'] += 'r'
- elif capability.getAttribute('type') == "Telephone":
- device['cap'] += 'T'
- elif capability.getAttribute('type') == "Docsis":
- device['cap'] += 'D'
- elif capability.getAttribute('type') == "Other":
- device['cap'] += 'O'
-
- # first change to <port> node and then retrieve <descr>
- port = neighbor.getElementsByTagName('port')
- port = port[0].getElementsByTagName('descr')[0].firstChild.data
- device['port'] = port
-
-
- return device
+def get_neighbors():
+ return cmd('/usr/sbin/lldpcli -f json show neighbors')
+
+def parse_data(data):
+ output = []
+ for tmp in data:
+ for local_if, values in tmp.items():
+ for chassis, c_value in values.get('chassis', {}).items():
+ capabilities = c_value['capability']
+ if isinstance(capabilities, dict):
+ capabilities = [capabilities]
+
+ cap = ''
+ for capability in capabilities:
+ if capability['enabled']:
+ if capability['type'] == 'Router':
+ cap += 'R'
+ if capability['type'] == 'Bridge':
+ cap += 'B'
+ if capability['type'] == 'Wlan':
+ cap += 'W'
+ if capability['type'] == 'Station':
+ cap += 'S'
+ if capability['type'] == 'Repeater':
+ cap += 'r'
+ if capability['type'] == 'Telephone':
+ cap += 'T'
+ if capability['type'] == 'Docsis':
+ cap += 'D'
+ if capability['type'] == 'Other':
+ cap += 'O'
+
+
+ remote_if = 'Unknown'
+ if 'descr' in values.get('port', {}):
+ remote_if = values.get('port', {}).get('descr')
+ elif 'id' in values.get('port', {}):
+ remote_if = values.get('port', {}).get('id').get('value', 'Unknown')
+
+ output.append({local_if: {'chassis': chassis,
+ 'remote_if': remote_if,
+ 'proto': values.get('via','Unknown'),
+ 'platform': c_value.get('descr', 'Unknown'),
+ 'capabilities': cap}})
+
+
+ output = {'neighbors': output}
+ return output
if __name__ == '__main__':
args = parser.parse_args()
@@ -147,24 +100,26 @@ if __name__ == '__main__':
print('Service LLDP is not configured')
exit(0)
- if args.all:
- neighbors = minidom.parseString(_get_neighbors())
- for neighbor in neighbors.getElementsByTagName('interface'):
- tmp['neighbors'].append( extract_neighbor(neighbor) )
+ if args.detail:
+ print(cmd('/usr/sbin/lldpctl -f plain'))
+ exit(0)
+ elif args.all or args.interface:
+ tmp = json.loads(get_neighbors())
- elif args.interface:
- neighbors = minidom.parseString(_get_neighbors())
- for neighbor in neighbors.getElementsByTagName('interface'):
- # check if neighbor appeared on proper interface
- if neighbor.getAttribute('name') == args.interface:
- tmp['neighbors'].append( extract_neighbor(neighbor) )
+ if args.all:
+ neighbors = tmp['lldp']['interface']
+ elif args.interface:
+ neighbors = []
+ for neighbor in tmp['lldp']['interface']:
+ if args.interface in neighbor:
+ neighbors.append(neighbor)
else:
parser.print_help()
exit(1)
- tmpl = jinja2.Template(lldp_out)
- config_text = tmpl.render(tmp)
+ tmpl = jinja2.Template(lldp_out, trim_blocks=True)
+ config_text = tmpl.render(parse_data(neighbors))
print(config_text)
exit(0)
diff --git a/src/op_mode/ping.py b/src/op_mode/ping.py
index e56952c38..29b430d53 100755
--- a/src/op_mode/ping.py
+++ b/src/op_mode/ping.py
@@ -118,7 +118,8 @@ options = {
'vrf': {
'ping': 'sudo ip vrf exec {value} {command}',
'type': '<vrf>',
- 'help': 'Use specified VRF table'
+ 'help': 'Use specified VRF table',
+ 'dflt': 'default',
},
'verbose': {
'ping': '{command} -v',
@@ -207,6 +208,11 @@ if __name__ == '__main__':
sys.stdout.write(options[matched[0]]['type'])
sys.exit(0)
+ for name,option in options.items():
+ if 'dflt' in option and name not in args:
+ args.append(name)
+ args.append(option['dflt'])
+
try:
ip = socket.gethostbyname(host)
except socket.gaierror:
diff --git a/src/op_mode/show_system_integrity.py b/src/op_mode/show_system_integrity.py
new file mode 100755
index 000000000..c34d41e80
--- /dev/null
+++ b/src/op_mode/show_system_integrity.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2020 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 json
+from datetime import datetime, timedelta
+
+version_file = r'/usr/share/vyos/version.json'
+
+
+def _get_sys_build_version():
+ if not os.path.exists(version_file):
+ return None
+ buf = open(version_file, 'r').read()
+ j = json.loads(buf)
+ if not 'built_on' in j:
+ return None
+ return datetime.strptime(j['built_on'], '%a %d %b %Y %H:%M %Z')
+
+
+def _check_pkgs(build_stamp):
+ pkg_diffs = {
+ 'buildtime': str(build_stamp),
+ 'pkg': {}
+ }
+
+ pkg_info = os.listdir('/var/lib/dpkg/info/')
+ for file in pkg_info:
+ if re.search('\.list$', file):
+ fts = os.stat('/var/lib/dpkg/info/' + file).st_mtime
+ dt_str = (datetime.utcfromtimestamp(
+ fts).strftime('%Y-%m-%d %H:%M:%S'))
+ fdt = datetime.strptime(dt_str, '%Y-%m-%d %H:%M:%S')
+ if fdt > build_stamp:
+ pkg_diffs['pkg'].update(
+ {str(re.sub('\.list', '', file)): str(fdt)})
+
+ if len(pkg_diffs['pkg']) != 0:
+ return pkg_diffs
+ else:
+ return None
+
+
+if __name__ == '__main__':
+ built_date = _get_sys_build_version()
+ if not built_date:
+ sys.exit(1)
+ pkgs = _check_pkgs(built_date)
+ if pkgs:
+ print (
+ "The following packages don\'t fit the image creation time\nbuild time:\t" + pkgs['buildtime'])
+ for k, v in pkgs['pkg'].items():
+ print ("installed: " + v + '\t' + k)
diff --git a/src/op_mode/system_integrity.py b/src/op_mode/system_integrity.py
deleted file mode 100755
index c0e3d1095..000000000
--- a/src/op_mode/system_integrity.py
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/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 itertools
-from datetime import datetime, timedelta
-
-from vyos.util import cmd
-
-verf = r'/usr/libexec/vyos/op_mode/version.py'
-
-def get_sys_build_version():
- if not os.path.exists(verf):
- return None
-
- a = cmd('/usr/libexec/vyos/op_mode/version.py')
- if re.search('^Built on:.+',a, re.M) == None:
- return None
-
- dt = ( re.sub('Built on: +','', re.search('^Built on:.+',a, re.M).group(0)) )
- return datetime.strptime(dt,'%a %d %b %Y %H:%M %Z')
-
-def check_pkgs(dt):
- pkg_diffs = {
- 'buildtime' : str(dt),
- 'pkg' : {}
- }
-
- pkg_info = os.listdir('/var/lib/dpkg/info/')
- for file in pkg_info:
- if re.search('\.list$', file):
- fts = os.stat('/var/lib/dpkg/info/' + file).st_mtime
- dt_str = (datetime.utcfromtimestamp(fts).strftime('%Y-%m-%d %H:%M:%S'))
- fdt = datetime.strptime(dt_str, '%Y-%m-%d %H:%M:%S')
- if fdt > dt:
- pkg_diffs['pkg'].update( { str(re.sub('\.list','',file)) : str(fdt)})
-
- if len(pkg_diffs['pkg']) != 0:
- return pkg_diffs
- else:
- return None
-
-def main():
- dt = get_sys_build_version()
- pkgs = check_pkgs(dt)
- if pkgs != None:
- print ("The following packages don\'t fit the image creation time\nbuild time:\t" + pkgs['buildtime'])
- for k, v in pkgs['pkg'].items():
- print ("installed: " + v + '\t' + k)
-
-if __name__ == '__main__':
- sys.exit( main() )
-
diff --git a/src/op_mode/wireguard.py b/src/op_mode/wireguard.py
index 15bf63e81..e08bc983a 100755
--- a/src/op_mode/wireguard.py
+++ b/src/op_mode/wireguard.py
@@ -21,22 +21,17 @@ import shutil
import syslog as sl
import re
+from vyos.config import Config
from vyos.ifconfig import WireGuardIf
-
+from vyos.util import cmd
+from vyos.util import run
+from vyos.util import check_kmod
from vyos import ConfigError
-from vyos.config import Config
-from vyos.util import cmd, run
dir = r'/config/auth/wireguard'
psk = dir + '/preshared.key'
-def check_kmod():
- """ check if kmod is loaded, if not load it """
- if not os.path.exists('/sys/module/wireguard'):
- sl.syslog(sl.LOG_NOTICE, "loading wirguard kmod")
- if run('sudo modprobe wireguard') != 0:
- sl.syslog(sl.LOG_ERR, "modprobe wireguard failed")
- raise ConfigError("modprobe wireguard failed")
+k_mod = 'wireguard'
def generate_keypair(pk, pub):
""" generates a keypair which is stored in /config/auth/wireguard """
@@ -106,7 +101,7 @@ def del_key_dir(kname):
if __name__ == '__main__':
- check_kmod()
+ check_kmod(k_mod)
parser = argparse.ArgumentParser(description='wireguard key management')
parser.add_argument(
'--genkey', action="store_true", help='generate key-pair')