mirror of
https://github.com/kellyjonbrazil/jc.git
synced 2025-07-17 01:32:37 +02:00
initial support for error replies in bsd/osx
This commit is contained in:
@ -35,14 +35,25 @@ Schema:
|
||||
"round_trip_ms_stddev": float,
|
||||
"responses": [
|
||||
{
|
||||
"type": string, # ('reply' or 'timeout')
|
||||
"type": string, # 'reply', 'timeout', etc. See type_map for all options
|
||||
"timestamp": float,
|
||||
"bytes": integer,
|
||||
"response_ip": string,
|
||||
"icmp_seq": integer,
|
||||
"ttl": integer,
|
||||
"time_ms": float,
|
||||
"duplicate": boolean
|
||||
"duplicate": boolean,
|
||||
"vr": integer, # hex value converted to decimal
|
||||
"hl": integer, # hex value converted to decimal
|
||||
"tos": integer, # hex value converted to decimal
|
||||
"len": integer, # hex value converted to decimal
|
||||
"id": integer, # hex value converted to decimal
|
||||
"flg": integer, # hex value converted to decimal
|
||||
"off": integer, # hex value converted to decimal
|
||||
"pro": integer, # hex value converted to decimal
|
||||
"cks": ingeger, # hex value converted to decimal
|
||||
"src": string,
|
||||
"dst": string
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -140,6 +151,7 @@ Examples:
|
||||
}
|
||||
"""
|
||||
import string
|
||||
import ipaddress
|
||||
import jc.utils
|
||||
|
||||
|
||||
@ -170,7 +182,8 @@ def _process(proc_data):
|
||||
|
||||
Dictionary. Structured data to conform to the schema.
|
||||
"""
|
||||
int_list = ['data_bytes', 'packets_transmitted', 'packets_received', 'bytes', 'icmp_seq', 'ttl', 'duplicates']
|
||||
int_list = ['data_bytes', 'packets_transmitted', 'packets_received', 'bytes', 'icmp_seq', 'ttl',
|
||||
'duplicates', 'vr', 'hl', 'tos', 'len', 'id', 'flg', 'off', 'pro', 'cks']
|
||||
float_list = ['packet_loss_percent', 'round_trip_ms_min', 'round_trip_ms_avg', 'round_trip_ms_max',
|
||||
'round_trip_ms_stddev', 'timestamp', 'time_ms']
|
||||
|
||||
@ -192,6 +205,54 @@ def _process(proc_data):
|
||||
return proc_data
|
||||
|
||||
|
||||
def _ipv6_in(line):
|
||||
line_list = line.replace('(', ' ').replace(')', ' ').replace(',', ' ').replace('%', ' ').split()
|
||||
ipv6 = False
|
||||
for item in line_list:
|
||||
try:
|
||||
_ = ipaddress.IPv6Address(item)
|
||||
ipv6 = True
|
||||
except Exception:
|
||||
pass
|
||||
return ipv6
|
||||
|
||||
|
||||
def _error_type(line):
|
||||
# from https://github.com/dgibson/iputils/blob/master/ping.c
|
||||
# https://android.googlesource.com/platform/external/ping/+/8fc3c91cf9e7f87bc20b9e6d3ea2982d87b70d9a/ping.c
|
||||
# https://opensource.apple.com/source/network_cmds/network_cmds-328/ping.tproj/ping.c
|
||||
type_map = {
|
||||
'Destination Net Unreachable': 'destination_net_unreachable',
|
||||
'Destination Host Unreachable': 'destination_host_unreachable',
|
||||
'Destination Protocol Unreachable': 'destination_protocol_unreachable',
|
||||
'Destination Port Unreachable': 'destination_port_unreachable',
|
||||
'Frag needed and DF set': 'frag_needed_and_df_set',
|
||||
'Source Route Failed': 'source_route_failed',
|
||||
'Destination Net Unknown': 'destination_net_unknown',
|
||||
'Destination Host Unknown': 'destination_host_unknown',
|
||||
'Source Host Isolated': 'source_host_isolated',
|
||||
'Destination Net Prohibited': 'destination_net_prohibited',
|
||||
'Destination Host Prohibited': 'destination_host_prohibited',
|
||||
'Destination Net Unreachable for Type of Service': 'destination_net_unreachable_for_type_of_service',
|
||||
'Destination Host Unreachable for Type of Service': 'destination_host_unreachable_for_type_of_service',
|
||||
'Packet filtered': 'packet_filtered',
|
||||
'Precedence Violation': 'precedence_violation',
|
||||
'Precedence Cutoff': 'precedence_cutoff',
|
||||
'Dest Unreachable, Bad Code': 'dest_unreachable_bad_code',
|
||||
'Redirect Network': 'redirect_network',
|
||||
'Redirect Host': 'redirect_host',
|
||||
'Redirect Type of Service and Network': 'redirect_type_of_service_and_network',
|
||||
'Redirect, Bad Code': 'redirect_bad_code',
|
||||
'Time to live exceeded': 'time_to_live_exceeded',
|
||||
'Frag reassembly time exceeded': 'frag_reassembly_time_exceeded',
|
||||
'Time exceeded, Bad Code': 'time_exceeded_bad_code'
|
||||
}
|
||||
|
||||
for err_type, code in type_map.items():
|
||||
if err_type in line:
|
||||
return code
|
||||
|
||||
|
||||
def _linux_parse(data):
|
||||
raw_output = {}
|
||||
ping_responses = []
|
||||
@ -346,6 +407,7 @@ def _bsd_parse(data):
|
||||
ping_responses = []
|
||||
pattern = None
|
||||
footer = False
|
||||
ping_error = False
|
||||
|
||||
linedata = data.splitlines()
|
||||
|
||||
@ -419,7 +481,7 @@ def _bsd_parse(data):
|
||||
# ping response lines
|
||||
else:
|
||||
# ipv4 lines
|
||||
if ',' not in line:
|
||||
if not _ipv6_in(line):
|
||||
|
||||
# request timeout
|
||||
if line.startswith('Request timeout for '):
|
||||
@ -430,6 +492,42 @@ def _bsd_parse(data):
|
||||
ping_responses.append(response)
|
||||
continue
|
||||
|
||||
# catch error responses
|
||||
err = _error_type(line)
|
||||
if err:
|
||||
response = {
|
||||
'type': err,
|
||||
'bytes': line.split()[0],
|
||||
'response_ip': line.split()[4].strip(':').strip('(').strip(')'),
|
||||
}
|
||||
ping_error = True
|
||||
continue
|
||||
|
||||
if ping_error:
|
||||
if line.startswith('Vr'):
|
||||
continue
|
||||
else:
|
||||
error_line = line.split()
|
||||
response.update(
|
||||
{
|
||||
'vr': int(error_line[0], 16),
|
||||
'hl': int(error_line[1], 16),
|
||||
'tos': int(error_line[2], 16),
|
||||
'len': int(error_line[3], 16),
|
||||
'id': int(error_line[4], 16),
|
||||
'flg': int(error_line[5], 16),
|
||||
'off': int(error_line[6], 16),
|
||||
'ttl': int(error_line[7], 16),
|
||||
'pro': int(error_line[8], 16),
|
||||
'cks': int(error_line[9], 16),
|
||||
'src': error_line[10],
|
||||
'dst': error_line[11],
|
||||
}
|
||||
)
|
||||
ping_responses.append(response)
|
||||
error_line = False
|
||||
continue
|
||||
|
||||
# normal response
|
||||
else:
|
||||
line = line.replace(':', ' ').replace('=', ' ')
|
||||
@ -462,8 +560,9 @@ def _bsd_parse(data):
|
||||
if ping_responses:
|
||||
seq_list = []
|
||||
for reply in ping_responses:
|
||||
seq_list.append(reply['icmp_seq'])
|
||||
reply['duplicate'] = True if seq_list.count(reply['icmp_seq']) > 1 else False
|
||||
if 'icmp_seq' in reply:
|
||||
seq_list.append(reply['icmp_seq'])
|
||||
reply['duplicate'] = True if seq_list.count(reply['icmp_seq']) > 1 else False
|
||||
|
||||
raw_output['responses'] = ping_responses
|
||||
|
||||
|
Reference in New Issue
Block a user