1
0
mirror of https://github.com/kellyjonbrazil/jc.git synced 2025-06-19 00:17:51 +02:00
Files
jc/jc/parsers/netstat.py

425 lines
12 KiB
Python
Raw Normal View History

2019-10-15 15:06:09 -07:00
"""jc - JSON CLI output utility netstat Parser
Usage:
2019-12-12 09:47:14 -08:00
2019-10-17 12:15:27 -07:00
Specify --netstat as the first argument if the piped input is coming from netstat
2019-10-15 15:06:09 -07:00
2020-05-22 11:09:41 -07:00
Caveats:
- Use of multiple 'l' options is not supported on OSX (e.g. 'netstat -rlll')
- Use of the 'A' option is not supported on OSX when using the 'r' option (e.g. netstat -rA)
2019-12-12 09:35:42 -08:00
Compatibility:
2019-12-12 09:47:14 -08:00
2020-05-29 12:04:58 -07:00
'linux', 'darwin', 'freebsd'
2019-12-12 09:35:42 -08:00
2019-11-07 14:49:21 -08:00
Examples:
2020-05-22 12:56:27 -07:00
# netstat -apee | jc --netstat -p
2019-11-11 18:30:46 -08:00
[
{
"proto": "tcp",
"recv_q": 0,
"send_q": 0,
"local_address": "localhost",
"foreign_address": "0.0.0.0",
"state": "LISTEN",
"user": "systemd-resolve",
"inode": 26958,
"program_name": "systemd-resolve",
"kind": "network",
"pid": 887,
"local_port": "domain",
"foreign_port": "*",
"transport_protocol": "tcp",
"network_protocol": "ipv4"
},
{
"proto": "tcp",
"recv_q": 0,
"send_q": 0,
"local_address": "0.0.0.0",
"foreign_address": "0.0.0.0",
"state": "LISTEN",
"user": "root",
"inode": 30499,
"program_name": "sshd",
"kind": "network",
"pid": 1186,
"local_port": "ssh",
"foreign_port": "*",
"transport_protocol": "tcp",
"network_protocol": "ipv4"
},
{
"proto": "tcp",
"recv_q": 0,
"send_q": 0,
"local_address": "localhost",
"foreign_address": "localhost",
"state": "ESTABLISHED",
"user": "root",
"inode": 46829,
"program_name": "sshd: root",
"kind": "network",
"pid": 2242,
"local_port": "ssh",
"foreign_port": "52186",
"transport_protocol": "tcp",
"network_protocol": "ipv4",
"foreign_port_num": 52186
},
{
"proto": "tcp",
"recv_q": 0,
"send_q": 0,
"local_address": "localhost",
"foreign_address": "localhost",
"state": "ESTABLISHED",
"user": "root",
"inode": 46828,
"program_name": "ssh",
"kind": "network",
"pid": 2241,
"local_port": "52186",
"foreign_port": "ssh",
"transport_protocol": "tcp",
"network_protocol": "ipv4",
"local_port_num": 52186
},
{
"proto": "tcp6",
"recv_q": 0,
"send_q": 0,
"local_address": "[::]",
"foreign_address": "[::]",
"state": "LISTEN",
"user": "root",
"inode": 30510,
"program_name": "sshd",
"kind": "network",
"pid": 1186,
"local_port": "ssh",
"foreign_port": "*",
"transport_protocol": "tcp",
"network_protocol": "ipv6"
},
{
"proto": "udp",
"recv_q": 0,
"send_q": 0,
"local_address": "localhost",
"foreign_address": "0.0.0.0",
"state": null,
"user": "systemd-resolve",
"inode": 26957,
"program_name": "systemd-resolve",
"kind": "network",
"pid": 887,
"local_port": "domain",
"foreign_port": "*",
"transport_protocol": "udp",
"network_protocol": "ipv4"
},
{
"proto": "raw6",
"recv_q": 0,
"send_q": 0,
"local_address": "[::]",
"foreign_address": "[::]",
"state": "7",
"user": "systemd-network",
"inode": 27001,
"program_name": "systemd-network",
"kind": "network",
"pid": 867,
"local_port": "ipv6-icmp",
"foreign_port": "*",
"transport_protocol": null,
"network_protocol": "ipv6"
},
{
"proto": "unix",
"refcnt": 2,
"flags": null,
"type": "DGRAM",
"state": null,
"inode": 33322,
"program_name": "systemd",
"path": "/run/user/1000/systemd/notify",
"kind": "socket",
"pid": 1607
},
{
"proto": "unix",
"refcnt": 2,
"flags": "ACC",
"type": "SEQPACKET",
"state": "LISTENING",
"inode": 20835,
"program_name": "init",
"path": "/run/udev/control",
"kind": "socket",
"pid": 1
},
...
]
2020-05-22 12:56:27 -07:00
$ netstat -r | jc --netstat -p
2019-11-11 18:30:46 -08:00
[
{
2020-05-22 12:56:27 -07:00
"destination": "default",
"gateway": "gateway",
"genmask": "0.0.0.0",
"route_flags": "UG",
"mss": 0,
"window": 0,
"irtt": 0,
"iface": "ens33",
"kind": "route"
},
{
"destination": "172.17.0.0",
"gateway": "0.0.0.0",
"genmask": "255.255.0.0",
"route_flags": "U",
"mss": 0,
"window": 0,
"irtt": 0,
"iface": "docker0",
"kind": "route"
},
{
"destination": "192.168.71.0",
"gateway": "0.0.0.0",
"genmask": "255.255.255.0",
"route_flags": "U",
"mss": 0,
"window": 0,
"irtt": 0,
"iface": "ens33",
"kind": "route"
}
2019-11-11 18:30:46 -08:00
]
2020-05-22 13:38:25 -07:00
$ netstat -i | jc --netstat -p
2020-05-22 14:04:11 -07:00
[
{
"iface": "ens33",
"mtu": 1500,
"rx_ok": 476,
"rx_err": 0,
"rx_drp": 0,
"rx_ovr": 0,
"tx_ok": 312,
"tx_err": 0,
"tx_drp": 0,
"tx_ovr": 0,
"flg": "BMRU",
"kind": "interface"
},
{
"iface": "lo",
"mtu": 65536,
"rx_ok": 0,
"rx_err": 0,
"rx_drp": 0,
"rx_ovr": 0,
"tx_ok": 0,
"tx_err": 0,
"tx_drp": 0,
"tx_ovr": 0,
"flg": "LRU",
"kind": "interface"
}
]
2019-10-15 15:06:09 -07:00
"""
2019-11-07 08:07:43 -08:00
2019-12-13 20:01:51 -08:00
class info():
2020-05-29 12:04:58 -07:00
version = '1.6'
2020-02-13 09:47:40 -05:00
description = 'netstat command parser'
2019-12-13 20:01:51 -08:00
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
2020-05-29 12:04:58 -07:00
compatible = ['linux', 'darwin', 'freebsd']
2020-02-11 18:09:21 -08:00
magic_commands = ['netstat']
2019-12-13 20:01:51 -08:00
2020-02-03 16:11:58 -08:00
__version__ = info.version
2019-11-07 08:07:43 -08:00
def process(proc_data):
2019-11-11 18:30:46 -08:00
"""
2019-11-12 11:28:10 -08:00
Final processing to conform to the schema.
Parameters:
2019-11-14 16:40:52 -08:00
2019-11-13 08:04:40 -08:00
proc_data: (dictionary) raw structured data to process
2019-11-12 11:28:10 -08:00
Returns:
2019-12-17 09:56:09 -08:00
List of dictionaries. Structured data with the following schema:
2019-11-14 16:40:52 -08:00
2019-11-11 18:30:46 -08:00
[
{
"proto": string,
"recv_q": integer,
"send_q": integer,
"transport_protocol" string,
"network_protocol": string,
"local_address": string,
"local_port": string,
"local_port_num": integer,
"foreign_address": string,
"foreign_port": string,
"foreign_port_num": integer,
"state": string,
"program_name": string,
"pid": integer,
"user": string,
"security_context": string,
"refcnt": integer,
"flags": string,
"type": string,
"inode": integer,
"path": string,
"kind": string,
"address": string,
"unix_inode": string,
"conn": string,
"refs": string,
"nextref": string,
"name": string,
"unit": integer,
"vendor": integer,
"class": integer,
"subcla": integer,
"unix_flags": integer,
"pcbcount": integer,
"rcvbuf": integer,
"sndbuf": integer,
"rxbytes": integer,
"txbytes": integer,
"destination": string,
"gateway": string,
"route_flags": string,
2020-05-29 12:51:04 -07:00
"route_flags_pretty": [
string,
2020-05-29 12:51:04 -07:00
]
"route_refs": integer,
"use": integer,
"mtu": integer,
"expire": string,
"genmask": string,
"mss": integer,
"window": integer,
"irtt": integer,
"iface": string,
"metric": integer,
"network": string,
"address": string,
"ipkts": integer, - = null
"ierrs": integer, - = null
"idrop": integer, - = null
"opkts": integer, - = null
"oerrs": integer, - = null
"coll": integer, - = null
"rx_ok": integer,
"rx_err": integer,
"rx_drp": integer,
"rx_ovr": integer,
"tx_ok": integer,
"tx_err": integer,
"tx_drp": integer,
"tx_ovr": integer,
2020-05-29 15:14:44 -07:00
"flg": string,
"ibytes": integer,
"obytes": integer
2019-11-11 18:30:46 -08:00
}
]
"""
2019-11-07 14:43:42 -08:00
for entry in proc_data:
# integer changes
2020-05-20 15:39:47 -07:00
int_list = ['recv_q', 'send_q', 'pid', 'refcnt', 'inode', 'unit', 'vendor', 'class',
2020-05-22 11:09:41 -07:00
'osx_flags', 'subcla', 'pcbcount', 'rcvbuf', 'sndbuf', 'rxbytes', 'txbytes',
2020-05-22 13:38:25 -07:00
'route_refs', 'use', 'mtu', 'mss', 'window', 'irtt', 'metric', 'ipkts',
2020-05-22 14:04:11 -07:00
'ierrs', 'opkts', 'oerrs', 'coll', 'rx_ok', 'rx_err', 'rx_drp', 'rx_ovr',
2020-05-29 15:14:44 -07:00
'tx_ok', 'tx_err', 'tx_drp', 'tx_ovr', 'idrop', 'ibytes', 'obytes']
2019-11-07 14:43:42 -08:00
for key in int_list:
if key in entry:
try:
key_int = int(entry[key])
entry[key] = key_int
except (ValueError):
entry[key] = None
if 'local_port' in entry:
try:
entry['local_port_num'] = int(entry['local_port'])
except (ValueError):
pass
if 'foreign_port' in entry:
try:
entry['foreign_port_num'] = int(entry['foreign_port'])
except (ValueError):
pass
2020-05-29 15:14:44 -07:00
# strip whitespace from beginning and end of all string values
for item in entry:
if isinstance(entry[item], str):
entry[item] = entry[item].strip()
2019-11-07 08:07:43 -08:00
return proc_data
def parse(data, raw=False, quiet=False):
2019-11-11 18:30:46 -08:00
"""
2019-11-12 11:17:33 -08:00
Main text parsing function
2019-11-11 18:30:46 -08:00
2019-11-12 11:17:33 -08:00
Parameters:
2019-11-14 16:40:52 -08:00
2019-11-12 11:17:33 -08:00
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
2019-11-11 18:30:46 -08:00
2019-11-12 11:17:33 -08:00
Returns:
2019-12-17 10:09:19 -08:00
List of dictionaries. Raw or processed structured data.
2019-11-11 18:30:46 -08:00
"""
2020-05-20 11:24:38 -07:00
import jc.utils
2019-11-07 08:07:43 -08:00
if not quiet:
2019-12-13 20:01:51 -08:00
jc.utils.compatibility(__name__, info.compatible)
2019-10-18 09:57:22 -07:00
2019-10-15 15:06:09 -07:00
cleandata = data.splitlines()
2019-11-07 10:52:02 -08:00
cleandata = list(filter(None, cleandata))
2019-11-07 08:07:43 -08:00
raw_output = []
2020-05-19 15:15:08 -07:00
# check for OSX vs Linux
# is this from OSX?
2020-05-20 16:43:53 -07:00
if cleandata[0] == 'Active Internet connections' \
or cleandata[0] == 'Active Internet connections (including servers)' \
or cleandata[0] == 'Active Multipath Internet connections' \
2020-05-20 16:43:53 -07:00
or cleandata[0] == 'Active LOCAL (UNIX) domain sockets' \
or cleandata[0] == 'Registered kernel control modules' \
or cleandata[0] == 'Active kernel event sockets' \
2020-05-22 11:09:41 -07:00
or cleandata[0] == 'Active kernel control sockets' \
2020-05-22 13:38:25 -07:00
or cleandata[0] == 'Routing tables' \
2020-05-29 12:04:58 -07:00
or cleandata[0].startswith('Name '):
# or cleandata[0] == 'Name Mtu Network Address Ipkts Ierrs Opkts Oerrs Coll' \
import jc.parsers.netstat_freebsd_osx
raw_output = jc.parsers.netstat_freebsd_osx.parse(cleandata)
2020-05-19 15:15:08 -07:00
# use linux parser
else:
2020-05-20 11:24:38 -07:00
import jc.parsers.netstat_linux
raw_output = jc.parsers.netstat_linux.parse(cleandata)
2019-11-07 08:07:43 -08:00
if raw:
return raw_output
else:
return process(raw_output)