diff options
author | Christian Poessinger <christian@poessinger.com> | 2019-11-23 20:54:46 +0100 |
---|---|---|
committer | Christian Poessinger <christian@poessinger.com> | 2019-11-23 20:54:46 +0100 |
commit | 24b23d41146eddd8fb0609ad4ae85d27e7c6ec6a (patch) | |
tree | e703aab15145f877f23c6dde064f86de5585e96f /src/op_mode/show_wireless.py | |
parent | d3b689ecb951c49dddf0402f36f51a2e0d8216b3 (diff) | |
parent | 9ab56f29f07a3c94a92bb7e1ffa54fcb4762a8fb (diff) | |
download | vyos-1x-24b23d41146eddd8fb0609ad4ae85d27e7c6ec6a.tar.gz vyos-1x-24b23d41146eddd8fb0609ad4ae85d27e7c6ec6a.zip |
Merge branch 'current' into equuleus
* current:
wireless: T1627: support station mode
wireless: T1627: support DHCP(v6) addresses
wireless: T1627: add support for RADIUS source-address
wireless: T1627: RADIUS servers must have a key specified
wireless: T1627: change RADIUS CLI syntax
l2tp: harmonize RADIUS wording
wireless: T1627: re-order WPA key in hostapd config
wireless: T1627: change priority from 318 to 400
wireless: T1627: fix generated ht_capab and vht_capab
wireless: T1627: fix regex for 'ht channel-set-width'
wireless: T1627: config migrator does not support camel casing
wireless: T1627: initial rewrite of show-wireless.pl in Python
wireless: T1627: add op-mode commands
wireless: T1627: initial rewrite in XML/Python style
pppoe-server: T1821: Set radius module priority
T1818: Print name of migration script on failure
T1814: Add log of migration scripts run during config migration
vyos-hostsd: T1812: run increment first
[vyos-hostsd] T1812: Reload pdns on dhcp client update
migration-scripts: l2tp: T1811: add missing check on server existence
Diffstat (limited to 'src/op_mode/show_wireless.py')
-rwxr-xr-x | src/op_mode/show_wireless.py | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/src/op_mode/show_wireless.py b/src/op_mode/show_wireless.py new file mode 100755 index 000000000..aff882559 --- /dev/null +++ b/src/op_mode/show_wireless.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2019 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 argparse +import re + +from sys import exit +from copy import deepcopy +from subprocess import Popen, PIPE, STDOUT + +from vyos.config import Config + +parser = argparse.ArgumentParser() +parser.add_argument("-s", "--scan", help="Scan for Wireless APs on given interface, e.g. 'wlan0'") +parser.add_argument("-b", "--brief", action="store_true", help="Show wireless configuration") +parser.add_argument("-c", "--stations", help="Show wireless clients connected on interface, e.g. 'wlan0'") + +def _cmd(command): + p = Popen(command, stdout=PIPE, stderr=STDOUT, shell=True) + tmp = p.communicate()[0].strip() + return tmp.decode() + +def show_brief(): + config = Config() + if len(config.list_effective_nodes('interfaces wireless')) == 0: + print("No Wireless interfaces configured") + exit(0) + + interfaces = [] + for intf in config.list_effective_nodes('interfaces wireless'): + config.set_level('interfaces wireless {}'.format(intf)) + data = { + 'name': intf, + 'type': '', + 'ssid': '', + 'channel': '' + } + data['type'] = config.return_effective_value('type') + data['ssid'] = config.return_effective_value('ssid') + data['channel'] = config.return_effective_value('channel') + + interfaces.append(data) + + return interfaces + +def ssid_scan(intf): + tmp = _cmd('/sbin/iw dev {} scan ap-force'.format(intf)) + networks = [] + data = { + 'ssid': '', + 'mac': '', + 'channel': '', + 'signal': '' + } + re_mac = re.compile(r'([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})') + for line in tmp.splitlines(): + if line.startswith('BSS '): + ssid = deepcopy(data) + ssid['mac'] = re.search(re_mac, line).group() + + elif line.lstrip().startswith('SSID: '): + # SSID can be " SSID: WLAN-57 6405", thus strip all leading whitespaces + ssid['ssid'] = line.lstrip().split(':')[-1].lstrip() + + elif line.lstrip().startswith('signal: '): + # Siganl can be " signal: -67.00 dBm", thus strip all leading whitespaces + ssid['signal'] = line.lstrip().split(':')[-1].split()[0] + + elif line.lstrip().startswith('DS Parameter set: channel'): + # Channel can be " DS Parameter set: channel 6" , thus + # strip all leading whitespaces + ssid['channel'] = line.lstrip().split(':')[-1].split()[-1] + networks.append(ssid) + continue + + return networks + +def show_clients(intf): + tmp = _cmd('/sbin/iw dev {} station dump'.format(intf)) + clients = [] + data = { + 'mac': '', + 'signal': '', + 'rx_bytes': '', + 'rx_packets': '', + 'tx_bytes': '', + 'tx_packets': '' + } + re_mac = re.compile(r'([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})') + for line in tmp.splitlines(): + if line.startswith('Station'): + client = deepcopy(data) + client['mac'] = re.search(re_mac, line).group() + + elif line.lstrip().startswith('signal avg:'): + client['signal'] = line.lstrip().split(':')[-1].lstrip().split()[0] + + elif line.lstrip().startswith('rx bytes:'): + client['rx_bytes'] = line.lstrip().split(':')[-1].lstrip() + + elif line.lstrip().startswith('rx packets:'): + client['rx_packets'] = line.lstrip().split(':')[-1].lstrip() + + elif line.lstrip().startswith('tx bytes:'): + client['tx_bytes'] = line.lstrip().split(':')[-1].lstrip() + + elif line.lstrip().startswith('tx packets:'): + client['tx_packets'] = line.lstrip().split(':')[-1].lstrip() + clients.append(client) + continue + + return clients + +if __name__ == '__main__': + args = parser.parse_args() + + if args.scan: + print("Address SSID Channel Signal (dbm)") + for network in ssid_scan(args.scan): + print("{:<17} {:<32} {:>3} {}".format(network['mac'], + network['ssid'], + network['channel'], + network['signal'])) + exit(0) + + elif args.brief: + print("Interface Type SSID Channel") + for intf in show_brief(): + print("{:<9} {:<12} {:<32} {:>3}".format(intf['name'], + intf['type'], + intf['ssid'], + intf['channel'])) + exit(0) + + elif args.stations: + print("Station Signal RX: bytes packets TX: bytes packets") + for client in show_clients(args.stations): + print("{:<17} {:>3} {:>15} {:>9} {:>15} {:>10} ".format(client['mac'], + client['signal'], client['rx_bytes'], client['rx_packets'], client['tx_bytes'], client['tx_packets'])) + + exit(0) + + else: + parser.print_help() + exit(1) |