From 11df8e09def30288fadecf6aa0f7b2426387733e Mon Sep 17 00:00:00 2001 From: Jarry Shaw Date: Mon, 14 Sep 2026 23:03:48 -0400 Subject: [PATCH 1/4] examples: make the legacy smoke scripts runnable again Twelve of the seventeen runnable demonstrations worked; the rest had rotted against the current API, and nothing in CI runs them so nothing noticed. test_analyse.py passed tcp=True and reasm_strict=True without reassembly=True, so Extractor.reassembly raised UnsupportedCall after parsing every frame. test_api.py had the same omission latently - its three reassembly knobs did nothing, and it passed only because it never touched .reassembly. test_engine.py and test_time.py died partway through on pyshark, which asks for an implicit asyncio event loop that Python 3.14 no longer provides. A demo that dies partway demonstrates nothing, so engines that work now still run and report while an unavailable one is reported as skipped with the reason. That needed care: Extractor does not raise when an engine's package is missing, it warns and silently falls back to its own parser, so the naive version credited PCAP's work to dpkt. The demos now name the driver that actually ran. Classification lives in the new _engine_support.py and covers exactly three cases - ImportError, a missing tshark, and the event-loop RuntimeError - so a real pcapkit failure is still loud. test_perf.py needs pyperf, which pcapkit does not depend on; it now says what to install and points at test_time.py, which does the same comparison with nothing extra. test_profile.py was also broken and was not on the list: cProfile will not create its output directory, so `python test_profile.py` profiled the whole run and then died at the dump. It makes its own temp/ now. Regenerating the four committed outputs was folklore, so `make fixtures` does it and the README says so. They are pinned to TZ=UTC because pcapkit renders frame timestamps in the host's zone: the committed files disagreed with each other, the PCAP three having been generated at UTC-05:00 and pcapng.txt at UTC+08:00. No single zone reproduces all four, and UTC is the only choice that is reproducible anywhere and, for PCAP-NG, correct. Regenerated here against current main. Also fixed a footgun: test_stream.py and test_stream_askpass.py wrote their buffer to ../captures/stream.pcap, a generated fixture the runtime tests pin, so running either would have broken the suite. They use a temporary directory now, and the macOS-only en0 is a named constant. 17/17 runnable scripts exit 0. Library suite unchanged at 508 passed, 4 skipped, 315 subtests. --- examples/captures/out.json | 610 ++++++++-------- examples/captures/out.plist | 12 +- examples/captures/out.txt | 12 +- examples/captures/pcapng.txt | 728 +++++++++++++------ examples/legacy_smoke/Makefile | 25 +- examples/legacy_smoke/README.md | 120 ++- examples/legacy_smoke/_engine_support.py | 151 ++++ examples/legacy_smoke/test_analyse.py | 7 +- examples/legacy_smoke/test_api.py | 6 +- examples/legacy_smoke/test_engine.py | 53 +- examples/legacy_smoke/test_perf.py | 58 +- examples/legacy_smoke/test_profile.py | 14 +- examples/legacy_smoke/test_stream.py | 24 +- examples/legacy_smoke/test_stream_askpass.py | 24 +- examples/legacy_smoke/test_time.py | 31 +- 15 files changed, 1270 insertions(+), 605 deletions(-) create mode 100644 examples/legacy_smoke/_engine_support.py diff --git a/examples/captures/out.json b/examples/captures/out.json index 1859041618..b9e18ab92d 100644 --- a/examples/captures/out.json +++ b/examples/captures/out.json @@ -16,12 +16,12 @@ "thiszone": 0, "sigfigs": 0, "snaplen": 262144, - "network": "LinkType::ETHERNET [1]", - "packet": { - "type": "bytes", - "value": "", - "hex": "" - } + "network": "LinkType::ETHERNET [1]", + "packet": { + "type": "bytes", + "value": "", + "hex": "" + } }, "Frame 1": { "frame_info": { @@ -30,7 +30,7 @@ "incl_len": 86, "orig_len": 86 }, - "time": "2017-11-19T10:49:05.471719", + "time": "2017-11-19T15:49:05.471719", "number": 1, "time_epoch": "1511106545.471719", "len": 86, @@ -53,31 +53,31 @@ "protocol": "TransType::IPv6_ICMP [58]", "raw": { "protocol": "TransType::IPv6_ICMP [58]", - "error": null, - "packet": { - "type": "bytes", - "value": "\ufffd\u0000\u000e\ufffd\u0000\u0000\u0000\u0000\ufffd\ufffd\u0000\u0000\u0000\u0000\u0000\u0000\u001c\ufffd|w\ufffd\ufffdF\ufffd\u0001\u0001\ufffd^`\ufffdk\ufffd", - "hex": "87000eaa00000000fe800000000000001ccd7c77bac746b70101a45e60d96b97" - } - }, - "packet": { - "type": "bytes", - "value": "\ufffd\u0000\u000e\ufffd\u0000\u0000\u0000\u0000\ufffd\ufffd\u0000\u0000\u0000\u0000\u0000\u0000\u001c\ufffd|w\ufffd\ufffdF\ufffd\u0001\u0001\ufffd^`\ufffdk\ufffd", - "hex": "87000eaa00000000fe800000000000001ccd7c77bac746b70101a45e60d96b97" - } - }, - "packet": { - "type": "bytes", - "value": "`\u0000\u0000\u0000\u0000 :\ufffd\ufffd\ufffd\u0000\u0000\u0000\u0000\u0000\u0000\u0000\ufffd\ufffd\ufffd'\ufffd\u0016\ufffd\ufffd\ufffd\u0000\u0000\u0000\u0000\u0000\u0000\u001c\ufffd|w\ufffd\ufffdF\ufffd\ufffd\u0000\u000e\ufffd\u0000\u0000\u0000\u0000\ufffd\ufffd\u0000\u0000\u0000\u0000\u0000\u0000\u001c\ufffd|w\ufffd\ufffdF\ufffd\u0001\u0001\ufffd^`\ufffdk\ufffd", - "hex": "6000000000203afffe8000000000000000a687f9279316eefe800000000000001ccd7c77bac746b787000eaa00000000fe800000000000001ccd7c77bac746b70101a45e60d96b97" - } - }, - "protocols": "Ethernet:IPv6:IPv6_ICMP", - "packet": { - "type": "bytes", - "value": "\ufffd\u0011Z\u001e\ufffd\u0008\u0000N\u0000\u0000\u0000N\u0000\u0000\u0000\ufffd^`\ufffdk\ufffd@3\u001a\u0445\u001c\ufffd\ufffd`\u0000\u0000\u0000\u0000\u0018:\ufffd\ufffd\ufffd\u0000\u0000\u0000\u0000\u0000\u0000\u001c\ufffd|w\ufffd\ufffdF\ufffd\ufffd\ufffd\u0000\u0000\u0000\u0000\u0000\u0000\u0000\ufffd\ufffd\ufffd'\ufffd\u0016\ufffd\u0000?\ufffd@\u0000\u0000\u0000\ufffd\ufffd\u0000\u0000\u0000\u0000\u0000\u0000", - "hex": "f1a7115a1ed208004e0000004e000000a45e60d96b9740331ad1851c86dd6000000000183afffe800000000000001ccd7c77bac746b7fe8000000000000000a687f9279316ee88003f8240000000fe80000000000000" - } + "error": null, + "packet": { + "type": "bytes", + "value": "\ufffd\u0000\u000e\ufffd\u0000\u0000\u0000\u0000\ufffd\ufffd\u0000\u0000\u0000\u0000\u0000\u0000\u001c\ufffd|w\ufffd\ufffdF\ufffd\u0001\u0001\ufffd^`\ufffdk\ufffd", + "hex": "87000eaa00000000fe800000000000001ccd7c77bac746b70101a45e60d96b97" + } + }, + "packet": { + "type": "bytes", + "value": "\ufffd\u0000\u000e\ufffd\u0000\u0000\u0000\u0000\ufffd\ufffd\u0000\u0000\u0000\u0000\u0000\u0000\u001c\ufffd|w\ufffd\ufffdF\ufffd\u0001\u0001\ufffd^`\ufffdk\ufffd", + "hex": "87000eaa00000000fe800000000000001ccd7c77bac746b70101a45e60d96b97" + } + }, + "packet": { + "type": "bytes", + "value": "`\u0000\u0000\u0000\u0000 :\ufffd\ufffd\ufffd\u0000\u0000\u0000\u0000\u0000\u0000\u0000\ufffd\ufffd\ufffd'\ufffd\u0016\ufffd\ufffd\ufffd\u0000\u0000\u0000\u0000\u0000\u0000\u001c\ufffd|w\ufffd\ufffdF\ufffd\ufffd\u0000\u000e\ufffd\u0000\u0000\u0000\u0000\ufffd\ufffd\u0000\u0000\u0000\u0000\u0000\u0000\u001c\ufffd|w\ufffd\ufffdF\ufffd\u0001\u0001\ufffd^`\ufffdk\ufffd", + "hex": "6000000000203afffe8000000000000000a687f9279316eefe800000000000001ccd7c77bac746b787000eaa00000000fe800000000000001ccd7c77bac746b70101a45e60d96b97" + } + }, + "protocols": "Ethernet:IPv6:IPv6_ICMP", + "packet": { + "type": "bytes", + "value": "\ufffd\u0011Z\u001e\ufffd\u0008\u0000N\u0000\u0000\u0000N\u0000\u0000\u0000\ufffd^`\ufffdk\ufffd@3\u001a\u0445\u001c\ufffd\ufffd`\u0000\u0000\u0000\u0000\u0018:\ufffd\ufffd\ufffd\u0000\u0000\u0000\u0000\u0000\u0000\u001c\ufffd|w\ufffd\ufffdF\ufffd\ufffd\ufffd\u0000\u0000\u0000\u0000\u0000\u0000\u0000\ufffd\ufffd\ufffd'\ufffd\u0016\ufffd\u0000?\ufffd@\u0000\u0000\u0000\ufffd\ufffd\u0000\u0000\u0000\u0000\u0000\u0000", + "hex": "f1a7115a1ed208004e0000004e000000a45e60d96b9740331ad1851c86dd6000000000183afffe800000000000001ccd7c77bac746b7fe8000000000000000a687f9279316ee88003f8240000000fe80000000000000" + } }, "Frame 2": { "frame_info": { @@ -86,7 +86,7 @@ "incl_len": 78, "orig_len": 78 }, - "time": "2017-11-19T10:49:05.578078", + "time": "2017-11-19T15:49:05.578078", "number": 2, "time_epoch": "1511106545.578078", "len": 78, @@ -109,31 +109,31 @@ "protocol": "TransType::IPv6_ICMP [58]", "raw": { "protocol": "TransType::IPv6_ICMP [58]", - "error": null, - "packet": { - "type": "bytes", - "value": "\ufffd\u0000?\ufffd@\u0000\u0000\u0000\ufffd\ufffd\u0000\u0000\u0000\u0000\u0000\u0000\u001c\ufffd|w\ufffd\ufffdF\ufffd", - "hex": "88003f8240000000fe800000000000001ccd7c77bac746b7" - } - }, - "packet": { - "type": "bytes", - "value": "\ufffd\u0000?\ufffd@\u0000\u0000\u0000\ufffd\ufffd\u0000\u0000\u0000\u0000\u0000\u0000\u001c\ufffd|w\ufffd\ufffdF\ufffd", - "hex": "88003f8240000000fe800000000000001ccd7c77bac746b7" - } - }, - "packet": { - "type": "bytes", - "value": "`\u0000\u0000\u0000\u0000\u0018:\ufffd\ufffd\ufffd\u0000\u0000\u0000\u0000\u0000\u0000\u001c\ufffd|w\ufffd\ufffdF\ufffd\ufffd\ufffd\u0000\u0000\u0000\u0000\u0000\u0000\u0000\ufffd\ufffd\ufffd'\ufffd\u0016\ufffd\u0000?\ufffd@\u0000\u0000\u0000\ufffd\ufffd\u0000\u0000\u0000\u0000\u0000\u0000\u001c\ufffd|w\ufffd\ufffdF\ufffd", - "hex": "6000000000183afffe800000000000001ccd7c77bac746b7fe8000000000000000a687f9279316ee88003f8240000000fe800000000000001ccd7c77bac746b7" - } - }, - "protocols": "Ethernet:IPv6:IPv6_ICMP", - "packet": { - "type": "bytes", - "value": "\ufffd\ufffd\u0011ZL\ufffd\u000b\u00006\u0000\u0000\u00006\u0000\u0000\u0000\ufffd^`\ufffdk\ufffd\ufffd\ufffd\ufffd\ufffd\ufffdG\u0008\u0000E\u0000\u0000(\ufffd4@\u0000+\u0006z\ufffd{\ufffd\u0487\ufffd\ufffd\u0001d\u0000P\ufffd\ufffd\u055f\ufffdT\ufffdz\ufffd\ufffdP\u0011|\ufffd|\ufffd\u0000\u0000\ufffd\ufffd\u0011Z\ufffd\ufffd\u000b\u0000", - "hex": "f5a7115a4cde0b003600000036000000a45e60d96b97b8f883a5f947080045000028c53440002b067a867b81d287c0a801640050d7c0d59fb154a67aa0ff50117cb07c8e0000f5a7115a8cde0b00" - } + "error": null, + "packet": { + "type": "bytes", + "value": "\ufffd\u0000?\ufffd@\u0000\u0000\u0000\ufffd\ufffd\u0000\u0000\u0000\u0000\u0000\u0000\u001c\ufffd|w\ufffd\ufffdF\ufffd", + "hex": "88003f8240000000fe800000000000001ccd7c77bac746b7" + } + }, + "packet": { + "type": "bytes", + "value": "\ufffd\u0000?\ufffd@\u0000\u0000\u0000\ufffd\ufffd\u0000\u0000\u0000\u0000\u0000\u0000\u001c\ufffd|w\ufffd\ufffdF\ufffd", + "hex": "88003f8240000000fe800000000000001ccd7c77bac746b7" + } + }, + "packet": { + "type": "bytes", + "value": "`\u0000\u0000\u0000\u0000\u0018:\ufffd\ufffd\ufffd\u0000\u0000\u0000\u0000\u0000\u0000\u001c\ufffd|w\ufffd\ufffdF\ufffd\ufffd\ufffd\u0000\u0000\u0000\u0000\u0000\u0000\u0000\ufffd\ufffd\ufffd'\ufffd\u0016\ufffd\u0000?\ufffd@\u0000\u0000\u0000\ufffd\ufffd\u0000\u0000\u0000\u0000\u0000\u0000\u001c\ufffd|w\ufffd\ufffdF\ufffd", + "hex": "6000000000183afffe800000000000001ccd7c77bac746b7fe8000000000000000a687f9279316ee88003f8240000000fe800000000000001ccd7c77bac746b7" + } + }, + "protocols": "Ethernet:IPv6:IPv6_ICMP", + "packet": { + "type": "bytes", + "value": "\ufffd\ufffd\u0011ZL\ufffd\u000b\u00006\u0000\u0000\u00006\u0000\u0000\u0000\ufffd^`\ufffdk\ufffd\ufffd\ufffd\ufffd\ufffd\ufffdG\u0008\u0000E\u0000\u0000(\ufffd4@\u0000+\u0006z\ufffd{\ufffd\u0487\ufffd\ufffd\u0001d\u0000P\ufffd\ufffd\u055f\ufffdT\ufffdz\ufffd\ufffdP\u0011|\ufffd|\ufffd\u0000\u0000\ufffd\ufffd\u0011Z\ufffd\ufffd\u000b\u0000", + "hex": "f5a7115a4cde0b003600000036000000a45e60d96b97b8f883a5f947080045000028c53440002b067a867b81d287c0a801640050d7c0d59fb154a67aa0ff50117cb07c8e0000f5a7115a8cde0b00" + } }, "Frame 3": { "frame_info": { @@ -142,7 +142,7 @@ "incl_len": 54, "orig_len": 54 }, - "time": "2017-11-19T10:49:09.777804", + "time": "2017-11-19T15:49:09.777804", "number": 3, "time_epoch": "1511106549.777804", "len": 54, @@ -177,71 +177,71 @@ }, "src": "123.129.210.135", "dst": "192.168.1.100", - "tcp": { - "srcport": { - "enum": "AppType::www_http [www-http [80 - tcp|udp]]", - "svc": "www-http", - "port": 80, - "proto": "TransportProtocol::tcp|udp [3]" - }, - "dstport": { - "enum": "AppType::PORT_55232_tcp [unknown [55232 - tcp]]", - "svc": "unknown", - "port": 55232, - "proto": "TransportProtocol::tcp [1]" - }, - "seq": 3584012628, - "ack": 2793054463, - "hdr_len": 20, - "flags": { - "cwr": false, - "ece": false, - "urg": false, - "ack": true, - "psh": false, - "rst": false, - "syn": false, - "fin": true - }, - "window_size": 31920, - "checksum": { - "type": "bytes", - "value": "|\ufffd", - "hex": "7c8e" - }, - "urgent_pointer": 0, - "connection": "Flags::ACK|FIN [34816]", - "nopayload": { - "packet": { - "type": "bytes", - "value": "", - "hex": "" - } - }, - "packet": { - "type": "bytes", - "value": "", - "hex": "" - } - }, - "packet": { - "type": "bytes", - "value": "\u0000P\ufffd\ufffd\u055f\ufffdT\ufffdz\ufffd\ufffdP\u0011|\ufffd|\ufffd\u0000\u0000", - "hex": "0050d7c0d59fb154a67aa0ff50117cb07c8e0000" - } - }, - "packet": { - "type": "bytes", - "value": "E\u0000\u0000(\ufffd4@\u0000+\u0006z\ufffd{\ufffd\u0487\ufffd\ufffd\u0001d\u0000P\ufffd\ufffd\u055f\ufffdT\ufffdz\ufffd\ufffdP\u0011|\ufffd|\ufffd\u0000\u0000", - "hex": "45000028c53440002b067a867b81d287c0a801640050d7c0d59fb154a67aa0ff50117cb07c8e0000" - } - }, - "protocols": "Ethernet:IPv4:TCP", - "packet": { - "type": "bytes", - "value": "\ufffd\ufffd\u0011Z\ufffd\ufffd\u000b\u00006\u0000\u0000\u00006\u0000\u0000\u0000\ufffd\ufffd\ufffd\ufffd\ufffdG\ufffd^`\ufffdk\ufffd\u0008\u0000E\u0000\u0000(\u0000\u0000@\u0000@\u0006*\ufffd\ufffd\ufffd\u0001d{\ufffd\u0487\ufffd\ufffd\u0000P", - "hex": "f5a7115a8cde0b003600000036000000b8f883a5f947a45e60d96b970800450000280000400040062abbc0a801647b81d287d7c00050" - } + "tcp": { + "srcport": { + "enum": "AppType::www_http [www-http [80 - tcp|udp]]", + "svc": "www-http", + "port": 80, + "proto": "TransportProtocol::tcp|udp [3]" + }, + "dstport": { + "enum": "AppType::PORT_55232_tcp [unknown [55232 - tcp]]", + "svc": "unknown", + "port": 55232, + "proto": "TransportProtocol::tcp [1]" + }, + "seq": 3584012628, + "ack": 2793054463, + "hdr_len": 20, + "flags": { + "cwr": false, + "ece": false, + "urg": false, + "ack": true, + "psh": false, + "rst": false, + "syn": false, + "fin": true + }, + "window_size": 31920, + "checksum": { + "type": "bytes", + "value": "|\ufffd", + "hex": "7c8e" + }, + "urgent_pointer": 0, + "connection": "Flags::ACK|FIN [34816]", + "nopayload": { + "packet": { + "type": "bytes", + "value": "", + "hex": "" + } + }, + "packet": { + "type": "bytes", + "value": "", + "hex": "" + } + }, + "packet": { + "type": "bytes", + "value": "\u0000P\ufffd\ufffd\u055f\ufffdT\ufffdz\ufffd\ufffdP\u0011|\ufffd|\ufffd\u0000\u0000", + "hex": "0050d7c0d59fb154a67aa0ff50117cb07c8e0000" + } + }, + "packet": { + "type": "bytes", + "value": "E\u0000\u0000(\ufffd4@\u0000+\u0006z\ufffd{\ufffd\u0487\ufffd\ufffd\u0001d\u0000P\ufffd\ufffd\u055f\ufffdT\ufffdz\ufffd\ufffdP\u0011|\ufffd|\ufffd\u0000\u0000", + "hex": "45000028c53440002b067a867b81d287c0a801640050d7c0d59fb154a67aa0ff50117cb07c8e0000" + } + }, + "protocols": "Ethernet:IPv4:TCP", + "packet": { + "type": "bytes", + "value": "\ufffd\ufffd\u0011Z\ufffd\ufffd\u000b\u00006\u0000\u0000\u00006\u0000\u0000\u0000\ufffd\ufffd\ufffd\ufffd\ufffdG\ufffd^`\ufffdk\ufffd\u0008\u0000E\u0000\u0000(\u0000\u0000@\u0000@\u0006*\ufffd\ufffd\ufffd\u0001d{\ufffd\u0487\ufffd\ufffd\u0000P", + "hex": "f5a7115a8cde0b003600000036000000b8f883a5f947a45e60d96b970800450000280000400040062abbc0a801647b81d287d7c00050" + } }, "Frame 4": { "frame_info": { @@ -250,7 +250,7 @@ "incl_len": 54, "orig_len": 54 }, - "time": "2017-11-19T10:49:09.777868", + "time": "2017-11-19T15:49:09.777868", "number": 4, "time_epoch": "1511106549.777868", "len": 54, @@ -285,71 +285,71 @@ }, "src": "192.168.1.100", "dst": "123.129.210.135", - "tcp": { - "srcport": { - "enum": "AppType::PORT_55232_tcp [unknown [55232 - tcp]]", - "svc": "unknown", - "port": 55232, - "proto": "TransportProtocol::tcp [1]" - }, - "dstport": { - "enum": "AppType::www_http [www-http [80 - tcp|udp]]", - "svc": "www-http", - "port": 80, - "proto": "TransportProtocol::tcp|udp [3]" - }, - "seq": 2793054463, - "ack": 3584012629, - "hdr_len": 20, - "flags": { - "cwr": false, - "ece": false, - "urg": false, - "ack": true, - "psh": false, - "rst": false, - "syn": false, - "fin": false - }, - "window_size": 65535, - "checksum": { - "type": "bytes", - "value": "\ufffd>", - "hex": "f93e" - }, - "urgent_pointer": 0, - "connection": "Flags::ACK [2048]", - "nopayload": { - "packet": { - "type": "bytes", - "value": "", - "hex": "" - } - }, - "packet": { - "type": "bytes", - "value": "", - "hex": "" - } - }, - "packet": { - "type": "bytes", - "value": "\ufffd\ufffd\u0000P\ufffdz\ufffd\ufffd\u055f\ufffdUP\u0010\ufffd\ufffd\ufffd>\u0000\u0000", - "hex": "d7c00050a67aa0ffd59fb1555010fffff93e0000" - } - }, - "packet": { - "type": "bytes", - "value": "E\u0000\u0000(\u0000\u0000@\u0000@\u0006*\ufffd\ufffd\ufffd\u0001d{\ufffd\u0487\ufffd\ufffd\u0000P\ufffdz\ufffd\ufffd\u055f\ufffdUP\u0010\ufffd\ufffd\ufffd>\u0000\u0000", - "hex": "450000280000400040062abbc0a801647b81d287d7c00050a67aa0ffd59fb1555010fffff93e0000" - } - }, - "protocols": "Ethernet:IPv4:TCP", - "packet": { - "type": "bytes", - "value": "\ufffd\ufffd\u0011Z8\ufffd\r\u00006\u0000\u0000\u00006\u0000\u0000\u0000\ufffd\ufffd\ufffd\ufffd\ufffdG\ufffd^`\ufffdk\ufffd\u0008\u0000E\u0000\u0000(\u0000\u0000@\u0000@\u0006*\ufffd\ufffd\ufffd\u0001d{\ufffd\u0487\u05f0\u0000P", - "hex": "f5a7115a38f10d003600000036000000b8f883a5f947a45e60d96b970800450000280000400040062abbc0a801647b81d287d7b00050" - } + "tcp": { + "srcport": { + "enum": "AppType::PORT_55232_tcp [unknown [55232 - tcp]]", + "svc": "unknown", + "port": 55232, + "proto": "TransportProtocol::tcp [1]" + }, + "dstport": { + "enum": "AppType::www_http [www-http [80 - tcp|udp]]", + "svc": "www-http", + "port": 80, + "proto": "TransportProtocol::tcp|udp [3]" + }, + "seq": 2793054463, + "ack": 3584012629, + "hdr_len": 20, + "flags": { + "cwr": false, + "ece": false, + "urg": false, + "ack": true, + "psh": false, + "rst": false, + "syn": false, + "fin": false + }, + "window_size": 65535, + "checksum": { + "type": "bytes", + "value": "\ufffd>", + "hex": "f93e" + }, + "urgent_pointer": 0, + "connection": "Flags::ACK [2048]", + "nopayload": { + "packet": { + "type": "bytes", + "value": "", + "hex": "" + } + }, + "packet": { + "type": "bytes", + "value": "", + "hex": "" + } + }, + "packet": { + "type": "bytes", + "value": "\ufffd\ufffd\u0000P\ufffdz\ufffd\ufffd\u055f\ufffdUP\u0010\ufffd\ufffd\ufffd>\u0000\u0000", + "hex": "d7c00050a67aa0ffd59fb1555010fffff93e0000" + } + }, + "packet": { + "type": "bytes", + "value": "E\u0000\u0000(\u0000\u0000@\u0000@\u0006*\ufffd\ufffd\ufffd\u0001d{\ufffd\u0487\ufffd\ufffd\u0000P\ufffdz\ufffd\ufffd\u055f\ufffdUP\u0010\ufffd\ufffd\ufffd>\u0000\u0000", + "hex": "450000280000400040062abbc0a801647b81d287d7c00050a67aa0ffd59fb1555010fffff93e0000" + } + }, + "protocols": "Ethernet:IPv4:TCP", + "packet": { + "type": "bytes", + "value": "\ufffd\ufffd\u0011Z8\ufffd\r\u00006\u0000\u0000\u00006\u0000\u0000\u0000\ufffd\ufffd\ufffd\ufffd\ufffdG\ufffd^`\ufffdk\ufffd\u0008\u0000E\u0000\u0000(\u0000\u0000@\u0000@\u0006*\ufffd\ufffd\ufffd\u0001d{\ufffd\u0487\u05f0\u0000P", + "hex": "f5a7115a38f10d003600000036000000b8f883a5f947a45e60d96b970800450000280000400040062abbc0a801647b81d287d7b00050" + } }, "Frame 5": { "frame_info": { @@ -358,7 +358,7 @@ "incl_len": 54, "orig_len": 54 }, - "time": "2017-11-19T10:49:09.913720", + "time": "2017-11-19T15:49:09.913720", "number": 5, "time_epoch": "1511106549.91372", "len": 54, @@ -393,71 +393,71 @@ }, "src": "192.168.1.100", "dst": "123.129.210.135", - "tcp": { - "srcport": { - "enum": "AppType::PORT_55216_tcp [unknown [55216 - tcp]]", - "svc": "unknown", - "port": 55216, - "proto": "TransportProtocol::tcp [1]" - }, - "dstport": { - "enum": "AppType::www_http [www-http [80 - tcp|udp]]", - "svc": "www-http", - "port": 80, - "proto": "TransportProtocol::tcp|udp [3]" - }, - "seq": 768904481, - "ack": 1835365486, - "hdr_len": 20, - "flags": { - "cwr": false, - "ece": false, - "urg": false, - "ack": true, - "psh": false, - "rst": false, - "syn": false, - "fin": true - }, - "window_size": 65535, - "checksum": { - "type": "bytes", - "value": "*\ufffd", - "hex": "2af4" - }, - "urgent_pointer": 0, - "connection": "Flags::ACK|FIN [34816]", - "nopayload": { - "packet": { - "type": "bytes", - "value": "", - "hex": "" - } - }, - "packet": { - "type": "bytes", - "value": "", - "hex": "" - } - }, - "packet": { - "type": "bytes", - "value": "\u05f0\u0000P-\u050d!metnP\u0011\ufffd\ufffd*\ufffd\u0000\u0000", - "hex": "d7b000502dd48d216d65746e5011ffff2af40000" - } - }, - "packet": { - "type": "bytes", - "value": "E\u0000\u0000(\u0000\u0000@\u0000@\u0006*\ufffd\ufffd\ufffd\u0001d{\ufffd\u0487\u05f0\u0000P-\u050d!metnP\u0011\ufffd\ufffd*\ufffd\u0000\u0000", - "hex": "450000280000400040062abbc0a801647b81d287d7b000502dd48d216d65746e5011ffff2af40000" + "tcp": { + "srcport": { + "enum": "AppType::PORT_55216_tcp [unknown [55216 - tcp]]", + "svc": "unknown", + "port": 55216, + "proto": "TransportProtocol::tcp [1]" + }, + "dstport": { + "enum": "AppType::www_http [www-http [80 - tcp|udp]]", + "svc": "www-http", + "port": 80, + "proto": "TransportProtocol::tcp|udp [3]" + }, + "seq": 768904481, + "ack": 1835365486, + "hdr_len": 20, + "flags": { + "cwr": false, + "ece": false, + "urg": false, + "ack": true, + "psh": false, + "rst": false, + "syn": false, + "fin": true + }, + "window_size": 65535, + "checksum": { + "type": "bytes", + "value": "*\ufffd", + "hex": "2af4" + }, + "urgent_pointer": 0, + "connection": "Flags::ACK|FIN [34816]", + "nopayload": { + "packet": { + "type": "bytes", + "value": "", + "hex": "" + } + }, + "packet": { + "type": "bytes", + "value": "", + "hex": "" + } + }, + "packet": { + "type": "bytes", + "value": "\u05f0\u0000P-\u050d!metnP\u0011\ufffd\ufffd*\ufffd\u0000\u0000", + "hex": "d7b000502dd48d216d65746e5011ffff2af40000" + } + }, + "packet": { + "type": "bytes", + "value": "E\u0000\u0000(\u0000\u0000@\u0000@\u0006*\ufffd\ufffd\ufffd\u0001d{\ufffd\u0487\u05f0\u0000P-\u050d!metnP\u0011\ufffd\ufffd*\ufffd\u0000\u0000", + "hex": "450000280000400040062abbc0a801647b81d287d7b000502dd48d216d65746e5011ffff2af40000" } }, - "protocols": "Ethernet:IPv4:TCP", - "packet": { - "type": "bytes", - "value": "\ufffd\ufffd\u0011Z\u0013\u0005\u0001\u0000\ufffd\u0000\u0000\u0000\ufffd\u0000\u0000\u0000\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffdG\u0008\u0000E\u0000\u0000\ufffd\u0000\u0000@\u0000@\u0011x\ufffd\ufffd\ufffd\u0001\u0001\ufffd\ufffd\ufffd\ufffd\ufffdD\u0013\ufffd", - "hex": "f7a7115a130501009f0000009f000000ffffffffffffb8f883a5f94708004500009100004000401178b3c0a80101ffffffff92441389" - } + "protocols": "Ethernet:IPv4:TCP", + "packet": { + "type": "bytes", + "value": "\ufffd\ufffd\u0011Z\u0013\u0005\u0001\u0000\ufffd\u0000\u0000\u0000\ufffd\u0000\u0000\u0000\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffdG\u0008\u0000E\u0000\u0000\ufffd\u0000\u0000@\u0000@\u0011x\ufffd\ufffd\ufffd\u0001\u0001\ufffd\ufffd\ufffd\ufffd\ufffdD\u0013\ufffd", + "hex": "f7a7115a130501009f0000009f000000ffffffffffffb8f883a5f94708004500009100004000401178b3c0a80101ffffffff92441389" + } }, "Frame 6": { "frame_info": { @@ -466,7 +466,7 @@ "incl_len": 159, "orig_len": 159 }, - "time": "2017-11-19T10:49:11.066835", + "time": "2017-11-19T15:49:11.066835", "number": 6, "time_epoch": "1511106551.066835", "len": 159, @@ -501,57 +501,57 @@ }, "src": "192.168.1.1", "dst": "255.255.255.255", - "udp": { - "srcport": { - "enum": "AppType::unassigned_37444 [unassigned [37444 - undefined]]", - "svc": "unassigned", - "port": 37444, - "proto": "TransportProtocol::undefined [0]" - }, - "dstport": { - "enum": "AppType::commplex_link [commplex-link [5001 - tcp|udp]]", - "svc": "commplex-link", - "port": 5001, - "proto": "TransportProtocol::tcp|udp [3]" - }, - "len": 125, - "checksum": { - "type": "bytes", - "value": "c\ufffd", - "hex": "63b1" - }, - "raw": { - "protocol": null, - "error": null, - "packet": { - "type": "bytes", - "value": "\u0001\u0001\u000e\u0000\ufffd+\ufffd\ufffd\ufffd\ufffd\u0000g\u0000\u0000\u0000\u0006\u0000\nTL-WDR6300\u0000\u000b\u0000\u00036.0\u0000\u0007\u0000\u0001\u0001\u0000\u0005\u0000\u0011B8-F8-83-A5-F9-47\u0000\u0008\u0000\u000b192.168.1.1\u0000\t\u0000\ntplogin.cn\u0000\n\u0000\u000eTL-WDR6300 6.0\u0000\f\u0000\u00051.7.4", - "hex": "01010e00e12b83c7f98b006700000006000a544c2d57445236333030000b0003362e3000070001010005001142382d46382d38332d41352d46392d34370008000b3139322e3136382e312e310009000a74706c6f67696e2e636e000a000e544c2d5744523633303020362e30000c0005312e372e34" - } - }, - "packet": { - "type": "bytes", - "value": "\u0001\u0001\u000e\u0000\ufffd+\ufffd\ufffd\ufffd\ufffd\u0000g\u0000\u0000\u0000\u0006\u0000\nTL-WDR6300\u0000\u000b\u0000\u00036.0\u0000\u0007\u0000\u0001\u0001\u0000\u0005\u0000\u0011B8-F8-83-A5-F9-47\u0000\u0008\u0000\u000b192.168.1.1\u0000\t\u0000\ntplogin.cn\u0000\n\u0000\u000eTL-WDR6300 6.0\u0000\f\u0000\u00051.7.4", - "hex": "01010e00e12b83c7f98b006700000006000a544c2d57445236333030000b0003362e3000070001010005001142382d46382d38332d41352d46392d34370008000b3139322e3136382e312e310009000a74706c6f67696e2e636e000a000e544c2d5744523633303020362e30000c0005312e372e34" - } - }, - "packet": { - "type": "bytes", - "value": "\ufffdD\u0013\ufffd\u0000}c\ufffd\u0001\u0001\u000e\u0000\ufffd+\ufffd\ufffd\ufffd\ufffd\u0000g\u0000\u0000\u0000\u0006\u0000\nTL-WDR6300\u0000\u000b\u0000\u00036.0\u0000\u0007\u0000\u0001\u0001\u0000\u0005\u0000\u0011B8-F8-83-A5-F9-47\u0000\u0008\u0000\u000b192.168.1.1\u0000\t\u0000\ntplogin.cn\u0000\n\u0000\u000eTL-WDR6300 6.0\u0000\f\u0000\u00051.7.4", - "hex": "92441389007d63b101010e00e12b83c7f98b006700000006000a544c2d57445236333030000b0003362e3000070001010005001142382d46382d38332d41352d46392d34370008000b3139322e3136382e312e310009000a74706c6f67696e2e636e000a000e544c2d5744523633303020362e30000c0005312e372e34" + "udp": { + "srcport": { + "enum": "AppType::unassigned_37444 [unassigned [37444 - undefined]]", + "svc": "unassigned", + "port": 37444, + "proto": "TransportProtocol::undefined [0]" + }, + "dstport": { + "enum": "AppType::commplex_link [commplex-link [5001 - tcp|udp]]", + "svc": "commplex-link", + "port": 5001, + "proto": "TransportProtocol::tcp|udp [3]" + }, + "len": 125, + "checksum": { + "type": "bytes", + "value": "c\ufffd", + "hex": "63b1" + }, + "raw": { + "protocol": null, + "error": null, + "packet": { + "type": "bytes", + "value": "\u0001\u0001\u000e\u0000\ufffd+\ufffd\ufffd\ufffd\ufffd\u0000g\u0000\u0000\u0000\u0006\u0000\nTL-WDR6300\u0000\u000b\u0000\u00036.0\u0000\u0007\u0000\u0001\u0001\u0000\u0005\u0000\u0011B8-F8-83-A5-F9-47\u0000\u0008\u0000\u000b192.168.1.1\u0000\t\u0000\ntplogin.cn\u0000\n\u0000\u000eTL-WDR6300 6.0\u0000\f\u0000\u00051.7.4", + "hex": "01010e00e12b83c7f98b006700000006000a544c2d57445236333030000b0003362e3000070001010005001142382d46382d38332d41352d46392d34370008000b3139322e3136382e312e310009000a74706c6f67696e2e636e000a000e544c2d5744523633303020362e30000c0005312e372e34" + } + }, + "packet": { + "type": "bytes", + "value": "\u0001\u0001\u000e\u0000\ufffd+\ufffd\ufffd\ufffd\ufffd\u0000g\u0000\u0000\u0000\u0006\u0000\nTL-WDR6300\u0000\u000b\u0000\u00036.0\u0000\u0007\u0000\u0001\u0001\u0000\u0005\u0000\u0011B8-F8-83-A5-F9-47\u0000\u0008\u0000\u000b192.168.1.1\u0000\t\u0000\ntplogin.cn\u0000\n\u0000\u000eTL-WDR6300 6.0\u0000\f\u0000\u00051.7.4", + "hex": "01010e00e12b83c7f98b006700000006000a544c2d57445236333030000b0003362e3000070001010005001142382d46382d38332d41352d46392d34370008000b3139322e3136382e312e310009000a74706c6f67696e2e636e000a000e544c2d5744523633303020362e30000c0005312e372e34" + } + }, + "packet": { + "type": "bytes", + "value": "\ufffdD\u0013\ufffd\u0000}c\ufffd\u0001\u0001\u000e\u0000\ufffd+\ufffd\ufffd\ufffd\ufffd\u0000g\u0000\u0000\u0000\u0006\u0000\nTL-WDR6300\u0000\u000b\u0000\u00036.0\u0000\u0007\u0000\u0001\u0001\u0000\u0005\u0000\u0011B8-F8-83-A5-F9-47\u0000\u0008\u0000\u000b192.168.1.1\u0000\t\u0000\ntplogin.cn\u0000\n\u0000\u000eTL-WDR6300 6.0\u0000\f\u0000\u00051.7.4", + "hex": "92441389007d63b101010e00e12b83c7f98b006700000006000a544c2d57445236333030000b0003362e3000070001010005001142382d46382d38332d41352d46392d34370008000b3139322e3136382e312e310009000a74706c6f67696e2e636e000a000e544c2d5744523633303020362e30000c0005312e372e34" } - }, - "packet": { - "type": "bytes", - "value": "E\u0000\u0000\ufffd\u0000\u0000@\u0000@\u0011x\ufffd\ufffd\ufffd\u0001\u0001\ufffd\ufffd\ufffd\ufffd\ufffdD\u0013\ufffd\u0000}c\ufffd\u0001\u0001\u000e\u0000\ufffd+\ufffd\ufffd\ufffd\ufffd\u0000g\u0000\u0000\u0000\u0006\u0000\nTL-WDR6300\u0000\u000b\u0000\u00036.0\u0000\u0007\u0000\u0001\u0001\u0000\u0005\u0000\u0011B8-F8-83-A5-F9-47\u0000\u0008\u0000\u000b192.168.1.1\u0000\t\u0000\ntplogin.cn\u0000\n\u0000\u000eTL-WDR6300 6.0\u0000\f\u0000\u00051.7.4", - "hex": "4500009100004000401178b3c0a80101ffffffff92441389007d63b101010e00e12b83c7f98b006700000006000a544c2d57445236333030000b0003362e3000070001010005001142382d46382d38332d41352d46392d34370008000b3139322e3136382e312e310009000a74706c6f67696e2e636e000a000e544c2d5744523633303020362e30000c0005312e372e34" + }, + "packet": { + "type": "bytes", + "value": "E\u0000\u0000\ufffd\u0000\u0000@\u0000@\u0011x\ufffd\ufffd\ufffd\u0001\u0001\ufffd\ufffd\ufffd\ufffd\ufffdD\u0013\ufffd\u0000}c\ufffd\u0001\u0001\u000e\u0000\ufffd+\ufffd\ufffd\ufffd\ufffd\u0000g\u0000\u0000\u0000\u0006\u0000\nTL-WDR6300\u0000\u000b\u0000\u00036.0\u0000\u0007\u0000\u0001\u0001\u0000\u0005\u0000\u0011B8-F8-83-A5-F9-47\u0000\u0008\u0000\u000b192.168.1.1\u0000\t\u0000\ntplogin.cn\u0000\n\u0000\u000eTL-WDR6300 6.0\u0000\f\u0000\u00051.7.4", + "hex": "4500009100004000401178b3c0a80101ffffffff92441389007d63b101010e00e12b83c7f98b006700000006000a544c2d57445236333030000b0003362e3000070001010005001142382d46382d38332d41352d46392d34370008000b3139322e3136382e312e310009000a74706c6f67696e2e636e000a000e544c2d5744523633303020362e30000c0005312e372e34" } }, - "protocols": "Ethernet:IPv4:UDP:Raw", - "packet": { - "type": "bytes", - "value": "", - "hex": "" - } + "protocols": "Ethernet:IPv4:UDP:Raw", + "packet": { + "type": "bytes", + "value": "", + "hex": "" + } } -} +} \ No newline at end of file diff --git a/examples/captures/out.plist b/examples/captures/out.plist index 2c7f7eb842..815ece9fab 100644 --- a/examples/captures/out.plist +++ b/examples/captures/out.plist @@ -48,7 +48,7 @@ 86 time - 2017-11-19T10:49:05.471719Z + 2017-11-19T15:49:05.471719Z number 1 time_epoch @@ -121,7 +121,7 @@ 78 time - 2017-11-19T10:49:05.578078Z + 2017-11-19T15:49:05.578078Z number 2 time_epoch @@ -194,7 +194,7 @@ 54 time - 2017-11-19T10:49:09.777804Z + 2017-11-19T15:49:09.777804Z number 3 time_epoch @@ -343,7 +343,7 @@ 54 time - 2017-11-19T10:49:09.777868Z + 2017-11-19T15:49:09.777868Z number 4 time_epoch @@ -492,7 +492,7 @@ 54 time - 2017-11-19T10:49:09.913720Z + 2017-11-19T15:49:09.913720Z number 5 time_epoch @@ -641,7 +641,7 @@ 159 time - 2017-11-19T10:49:11.066835Z + 2017-11-19T15:49:11.066835Z number 6 time_epoch diff --git a/examples/captures/out.txt b/examples/captures/out.txt index 687a5d20b6..824fb657b7 100644 --- a/examples/captures/out.txt +++ b/examples/captures/out.txt @@ -20,7 +20,7 @@ Frame 1 | |-- ts_usec -> 471719 | |-- incl_len -> 86 | |-- orig_len -> 86 - |-- time -> 2017-11-19T10:49:05.471719 + |-- time -> 2017-11-19T15:49:05.471719 |-- number -> 1 |-- time_epoch -> 1511106545.471719 |-- len -> 86 @@ -73,7 +73,7 @@ Frame 2 | |-- ts_usec -> 578078 | |-- incl_len -> 78 | |-- orig_len -> 78 - |-- time -> 2017-11-19T10:49:05.578078 + |-- time -> 2017-11-19T15:49:05.578078 |-- number -> 2 |-- time_epoch -> 1511106545.578078 |-- len -> 78 @@ -124,7 +124,7 @@ Frame 3 | |-- ts_usec -> 777804 | |-- incl_len -> 54 | |-- orig_len -> 54 - |-- time -> 2017-11-19T10:49:09.777804 + |-- time -> 2017-11-19T15:49:09.777804 |-- number -> 3 |-- time_epoch -> 1511106549.777804 |-- len -> 54 @@ -209,7 +209,7 @@ Frame 4 | |-- ts_usec -> 777868 | |-- incl_len -> 54 | |-- orig_len -> 54 - |-- time -> 2017-11-19T10:49:09.777868 + |-- time -> 2017-11-19T15:49:09.777868 |-- number -> 4 |-- time_epoch -> 1511106549.777868 |-- len -> 54 @@ -294,7 +294,7 @@ Frame 5 | |-- ts_usec -> 913720 | |-- incl_len -> 54 | |-- orig_len -> 54 - |-- time -> 2017-11-19T10:49:09.913720 + |-- time -> 2017-11-19T15:49:09.913720 |-- number -> 5 |-- time_epoch -> 1511106549.91372 |-- len -> 54 @@ -379,7 +379,7 @@ Frame 6 | |-- ts_usec -> 66835 | |-- incl_len -> 159 | |-- orig_len -> 159 - |-- time -> 2017-11-19T10:49:11.066835 + |-- time -> 2017-11-19T15:49:11.066835 |-- number -> 6 |-- time_epoch -> 1511106551.066835 |-- len -> 159 diff --git a/examples/captures/pcapng.txt b/examples/captures/pcapng.txt index 0d7fa0bfeb..9c3c284174 100644 --- a/examples/captures/pcapng.txt +++ b/examples/captures/pcapng.txt @@ -11,6 +11,7 @@ Section Header 1 | |--> 0 |-- section_length -> -1 |-- options -> NIL + |-- packet -> NIL Interface Description 1 |-- type @@ -20,23 +21,24 @@ Interface Description 1 |-- linktype -> LinkType::ETHERNET [1] |-- snaplen -> 65535 |-- options - |-- OptionType::if_tsresol [if_tsresol [9]] - | |--> -- - | |-- type - | | |-- enum -> OptionType::if_tsresol [if_tsresol [9]] - | | |-- opt_name -> if_tsresol - | | |-- opt_value -> 9 - | |-- length -> 1 - | |-- resolution -> 1000000 - |-- OptionType::opt_endofopt [opt_endofopt [0]] - |--> -- - |-- type - | |-- enum - | | |--> OptionType::opt_endofopt [opt_endofopt - | | [0]] - | |-- opt_name -> opt_endofopt - | |-- opt_value -> 0 - |-- length -> 0 + | |-- OptionType::if_tsresol [if_tsresol [9]] + | | |--> -- + | | |-- type + | | | |-- enum -> OptionType::if_tsresol [if_tsresol [9]] + | | | |-- opt_name -> if_tsresol + | | | |-- opt_value -> 9 + | | |-- length -> 1 + | | |-- resolution -> 1000000 + | |-- OptionType::opt_endofopt [opt_endofopt [0]] + | |--> -- + | |-- type + | | |-- enum + | | | |--> OptionType::opt_endofopt [opt_endofopt + | | | [0]] + | | |-- opt_name -> opt_endofopt + | | |-- opt_value -> 0 + | |-- length -> 0 + |-- packet -> NIL Frame 1 |-- type -> BlockType::Enhanced_Packet_Block [6] @@ -44,8 +46,8 @@ Frame 1 |-- section_number -> 1 |-- number -> 1 |-- interface_id -> 0 - |-- timestamp -> 2004-12-06T03:16:24.317453+08:00 - |-- timestamp_epoch -> 1102302984.317453 + |-- timestamp -> 2004-12-05T19:16:24.317453+00:00 + |-- timestamp_epoch -> 1102274184.317453 |-- captured_len -> 314 |-- original_len -> 314 |-- options -> NIL @@ -56,60 +58,118 @@ Frame 1 | | |--> EtherType::Internet_Protocol_version_4 | | [2048] | |-- ipv4 - | |-- version -> 4 - | |-- hdr_len -> 20 - | |-- tos - | | |-- pre -> ToSPrecedence::Routine [0] - | | |-- del -> ToSDelay::NORMAL [0] - | | |-- thr -> ToSThroughput::NORMAL [0] - | | |-- rel -> ToSReliability::NORMAL [0] - | | |-- ecn -> ToSECN::Not_ECT [0] - | |-- len -> 300 - | |-- id -> 43062 - | |-- flags - | | |-- df -> False - | | |-- mf -> False - | |-- offset -> 0 - | |-- ttl -> 250.0 - | |-- protocol -> TransType::UDP [17] - | |-- checksum -> 17 8b - | |-- src -> 0.0.0.0 - | |-- dst -> 255.255.255.255 - | |-- udp - | |-- srcport - | | |-- enum -> AppType::bootpc [bootpc [68 - tcp|udp]] - | | |-- svc -> bootpc - | | |-- port -> 68 - | | |-- proto -> TransportProtocol::tcp|udp [3] - | |-- dstport - | | |-- enum -> AppType::bootps [bootps [67 - tcp|udp]] - | | |-- svc -> bootps - | | |-- port -> 67 - | | |-- proto -> TransportProtocol::tcp|udp [3] - | |-- len -> 280 - | |-- checksum -> 59 1f - | |-- raw - | |-- protocol -> NIL - | |-- packet - | | |--> 01 01 06 00 00 00 3d 1d 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 0b 82 01 - | | fc 42 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 63 82 53 63 - | | 35 01 01 3d 07 01 00 0b 82 01 fc 42 32 04 00 00 - | | 00 00 37 04 01 03 06 2a ff 00 00 00 00 00 00 00 - | |-- error -> NIL + | | |-- version -> 4 + | | |-- hdr_len -> 20 + | | |-- tos + | | | |-- pre -> ToSPrecedence::Routine [0] + | | | |-- del -> ToSDelay::NORMAL [0] + | | | |-- thr -> ToSThroughput::NORMAL [0] + | | | |-- rel -> ToSReliability::NORMAL [0] + | | | |-- ecn -> ToSECN::Not_ECT [0] + | | |-- len -> 300 + | | |-- id -> 43062 + | | |-- flags + | | | |-- df -> False + | | | |-- mf -> False + | | |-- offset -> 0 + | | |-- ttl -> 250.0 + | | |-- protocol -> TransType::UDP [17] + | | |-- checksum -> 17 8b + | | |-- src -> 0.0.0.0 + | | |-- dst -> 255.255.255.255 + | | |-- udp + | | | |-- srcport + | | | | |-- enum -> AppType::bootpc [bootpc [68 - tcp|udp]] + | | | | |-- svc -> bootpc + | | | | |-- port -> 68 + | | | | |-- proto -> TransportProtocol::tcp|udp [3] + | | | |-- dstport + | | | | |-- enum -> AppType::bootps [bootps [67 - tcp|udp]] + | | | | |-- svc -> bootps + | | | | |-- port -> 67 + | | | | |-- proto -> TransportProtocol::tcp|udp [3] + | | | |-- len -> 280 + | | | |-- checksum -> 59 1f + | | | |-- raw + | | | | |-- protocol -> NIL + | | | | |-- error -> NIL + | | | | |-- packet + | | | | |--> 01 01 06 00 00 00 3d 1d 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 0b 82 01 + | | | | fc 42 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 63 82 53 63 + | | | | 35 01 01 3d 07 01 00 0b 82 01 fc 42 32 04 00 00 + | | | | 00 00 37 04 01 03 06 2a ff 00 00 00 00 00 00 00 + | | | |-- packet + | | | |--> 01 01 06 00 00 00 3d 1d 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 0b 82 01 + | | | fc 42 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 63 82 53 63 + | | | 35 01 01 3d 07 01 00 0b 82 01 fc 42 32 04 00 00 + | | | 00 00 37 04 01 03 06 2a ff 00 00 00 00 00 00 00 + | | |-- packet + | | |--> 00 44 00 43 01 18 59 1f 01 01 06 00 00 00 3d 1d + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 0b 82 01 fc 42 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 63 82 53 63 35 01 01 3d 07 01 00 0b + | | 82 01 fc 42 32 04 00 00 00 00 37 04 01 03 06 2a + | | ff 00 00 00 00 00 00 00 + | |-- packet + | |--> 45 00 01 2c a8 36 00 00 fa 11 17 8b 00 00 00 00 + | ff ff ff ff 00 44 00 43 01 18 59 1f 01 01 06 00 + | 00 00 3d 1d 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 0b 82 01 fc 42 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 63 82 53 63 35 01 01 3d + | 07 01 00 0b 82 01 fc 42 32 04 00 00 00 00 37 04 + | 01 03 06 2a ff 00 00 00 00 00 00 00 |-- protocols -> Ethernet:IPv4:UDP:Raw + |-- packet -> NIL Frame 2 |-- type -> BlockType::Enhanced_Packet_Block [6] @@ -117,8 +177,8 @@ Frame 2 |-- section_number -> 1 |-- number -> 2 |-- interface_id -> 0 - |-- timestamp -> 2004-12-06T03:16:24.317748+08:00 - |-- timestamp_epoch -> 1102302984.317748 + |-- timestamp -> 2004-12-05T19:16:24.317748+00:00 + |-- timestamp_epoch -> 1102274184.317748 |-- captured_len -> 342 |-- original_len -> 342 |-- options -> NIL @@ -129,62 +189,126 @@ Frame 2 | | |--> EtherType::Internet_Protocol_version_4 | | [2048] | |-- ipv4 - | |-- version -> 4 - | |-- hdr_len -> 20 - | |-- tos - | | |-- pre -> ToSPrecedence::Routine [0] - | | |-- del -> ToSDelay::NORMAL [0] - | | |-- thr -> ToSThroughput::NORMAL [0] - | | |-- rel -> ToSReliability::NORMAL [0] - | | |-- ecn -> ToSECN::Not_ECT [0] - | |-- len -> 328 - | |-- id -> 1093 - | |-- flags - | | |-- df -> False - | | |-- mf -> False - | |-- offset -> 0 - | |-- ttl -> 128.0 - | |-- protocol -> TransType::UDP [17] - | |-- checksum -> 00 00 - | |-- src -> 192.168.0.1 - | |-- dst -> 192.168.0.10 - | |-- udp - | |-- srcport - | | |-- enum -> AppType::bootps [bootps [67 - tcp|udp]] - | | |-- svc -> bootps - | | |-- port -> 67 - | | |-- proto -> TransportProtocol::tcp|udp [3] - | |-- dstport - | | |-- enum -> AppType::bootpc [bootpc [68 - tcp|udp]] - | | |-- svc -> bootpc - | | |-- port -> 68 - | | |-- proto -> TransportProtocol::tcp|udp [3] - | |-- len -> 308 - | |-- checksum -> 22 33 - | |-- raw - | |-- protocol -> NIL - | |-- packet - | | |--> 02 01 06 00 00 00 3d 1d 00 00 00 00 00 00 00 00 - | | c0 a8 00 0a c0 a8 00 01 00 00 00 00 00 0b 82 01 - | | fc 42 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 63 82 53 63 - | | 35 01 02 01 04 ff ff ff 00 3a 04 00 00 07 08 3b - | | 04 00 00 0c 4e 33 04 00 00 0e 10 36 04 c0 a8 00 - | | 01 ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 - | |-- error -> NIL + | | |-- version -> 4 + | | |-- hdr_len -> 20 + | | |-- tos + | | | |-- pre -> ToSPrecedence::Routine [0] + | | | |-- del -> ToSDelay::NORMAL [0] + | | | |-- thr -> ToSThroughput::NORMAL [0] + | | | |-- rel -> ToSReliability::NORMAL [0] + | | | |-- ecn -> ToSECN::Not_ECT [0] + | | |-- len -> 328 + | | |-- id -> 1093 + | | |-- flags + | | | |-- df -> False + | | | |-- mf -> False + | | |-- offset -> 0 + | | |-- ttl -> 128.0 + | | |-- protocol -> TransType::UDP [17] + | | |-- checksum -> 00 00 + | | |-- src -> 192.168.0.1 + | | |-- dst -> 192.168.0.10 + | | |-- udp + | | | |-- srcport + | | | | |-- enum -> AppType::bootps [bootps [67 - tcp|udp]] + | | | | |-- svc -> bootps + | | | | |-- port -> 67 + | | | | |-- proto -> TransportProtocol::tcp|udp [3] + | | | |-- dstport + | | | | |-- enum -> AppType::bootpc [bootpc [68 - tcp|udp]] + | | | | |-- svc -> bootpc + | | | | |-- port -> 68 + | | | | |-- proto -> TransportProtocol::tcp|udp [3] + | | | |-- len -> 308 + | | | |-- checksum -> 22 33 + | | | |-- raw + | | | | |-- protocol -> NIL + | | | | |-- error -> NIL + | | | | |-- packet + | | | | |--> 02 01 06 00 00 00 3d 1d 00 00 00 00 00 00 00 00 + | | | | c0 a8 00 0a c0 a8 00 01 00 00 00 00 00 0b 82 01 + | | | | fc 42 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 63 82 53 63 + | | | | 35 01 02 01 04 ff ff ff 00 3a 04 00 00 07 08 3b + | | | | 04 00 00 0c 4e 33 04 00 00 0e 10 36 04 c0 a8 00 + | | | | 01 ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 + | | | |-- packet + | | | |--> 02 01 06 00 00 00 3d 1d 00 00 00 00 00 00 00 00 + | | | c0 a8 00 0a c0 a8 00 01 00 00 00 00 00 0b 82 01 + | | | fc 42 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 63 82 53 63 + | | | 35 01 02 01 04 ff ff ff 00 3a 04 00 00 07 08 3b + | | | 04 00 00 0c 4e 33 04 00 00 0e 10 36 04 c0 a8 00 + | | | 01 ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 + | | |-- packet + | | |--> 00 43 00 44 01 34 22 33 02 01 06 00 00 00 3d 1d + | | 00 00 00 00 00 00 00 00 c0 a8 00 0a c0 a8 00 01 + | | 00 00 00 00 00 0b 82 01 fc 42 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 63 82 53 63 35 01 02 01 04 ff ff ff + | | 00 3a 04 00 00 07 08 3b 04 00 00 0c 4e 33 04 00 + | | 00 0e 10 36 04 c0 a8 00 01 ff 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 + | |-- packet + | |--> 45 00 01 48 04 45 00 00 80 11 00 00 c0 a8 00 01 + | c0 a8 00 0a 00 43 00 44 01 34 22 33 02 01 06 00 + | 00 00 3d 1d 00 00 00 00 00 00 00 00 c0 a8 00 0a + | c0 a8 00 01 00 00 00 00 00 0b 82 01 fc 42 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 63 82 53 63 35 01 02 01 + | 04 ff ff ff 00 3a 04 00 00 07 08 3b 04 00 00 0c + | 4e 33 04 00 00 0e 10 36 04 c0 a8 00 01 ff 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 |-- protocols -> Ethernet:IPv4:UDP:Raw + |-- packet -> NIL Frame 3 |-- type -> BlockType::Enhanced_Packet_Block [6] @@ -192,8 +316,8 @@ Frame 3 |-- section_number -> 1 |-- number -> 3 |-- interface_id -> 0 - |-- timestamp -> 2004-12-06T03:16:24.387484+08:00 - |-- timestamp_epoch -> 1102302984.387484 + |-- timestamp -> 2004-12-05T19:16:24.387484+00:00 + |-- timestamp_epoch -> 1102274184.387484 |-- captured_len -> 314 |-- original_len -> 314 |-- options -> NIL @@ -204,60 +328,118 @@ Frame 3 | | |--> EtherType::Internet_Protocol_version_4 | | [2048] | |-- ipv4 - | |-- version -> 4 - | |-- hdr_len -> 20 - | |-- tos - | | |-- pre -> ToSPrecedence::Routine [0] - | | |-- del -> ToSDelay::NORMAL [0] - | | |-- thr -> ToSThroughput::NORMAL [0] - | | |-- rel -> ToSReliability::NORMAL [0] - | | |-- ecn -> ToSECN::Not_ECT [0] - | |-- len -> 300 - | |-- id -> 43063 - | |-- flags - | | |-- df -> False - | | |-- mf -> False - | |-- offset -> 0 - | |-- ttl -> 250.0 - | |-- protocol -> TransType::UDP [17] - | |-- checksum -> 17 8a - | |-- src -> 0.0.0.0 - | |-- dst -> 255.255.255.255 - | |-- udp - | |-- srcport - | | |-- enum -> AppType::bootpc [bootpc [68 - tcp|udp]] - | | |-- svc -> bootpc - | | |-- port -> 68 - | | |-- proto -> TransportProtocol::tcp|udp [3] - | |-- dstport - | | |-- enum -> AppType::bootps [bootps [67 - tcp|udp]] - | | |-- svc -> bootps - | | |-- port -> 67 - | | |-- proto -> TransportProtocol::tcp|udp [3] - | |-- len -> 280 - | |-- checksum -> 9f bd - | |-- raw - | |-- protocol -> NIL - | |-- packet - | | |--> 01 01 06 00 00 00 3d 1e 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 0b 82 01 - | | fc 42 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 63 82 53 63 - | | 35 01 03 3d 07 01 00 0b 82 01 fc 42 32 04 c0 a8 - | | 00 0a 36 04 c0 a8 00 01 37 04 01 03 06 2a ff 00 - | |-- error -> NIL + | | |-- version -> 4 + | | |-- hdr_len -> 20 + | | |-- tos + | | | |-- pre -> ToSPrecedence::Routine [0] + | | | |-- del -> ToSDelay::NORMAL [0] + | | | |-- thr -> ToSThroughput::NORMAL [0] + | | | |-- rel -> ToSReliability::NORMAL [0] + | | | |-- ecn -> ToSECN::Not_ECT [0] + | | |-- len -> 300 + | | |-- id -> 43063 + | | |-- flags + | | | |-- df -> False + | | | |-- mf -> False + | | |-- offset -> 0 + | | |-- ttl -> 250.0 + | | |-- protocol -> TransType::UDP [17] + | | |-- checksum -> 17 8a + | | |-- src -> 0.0.0.0 + | | |-- dst -> 255.255.255.255 + | | |-- udp + | | | |-- srcport + | | | | |-- enum -> AppType::bootpc [bootpc [68 - tcp|udp]] + | | | | |-- svc -> bootpc + | | | | |-- port -> 68 + | | | | |-- proto -> TransportProtocol::tcp|udp [3] + | | | |-- dstport + | | | | |-- enum -> AppType::bootps [bootps [67 - tcp|udp]] + | | | | |-- svc -> bootps + | | | | |-- port -> 67 + | | | | |-- proto -> TransportProtocol::tcp|udp [3] + | | | |-- len -> 280 + | | | |-- checksum -> 9f bd + | | | |-- raw + | | | | |-- protocol -> NIL + | | | | |-- error -> NIL + | | | | |-- packet + | | | | |--> 01 01 06 00 00 00 3d 1e 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 0b 82 01 + | | | | fc 42 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 63 82 53 63 + | | | | 35 01 03 3d 07 01 00 0b 82 01 fc 42 32 04 c0 a8 + | | | | 00 0a 36 04 c0 a8 00 01 37 04 01 03 06 2a ff 00 + | | | |-- packet + | | | |--> 01 01 06 00 00 00 3d 1e 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 0b 82 01 + | | | fc 42 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 63 82 53 63 + | | | 35 01 03 3d 07 01 00 0b 82 01 fc 42 32 04 c0 a8 + | | | 00 0a 36 04 c0 a8 00 01 37 04 01 03 06 2a ff 00 + | | |-- packet + | | |--> 00 44 00 43 01 18 9f bd 01 01 06 00 00 00 3d 1e + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 0b 82 01 fc 42 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 63 82 53 63 35 01 03 3d 07 01 00 0b + | | 82 01 fc 42 32 04 c0 a8 00 0a 36 04 c0 a8 00 01 + | | 37 04 01 03 06 2a ff 00 + | |-- packet + | |--> 45 00 01 2c a8 37 00 00 fa 11 17 8a 00 00 00 00 + | ff ff ff ff 00 44 00 43 01 18 9f bd 01 01 06 00 + | 00 00 3d 1e 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 0b 82 01 fc 42 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 63 82 53 63 35 01 03 3d + | 07 01 00 0b 82 01 fc 42 32 04 c0 a8 00 0a 36 04 + | c0 a8 00 01 37 04 01 03 06 2a ff 00 |-- protocols -> Ethernet:IPv4:UDP:Raw + |-- packet -> NIL Frame 4 |-- type -> BlockType::Enhanced_Packet_Block [6] @@ -265,8 +447,8 @@ Frame 4 |-- section_number -> 1 |-- number -> 4 |-- interface_id -> 0 - |-- timestamp -> 2004-12-06T03:16:24.387798+08:00 - |-- timestamp_epoch -> 1102302984.387798 + |-- timestamp -> 2004-12-05T19:16:24.387798+00:00 + |-- timestamp_epoch -> 1102274184.387798 |-- captured_len -> 342 |-- original_len -> 342 |-- options -> NIL @@ -277,59 +459,123 @@ Frame 4 | | |--> EtherType::Internet_Protocol_version_4 | | [2048] | |-- ipv4 - | |-- version -> 4 - | |-- hdr_len -> 20 - | |-- tos - | | |-- pre -> ToSPrecedence::Routine [0] - | | |-- del -> ToSDelay::NORMAL [0] - | | |-- thr -> ToSThroughput::NORMAL [0] - | | |-- rel -> ToSReliability::NORMAL [0] - | | |-- ecn -> ToSECN::Not_ECT [0] - | |-- len -> 328 - | |-- id -> 1094 - | |-- flags - | | |-- df -> False - | | |-- mf -> False - | |-- offset -> 0 - | |-- ttl -> 128.0 - | |-- protocol -> TransType::UDP [17] - | |-- checksum -> 00 00 - | |-- src -> 192.168.0.1 - | |-- dst -> 192.168.0.10 - | |-- udp - | |-- srcport - | | |-- enum -> AppType::bootps [bootps [67 - tcp|udp]] - | | |-- svc -> bootps - | | |-- port -> 67 - | | |-- proto -> TransportProtocol::tcp|udp [3] - | |-- dstport - | | |-- enum -> AppType::bootpc [bootpc [68 - tcp|udp]] - | | |-- svc -> bootpc - | | |-- port -> 68 - | | |-- proto -> TransportProtocol::tcp|udp [3] - | |-- len -> 308 - | |-- checksum -> df db - | |-- raw - | |-- protocol -> NIL - | |-- packet - | | |--> 02 01 06 00 00 00 3d 1e 00 00 00 00 00 00 00 00 - | | c0 a8 00 0a 00 00 00 00 00 00 00 00 00 0b 82 01 - | | fc 42 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 63 82 53 63 - | | 35 01 05 3a 04 00 00 07 08 3b 04 00 00 0c 4e 33 - | | 04 00 00 0e 10 36 04 c0 a8 00 01 01 04 ff ff ff - | | 00 ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - | | 00 00 00 00 00 00 00 00 00 00 00 00 - | |-- error -> NIL + | | |-- version -> 4 + | | |-- hdr_len -> 20 + | | |-- tos + | | | |-- pre -> ToSPrecedence::Routine [0] + | | | |-- del -> ToSDelay::NORMAL [0] + | | | |-- thr -> ToSThroughput::NORMAL [0] + | | | |-- rel -> ToSReliability::NORMAL [0] + | | | |-- ecn -> ToSECN::Not_ECT [0] + | | |-- len -> 328 + | | |-- id -> 1094 + | | |-- flags + | | | |-- df -> False + | | | |-- mf -> False + | | |-- offset -> 0 + | | |-- ttl -> 128.0 + | | |-- protocol -> TransType::UDP [17] + | | |-- checksum -> 00 00 + | | |-- src -> 192.168.0.1 + | | |-- dst -> 192.168.0.10 + | | |-- udp + | | | |-- srcport + | | | | |-- enum -> AppType::bootps [bootps [67 - tcp|udp]] + | | | | |-- svc -> bootps + | | | | |-- port -> 67 + | | | | |-- proto -> TransportProtocol::tcp|udp [3] + | | | |-- dstport + | | | | |-- enum -> AppType::bootpc [bootpc [68 - tcp|udp]] + | | | | |-- svc -> bootpc + | | | | |-- port -> 68 + | | | | |-- proto -> TransportProtocol::tcp|udp [3] + | | | |-- len -> 308 + | | | |-- checksum -> df db + | | | |-- raw + | | | | |-- protocol -> NIL + | | | | |-- error -> NIL + | | | | |-- packet + | | | | |--> 02 01 06 00 00 00 3d 1e 00 00 00 00 00 00 00 00 + | | | | c0 a8 00 0a 00 00 00 00 00 00 00 00 00 0b 82 01 + | | | | fc 42 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 63 82 53 63 + | | | | 35 01 05 3a 04 00 00 07 08 3b 04 00 00 0c 4e 33 + | | | | 04 00 00 0e 10 36 04 c0 a8 00 01 01 04 ff ff ff + | | | | 00 ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | | 00 00 00 00 00 00 00 00 00 00 00 00 + | | | |-- packet + | | | |--> 02 01 06 00 00 00 3d 1e 00 00 00 00 00 00 00 00 + | | | c0 a8 00 0a 00 00 00 00 00 00 00 00 00 0b 82 01 + | | | fc 42 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 63 82 53 63 + | | | 35 01 05 3a 04 00 00 07 08 3b 04 00 00 0c 4e 33 + | | | 04 00 00 0e 10 36 04 c0 a8 00 01 01 04 ff ff ff + | | | 00 ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | | 00 00 00 00 00 00 00 00 00 00 00 00 + | | |-- packet + | | |--> 00 43 00 44 01 34 df db 02 01 06 00 00 00 3d 1e + | | 00 00 00 00 00 00 00 00 c0 a8 00 0a 00 00 00 00 + | | 00 00 00 00 00 0b 82 01 fc 42 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 63 82 53 63 35 01 05 3a 04 00 00 07 + | | 08 3b 04 00 00 0c 4e 33 04 00 00 0e 10 36 04 c0 + | | a8 00 01 01 04 ff ff ff 00 ff 00 00 00 00 00 00 + | | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | | 00 00 00 00 + | |-- packet + | |--> 45 00 01 48 04 46 00 00 80 11 00 00 c0 a8 00 01 + | c0 a8 00 0a 00 43 00 44 01 34 df db 02 01 06 00 + | 00 00 3d 1e 00 00 00 00 00 00 00 00 c0 a8 00 0a + | 00 00 00 00 00 00 00 00 00 0b 82 01 fc 42 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 63 82 53 63 35 01 05 3a + | 04 00 00 07 08 3b 04 00 00 0c 4e 33 04 00 00 0e + | 10 36 04 c0 a8 00 01 01 04 ff ff ff 00 ff 00 00 + | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + | 00 00 00 00 00 00 00 00 |-- protocols -> Ethernet:IPv4:UDP:Raw + |-- packet -> NIL diff --git a/examples/legacy_smoke/Makefile b/examples/legacy_smoke/Makefile index baf5fc364e..e7b6bb4bd3 100644 --- a/examples/legacy_smoke/Makefile +++ b/examples/legacy_smoke/Makefile @@ -1,7 +1,28 @@ -.PHONY: +.PHONY: fixtures profile +#: Interpreter to run the demos with. Override for a virtualenv, e.g. +#: `make fixtures PYTHON=../../.venv/bin/python`. +PYTHON ?= python + +#: Timezone the committed fixtures are generated in. Pinned because pcapkit renders +#: frame timestamps in the host's local zone, so an unpinned run rewrites every +#: timestamp line with wherever it happened to be run. UTC is also the only zone in +#: which PCAP-NG's `timestamp_epoch` comes out as the true UNIX epoch -- see the +#: README for the reason. +FIXTURE_TZ ?= UTC + +## Regenerate the four committed fixtures in ../captures/. +## out.json, out.plist, out.txt <- test_extractor.py, from ../captures/in.pcap +## pcapng.txt <- test_pcapng.py, from ../captures/dhcp.pcapng +## Both inputs are committed, so this needs no `make samples` first. +fixtures: + TZ=$(FIXTURE_TZ) $(PYTHON) test_extractor.py + TZ=$(FIXTURE_TZ) $(PYTHON) test_pcapng.py + @echo 'regenerated ../captures/{out.json,out.plist,out.txt,pcapng.txt}' + +## Profile one extraction and render the call graph. profile: mkdir -p temp - python test_profile.py + $(PYTHON) test_profile.py gprof2dot -f pstats temp/parse_pcap.pstats | dot -Tpng -o temp/parse_pcap.png snakeviz temp/parse_pcap.pstats diff --git a/examples/legacy_smoke/README.md b/examples/legacy_smoke/README.md index 319debaf6b..205fe2759a 100644 --- a/examples/legacy_smoke/README.md +++ b/examples/legacy_smoke/README.md @@ -1,13 +1,107 @@ -# Test Samples - -  Here we provide several test samples. Though the original PCAP files are not uploaded due to restrictions on file size of GitHub, you may still easily get a simple but thorough view of `pcapkit`, either on how to use it or on what it can do. - - - [`test_extraction`](https://github.com/JarryShaw/pcapkit/tree/main/examples/legacy_smoke/test_extraction.py) -- samples on usage of `pcapkit.extract`, which extracts a PCAP file and dumps to a specificly formatted output file - - [`test_ipv6`](https://github.com/JarryShaw/pcapkit/tree/main/examples/legacy_smoke/test_ipv6.py) -- samples on extraction of IPv6 packets, whilst dumping a tree-view text file - - [`test_http`](https://github.com/JarryShaw/pcapkit/tree/main/examples/legacy_smoke/test_http.py) -- samples on extraction of HTTP packets, whilst checking if HTTP is `in` the frame - - [`test_reassembly`](https://github.com/JarryShaw/pcapkit/tree/main/examples/legacy_smoke/test_reassembly.py) -- samples on reassembly of TCP payloads, whilst writing the reassembled payloads into an output file - - [`test_analyse`](https://github.com/JarryShaw/pcapkit/tree/main/examples/legacy_smoke/test_analyse.py) -- samples on analysis of application layer after reassembly, which writes the extracted HTTP frame to `stdout` - - [`test_time`](https://github.com/JarryShaw/pcapkit/tree/main/examples/legacy_smoke/test_time.py) -- samples on a minimum usage of `pcapkit.extract`, whilst timing the whole procedure - - [`test_trace`](https://github.com/JarryShaw/pcapkit/tree/main/examples/legacy_smoke/test_trace.py) -- samples on tracing TCP flows - - [`test_engine`](https://github.com/JarryShaw/pcapkit/tree/main/examples/legacy_smoke/test_engine.py) -- samples on different extraction engines - - [`test_profile`](https://github.com/JarryShaw/pcapkit/tree/main/examples/legacy_smoke/test_profile.py) -- samples on performance analysis of `pcapkit` +# Demonstration Scripts + +  A tour of `pcapkit` by example: each script here does one thing and prints or dumps the +result, so you can get a thorough view of the library either on how to use it or on what it +can do. They are demos rather than tests -- `pytest` does not collect this directory +(`testpaths = ["tests"]`) and nothing in CI runs them, so they are also where API drift goes +unnoticed the longest. Run them after changing anything public. + +## Running them + +  Every script reads its capture with a path relative to its own directory, so **run them +from inside `examples/legacy_smoke/`**, not from the repository root: + +```shell +cd examples/legacy_smoke +python test_basic.py +``` + +  The captures live in `../captures/`. Only `in.pcap` and `dhcp.pcapng` are committed; the +rest are generated, so build them once before running anything else: + +```shell +python ../samples/make_samples.py # or: make samples, from the repository root +``` + +## The scripts + +| Script | What it demonstrates | +|---|---| +| [`test_basic`](test_basic.py) | the smallest useful call -- extract `in.pcap` to a tree-view text file | +| [`test_extractor`](test_extractor.py) | `pcapkit.extract` dumping the same capture as plist, JSON and tree | +| [`test_file`](test_file.py) | reading from an already-open binary file object rather than a path | +| [`test_api`](test_api.py) | most of the keyword surface at once: per-frame files, reassembly and flow tracing | +| [`test_tcp`](test_tcp.py) | extraction of TCP packets | +| [`test_ipv6`](test_ipv6.py) | extraction of IPv6 packets, one output file per frame | +| [`test_pcapng`](test_pcapng.py) | extraction of a PCAP-NG capture, which uses a different engine | +| [`test_http`](test_http.py) | iterating frames manually and testing `pcapkit.HTTP in frame` | +| [`test_reassembly`](test_reassembly.py) | TCP payload reassembly, writing the reassembled datagrams out | +| [`test_ip_reasm`](test_ip_reasm.py) | IPv4 fragment reassembly | +| [`test_ipv6_reasm`](test_ipv6_reasm.py) | IPv6 fragment reassembly | +| [`test_analyse`](test_analyse.py) | analysis of the application layer *after* reassembly, printing the recovered HTTP messages | +| [`test_trace`](test_trace.py) | tracing TCP flows and dumping the flow index | +| [`test_engine`](test_engine.py) | the same capture through each extraction engine, side by side | +| [`test_time`](test_time.py) | timing each engine, reported as milliseconds per packet | +| [`test_profile`](test_profile.py) | cProfile stats for one extraction; `make profile` renders the call graph | +| [`test_perf`](test_perf.py) | the same comparison under the `pyperf` benchmark harness | +| [`test_stream`](test_stream.py) | extracting a live capture streamed from `tcpdump` on stdin | +| [`test_stream_askpass`](test_stream_askpass.py) | the same, with `sudo -A` for a non-interactive password | + +  `_engine_support.py` is not a demo -- it is the shared helper the engine demos use to +work out whether an engine can run on this host. + +## What needs more than pcapkit + +  Most of these run with nothing but `pcapkit`. These do not: + +- **`test_engine`, `test_time`, `test_perf`** exercise the `dpkt`, `scapy` and `pyshark` + engines. Those are optional packages, and `pyshark` additionally drives Wireshark's + `tshark` binary. An engine that is missing is reported as skipped, with the reason, and the + rest still run -- see `_engine_support.py`. Two things worth knowing: + - `pyshark` 0.6 does not work on Python 3.14 at all. It asks + `asyncio.get_event_loop_policy().get_event_loop()` for a loop on a thread that has none, + which 3.14 no longer creates implicitly, so every extraction through it raises + `RuntimeError: There is no current event loop in thread 'MainThread'` before `tshark` is + even reached. That is a pyshark bug, not a pcapkit one, and there is nothing to configure + around it. + - When an engine's *package* is missing, `pcapkit.extract` does not fail. It warns and + falls back to pcapkit's own parser, so the extraction succeeds under the wrong engine. + The demos name the driver that actually ran, so a fallback is visible rather than being + reported as a healthy result. +- **`test_perf`** needs the `pyperf` harness, which `pcapkit` does not depend on: + `python -m pip install pyperf`. Without it the script says so and stops. `test_time.py` + does the same comparison with no extra dependency. +- **`test_profile`**'s `make profile` target needs `gprof2dot`, `graphviz` and `snakeviz` to + render the call graph. The script itself only needs `pcapkit`. +- **`test_stream`, `test_stream_askpass`** run `sudo tcpdump` against a live interface, so + they need root and cannot run unattended. `INTERFACE` at the top of each is `en0` (macOS); + on Linux it is usually `eth0` or `wlan0`. They buffer the live capture into a temporary + file -- never into `../captures/`, which holds generated captures the test suite pins. + +## Regenerating the committed fixtures + +  Four files in `../captures/` are committed outputs rather than inputs, and they are +produced by two of the scripts here. To refresh them after a change to how `pcapkit` renders +a capture: + +```shell +cd examples/legacy_smoke && make fixtures +``` + +  That is the whole recipe. It runs, equivalently: + +```shell +TZ=UTC python test_extractor.py # ../captures/out.json, out.plist, out.txt <- in.pcap +TZ=UTC python test_pcapng.py # ../captures/pcapng.txt <- dhcp.pcapng +``` + +  Both inputs are committed, so this works on a fresh clone with no `make samples` first. +Use `make fixtures PYTHON=../../.venv/bin/python` to pick a specific interpreter. + +  **`TZ=UTC` is not decoration.** `pcapkit` renders frame timestamps in the host's local +zone, so an unpinned run rewrites every timestamp line in all four files with wherever it +happened to be run -- which is how these fixtures came to disagree with each other, the PCAP +three having been generated at UTC-05:00 and `pcapng.txt` at UTC+08:00. Pinning UTC makes the +output reproducible on any host. It also happens to be the only zone in which PCAP-NG's +`timestamp_epoch` is the true UNIX epoch: `PCAPNG._read_timestamp` adds the zone's UTC offset +to the value it returns, so a fixture generated anywhere else bakes in that offset. diff --git a/examples/legacy_smoke/_engine_support.py b/examples/legacy_smoke/_engine_support.py new file mode 100644 index 0000000000..74bf7fb71a --- /dev/null +++ b/examples/legacy_smoke/_engine_support.py @@ -0,0 +1,151 @@ +# -*- coding: utf-8 -*- +"""Which extraction engines can actually run on this host. + +``pcapkit`` ships four extraction engines and three of them lean on something the +host may simply not have: ``dpkt``, ``scapy`` and ``pyshark`` are optional +third-party packages, and ``pyshark`` additionally drives the external ``tshark`` +binary from Wireshark. On top of that, ``pyshark`` 0.6 calls +``asyncio.get_event_loop_policy().get_event_loop()`` on a thread with no running +loop. Creating one implicitly there was deprecated years ago and Python 3.14 no +longer does it, raising ``RuntimeError: There is no current event loop in thread +'MainThread'`` instead -- so on 3.14 ``pyshark`` cannot be used at all, whatever else +is installed. + +None of those is a ``pcapkit`` defect, and the demos in this directory should not +die on any of them. So they call :func:`unavailable` on whatever the engine raised: +it returns a human-readable reason when the engine is merely unavailable here, and +:data:`None` when the failure is real and must be allowed to propagate. + +There is a quieter failure to account for as well. When an engine's package is not +installed at all, ``Extractor`` does *not* raise -- it emits an ``EngineWarning`` +and falls back to pcapkit's own parser, so the extraction succeeds and reports a +frame count that has nothing to do with the engine that was asked for. +:func:`ran_as_asked` is how the demos tell the two apart. + +This module is a helper for the demos, not a demo itself. + +""" + +from __future__ import annotations + +import sys +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from pcapkit.foundation.extraction import Extractor + +__all__ = ['ENGINES', 'unavailable', 'ran_as_asked', 'report', 'preflight'] + +#: The extraction engines ``pcapkit.extract(engine=...)`` accepts, in the order the +#: demos exercise them. ``'default'`` is pcapkit's own parser (also spelled +#: ``'pcapkit'``) and is the only one with no third-party requirement; further +#: engines can be added at runtime with +#: :func:`pcapkit.foundation.registry.foundation.register_extractor_engine`. +ENGINES = ('default', 'pyshark', 'scapy', 'dpkt') + +#: ``__engine_name__`` of the driver each ``engine=`` value should end up using. +#: ``'default'`` and ``'pcapkit'`` pick their parser from the file's magic number, +#: so either of two names is correct for them. +ENGINE_DRIVERS = { + 'default': ('PCAP', 'PCAP-NG'), + 'pcapkit': ('PCAP', 'PCAP-NG'), + 'dpkt': ('DPKT',), + 'scapy': ('Scapy',), + 'pyshark': ('PyShark',), +} + + +def unavailable(exc: 'Exception') -> 'str | None': + """Explain *exc* if it means the engine cannot run on this host. + + Args: + exc: Exception the engine raised. + + Returns: + A reason to report the engine as skipped, or :data:`None` if *exc* is a + genuine failure that the caller should re-raise. + + """ + # A missing optional package. pcapkit raises its own ModuleNotFound, which + # derives from ImportError, so one check covers both it and a plain import. + if isinstance(exc, ImportError): + return f'{exc.name or exc} is not installed' + + # pyshark needs Wireshark's tshark on PATH. Matched by name rather than + # imported, since pyshark itself may be the thing that is missing. + if type(exc).__name__ == 'TSharkNotFoundException': + return 'the tshark binary from Wireshark is not installed' + + # pyshark 0.6 on Python 3.14: it asks the event loop policy for the current + # loop on a thread that has none. Not something pcapkit can work around. + if isinstance(exc, RuntimeError) and 'event loop' in str(exc): + version = '.'.join(str(part) for part in sys.version_info[:3]) + return (f'{exc} -- pyshark asks for an implicit asyncio event loop, ' + f'which Python {version} no longer provides (pyshark bug, not pcapkit)') + + return None + + +def ran_as_asked(engine: 'str', extraction: 'Extractor') -> 'tuple[str, bool]': + """Which driver *extraction* really used, and whether it is the one asked for. + + Args: + engine: Engine name that was passed to ``pcapkit.extract``. + extraction: The resulting extractor. + + Returns: + The driver's ``__engine_name__`` and whether it matches *engine*. A + mismatch means the engine's package is not installed and ``Extractor`` + fell back to its own parser, having only warned about it. + + """ + driver = extraction.engine.__engine_name__ + return driver, driver in ENGINE_DRIVERS.get(engine, (engine,)) + + +def report(engine: 'str', detail: 'str') -> 'None': + """Print one line of an engine report. + + Args: + engine: Engine name. + detail: What happened, e.g. ``'6 frames'`` or ``'skipped -- ...'``. + + """ + print(f'{engine:>8}: {detail}', flush=True) + + +def preflight(engine: 'str', fin: 'str') -> 'str | None': + """Try *engine* once on *fin* and report whether it works here. + + Useful before a timing or benchmarking run, where the extraction itself is + repeated thousands of times and a failure on the first round would throw the + whole measurement away. + + Args: + engine: Engine name to try. + fin: Capture file to read. + + Returns: + :data:`None` if the engine works, else the reason it is unavailable. + + Raises: + Exception: Whatever the engine raised, if it is a real failure rather than + the engine being unavailable on this host. + + """ + import pcapkit # imported here so this module stays importable on its own + + try: + extraction = pcapkit.extract(fin=fin, store=False, nofile=True, verbose=False, + engine=engine) # type: ignore[arg-type] + except Exception as exc: # pylint: disable=broad-except + reason = unavailable(exc) + if reason is None: + raise + return reason + + driver, asked = ran_as_asked(engine, extraction) + if not asked: + return (f'its package is not installed -- pcapkit fell back to its own ' + f'{driver} parser, so timing it would measure the wrong thing') + return None diff --git a/examples/legacy_smoke/test_analyse.py b/examples/legacy_smoke/test_analyse.py index 765fd93fe6..2b017d8297 100644 --- a/examples/legacy_smoke/test_analyse.py +++ b/examples/legacy_smoke/test_analyse.py @@ -4,9 +4,14 @@ import pcapkit +# NOTE: ``reassembly=True`` is what turns reassembly on; ``tcp=True`` only selects +# which protocol to reassemble, and ``reasm_strict`` only tunes it. Without it the +# extraction runs to completion and then ``extraction.reassembly`` raises +# ``UnsupportedCall``, since the attribute is gated on the reassembly flag. extraction = pcapkit.extract( fin='../captures/http6.cap', # fout='../captures/http.txt', format='tree', - store=False, tcp=True, verbose=True, nofile=True, reasm_strict=True, extension=False + store=False, tcp=True, verbose=True, nofile=True, reassembly=True, + reasm_strict=True, extension=False ) # pprint.pprint(extraction.reassembly.tcp) print() diff --git a/examples/legacy_smoke/test_api.py b/examples/legacy_smoke/test_api.py index 3d254c9590..68f6f6af92 100644 --- a/examples/legacy_smoke/test_api.py +++ b/examples/legacy_smoke/test_api.py @@ -2,6 +2,10 @@ import pcapkit +# NOTE: ``ip``, ``tcp`` and ``reasm_strict`` are reassembly knobs and do nothing on +# their own -- ``reassembly=True`` is the flag that switches reassembly on, just as +# ``trace=True`` switches flow tracing on. ``tcp=True`` feeds both. json = pcapkit.extract(fin='../captures/http.pcap', fout='../captures/http', format='json', files=True, - store=True, verbose=True, ip=True, tcp=True, reasm_strict=False, trace=True, + store=True, verbose=True, reassembly=True, ip=True, tcp=True, + reasm_strict=False, trace=True, trace_format='json', trace_fout='../captures/trace') diff --git a/examples/legacy_smoke/test_engine.py b/examples/legacy_smoke/test_engine.py index fde59cf7be..c4e110751b 100644 --- a/examples/legacy_smoke/test_engine.py +++ b/examples/legacy_smoke/test_engine.py @@ -1,16 +1,45 @@ # -*- coding: utf-8 -*- +"""Extract one capture with each of pcapkit's extraction engines. + +Every engine is asked for the same tree-view dump of the same file, so the outputs +under ``../captures/engines/`` can be compared side by side. + +An engine that is not available on this host is reported as skipped, with the +reason, and the rest of the demo carries on -- see :mod:`_engine_support` for what +counts as unavailable. Anything else is a real failure and is left to propagate. + +Each line also names the driver that actually ran, because an engine whose package +is missing does not fail: ``Extractor`` warns and quietly uses pcapkit's own parser +instead, which would otherwise show up here as a healthy frame count. + +""" + +import os import pcapkit +from _engine_support import ENGINES, ran_as_asked, report, unavailable + +for engine in ENGINES: + fout = f'../captures/engines/{engine}.txt' + + try: + extraction = pcapkit.extract(fin='../captures/in.pcap', fout=fout, + format='tree', engine=engine) # type: ignore[arg-type] + except Exception as exc: # pylint: disable=broad-except + reason = unavailable(exc) + if reason is None: + raise + report(engine, f'skipped -- {reason}') -default = pcapkit.extract(fin='../captures/in.pcap', - fout='../captures/engines/default.txt', format='tree', engine='default') -pyshark = pcapkit.extract(fin='../captures/in.pcap', - fout='../captures/engines/pyshark.txt', format='tree', engine='pyshark') -scapy = pcapkit.extract(fin='../captures/in.pcap', - fout='../captures/engines/scapy.txt', format='tree', engine='scapy') -dpkt = pcapkit.extract(fin='../captures/in.pcap', - fout='../captures/engines/dpkt.txt', format='tree', engine='dpkt') - -# pipeline = pcapkit.extract(fin='../captures/in.pcap', -# nofile=True, engine='pipeline') -# server = pcapkit.extract(fin='../captures/in.pcap', nofile=True, engine='server') + # The dump file is opened before the engine runs, so a skipped engine + # leaves an empty one behind. Drop it: a 0-byte engines/pyshark.txt next + # to a full engines/default.txt reads as "pyshark parsed nothing". + if os.path.exists(fout) and os.path.getsize(fout) == 0: + os.remove(fout) + else: + driver, asked = ran_as_asked(engine, extraction) + if asked: + report(engine, f'{extraction.length} frames via {driver} -> {fout}') + else: + report(engine, f'its package is not installed -- pcapkit fell back to ' + f'{driver}; {extraction.length} frames -> {fout}') diff --git a/examples/legacy_smoke/test_perf.py b/examples/legacy_smoke/test_perf.py index e81444e50c..ffe6ab42e9 100644 --- a/examples/legacy_smoke/test_perf.py +++ b/examples/legacy_smoke/test_perf.py @@ -1,8 +1,37 @@ # -*- coding: utf-8 -*- +"""Benchmark ``pcapkit.extract`` across engines with pyperf. -import pyperf +``pyperf`` is not a pcapkit dependency -- it is a benchmarking harness this one demo +uses -- so it will not be present in a plain ``pip install pcapkit`` environment. +When it is missing the demo says how to get it and stops there rather than dying on +an import traceback. -from pcapkit import extract +An engine that is not available on this host is reported as skipped, with the +reason, and only the engines that work are handed to the benchmark runner: pyperf +re-runs each benchmark in worker processes dozens of times, so an engine that +raises would fail the whole run rather than just its own row. See +:mod:`_engine_support` for what counts as unavailable. + +""" + +import sys + +from _engine_support import ENGINES, preflight, report + +try: + import pyperf +except ImportError: + print('test_perf: skipped -- pyperf is not installed.\n' + '\n' + ' This demo needs the pyperf benchmarking harness, which pcapkit does\n' + ' not depend on. Install it into the same environment as pcapkit:\n' + '\n' + ' python -m pip install pyperf\n' + '\n' + ' For a timing run with no extra dependency, use test_time.py instead.') + sys.exit(0) + +from pcapkit import extract # noqa: E402 # pylint: disable=wrong-import-position def default() -> 'None': @@ -25,8 +54,25 @@ def pyshark() -> 'None': format='tree', engine='pyshark') +#: The benchmark for each engine name in :data:`_engine_support.ENGINES`. +BENCHMARKS = { + 'default': default, + 'pyshark': pyshark, + 'scapy': scapy, + 'dpkt': dpkt, +} + runner = pyperf.Runner() -runner.bench_func('default', default) -runner.bench_func('scapy', scapy) -runner.bench_func('dpkt', dpkt) -runner.bench_func('pyshark', pyshark) + +benched = 0 +for engine in ENGINES: + reason = preflight(engine, '../captures/in.pcap') + if reason is not None: + report(engine, f'skipped -- {reason}') + continue + + runner.bench_func(engine, BENCHMARKS[engine]) + benched += 1 + +if not benched: + print('test_perf: nothing to benchmark -- every engine was skipped above.') diff --git a/examples/legacy_smoke/test_profile.py b/examples/legacy_smoke/test_profile.py index 7fbcfeff5f..f341d03b32 100644 --- a/examples/legacy_smoke/test_profile.py +++ b/examples/legacy_smoke/test_profile.py @@ -1,9 +1,14 @@ # -*- coding: utf-8 -*- +"""Profile a ``pcapkit.extract`` run and write cProfile stats for ``make profile``.""" import cProfile +import os import pcapkit +#: Where cProfile writes its stats. ``make profile`` renders this into a call graph. +STATS = os.path.join('temp', 'parse_pcap.pstats') + def test() -> 'None': pcapkit.extract(fin='../captures/http.pcap', store=True, @@ -11,7 +16,14 @@ def test() -> 'None': if __name__ == '__main__': + # cProfile will not create the directory it dumps into, so `python + # test_profile.py` on a fresh checkout used to profile the whole run and then + # die with FileNotFoundError. `make profile` does mkdir first; the script + # should not need it to. + os.makedirs(os.path.dirname(STATS), exist_ok=True) + cProfile.run( 'test()', - 'temp/parse_pcap.pstats', + STATS, ) + print(f'test_profile: wrote {STATS}') diff --git a/examples/legacy_smoke/test_stream.py b/examples/legacy_smoke/test_stream.py index c0b4aab8da..78a00e4565 100644 --- a/examples/legacy_smoke/test_stream.py +++ b/examples/legacy_smoke/test_stream.py @@ -1,11 +1,31 @@ # -*- coding: utf-8 -*- +"""Extract a live capture streamed from ``tcpdump`` on stdin. +Needs root, since it shells out to ``sudo tcpdump``, so it cannot run unattended. +Use :file:`test_stream_askpass.py` where ``sudo`` is configured with an askpass +helper. + +""" + +import os import shlex import subprocess # nosec: B404 +import tempfile import pcapkit -with subprocess.Popen(shlex.split('sudo tcpdump -i en0 -s 0 -w - -U'), # nosec: B603 +#: Interface to capture on. ``en0`` is macOS; on Linux this is usually ``eth0`` +#: or ``wlan0`` -- see ``ip link`` or ``tcpdump -D``. +INTERFACE = 'en0' + +# NOTE: buffer_path must not point inside ../captures/. That directory holds generated +# captures -- ../captures/stream.pcap among them -- which the runtime tests read and +# pin byte for byte, so buffering a live capture over it would quietly break the +# test suite. Buffer into a throwaway temporary file instead. +BUFFER = os.path.join(tempfile.mkdtemp(prefix='pcapkit-stream-'), 'stream.pcap') +print(f'buffering the live capture to {BUFFER}') + +with subprocess.Popen(shlex.split(f'sudo tcpdump -i {INTERFACE} -s 0 -w - -U'), # nosec: B603 stdout=subprocess.PIPE) as file: pcapkit.extract(fin=file.stdout, fout='../captures/stream.txt', format='tree', no_eof=True, - verbose=True, buffer_save=True, buffer_path='../captures/stream.pcap') + verbose=True, buffer_save=True, buffer_path=BUFFER) diff --git a/examples/legacy_smoke/test_stream_askpass.py b/examples/legacy_smoke/test_stream_askpass.py index 2312d4dc1d..f835b239df 100644 --- a/examples/legacy_smoke/test_stream_askpass.py +++ b/examples/legacy_smoke/test_stream_askpass.py @@ -1,11 +1,31 @@ # -*- coding: utf-8 -*- +"""Extract a live capture streamed from ``tcpdump``, with ``sudo -A``. +Same as :file:`test_stream.py`, but uses ``sudo -A`` so the password comes from the +``SUDO_ASKPASS`` helper rather than a terminal prompt. Still needs root, so it +cannot run unattended. + +""" + +import os import shlex import subprocess # nosec: B404 +import tempfile import pcapkit -with subprocess.Popen(shlex.split('sudo -A tcpdump -i en0 -s 0 -w - -U'), # nosec: B603 +#: Interface to capture on. ``en0`` is macOS; on Linux this is usually ``eth0`` +#: or ``wlan0`` -- see ``ip link`` or ``tcpdump -D``. +INTERFACE = 'en0' + +# NOTE: buffer_path must not point inside ../captures/. That directory holds generated +# captures -- ../captures/stream.pcap among them -- which the runtime tests read and +# pin byte for byte, so buffering a live capture over it would quietly break the +# test suite. Buffer into a throwaway temporary file instead. +BUFFER = os.path.join(tempfile.mkdtemp(prefix='pcapkit-stream-'), 'stream.pcap') +print(f'buffering the live capture to {BUFFER}') + +with subprocess.Popen(shlex.split(f'sudo -A tcpdump -i {INTERFACE} -s 0 -w - -U'), # nosec: B603 stdout=subprocess.PIPE) as file: pcapkit.extract(fin=file.stdout, fout='../captures/stream.txt', format='tree', no_eof=True, - verbose=True, buffer_save=True, buffer_path='../captures/stream.pcap') + verbose=True, buffer_save=True, buffer_path=BUFFER) diff --git a/examples/legacy_smoke/test_time.py b/examples/legacy_smoke/test_time.py index 13b94a490f..9c972353a2 100644 --- a/examples/legacy_smoke/test_time.py +++ b/examples/legacy_smoke/test_time.py @@ -1,22 +1,39 @@ # -*- coding: utf-8 -*- +"""Time ``pcapkit.extract`` on each engine and report milliseconds per packet. + +An engine that is not available on this host is reported as skipped, with the +reason, and the remaining engines are still timed -- see :mod:`_engine_support` for +what counts as unavailable. Anything else is a real failure and is left to +propagate. + +Note that the engines are tried once each before being timed: a failure halfway +through a thousand rounds throws the whole measurement away, and an engine this +host does not have is not a result worth measuring. + +""" import statistics import time -import dpkt -import pyshark -import scapy.all - import pcapkit +from _engine_support import ENGINES, preflight from pcapkit.utilities.logging import logger logger.setLevel('INFO') -for engine in ['default', 'dpkt', 'scapy', 'pyshark']: +#: Timed extractions per engine. The first is discarded as a warm-up round. +ROUNDS = 1_000 + +for engine in ENGINES: + reason = preflight(engine, '../captures/in.pcap') + if reason is not None: + print(f'Report: [{engine}] skipped -- {reason}') + continue + print(f'Testing: [{engine}] starting...', end='', flush=True) - lid = [] - for index in range(0, 1_000): + lid = [] # type: list[float] + for index in range(0, ROUNDS): now = time.time_ns() extraction = pcapkit.extract(fin='../captures/in.pcap', store=False, nofile=True, verbose=False, engine=engine) # type: ignore[arg-type] From 3a4df14e3de7951500afa747b1f32cdf911c8dea Mon Sep 17 00:00:00 2001 From: Jarry Shaw Date: Tue, 15 Sep 2026 00:45:05 -0400 Subject: [PATCH 2/4] examples: time the extraction demo with a monotonic clock test_time.py measured durations with time.time_ns(), which is wall clock: an NTP adjustment mid-run can step it backwards and yield a negative delta. perf_counter_ns is monotonic and is what a duration wants. Pre-existing, but this is a timing demo and the file is already being rewritten here. Addresses a suppressed Copilot comment on #387. --- examples/legacy_smoke/test_time.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/legacy_smoke/test_time.py b/examples/legacy_smoke/test_time.py index 9c972353a2..3a150ca74c 100644 --- a/examples/legacy_smoke/test_time.py +++ b/examples/legacy_smoke/test_time.py @@ -34,11 +34,13 @@ lid = [] # type: list[float] for index in range(0, ROUNDS): - now = time.time_ns() + # NOTE: perf_counter_ns is monotonic; time_ns is wall clock and can step + # backwards under an NTP adjustment, which would give a negative delta. + now = time.perf_counter_ns() extraction = pcapkit.extract(fin='../captures/in.pcap', store=False, nofile=True, verbose=False, engine=engine) # type: ignore[arg-type] - delta = time.time_ns() - now + delta = time.perf_counter_ns() - now # print(f'[{engine}] No. {index:>3d}: {extraction.length} packets extracted in {delta} seconds.') lid.append(float(delta)) From 00e10390b378839166d114ea75f31913e869274e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 15 Sep 2026 03:57:15 +0000 Subject: [PATCH 3/4] Remove `from __future__ import annotations` from _engine_support.py for Python 3.6 compatibility Co-authored-by: JarryShaw <15666417+JarryShaw@users.noreply.github.com> --- examples/legacy_smoke/_engine_support.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/legacy_smoke/_engine_support.py b/examples/legacy_smoke/_engine_support.py index 74bf7fb71a..7fbd1e4bed 100644 --- a/examples/legacy_smoke/_engine_support.py +++ b/examples/legacy_smoke/_engine_support.py @@ -26,8 +26,6 @@ """ -from __future__ import annotations - import sys from typing import TYPE_CHECKING From 225c72ad05298756e5023d90a017cf90b92dea5b Mon Sep 17 00:00:00 2001 From: Jarry Shaw Date: Tue, 15 Sep 2026 01:55:34 -0400 Subject: [PATCH 4/4] docs: point the legacy_smoke README at the real generator path The sample-generation command read `../samples/make_samples.py`, a path left over from before `examples/samplegen/` was renamed to `examples/generators/`. There is no `examples/samples/` directory, so the one command a fresh clone has to run before the other scripts work was the one command that could not. Verified by running it from `examples/legacy_smoke/`, which is the directory the README tells the reader to be in. Copilot also flagged `time.time_ns()` in test_time.py as a suppressed "previously missed" comment; that one is stale -- the file has used the monotonic `time.perf_counter_ns()` since 00e10390b, with a comment saying why. --- examples/legacy_smoke/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/legacy_smoke/README.md b/examples/legacy_smoke/README.md index 205fe2759a..e31a4cb616 100644 --- a/examples/legacy_smoke/README.md +++ b/examples/legacy_smoke/README.md @@ -20,7 +20,7 @@ python test_basic.py rest are generated, so build them once before running anything else: ```shell -python ../samples/make_samples.py # or: make samples, from the repository root +python ../generators/make_samples.py # or: make samples, from the repository root ``` ## The scripts