1
0
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:
Kelly Brazil
2021-04-30 16:53:52 -07:00
parent 6150aae0ae
commit b921d5ec95

View File

@ -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,6 +560,7 @@ def _bsd_parse(data):
if ping_responses:
seq_list = []
for reply in ping_responses:
if 'icmp_seq' in reply:
seq_list.append(reply['icmp_seq'])
reply['duplicate'] = True if seq_list.count(reply['icmp_seq']) > 1 else False