mirror of
https://github.com/Horizontal42/netsleuth.git
synced 2026-11-11 02:12:04 +03:00
traceparse: bsd/macos parser with multipath hops and annotations
This commit is contained in:
parent
61c22b218d
commit
e8e55278a7
4 changed files with 93 additions and 0 deletions
|
|
@ -110,3 +110,40 @@ def parse_windows(text: str) -> list[TraceHop]:
|
|||
rdns = None
|
||||
hops.append(finalize_hop(TraceHop(ttl=ttl, ip=ip, reverse_dns=rdns, probes=probes)))
|
||||
return hops
|
||||
|
||||
|
||||
_BSD_CONTINUATION_RE = re.compile(r"^\s+\S")
|
||||
|
||||
|
||||
def parse_darwin(text: str) -> list[TraceHop]:
|
||||
hops: list[TraceHop] = []
|
||||
for line in text.splitlines():
|
||||
match = _HOP_LINE_RE.match(line)
|
||||
if match:
|
||||
ttl, body = int(match.group(1)), match.group(2)
|
||||
rdns, ip = _unix_host_and_ip(body)
|
||||
hops.append(
|
||||
TraceHop(
|
||||
ttl=ttl,
|
||||
ip=ip,
|
||||
reverse_dns=rdns,
|
||||
probes=_unix_probes(body),
|
||||
annotations=_unix_annotations(body),
|
||||
)
|
||||
)
|
||||
continue
|
||||
if not hops or not _BSD_CONTINUATION_RE.match(line):
|
||||
continue
|
||||
# BSD prints one continuation line per probe that came back from a
|
||||
# different router than the hop's first probe.
|
||||
hop = hops[-1]
|
||||
_, extra_ip = _unix_host_and_ip(line)
|
||||
hop.probes.extend(_unix_probes(line))
|
||||
if extra_ip and extra_ip != hop.ip:
|
||||
marker = f"alt:{extra_ip}"
|
||||
if marker not in hop.annotations:
|
||||
hop.annotations.append(marker)
|
||||
for token in _unix_annotations(line):
|
||||
if token not in hop.annotations:
|
||||
hop.annotations.append(token)
|
||||
return [finalize_hop(hop) for hop in hops]
|
||||
|
|
|
|||
6
tests/fixtures/traceroute/darwin/bsd_basic.txt
vendored
Normal file
6
tests/fixtures/traceroute/darwin/bsd_basic.txt
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
traceroute to one.one.one.one (1.1.1.1), 64 hops max, 52 byte packets
|
||||
1 192.168.1.1 (192.168.1.1) 2.145 ms 1.902 ms 1.870 ms
|
||||
2 10.64.0.1 (10.64.0.1) 9.001 ms 8.940 ms 8.870 ms
|
||||
3 * * *
|
||||
4 ae-1.r01.ams.example.net (77.88.1.5) 12.400 ms 12.100 ms 12.220 ms
|
||||
5 one.one.one.one (1.1.1.1) 13.900 ms 13.700 ms 13.610 ms
|
||||
8
tests/fixtures/traceroute/darwin/bsd_multipath.txt
vendored
Normal file
8
tests/fixtures/traceroute/darwin/bsd_multipath.txt
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
traceroute to 203.0.113.9 (203.0.113.9), 64 hops max, 52 byte packets
|
||||
1 192.168.1.1 (192.168.1.1) 2.100 ms 1.900 ms 1.850 ms
|
||||
2 10.64.0.1 (10.64.0.1) 9.001 ms
|
||||
10.64.0.5 (10.64.0.5) 9.220 ms
|
||||
10.64.0.1 (10.64.0.1) 8.870 ms
|
||||
3 * 11.200 ms *
|
||||
4 border.example.net (198.51.100.7) 15.100 ms !H 15.200 ms 15.050 ms
|
||||
5 filtered.example.net (198.51.100.9) 16.000 ms !X 16.100 ms !X 16.200 ms !X
|
||||
|
|
@ -141,3 +141,45 @@ def test_windows_destination_unreachable_hop_keeps_its_ip(trace_fixture):
|
|||
|
||||
def test_windows_parser_tolerates_empty_input():
|
||||
assert parse_windows("") == []
|
||||
|
||||
|
||||
from netcheck.traceparse import parse_darwin
|
||||
|
||||
|
||||
def test_darwin_basic_hops_match_the_gnu_shape(trace_fixture):
|
||||
hops = parse_darwin(trace_fixture("darwin", "bsd_basic.txt"))
|
||||
assert [h.ttl for h in hops] == [1, 2, 3, 4, 5]
|
||||
assert hops[0].ip == "192.168.1.1"
|
||||
assert hops[0].reverse_dns is None
|
||||
assert hops[3].reverse_dns == "ae-1.r01.ams.example.net"
|
||||
assert hops[2].probes == [None, None, None]
|
||||
|
||||
|
||||
def test_darwin_merges_continuation_lines_into_one_hop(trace_fixture):
|
||||
hops = parse_darwin(trace_fixture("darwin", "bsd_multipath.txt"))
|
||||
assert [h.ttl for h in hops] == [1, 2, 3, 4, 5]
|
||||
hop = hops[1]
|
||||
assert hop.probes == [9.001, 9.22, 8.87]
|
||||
assert hop.ip == "10.64.0.1"
|
||||
|
||||
|
||||
def test_darwin_records_alternate_addresses_for_a_multipath_hop(trace_fixture):
|
||||
hops = parse_darwin(trace_fixture("darwin", "bsd_multipath.txt"))
|
||||
assert "alt:10.64.0.5" in hops[1].annotations
|
||||
assert "alt:10.64.0.1" not in hops[1].annotations
|
||||
|
||||
|
||||
def test_darwin_keeps_bsd_only_annotations(trace_fixture):
|
||||
hops = parse_darwin(trace_fixture("darwin", "bsd_multipath.txt"))
|
||||
assert hops[3].annotations == ["!H"]
|
||||
assert hops[4].annotations == ["!X"]
|
||||
|
||||
|
||||
def test_darwin_partial_timeout_hop_keeps_positions(trace_fixture):
|
||||
hops = parse_darwin(trace_fixture("darwin", "bsd_multipath.txt"))
|
||||
assert hops[2].probes == [None, 11.2, None]
|
||||
assert hops[2].loss_pct == pytest.approx(66.667)
|
||||
|
||||
|
||||
def test_darwin_parser_tolerates_empty_input():
|
||||
assert parse_darwin("") == []
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue