pypcapkit 1.3.5.post6__cp312-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- pcapkit/__init__.py +124 -0
- pcapkit/__main__.py +138 -0
- pcapkit/all.py +136 -0
- pcapkit/const/__init__.py +81 -0
- pcapkit/const/arp/__init__.py +25 -0
- pcapkit/const/arp/hardware.py +181 -0
- pcapkit/const/arp/operation.py +131 -0
- pcapkit/const/ftp/__init__.py +25 -0
- pcapkit/const/ftp/command.py +309 -0
- pcapkit/const/ftp/return_code.py +304 -0
- pcapkit/const/hip/__init__.py +94 -0
- pcapkit/const/hip/certificate.py +77 -0
- pcapkit/const/hip/cipher.py +65 -0
- pcapkit/const/hip/di.py +59 -0
- pcapkit/const/hip/ecdsa_curve.py +59 -0
- pcapkit/const/hip/ecdsa_low_curve.py +56 -0
- pcapkit/const/hip/eddsa_curve.py +65 -0
- pcapkit/const/hip/esp_transform_suite.py +98 -0
- pcapkit/const/hip/group.py +86 -0
- pcapkit/const/hip/hi_algorithm.py +86 -0
- pcapkit/const/hip/hit_suite.py +68 -0
- pcapkit/const/hip/nat_traversal.py +62 -0
- pcapkit/const/hip/notify_message.py +200 -0
- pcapkit/const/hip/packet.py +89 -0
- pcapkit/const/hip/parameter.py +377 -0
- pcapkit/const/hip/registration.py +68 -0
- pcapkit/const/hip/registration_failure.py +84 -0
- pcapkit/const/hip/suite.py +71 -0
- pcapkit/const/hip/transport.py +59 -0
- pcapkit/const/http/__init__.py +39 -0
- pcapkit/const/http/error_code.py +95 -0
- pcapkit/const/http/frame.py +95 -0
- pcapkit/const/http/method.py +184 -0
- pcapkit/const/http/setting.py +96 -0
- pcapkit/const/http/status_code.py +298 -0
- pcapkit/const/ipv4/__init__.py +57 -0
- pcapkit/const/ipv4/classification_level.py +64 -0
- pcapkit/const/ipv4/option_class.py +55 -0
- pcapkit/const/ipv4/option_number.py +137 -0
- pcapkit/const/ipv4/protection_authority.py +63 -0
- pcapkit/const/ipv4/qs_function.py +51 -0
- pcapkit/const/ipv4/router_alert.py +251 -0
- pcapkit/const/ipv4/tos_del.py +51 -0
- pcapkit/const/ipv4/tos_ecn.py +55 -0
- pcapkit/const/ipv4/tos_pre.py +63 -0
- pcapkit/const/ipv4/tos_rel.py +51 -0
- pcapkit/const/ipv4/tos_thr.py +51 -0
- pcapkit/const/ipv4/ts_flag.py +53 -0
- pcapkit/const/ipv6/__init__.py +53 -0
- pcapkit/const/ipv6/extension_header.py +69 -0
- pcapkit/const/ipv6/option.py +137 -0
- pcapkit/const/ipv6/option_action.py +55 -0
- pcapkit/const/ipv6/qs_function.py +51 -0
- pcapkit/const/ipv6/router_alert.py +266 -0
- pcapkit/const/ipv6/routing.py +80 -0
- pcapkit/const/ipv6/seed_id.py +55 -0
- pcapkit/const/ipv6/smf_dpd_mode.py +51 -0
- pcapkit/const/ipv6/tagger_id.py +62 -0
- pcapkit/const/ipx/__init__.py +27 -0
- pcapkit/const/ipx/packet.py +72 -0
- pcapkit/const/ipx/socket.py +104 -0
- pcapkit/const/l2tp/__init__.py +21 -0
- pcapkit/const/l2tp/type.py +51 -0
- pcapkit/const/mh/__init__.py +204 -0
- pcapkit/const/mh/access_type.py +92 -0
- pcapkit/const/mh/ack_status_code.py +71 -0
- pcapkit/const/mh/ani_suboption.py +74 -0
- pcapkit/const/mh/auth_subtype.py +53 -0
- pcapkit/const/mh/binding_ack_flag.py +66 -0
- pcapkit/const/mh/binding_error.py +51 -0
- pcapkit/const/mh/binding_revocation.py +59 -0
- pcapkit/const/mh/binding_update_flag.py +81 -0
- pcapkit/const/mh/cga_extension.py +66 -0
- pcapkit/const/mh/cga_sec.py +57 -0
- pcapkit/const/mh/cga_type.py +68 -0
- pcapkit/const/mh/dhcp_support_mode.py +53 -0
- pcapkit/const/mh/dns_status_code.py +65 -0
- pcapkit/const/mh/dsmip6_tls_packet.py +62 -0
- pcapkit/const/mh/dsmipv6_home_address.py +74 -0
- pcapkit/const/mh/enumerating_algorithm.py +56 -0
- pcapkit/const/mh/fb_ack_status.py +62 -0
- pcapkit/const/mh/fb_action.py +71 -0
- pcapkit/const/mh/fb_indication_trigger.py +65 -0
- pcapkit/const/mh/fb_type.py +59 -0
- pcapkit/const/mh/flow_id_status.py +77 -0
- pcapkit/const/mh/flow_id_suboption.py +71 -0
- pcapkit/const/mh/handoff_type.py +71 -0
- pcapkit/const/mh/handover_ack_flag.py +54 -0
- pcapkit/const/mh/handover_ack_status.py +92 -0
- pcapkit/const/mh/handover_initiate_flag.py +57 -0
- pcapkit/const/mh/handover_initiate_status.py +62 -0
- pcapkit/const/mh/home_address_reply.py +71 -0
- pcapkit/const/mh/lla_code.py +63 -0
- pcapkit/const/mh/lma_mag_suboption.py +59 -0
- pcapkit/const/mh/mn_group_id.py +59 -0
- pcapkit/const/mh/mn_id_subtype.py +77 -0
- pcapkit/const/mh/operator_id.py +63 -0
- pcapkit/const/mh/option.py +260 -0
- pcapkit/const/mh/packet.py +119 -0
- pcapkit/const/mh/qos_attribute.py +89 -0
- pcapkit/const/mh/revocation_status_code.py +83 -0
- pcapkit/const/mh/revocation_trigger.py +86 -0
- pcapkit/const/mh/status_code.py +232 -0
- pcapkit/const/mh/traffic_selector.py +62 -0
- pcapkit/const/mh/upa_status.py +71 -0
- pcapkit/const/mh/upn_reason.py +80 -0
- pcapkit/const/ospf/__init__.py +27 -0
- pcapkit/const/ospf/authentication.py +65 -0
- pcapkit/const/ospf/packet.py +71 -0
- pcapkit/const/pcapng/__init__.py +51 -0
- pcapkit/const/pcapng/block_type.py +152 -0
- pcapkit/const/pcapng/filter_type.py +48 -0
- pcapkit/const/pcapng/hash_algorithm.py +59 -0
- pcapkit/const/pcapng/option_type.py +233 -0
- pcapkit/const/pcapng/record_type.py +57 -0
- pcapkit/const/pcapng/secrets_type.py +56 -0
- pcapkit/const/pcapng/verdict_type.py +53 -0
- pcapkit/const/reg/__init__.py +34 -0
- pcapkit/const/reg/apptype.py +32728 -0
- pcapkit/const/reg/ethertype.py +714 -0
- pcapkit/const/reg/linktype.py +890 -0
- pcapkit/const/reg/transtype.py +526 -0
- pcapkit/const/tcp/__init__.py +35 -0
- pcapkit/const/tcp/checksum.py +55 -0
- pcapkit/const/tcp/flags.py +73 -0
- pcapkit/const/tcp/mp_tcp_option.py +80 -0
- pcapkit/const/tcp/option.py +198 -0
- pcapkit/const/vlan/__init__.py +23 -0
- pcapkit/const/vlan/priority_level.py +71 -0
- pcapkit/corekit/__init__.py +59 -0
- pcapkit/corekit/fields/__init__.py +45 -0
- pcapkit/corekit/fields/collections.py +282 -0
- pcapkit/corekit/fields/field.py +269 -0
- pcapkit/corekit/fields/ipaddress.py +274 -0
- pcapkit/corekit/fields/misc.py +722 -0
- pcapkit/corekit/fields/numbers.py +375 -0
- pcapkit/corekit/fields/strings.py +245 -0
- pcapkit/corekit/infoclass.py +394 -0
- pcapkit/corekit/io.py +506 -0
- pcapkit/corekit/module.py +39 -0
- pcapkit/corekit/multidict.py +626 -0
- pcapkit/corekit/protochain.py +263 -0
- pcapkit/corekit/version.py +33 -0
- pcapkit/dumpkit/__init__.py +15 -0
- pcapkit/dumpkit/common.py +199 -0
- pcapkit/dumpkit/null.py +77 -0
- pcapkit/dumpkit/pcap.py +144 -0
- pcapkit/foundation/__init__.py +45 -0
- pcapkit/foundation/engines/__init__.py +36 -0
- pcapkit/foundation/engines/dpkt.py +230 -0
- pcapkit/foundation/engines/engine.py +194 -0
- pcapkit/foundation/engines/pcap.py +188 -0
- pcapkit/foundation/engines/pcapng.py +310 -0
- pcapkit/foundation/engines/pyshark.py +166 -0
- pcapkit/foundation/engines/scapy.py +161 -0
- pcapkit/foundation/extraction.py +915 -0
- pcapkit/foundation/reassembly/__init__.py +49 -0
- pcapkit/foundation/reassembly/data/__init__.py +48 -0
- pcapkit/foundation/reassembly/data/ip.py +117 -0
- pcapkit/foundation/reassembly/data/tcp.py +145 -0
- pcapkit/foundation/reassembly/ip.py +192 -0
- pcapkit/foundation/reassembly/ipv4.py +50 -0
- pcapkit/foundation/reassembly/ipv6.py +50 -0
- pcapkit/foundation/reassembly/reassembly.py +389 -0
- pcapkit/foundation/reassembly/tcp.py +249 -0
- pcapkit/foundation/registry/__init__.py +41 -0
- pcapkit/foundation/registry/foundation.py +327 -0
- pcapkit/foundation/registry/protocols.py +885 -0
- pcapkit/foundation/traceflow/__init__.py +44 -0
- pcapkit/foundation/traceflow/data/__init__.py +30 -0
- pcapkit/foundation/traceflow/data/tcp.py +105 -0
- pcapkit/foundation/traceflow/tcp.py +159 -0
- pcapkit/foundation/traceflow/traceflow.py +390 -0
- pcapkit/interface/__init__.py +22 -0
- pcapkit/interface/core.py +185 -0
- pcapkit/interface/misc.py +120 -0
- pcapkit/protocols/__init__.py +85 -0
- pcapkit/protocols/application/NotImplemented/bgp.py +0 -0
- pcapkit/protocols/application/NotImplemented/dhcp.py +0 -0
- pcapkit/protocols/application/NotImplemented/dhcpv6.py +0 -0
- pcapkit/protocols/application/NotImplemented/dns.py +0 -0
- pcapkit/protocols/application/NotImplemented/imap.py +0 -0
- pcapkit/protocols/application/NotImplemented/ldap.py +0 -0
- pcapkit/protocols/application/NotImplemented/mqtt.py +0 -0
- pcapkit/protocols/application/NotImplemented/nntp.py +0 -0
- pcapkit/protocols/application/NotImplemented/ntp.py +0 -0
- pcapkit/protocols/application/NotImplemented/onc_rpc.py +0 -0
- pcapkit/protocols/application/NotImplemented/pop.py +0 -0
- pcapkit/protocols/application/NotImplemented/rip.py +0 -0
- pcapkit/protocols/application/NotImplemented/rtp.py +0 -0
- pcapkit/protocols/application/NotImplemented/sip.py +0 -0
- pcapkit/protocols/application/NotImplemented/smtp.py +0 -0
- pcapkit/protocols/application/NotImplemented/snmp.py +0 -0
- pcapkit/protocols/application/NotImplemented/ssh.py +0 -0
- pcapkit/protocols/application/NotImplemented/telnet.py +0 -0
- pcapkit/protocols/application/NotImplemented/tls.py +0 -0
- pcapkit/protocols/application/NotImplemented/xmpp.py +0 -0
- pcapkit/protocols/application/__init__.py +34 -0
- pcapkit/protocols/application/application.py +114 -0
- pcapkit/protocols/application/ftp.py +206 -0
- pcapkit/protocols/application/http.py +176 -0
- pcapkit/protocols/application/httpv1.py +320 -0
- pcapkit/protocols/application/httpv2.py +1255 -0
- pcapkit/protocols/data/__init__.py +192 -0
- pcapkit/protocols/data/application/__init__.py +57 -0
- pcapkit/protocols/data/application/ftp.py +59 -0
- pcapkit/protocols/data/application/httpv1.py +79 -0
- pcapkit/protocols/data/application/httpv2.py +293 -0
- pcapkit/protocols/data/data.py +25 -0
- pcapkit/protocols/data/internet/__init__.py +298 -0
- pcapkit/protocols/data/internet/ah.py +31 -0
- pcapkit/protocols/data/internet/hip.py +804 -0
- pcapkit/protocols/data/internet/hopopt.py +351 -0
- pcapkit/protocols/data/internet/ipv4.py +369 -0
- pcapkit/protocols/data/internet/ipv6.py +67 -0
- pcapkit/protocols/data/internet/ipv6_frag.py +29 -0
- pcapkit/protocols/data/internet/ipv6_opts.py +368 -0
- pcapkit/protocols/data/internet/ipv6_route.py +86 -0
- pcapkit/protocols/data/internet/ipx.py +56 -0
- pcapkit/protocols/data/internet/mh.py +509 -0
- pcapkit/protocols/data/link/__init__.py +33 -0
- pcapkit/protocols/data/link/arp.py +74 -0
- pcapkit/protocols/data/link/ethernet.py +28 -0
- pcapkit/protocols/data/link/l2tp.py +63 -0
- pcapkit/protocols/data/link/ospf.py +58 -0
- pcapkit/protocols/data/link/vlan.py +42 -0
- pcapkit/protocols/data/misc/__init__.py +109 -0
- pcapkit/protocols/data/misc/null.py +18 -0
- pcapkit/protocols/data/misc/pcap/__init__.py +18 -0
- pcapkit/protocols/data/misc/pcap/frame.py +56 -0
- pcapkit/protocols/data/misc/pcap/header.py +53 -0
- pcapkit/protocols/data/misc/pcapng.py +925 -0
- pcapkit/protocols/data/misc/raw.py +25 -0
- pcapkit/protocols/data/protocol.py +32 -0
- pcapkit/protocols/data/transport/__init__.py +71 -0
- pcapkit/protocols/data/transport/tcp.py +555 -0
- pcapkit/protocols/data/transport/udp.py +29 -0
- pcapkit/protocols/internet/NotImplemented/ecn.py +0 -0
- pcapkit/protocols/internet/NotImplemented/esp.py +97 -0
- pcapkit/protocols/internet/NotImplemented/icmp.py +0 -0
- pcapkit/protocols/internet/NotImplemented/icmpv6.py +0 -0
- pcapkit/protocols/internet/NotImplemented/igmp.py +0 -0
- pcapkit/protocols/internet/NotImplemented/shim6.py +0 -0
- pcapkit/protocols/internet/__init__.py +43 -0
- pcapkit/protocols/internet/ah.py +275 -0
- pcapkit/protocols/internet/hip.py +4727 -0
- pcapkit/protocols/internet/hopopt.py +1879 -0
- pcapkit/protocols/internet/internet.py +249 -0
- pcapkit/protocols/internet/ip.py +51 -0
- pcapkit/protocols/internet/ipsec.py +50 -0
- pcapkit/protocols/internet/ipv4.py +1782 -0
- pcapkit/protocols/internet/ipv6.py +412 -0
- pcapkit/protocols/internet/ipv6_frag.py +258 -0
- pcapkit/protocols/internet/ipv6_opts.py +1890 -0
- pcapkit/protocols/internet/ipv6_route.py +708 -0
- pcapkit/protocols/internet/ipx.py +230 -0
- pcapkit/protocols/internet/mh.py +2764 -0
- pcapkit/protocols/link/NotImplemented/dsl.py +0 -0
- pcapkit/protocols/link/NotImplemented/eapol.py +1 -0
- pcapkit/protocols/link/NotImplemented/fddi.py +0 -0
- pcapkit/protocols/link/NotImplemented/isdn.py +0 -0
- pcapkit/protocols/link/NotImplemented/ndp.py +0 -0
- pcapkit/protocols/link/NotImplemented/ppp.py +0 -0
- pcapkit/protocols/link/__init__.py +35 -0
- pcapkit/protocols/link/arp.py +421 -0
- pcapkit/protocols/link/ethernet.py +248 -0
- pcapkit/protocols/link/l2tp.py +267 -0
- pcapkit/protocols/link/link.py +140 -0
- pcapkit/protocols/link/ospf.py +342 -0
- pcapkit/protocols/link/rarp.py +82 -0
- pcapkit/protocols/link/vlan.py +225 -0
- pcapkit/protocols/misc/__init__.py +37 -0
- pcapkit/protocols/misc/null.py +129 -0
- pcapkit/protocols/misc/pcap/__init__.py +17 -0
- pcapkit/protocols/misc/pcap/frame.py +478 -0
- pcapkit/protocols/misc/pcap/header.py +358 -0
- pcapkit/protocols/misc/pcapng.py +5520 -0
- pcapkit/protocols/misc/raw.py +180 -0
- pcapkit/protocols/protocol.py +1216 -0
- pcapkit/protocols/schema/__init__.py +140 -0
- pcapkit/protocols/schema/application/__init__.py +40 -0
- pcapkit/protocols/schema/application/ftp.py +21 -0
- pcapkit/protocols/schema/application/httpv1.py +21 -0
- pcapkit/protocols/schema/application/httpv2.py +384 -0
- pcapkit/protocols/schema/internet/__init__.py +294 -0
- pcapkit/protocols/schema/internet/ah.py +40 -0
- pcapkit/protocols/schema/internet/hip.py +1184 -0
- pcapkit/protocols/schema/internet/hopopt.py +679 -0
- pcapkit/protocols/schema/internet/ipv4.py +576 -0
- pcapkit/protocols/schema/internet/ipv6.py +63 -0
- pcapkit/protocols/schema/internet/ipv6_frag.py +48 -0
- pcapkit/protocols/schema/internet/ipv6_opts.py +680 -0
- pcapkit/protocols/schema/internet/ipv6_route.py +197 -0
- pcapkit/protocols/schema/internet/ipx.py +40 -0
- pcapkit/protocols/schema/internet/mh.py +718 -0
- pcapkit/protocols/schema/link/__init__.py +19 -0
- pcapkit/protocols/schema/link/arp.py +39 -0
- pcapkit/protocols/schema/link/ethernet.py +51 -0
- pcapkit/protocols/schema/link/l2tp.py +88 -0
- pcapkit/protocols/schema/link/ospf.py +90 -0
- pcapkit/protocols/schema/link/vlan.py +69 -0
- pcapkit/protocols/schema/misc/__init__.py +108 -0
- pcapkit/protocols/schema/misc/null.py +18 -0
- pcapkit/protocols/schema/misc/pcap/__init__.py +10 -0
- pcapkit/protocols/schema/misc/pcap/frame.py +51 -0
- pcapkit/protocols/schema/misc/pcap/header.py +63 -0
- pcapkit/protocols/schema/misc/pcapng.py +1689 -0
- pcapkit/protocols/schema/misc/raw.py +24 -0
- pcapkit/protocols/schema/schema.py +809 -0
- pcapkit/protocols/schema/transport/__init__.py +69 -0
- pcapkit/protocols/schema/transport/tcp.py +928 -0
- pcapkit/protocols/schema/transport/udp.py +90 -0
- pcapkit/protocols/transport/NotImplemented/dccp.py +0 -0
- pcapkit/protocols/transport/NotImplemented/rsvp.py +0 -0
- pcapkit/protocols/transport/NotImplemented/sctp.py +0 -0
- pcapkit/protocols/transport/__init__.py +27 -0
- pcapkit/protocols/transport/tcp.py +3025 -0
- pcapkit/protocols/transport/transport.py +158 -0
- pcapkit/protocols/transport/udp.py +214 -0
- pcapkit/py.typed +0 -0
- pcapkit/toolkit/__init__.py +57 -0
- pcapkit/toolkit/dpkt.py +306 -0
- pcapkit/toolkit/pcap.py +212 -0
- pcapkit/toolkit/pcapng.py +251 -0
- pcapkit/toolkit/pyshark.py +99 -0
- pcapkit/toolkit/scapy.py +297 -0
- pcapkit/utilities/__init__.py +20 -0
- pcapkit/utilities/compat.py +196 -0
- pcapkit/utilities/decorators.py +197 -0
- pcapkit/utilities/exceptions.py +365 -0
- pcapkit/utilities/logging.py +55 -0
- pcapkit/utilities/warnings.py +185 -0
- pcapkit/vendor/__init__.py +105 -0
- pcapkit/vendor/__main__.py +92 -0
- pcapkit/vendor/arp/__init__.py +27 -0
- pcapkit/vendor/arp/hardware.py +29 -0
- pcapkit/vendor/arp/operation.py +29 -0
- pcapkit/vendor/default.py +474 -0
- pcapkit/vendor/ftp/__init__.py +27 -0
- pcapkit/vendor/ftp/command.py +244 -0
- pcapkit/vendor/ftp/return_code.py +256 -0
- pcapkit/vendor/hip/__init__.py +94 -0
- pcapkit/vendor/hip/certificate.py +29 -0
- pcapkit/vendor/hip/cipher.py +29 -0
- pcapkit/vendor/hip/di.py +29 -0
- pcapkit/vendor/hip/ecdsa_curve.py +29 -0
- pcapkit/vendor/hip/ecdsa_low_curve.py +29 -0
- pcapkit/vendor/hip/eddsa_curve.py +85 -0
- pcapkit/vendor/hip/esp_transform_suite.py +29 -0
- pcapkit/vendor/hip/group.py +87 -0
- pcapkit/vendor/hip/hi_algorithm.py +29 -0
- pcapkit/vendor/hip/hit_suite.py +29 -0
- pcapkit/vendor/hip/nat_traversal.py +29 -0
- pcapkit/vendor/hip/notify_message.py +29 -0
- pcapkit/vendor/hip/packet.py +88 -0
- pcapkit/vendor/hip/parameter.py +88 -0
- pcapkit/vendor/hip/registration.py +29 -0
- pcapkit/vendor/hip/registration_failure.py +29 -0
- pcapkit/vendor/hip/suite.py +29 -0
- pcapkit/vendor/hip/transport.py +29 -0
- pcapkit/vendor/http/__init__.py +39 -0
- pcapkit/vendor/http/error_code.py +95 -0
- pcapkit/vendor/http/frame.py +91 -0
- pcapkit/vendor/http/method.py +167 -0
- pcapkit/vendor/http/setting.py +93 -0
- pcapkit/vendor/http/status_code.py +185 -0
- pcapkit/vendor/ipv4/__init__.py +57 -0
- pcapkit/vendor/ipv4/classification_level.py +91 -0
- pcapkit/vendor/ipv4/option_class.py +80 -0
- pcapkit/vendor/ipv4/option_number.py +105 -0
- pcapkit/vendor/ipv4/protection_authority.py +84 -0
- pcapkit/vendor/ipv4/qs_function.py +78 -0
- pcapkit/vendor/ipv4/router_alert.py +93 -0
- pcapkit/vendor/ipv4/tos_del.py +78 -0
- pcapkit/vendor/ipv4/tos_ecn.py +95 -0
- pcapkit/vendor/ipv4/tos_pre.py +84 -0
- pcapkit/vendor/ipv4/tos_rel.py +78 -0
- pcapkit/vendor/ipv4/tos_thr.py +77 -0
- pcapkit/vendor/ipv4/ts_flag.py +79 -0
- pcapkit/vendor/ipv6/__init__.py +53 -0
- pcapkit/vendor/ipv6/extension_header.py +171 -0
- pcapkit/vendor/ipv6/option.py +104 -0
- pcapkit/vendor/ipv6/option_action.py +90 -0
- pcapkit/vendor/ipv6/qs_function.py +78 -0
- pcapkit/vendor/ipv6/router_alert.py +93 -0
- pcapkit/vendor/ipv6/routing.py +87 -0
- pcapkit/vendor/ipv6/seed_id.py +81 -0
- pcapkit/vendor/ipv6/smf_dpd_mode.py +78 -0
- pcapkit/vendor/ipv6/tagger_id.py +81 -0
- pcapkit/vendor/ipx/__init__.py +37 -0
- pcapkit/vendor/ipx/packet.py +123 -0
- pcapkit/vendor/ipx/socket.py +125 -0
- pcapkit/vendor/l2tp/__init__.py +21 -0
- pcapkit/vendor/l2tp/type.py +78 -0
- pcapkit/vendor/mh/__init__.py +204 -0
- pcapkit/vendor/mh/access_type.py +87 -0
- pcapkit/vendor/mh/ack_status_code.py +88 -0
- pcapkit/vendor/mh/ani_suboption.py +88 -0
- pcapkit/vendor/mh/auth_subtype.py +83 -0
- pcapkit/vendor/mh/binding_ack_flag.py +148 -0
- pcapkit/vendor/mh/binding_error.py +78 -0
- pcapkit/vendor/mh/binding_revocation.py +87 -0
- pcapkit/vendor/mh/binding_update_flag.py +147 -0
- pcapkit/vendor/mh/cga_extension.py +91 -0
- pcapkit/vendor/mh/cga_sec.py +91 -0
- pcapkit/vendor/mh/cga_type.py +74 -0
- pcapkit/vendor/mh/dhcp_support_mode.py +77 -0
- pcapkit/vendor/mh/dns_status_code.py +87 -0
- pcapkit/vendor/mh/dsmip6_tls_packet.py +87 -0
- pcapkit/vendor/mh/dsmipv6_home_address.py +87 -0
- pcapkit/vendor/mh/enumerating_algorithm.py +82 -0
- pcapkit/vendor/mh/fb_ack_status.py +87 -0
- pcapkit/vendor/mh/fb_action.py +88 -0
- pcapkit/vendor/mh/fb_indication_trigger.py +87 -0
- pcapkit/vendor/mh/fb_type.py +88 -0
- pcapkit/vendor/mh/flow_id_status.py +87 -0
- pcapkit/vendor/mh/flow_id_suboption.py +87 -0
- pcapkit/vendor/mh/handoff_type.py +87 -0
- pcapkit/vendor/mh/handover_ack_flag.py +143 -0
- pcapkit/vendor/mh/handover_ack_status.py +87 -0
- pcapkit/vendor/mh/handover_initiate_flag.py +143 -0
- pcapkit/vendor/mh/handover_initiate_status.py +87 -0
- pcapkit/vendor/mh/home_address_reply.py +87 -0
- pcapkit/vendor/mh/lla_code.py +97 -0
- pcapkit/vendor/mh/lma_mag_suboption.py +88 -0
- pcapkit/vendor/mh/mn_group_id.py +87 -0
- pcapkit/vendor/mh/mn_id_subtype.py +87 -0
- pcapkit/vendor/mh/operator_id.py +87 -0
- pcapkit/vendor/mh/option.py +83 -0
- pcapkit/vendor/mh/packet.py +82 -0
- pcapkit/vendor/mh/qos_attribute.py +87 -0
- pcapkit/vendor/mh/revocation_status_code.py +87 -0
- pcapkit/vendor/mh/revocation_trigger.py +87 -0
- pcapkit/vendor/mh/status_code.py +91 -0
- pcapkit/vendor/mh/traffic_selector.py +87 -0
- pcapkit/vendor/mh/upa_status.py +87 -0
- pcapkit/vendor/mh/upn_reason.py +87 -0
- pcapkit/vendor/ospf/__init__.py +27 -0
- pcapkit/vendor/ospf/authentication.py +29 -0
- pcapkit/vendor/ospf/packet.py +29 -0
- pcapkit/vendor/pcapng/__init__.py +51 -0
- pcapkit/vendor/pcapng/block_type.py +94 -0
- pcapkit/vendor/pcapng/filter_type.py +77 -0
- pcapkit/vendor/pcapng/hash_algorithm.py +82 -0
- pcapkit/vendor/pcapng/option_type.py +287 -0
- pcapkit/vendor/pcapng/record_type.py +81 -0
- pcapkit/vendor/pcapng/secrets_type.py +81 -0
- pcapkit/vendor/pcapng/verdict_type.py +79 -0
- pcapkit/vendor/reg/__init__.py +34 -0
- pcapkit/vendor/reg/apptype.py +338 -0
- pcapkit/vendor/reg/ethertype.py +121 -0
- pcapkit/vendor/reg/linktype.py +110 -0
- pcapkit/vendor/reg/transtype.py +111 -0
- pcapkit/vendor/tcp/__init__.py +35 -0
- pcapkit/vendor/tcp/checksum.py +80 -0
- pcapkit/vendor/tcp/flags.py +149 -0
- pcapkit/vendor/tcp/mp_tcp_option.py +90 -0
- pcapkit/vendor/tcp/option.py +103 -0
- pcapkit/vendor/vlan/__init__.py +23 -0
- pcapkit/vendor/vlan/priority_level.py +97 -0
- pypcapkit-1.3.5.post6.dist-info/LICENSE +29 -0
- pypcapkit-1.3.5.post6.dist-info/METADATA +238 -0
- pypcapkit-1.3.5.post6.dist-info/RECORD +466 -0
- pypcapkit-1.3.5.post6.dist-info/WHEEL +5 -0
- pypcapkit-1.3.5.post6.dist-info/entry_points.txt +3 -0
- pypcapkit-1.3.5.post6.dist-info/top_level.txt +1 -0
@@ -0,0 +1,915 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# pylint: disable=import-outside-toplevel,fixme
|
3
|
+
# mypy: disable-error-code=dict-item
|
4
|
+
"""Extractor for PCAP Files
|
5
|
+
==============================
|
6
|
+
|
7
|
+
.. module:: pcapkit.foundation.extraction
|
8
|
+
|
9
|
+
:mod:`pcapkit.foundation.extraction` contains
|
10
|
+
:class:`~pcapkit.foundation.extraction.Extractor` only,
|
11
|
+
which synthesises file I/O and protocol analysis,
|
12
|
+
coordinates information exchange in all network layers,
|
13
|
+
extracts parametres from a PCAP file.
|
14
|
+
|
15
|
+
"""
|
16
|
+
import collections
|
17
|
+
import importlib
|
18
|
+
import io
|
19
|
+
import os
|
20
|
+
import sys
|
21
|
+
from typing import TYPE_CHECKING, Generic, TypeVar, cast
|
22
|
+
|
23
|
+
from dictdumper.dumper import Dumper
|
24
|
+
|
25
|
+
from pcapkit.corekit.io import SeekableReader
|
26
|
+
from pcapkit.corekit.module import ModuleDescriptor
|
27
|
+
from pcapkit.dumpkit.common import make_dumper
|
28
|
+
from pcapkit.foundation.engines.engine import Engine
|
29
|
+
from pcapkit.foundation.engines.pcap import PCAP as PCAP_Engine
|
30
|
+
from pcapkit.foundation.engines.pcapng import PCAPNG as PCAPNG_Engine
|
31
|
+
from pcapkit.foundation.reassembly import ReassemblyManager
|
32
|
+
from pcapkit.foundation.reassembly.data import ReassemblyData
|
33
|
+
from pcapkit.foundation.reassembly.reassembly import Reassembly
|
34
|
+
from pcapkit.foundation.traceflow import TraceFlowManager
|
35
|
+
from pcapkit.foundation.traceflow.data import TraceFlowData
|
36
|
+
from pcapkit.foundation.traceflow.traceflow import TraceFlow
|
37
|
+
from pcapkit.utilities.exceptions import (CallableError, FileNotFound, FormatError, IterableError,
|
38
|
+
RegistryError, UnsupportedCall, stacklevel)
|
39
|
+
from pcapkit.utilities.logging import logger
|
40
|
+
from pcapkit.utilities.warnings import (EngineWarning, ExtractionWarning, FormatWarning,
|
41
|
+
RegistryWarning, warn)
|
42
|
+
|
43
|
+
if TYPE_CHECKING:
|
44
|
+
from io import BufferedReader
|
45
|
+
from types import ModuleType, TracebackType
|
46
|
+
from typing import IO, Any, Callable, DefaultDict, Optional, Type, Union
|
47
|
+
|
48
|
+
from dpkt.dpkt import Packet as DPKTPacket
|
49
|
+
from pyshark.packet.packet import Packet as PySharkPacket
|
50
|
+
from scapy.packet import Packet as ScapyPacket
|
51
|
+
from typing_extensions import Literal
|
52
|
+
|
53
|
+
from pcapkit.foundation.reassembly.ipv4 import IPv4 as IPv4_Reassembly
|
54
|
+
from pcapkit.foundation.reassembly.ipv6 import IPv6 as IPv6_Reassembly
|
55
|
+
from pcapkit.foundation.reassembly.tcp import TCP as TCP_Reassembly
|
56
|
+
from pcapkit.foundation.traceflow.tcp import TCP as TCP_TraceFlow
|
57
|
+
from pcapkit.protocols.misc.pcap.frame import Frame
|
58
|
+
from pcapkit.protocols.misc.pcapng import PCAPNG
|
59
|
+
from pcapkit.protocols.protocol import ProtocolBase as Protocol
|
60
|
+
|
61
|
+
Formats = Literal['pcap', 'json', 'tree', 'plist']
|
62
|
+
Engines = Literal['default', 'pcapkit', 'dpkt', 'scapy', 'pyshark']
|
63
|
+
Layers = Literal['link', 'internet', 'transport', 'application', 'none']
|
64
|
+
|
65
|
+
Packet = Union[Frame, PCAPNG, ScapyPacket, DPKTPacket, PySharkPacket]
|
66
|
+
|
67
|
+
Protocols = Union[str, Protocol, Type[Protocol]]
|
68
|
+
VerboseHandler = Callable[['Extractor', Packet], Any]
|
69
|
+
|
70
|
+
__all__ = ['Extractor']
|
71
|
+
|
72
|
+
_P = TypeVar('_P')
|
73
|
+
|
74
|
+
|
75
|
+
class Extractor(Generic[_P]):
|
76
|
+
"""Extractor for PCAP files.
|
77
|
+
|
78
|
+
Notes:
|
79
|
+
For supported engines, please refer to
|
80
|
+
:meth:`~pcapkit.foundation.extraction.Extractor.run`.
|
81
|
+
|
82
|
+
"""
|
83
|
+
if TYPE_CHECKING:
|
84
|
+
#: Input file name.
|
85
|
+
_ifnm: 'str'
|
86
|
+
#: Output file name.
|
87
|
+
_ofnm: 'Optional[str]'
|
88
|
+
#: Output file extension.
|
89
|
+
_fext: 'Optional[str]'
|
90
|
+
|
91
|
+
#: Auto extract flag. It indicates if the extraction process should
|
92
|
+
#: continue automatically until the EOF is reached.
|
93
|
+
_flag_a: 'bool'
|
94
|
+
#: Store data flag. It indicates if the extracted frames should be
|
95
|
+
#: stored in memory.
|
96
|
+
_flag_d: 'bool'
|
97
|
+
#: EOF flag. It indicates if the EOF is reached.
|
98
|
+
_flag_e: 'bool'
|
99
|
+
#: Split file flag, i.e. dump each frame into different files.
|
100
|
+
_flag_f: 'bool'
|
101
|
+
#: No output file, i.e., no output file is to be generated.
|
102
|
+
_flag_q: 'bool'
|
103
|
+
#: Trace flag. It indicates if the flow tracing is enabled.
|
104
|
+
_flag_t: 'bool'
|
105
|
+
#: Verbose flag. This is used to determine if the verbose callback
|
106
|
+
#: function should be called at each frame.
|
107
|
+
_flag_v: 'bool'
|
108
|
+
#: No EOF flag. It is useful when the input file is a live capture,
|
109
|
+
#: as the extraction process will not stop until the user interrupt
|
110
|
+
#: the process.
|
111
|
+
_flag_n: 'bool'
|
112
|
+
#: Input filename flag. It indicates if the input file is a file
|
113
|
+
#: name or a binary IO object. For the latter, we should not close
|
114
|
+
#: the file object after extraction.
|
115
|
+
_flag_s: 'bool'
|
116
|
+
|
117
|
+
#: Verbose callback function.
|
118
|
+
#_vfunc: 'VerboseHandler'
|
119
|
+
|
120
|
+
#: Frame number.
|
121
|
+
_frnum: 'int'
|
122
|
+
#: Frame records.
|
123
|
+
_frame: 'list[Packet]'
|
124
|
+
|
125
|
+
#: Frame record for reassembly.
|
126
|
+
_reasm: 'ReassemblyManager'
|
127
|
+
#: Frame record for flow tracing.
|
128
|
+
_trace: 'TraceFlowManager'
|
129
|
+
|
130
|
+
#: IPv4 flag. It indicates if the IPv4 reassembly and/or flow tracing
|
131
|
+
#: is enabled.
|
132
|
+
_ipv4: 'bool'
|
133
|
+
#: IPv6 flag. It indicates if the IPv6 reassembly and/or flow tracing
|
134
|
+
#: is enabled.
|
135
|
+
_ipv6: 'bool'
|
136
|
+
#: TCP flag. It indicates if the TCP reassembly and/or flow tracing
|
137
|
+
#: is enabled.
|
138
|
+
_tcp: 'bool'
|
139
|
+
|
140
|
+
#: Extract til protocol.
|
141
|
+
_exptl: 'Protocols'
|
142
|
+
#: Extract til layer.
|
143
|
+
_exlyr: 'Layers'
|
144
|
+
#: Extraction engine name.
|
145
|
+
_exnam: 'Engines'
|
146
|
+
#: Extraction engine instance.
|
147
|
+
_exeng: 'Engine[_P]'
|
148
|
+
|
149
|
+
#: Input file object.
|
150
|
+
_ifile: 'BufferedReader'
|
151
|
+
#: Output file object.
|
152
|
+
_ofile: 'Dumper | Type[Dumper]'
|
153
|
+
|
154
|
+
#: Magic number.
|
155
|
+
_magic: 'bytes'
|
156
|
+
#: Output format.
|
157
|
+
_offmt: 'Formats'
|
158
|
+
|
159
|
+
#: List of potential PCAP file extentions.
|
160
|
+
PCAP_EXT = ['.pcap', '.cap', '.pcapng']
|
161
|
+
|
162
|
+
##########################################################################
|
163
|
+
# Defaults.
|
164
|
+
##########################################################################
|
165
|
+
|
166
|
+
#: Format dumper mapping for writing output files. The values should be a
|
167
|
+
#: tuple representing the module name and class name, or a
|
168
|
+
#: :class:`dictdumper.dumper.Dumper` subclass, and corresponding file extension.
|
169
|
+
__output__ = collections.defaultdict(
|
170
|
+
lambda: (ModuleDescriptor('pcapkit.dumpkit', 'NotImplementedIO'), None),
|
171
|
+
{
|
172
|
+
'pcap': (ModuleDescriptor('pcapkit.dumpkit', 'PCAPIO'), '.pcap'),
|
173
|
+
'cap': (ModuleDescriptor('pcapkit.dumpkit', 'PCAPIO'), '.pcap'),
|
174
|
+
'plist': (ModuleDescriptor('dictdumper', 'PLIST'), '.plist'),
|
175
|
+
'xml': (ModuleDescriptor('dictdumper', 'PLIST'), '.plist'),
|
176
|
+
'json': (ModuleDescriptor('dictdumper', 'JSON'), '.json'),
|
177
|
+
'tree': (ModuleDescriptor('dictdumper', 'Tree'), '.txt'),
|
178
|
+
'text': (ModuleDescriptor('dictdumper', 'Text'), '.txt'),
|
179
|
+
'txt': (ModuleDescriptor('dictdumper', 'Tree'), '.txt'),
|
180
|
+
},
|
181
|
+
) # type: DefaultDict[str, tuple[ModuleDescriptor[Dumper] | Type[Dumper], str | None]]
|
182
|
+
|
183
|
+
#: Engine mapping for extracting frames. The values should be a tuple representing
|
184
|
+
#: the module name and class name, or an :class:`~pcapkit.foundation.engines.engine.Engine`
|
185
|
+
#: subclass.
|
186
|
+
__engine__ = {
|
187
|
+
'scapy': ModuleDescriptor('pcapkit.foundation.engines.scapy', 'Scapy'),
|
188
|
+
'dpkt': ModuleDescriptor('pcapkit.foundation.engines.dpkt', 'DPKT'),
|
189
|
+
'pyshark': ModuleDescriptor('pcapkit.foundation.engines.pyshark', 'PyShark'),
|
190
|
+
} # type: dict[str, ModuleDescriptor[Engine] | Type[Engine]]
|
191
|
+
|
192
|
+
#: Reassembly support mapping for extracting frames. The values should be a tuple
|
193
|
+
#: representing the module name and class name, or a :class:`~pcapkit.foundation.reassembly.reassembly.Reassembly`
|
194
|
+
#: subclass.
|
195
|
+
__reassembly__ = {
|
196
|
+
'ipv4': ModuleDescriptor('pcapkit.foundation.reassembly.ipv4', 'IPv4'),
|
197
|
+
'ipv6': ModuleDescriptor('pcapkit.foundation.reassembly.ipv6', 'IPv6'),
|
198
|
+
'tcp': ModuleDescriptor('pcapkit.foundation.reassembly.tcp', 'TCP'),
|
199
|
+
} # type: dict[str, ModuleDescriptor[Reassembly] | Type[Reassembly]]
|
200
|
+
|
201
|
+
#: Flow tracing support mapping for extracting frames. The values should be a tuple
|
202
|
+
#: representing the module name and class name, or a :class:`~pcapkit.foundation.traceflow.traceflow.TraceFlow`
|
203
|
+
#: subclass.
|
204
|
+
__traceflow__ = {
|
205
|
+
'tcp': ModuleDescriptor('pcapkit.foundation.traceflow.tcp', 'TCP'),
|
206
|
+
} # type: dict[str, ModuleDescriptor[TraceFlow] | Type[TraceFlow]]
|
207
|
+
|
208
|
+
##########################################################################
|
209
|
+
# Properties.
|
210
|
+
##########################################################################
|
211
|
+
|
212
|
+
@property
|
213
|
+
def length(self) -> 'int':
|
214
|
+
"""Frame number (of current extracted frame or all)."""
|
215
|
+
return self._frnum
|
216
|
+
|
217
|
+
@property
|
218
|
+
def format(self) -> 'Formats':
|
219
|
+
"""Format of output file.
|
220
|
+
|
221
|
+
Raises:
|
222
|
+
UnsupportedCall: If :attr:`self._flag_q <pcapkit.foundation.extraction.Extractor._flag_q>`
|
223
|
+
is set as :data:`True`, as output is disabled by initialisation parameter.
|
224
|
+
|
225
|
+
"""
|
226
|
+
if self._flag_q:
|
227
|
+
raise UnsupportedCall("'Extractor(nofile=True)' object has no attribute 'format'")
|
228
|
+
return self._offmt
|
229
|
+
|
230
|
+
@property
|
231
|
+
def input(self) -> 'str':
|
232
|
+
"""Name of input PCAP file."""
|
233
|
+
return self._ifnm
|
234
|
+
|
235
|
+
@property
|
236
|
+
def output(self) -> 'str':
|
237
|
+
"""Name of output file.
|
238
|
+
|
239
|
+
Raises:
|
240
|
+
UnsupportedCall: If :attr:`self._flag_q <pcapkit.foundation.extraction.Extractor._flag_q>`
|
241
|
+
is set as :data:`True`, as output is disabled by initialisation parameter.
|
242
|
+
|
243
|
+
"""
|
244
|
+
if self._flag_q:
|
245
|
+
raise UnsupportedCall("'Extractor(nofile=True)' object has no attribute 'format'")
|
246
|
+
return cast('str', self._ofnm)
|
247
|
+
|
248
|
+
@property
|
249
|
+
def frame(self) -> 'tuple[Packet, ...]':
|
250
|
+
"""Extracted frames.
|
251
|
+
|
252
|
+
Raises:
|
253
|
+
UnsupportedCall: If :attr:`self._flag_d <pcapkit.foundation.extraction.Extractor._flag_d>`
|
254
|
+
is :data:`False`, as storing frame data is disabled.
|
255
|
+
|
256
|
+
"""
|
257
|
+
if self._flag_d:
|
258
|
+
return tuple(self._frame)
|
259
|
+
raise UnsupportedCall("'Extractor(store=False)' object has no attribute 'frame'")
|
260
|
+
|
261
|
+
@property
|
262
|
+
def reassembly(self) -> 'ReassemblyData':
|
263
|
+
"""Frame record for reassembly.
|
264
|
+
|
265
|
+
* ``ipv4`` -- tuple of IPv4 payload fragment (:term:`reasm.ipv4.datagram`)
|
266
|
+
* ``ipv6`` -- tuple of IPv6 payload fragment (:term:`reasm.ipv6.datagram`)
|
267
|
+
* ``tcp`` -- tuple of TCP payload fragment (:term:`reasm.tcp.datagram`)
|
268
|
+
|
269
|
+
Raises:
|
270
|
+
UnsupportedCall: If :attr:`self._flag_r <pcapkit.foundation.extraction.Extractor._flag_r>`
|
271
|
+
is :data:`False`, as reassembly is disabled.
|
272
|
+
|
273
|
+
"""
|
274
|
+
if self._flag_r:
|
275
|
+
data = ReassemblyData(
|
276
|
+
ipv4=tuple(self._reasm.ipv4.datagram) if self._ipv4 else None,
|
277
|
+
ipv6=tuple(self._reasm.ipv6.datagram) if self._ipv6 else None,
|
278
|
+
tcp=tuple(self._reasm.tcp.datagram) if self._tcp else None,
|
279
|
+
)
|
280
|
+
return data
|
281
|
+
raise UnsupportedCall("'Extractor(reassembly=False)' object has no attribute 'reassembly'")
|
282
|
+
|
283
|
+
@property
|
284
|
+
def trace(self) -> 'TraceFlowData':
|
285
|
+
"""Index table for traced flow.
|
286
|
+
|
287
|
+
* ``tcp`` -- tuple of TCP flows (:term:`trace.tcp.index`)
|
288
|
+
|
289
|
+
Raises:
|
290
|
+
UnsupportedCall: If :attr:`self._flag_t <pcapkit.foundation.extraction.Extractor._flag_t>`
|
291
|
+
is :data:`False`, as flow tracing is disabled.
|
292
|
+
|
293
|
+
"""
|
294
|
+
if self._flag_t:
|
295
|
+
data = TraceFlowData(
|
296
|
+
tcp=tuple(self._trace.tcp.index) if self._tcp else None,
|
297
|
+
)
|
298
|
+
return data
|
299
|
+
raise UnsupportedCall("'Extractor(trace=False)' object has no attribute 'trace'")
|
300
|
+
|
301
|
+
@property
|
302
|
+
def engine(self) -> 'Engine':
|
303
|
+
"""PCAP extraction engine."""
|
304
|
+
return self._exeng
|
305
|
+
|
306
|
+
@property
|
307
|
+
def magic_number(self) -> 'bytes':
|
308
|
+
"""Magic number of input PCAP file."""
|
309
|
+
return self._magic
|
310
|
+
|
311
|
+
##########################################################################
|
312
|
+
# Methods.
|
313
|
+
##########################################################################
|
314
|
+
|
315
|
+
@classmethod
|
316
|
+
def register_dumper(cls, format: 'str', dumper: 'ModuleDescriptor[Dumper] | Type[Dumper]', ext: 'str') -> 'None':
|
317
|
+
r"""Register a new dumper class.
|
318
|
+
|
319
|
+
Notes:
|
320
|
+
The full qualified class name of the new dumper class
|
321
|
+
should be as ``{dumper.module}.{dumper.name}``.
|
322
|
+
|
323
|
+
Arguments:
|
324
|
+
format: format name
|
325
|
+
dumper: module descriptor or a :class:`dictdumper.dumper.Dumper` subclass
|
326
|
+
ext: file extension
|
327
|
+
|
328
|
+
"""
|
329
|
+
if isinstance(dumper, ModuleDescriptor):
|
330
|
+
dumper = dumper.klass
|
331
|
+
if not issubclass(dumper, Dumper):
|
332
|
+
raise RegistryError(f'dumper must be a Dumper subclass, not {dumper!r}')
|
333
|
+
if format in cls.__output__:
|
334
|
+
warn(f'dumper {format} already registered, overwriting', RegistryWarning)
|
335
|
+
cls.__output__[format] = (dumper, ext)
|
336
|
+
|
337
|
+
@classmethod
|
338
|
+
def register_engine(cls, name: 'str', engine: 'ModuleDescriptor[Engine] | Type[Engine]') -> 'None':
|
339
|
+
r"""Register a new extraction engine.
|
340
|
+
|
341
|
+
Notes:
|
342
|
+
The full qualified class name of the new extraction engine
|
343
|
+
should be as ``{engine.module}.{engine.name}``.
|
344
|
+
|
345
|
+
Arguments:
|
346
|
+
name: engine name
|
347
|
+
engine: module descriptor or an
|
348
|
+
:class:`~pcapkit.foundation.engines.engine.Engine` subclass
|
349
|
+
|
350
|
+
"""
|
351
|
+
if isinstance(engine, ModuleDescriptor):
|
352
|
+
engine = engine.klass
|
353
|
+
if not issubclass(engine, Engine):
|
354
|
+
raise RegistryError(f'engine must be an Engine subclass, not {engine!r}')
|
355
|
+
if name in cls.__engine__:
|
356
|
+
warn(f'engine {name} already registered, overwriting', RegistryWarning)
|
357
|
+
cls.__engine__[name] = engine
|
358
|
+
|
359
|
+
@classmethod
|
360
|
+
def register_reassembly(cls, protocol: 'str', reassembly: 'ModuleDescriptor[Reassembly] | Type[Reassembly]') -> 'None':
|
361
|
+
r"""Register a new reassembly engine.
|
362
|
+
|
363
|
+
Notes:
|
364
|
+
The full qualified class name of the new reassembly engine
|
365
|
+
should be as ``{reassembly.module}.{reassembly.name}``.
|
366
|
+
|
367
|
+
Arguments:
|
368
|
+
protocol: protocol name
|
369
|
+
reassembly: module descriptor or a
|
370
|
+
:class:`~pcapkit.foundation.reassembly.reassembly.Reassembly` subclass
|
371
|
+
|
372
|
+
"""
|
373
|
+
if isinstance(reassembly, ModuleDescriptor):
|
374
|
+
reassembly = reassembly.klass
|
375
|
+
if not issubclass(reassembly, Reassembly):
|
376
|
+
raise RegistryError(f'reassembly must be a Reassembly subclass, not {reassembly!r}')
|
377
|
+
if protocol in cls.__reassembly__:
|
378
|
+
warn(f'reassembly {protocol} already registered, overwriting', RegistryWarning)
|
379
|
+
cls.__reassembly__[protocol] = reassembly
|
380
|
+
|
381
|
+
@classmethod
|
382
|
+
def register_traceflow(cls, protocol: 'str', traceflow: 'ModuleDescriptor[TraceFlow] | Type[TraceFlow]') -> 'None':
|
383
|
+
r"""Register a new flow tracing engine.
|
384
|
+
|
385
|
+
Notes:
|
386
|
+
The full qualified class name of the new flow tracing engine
|
387
|
+
should be as ``{traceflow.module}.{traceflow.name}``.
|
388
|
+
|
389
|
+
Arguments:
|
390
|
+
protocol: protocol name
|
391
|
+
traceflow: module descriptor or a
|
392
|
+
:class:`~pcapkit.foundation.traceflow.traceflow.TraceFlow` subclass
|
393
|
+
|
394
|
+
"""
|
395
|
+
if isinstance(traceflow, ModuleDescriptor):
|
396
|
+
traceflow = traceflow.klass
|
397
|
+
if not issubclass(traceflow, TraceFlow):
|
398
|
+
raise RegistryError(f'traceflow must be a TraceFlow subclass, not {traceflow!r}')
|
399
|
+
if protocol in cls.__traceflow__:
|
400
|
+
warn(f'traceflow {protocol} already registered, overwriting', RegistryWarning)
|
401
|
+
cls.__traceflow__[protocol] = traceflow
|
402
|
+
|
403
|
+
def run(self) -> 'None': # pylint: disable=inconsistent-return-statements
|
404
|
+
"""Start extraction.
|
405
|
+
|
406
|
+
We uses :meth:`~pcapkit.foundation.extraction.Extractor.import_test` to check if
|
407
|
+
a certain engine is available or not. For supported engines, each engine has
|
408
|
+
different driver method:
|
409
|
+
|
410
|
+
* Default drivers:
|
411
|
+
|
412
|
+
- PCAP Format: :class:`pcapkit.foundation.engines.pcap.PCAP`
|
413
|
+
- PCAP-NG Format: :class:`pcapkit.foundation.engines.pcapng.PCAPNG`
|
414
|
+
|
415
|
+
* DPKT driver: :class:`pcapkit.foundation.engines.dpkt.DPKT`
|
416
|
+
* Scapy driver: :class:`pcapkit.foundation.engines.scapy.Scapy`
|
417
|
+
* PyShark driver: :class:`pcapkit.foundation.engines.pyshark.PyShark`
|
418
|
+
|
419
|
+
Warns:
|
420
|
+
pcapkit.utilities.warnings.EngineWarning: If the extraction engine is not
|
421
|
+
available. This is either due to dependency not installed, or supplied
|
422
|
+
engine unknown.
|
423
|
+
|
424
|
+
:rtype: None
|
425
|
+
"""
|
426
|
+
if self._exnam in self.__engine__: # check if engine is supported
|
427
|
+
eng = self.__engine__[self._exnam]
|
428
|
+
if isinstance(eng, ModuleDescriptor):
|
429
|
+
eng = eng.klass
|
430
|
+
|
431
|
+
if self.import_test(eng.module, name=eng.name) is not None: # type: ignore[arg-type]
|
432
|
+
self._exeng = eng(self)
|
433
|
+
self._exeng.run()
|
434
|
+
|
435
|
+
# start iteration
|
436
|
+
self.record_frames()
|
437
|
+
return
|
438
|
+
|
439
|
+
warn(f'engine {eng.name} (`{eng.module}`) is not installed; '
|
440
|
+
'using default engine instead', EngineWarning, stacklevel=stacklevel())
|
441
|
+
self._exnam = 'default' # using default/pcapkit engine
|
442
|
+
|
443
|
+
if self._exnam not in ('default', 'pcapkit'):
|
444
|
+
warn(f'unsupported extraction engine: {self._exnam}; '
|
445
|
+
'using default engine instead', EngineWarning, stacklevel=stacklevel())
|
446
|
+
self._exnam = 'default' # using default/pcapkit engine
|
447
|
+
|
448
|
+
if self._magic in PCAP_Engine.MAGIC_NUMBER:
|
449
|
+
self._exeng = cast('Engine[_P]', PCAP_Engine(self))
|
450
|
+
elif self._magic in PCAPNG_Engine.MAGIC_NUMBER:
|
451
|
+
self._exeng = cast('Engine[_P]', PCAPNG_Engine(self))
|
452
|
+
else:
|
453
|
+
raise FormatError(f'unknown file format: {self._magic!r}')
|
454
|
+
|
455
|
+
# start engine
|
456
|
+
self._exeng.run()
|
457
|
+
|
458
|
+
# start iteration
|
459
|
+
self.record_frames()
|
460
|
+
|
461
|
+
@staticmethod
|
462
|
+
def import_test(engine: 'str', *, name: 'Optional[str]' = None) -> 'Optional[ModuleType]':
|
463
|
+
"""Test import for extractcion engine.
|
464
|
+
|
465
|
+
Args:
|
466
|
+
engine: Extraction engine module name.
|
467
|
+
name: Extraction engine display name.
|
468
|
+
|
469
|
+
Warns:
|
470
|
+
pcapkit.utilities.warnings.EngineWarning: If the engine module is not installed.
|
471
|
+
|
472
|
+
Returns:
|
473
|
+
If succeeded, returns the module; otherwise, returns :data:`None`.
|
474
|
+
|
475
|
+
"""
|
476
|
+
try:
|
477
|
+
module = importlib.import_module(engine)
|
478
|
+
except ImportError:
|
479
|
+
module = None
|
480
|
+
warn(f"extraction engine '{name or engine}' not available; "
|
481
|
+
'using default engine instead', EngineWarning, stacklevel=stacklevel())
|
482
|
+
return module
|
483
|
+
|
484
|
+
@classmethod
|
485
|
+
def make_name(cls, fin: 'str | IO[bytes]' = 'in.pcap', fout: 'str' = 'out',
|
486
|
+
fmt: 'Formats' = 'tree', extension: 'bool' = True, *, files: 'bool' = False,
|
487
|
+
nofile: 'bool' = False) -> 'tuple[str, Optional[str], Formats, Optional[str], bool]':
|
488
|
+
"""Generate input and output filenames.
|
489
|
+
|
490
|
+
The method will perform following processing:
|
491
|
+
|
492
|
+
1. sanitise ``fin`` as the input PCAP filename; ``in.pcap`` as default value and
|
493
|
+
append ``.pcap`` extension if needed and ``extension`` is :data:`True`; as well
|
494
|
+
as test if the file exists;
|
495
|
+
2. if ``nofile`` is :data:`True`, skips following processing;
|
496
|
+
3. if ``fmt`` provided, then it presumes corresponding output file extension;
|
497
|
+
4. if ``fout`` not provided, it presumes the output file name based on the presumptive
|
498
|
+
file extension; the stem of the output file name is set as ``out``; should the file
|
499
|
+
extension is not available, then it raises :exc:`~pcapkit.utilities.exceptions.FormatError`;
|
500
|
+
5. if ``fout`` provided, it presumes corresponding output format if needed; should the
|
501
|
+
presumption cannot be made, then it raises :exc:`~pcapkit.utilities.exceptions.FormatError`;
|
502
|
+
6. it will also append corresponding file extension to the output file name if needed
|
503
|
+
and ``extension`` is :data:`True`.
|
504
|
+
|
505
|
+
And the method returns the generated input and output filenames as follows:
|
506
|
+
|
507
|
+
0. input filename
|
508
|
+
1. output filename / directory name
|
509
|
+
2. output format
|
510
|
+
3. output file extension (without ``.``)
|
511
|
+
4. if split each frame into different files
|
512
|
+
|
513
|
+
Args:
|
514
|
+
fin: Input filename or a binary IO object.
|
515
|
+
fout: Output filename.
|
516
|
+
fmt: Output file format.
|
517
|
+
extension: If append ``.pcap`` file extension to the input filename
|
518
|
+
if ``fin`` does not have such file extension; if check and append extensions
|
519
|
+
to output file.
|
520
|
+
files: If split each frame into different files.
|
521
|
+
nofile: If no output file is to be dumped.
|
522
|
+
|
523
|
+
Returns:
|
524
|
+
Generated input and output filenames.
|
525
|
+
|
526
|
+
Raises:
|
527
|
+
FileNotFound: If input file does not exists.
|
528
|
+
FormatError: If output format not provided and cannot be presumpted.
|
529
|
+
|
530
|
+
"""
|
531
|
+
if isinstance(fin, str):
|
532
|
+
if extension: # pylint: disable=else-if-used
|
533
|
+
ifnm = fin if os.path.splitext(fin)[1] in cls.PCAP_EXT else f'{fin}.pcap'
|
534
|
+
else:
|
535
|
+
ifnm = fin
|
536
|
+
|
537
|
+
if not os.path.isfile(ifnm):
|
538
|
+
raise FileNotFound(2, 'No such file or directory', ifnm)
|
539
|
+
else:
|
540
|
+
ifnm = fin.name
|
541
|
+
|
542
|
+
if nofile:
|
543
|
+
ofnm = None
|
544
|
+
ext = None
|
545
|
+
else:
|
546
|
+
ext = cls.__output__[fmt][1]
|
547
|
+
if ext is None:
|
548
|
+
raise FormatError(f'unknown output format: {fmt}')
|
549
|
+
|
550
|
+
if (parent := os.path.split(fout)[0]):
|
551
|
+
os.makedirs(parent, exist_ok=True)
|
552
|
+
|
553
|
+
if files:
|
554
|
+
ofnm = fout
|
555
|
+
os.makedirs(ofnm, exist_ok=True)
|
556
|
+
elif extension:
|
557
|
+
ofnm = fout if os.path.splitext(fout)[1] == ext else f'{fout}{ext}'
|
558
|
+
else:
|
559
|
+
ofnm = fout
|
560
|
+
|
561
|
+
return ifnm, ofnm, fmt, ext, files
|
562
|
+
|
563
|
+
def record_header(self) -> 'Engine':
|
564
|
+
"""Read global header.
|
565
|
+
|
566
|
+
The method will parse the PCAP global header and save the parsed result
|
567
|
+
to its extraction context. Information such as PCAP version, data link
|
568
|
+
layer protocol type, nanosecond flag and byteorder will also be save
|
569
|
+
the current :class:`~pcapkit.foundation.engins.engine.Engine` instance
|
570
|
+
as well.
|
571
|
+
|
572
|
+
If TCP flow tracing is enabled, the nanosecond flag and byteorder will
|
573
|
+
be used for the output PCAP file of the traced TCP flows.
|
574
|
+
|
575
|
+
For output, the method will dump the parsed PCAP global header under
|
576
|
+
the name of ``Global Header``.
|
577
|
+
|
578
|
+
"""
|
579
|
+
# pylint: disable=attribute-defined-outside-init,protected-access
|
580
|
+
if self._magic in PCAP_Engine.MAGIC_NUMBER:
|
581
|
+
engine = PCAP_Engine(self)
|
582
|
+
engine.run()
|
583
|
+
|
584
|
+
self._ifile.seek(0, os.SEEK_SET)
|
585
|
+
return engine # type: ignore[return-value]
|
586
|
+
|
587
|
+
if self._magic in PCAPNG_Engine.MAGIC_NUMBER:
|
588
|
+
engine = PCAPNG_Engine(self) # type: ignore[assignment]
|
589
|
+
engine.run()
|
590
|
+
|
591
|
+
self._ifile.seek(0, os.SEEK_SET)
|
592
|
+
return engine # type: ignore[return-value]
|
593
|
+
|
594
|
+
raise FormatError(f'unknown file format: {self._magic!r}')
|
595
|
+
|
596
|
+
def record_frames(self) -> 'None':
|
597
|
+
"""Read packet frames.
|
598
|
+
|
599
|
+
The method calls :meth:`self._exeng.read_frame <pcapkit.foundation.engines.engine.Engine.read_frame>`
|
600
|
+
to parse each frame from the input PCAP file; and
|
601
|
+
performs cleanup by calling :meth:`self._exeng.close <pcapkit.foundation.engines.engine.Engine.close>`
|
602
|
+
upon completion of the parsing process.
|
603
|
+
|
604
|
+
Notes:
|
605
|
+
Under non-auto mode, i.e. :attr:`self._flag_a <Extractor._flag_a>` is
|
606
|
+
:data:`False`, the method performs no action.
|
607
|
+
|
608
|
+
"""
|
609
|
+
if self._flag_a:
|
610
|
+
while True:
|
611
|
+
try:
|
612
|
+
self._exeng.read_frame()
|
613
|
+
except (EOFError, StopIteration):
|
614
|
+
warn('EOF reached', ExtractionWarning, stacklevel=stacklevel())
|
615
|
+
|
616
|
+
if self._flag_n:
|
617
|
+
continue
|
618
|
+
|
619
|
+
# quit when EOF
|
620
|
+
break
|
621
|
+
except KeyboardInterrupt:
|
622
|
+
self._cleanup()
|
623
|
+
raise
|
624
|
+
|
625
|
+
self._cleanup()
|
626
|
+
|
627
|
+
##########################################################################
|
628
|
+
# Data models.
|
629
|
+
##########################################################################
|
630
|
+
|
631
|
+
def __init__(self,
|
632
|
+
fin: 'Optional[str | IO[bytes]]' = None, fout: 'Optional[str]' = None, format: 'Optional[Formats]' = None, # basic settings # pylint: disable=redefined-builtin
|
633
|
+
auto: 'bool' = True, extension: 'bool' = True, store: 'bool' = True, # internal settings # pylint: disable=line-too-long
|
634
|
+
files: 'bool' = False, nofile: 'bool' = False, verbose: 'bool | VerboseHandler' = False, # output settings # pylint: disable=line-too-long
|
635
|
+
engine: 'Optional[Engines]' = None, layer: 'Optional[Layers]' = None, protocol: 'Optional[Protocols]' = None, # extraction settings # pylint: disable=line-too-long
|
636
|
+
reassembly: 'bool' = False, reasm_strict: 'bool' = True, reasm_store: 'bool' = True, # reassembly settings # pylint: disable=line-too-long
|
637
|
+
trace: 'bool' = False, trace_fout: 'Optional[str]' = None, trace_format: 'Optional[Formats]' = None, # trace settings # pylint: disable=line-too-long
|
638
|
+
trace_byteorder: 'Literal["big", "little"]' = sys.byteorder, trace_nanosecond: 'bool' = False, # trace settings # pylint: disable=line-too-long
|
639
|
+
ip: 'bool' = False, ipv4: 'bool' = False, ipv6: 'bool' = False, tcp: 'bool' = False, # reassembly/trace settings # pylint: disable=line-too-long
|
640
|
+
buffer_size: 'int' = io.DEFAULT_BUFFER_SIZE, buffer_save: 'bool' = False, buffer_path: 'Optional[str]' = None, # buffer settings # pylint: disable=line-too-long
|
641
|
+
no_eof: 'bool' = False) -> 'None':
|
642
|
+
"""Initialise PCAP Reader.
|
643
|
+
|
644
|
+
Args:
|
645
|
+
fin: file name to be read or a binary IO object;
|
646
|
+
if file not exist, raise :exc:`FileNotFound`
|
647
|
+
fout: file name to be written
|
648
|
+
format: file format of output
|
649
|
+
|
650
|
+
auto: if automatically run till EOF
|
651
|
+
extension: if check and append extensions to output file
|
652
|
+
store: if store extracted packet info
|
653
|
+
|
654
|
+
files: if split each frame into different files
|
655
|
+
nofile: if no output file is to be dumped
|
656
|
+
verbose: a :obj:`bool` value or a function takes the :class:`Extractor`
|
657
|
+
instance and current parsed frame (depends on engine selected) as
|
658
|
+
parameters to print verbose output information
|
659
|
+
|
660
|
+
engine: extraction engine to be used
|
661
|
+
layer: extract til which layer
|
662
|
+
protocol: extract til which protocol
|
663
|
+
|
664
|
+
reassembly: if perform reassembly
|
665
|
+
reasm_strict: if set strict flag for reassembly
|
666
|
+
reasm_store: if store reassembled datagrams
|
667
|
+
|
668
|
+
trace: if trace TCP traffic flows
|
669
|
+
trace_fout: path name for flow tracer if necessary
|
670
|
+
trace_format: output file format of flow tracer
|
671
|
+
trace_byteorder: output file byte order
|
672
|
+
trace_nanosecond: output nanosecond-resolution file flag
|
673
|
+
|
674
|
+
ip: if record data for IPv4 & IPv6 reassembly (must be used with ``reassembly=True``)
|
675
|
+
ipv4: if perform IPv4 reassembly (must be used with ``reassembly=True``)
|
676
|
+
ipv6: if perform IPv6 reassembly (must be used with ``reassembly=True``)
|
677
|
+
tcp: if perform TCP reassembly and/or flow tracing
|
678
|
+
(must be used with ``reassembly=True`` or ``trace=True``)
|
679
|
+
|
680
|
+
buffer_size: buffer size for reading input file (for :class:`~pcapkit.corekit.io.SeekableReader` only)
|
681
|
+
buffer_save: if save buffer to file (for :class:`~pcapkit.corekit.io.SeekableReader` only)
|
682
|
+
buffer_path: path name for buffer file if necessary (for :class:`~pcapkit.corekit.io.SeekableReader` only)
|
683
|
+
|
684
|
+
no_eof: if raise :exc:`EOFError` when EOF
|
685
|
+
|
686
|
+
Warns:
|
687
|
+
pcapkit.utilities.warnings.FormatWarning: Warns under following circumstances:
|
688
|
+
|
689
|
+
* If using PCAP output for TCP flow tracing while the extraction engine is PyShark.
|
690
|
+
* If output file format is not supported.
|
691
|
+
|
692
|
+
"""
|
693
|
+
if fin is None:
|
694
|
+
fin = 'in.pcap'
|
695
|
+
if fout is None:
|
696
|
+
fout = 'out'
|
697
|
+
if format is None:
|
698
|
+
format = 'tree'
|
699
|
+
|
700
|
+
ifnm, ofnm, fmt, oext, files = self.make_name(fin, fout, format, extension, files=files, nofile=nofile)
|
701
|
+
|
702
|
+
self._ifnm = ifnm # input file name
|
703
|
+
self._ofnm = ofnm # output file name
|
704
|
+
self._fext = oext # output file extension
|
705
|
+
|
706
|
+
self._flag_a = auto # auto extract flag
|
707
|
+
self._flag_d = store # store data flag
|
708
|
+
self._flag_e = False # EOF flag
|
709
|
+
self._flag_f = files # split file flag
|
710
|
+
self._flag_q = nofile # no output flag
|
711
|
+
self._flag_r = reassembly # reassembly flag
|
712
|
+
self._flag_t = trace # trace flag
|
713
|
+
self._flag_v = False # verbose flag
|
714
|
+
self._flag_s = isinstance(fin, str) # input filename flag
|
715
|
+
self._flag_n = no_eof # no EOF flag
|
716
|
+
|
717
|
+
# verbose callback function
|
718
|
+
if isinstance(verbose, bool):
|
719
|
+
self._flag_v = verbose
|
720
|
+
if verbose:
|
721
|
+
self._vfunc = lambda e, f: print(
|
722
|
+
f'Frame {e._frnum:>3d}: {f.protochain}' # pylint: disable=protected-access
|
723
|
+
) # pylint: disable=logging-fstring-interpolation
|
724
|
+
else:
|
725
|
+
self._vfunc = lambda e, f: None
|
726
|
+
else:
|
727
|
+
self._flag_v = True
|
728
|
+
self._vfunc = verbose
|
729
|
+
|
730
|
+
self._frnum = 0 # frame number
|
731
|
+
self._frame = [] # frame record
|
732
|
+
|
733
|
+
self._ipv4 = ipv4 or ip # IPv4 Reassembly
|
734
|
+
self._ipv6 = ipv6 or ip # IPv6 Reassembly
|
735
|
+
self._tcp = tcp # TCP Reassembly
|
736
|
+
|
737
|
+
self._exptl = protocol or 'null' # extract til protocol
|
738
|
+
self._exlyr = cast('Layers', (layer or 'none').lower()) # extract til layer
|
739
|
+
self._exnam = cast('Engines', (engine or 'default').lower()) # extract using engine
|
740
|
+
|
741
|
+
if reassembly:
|
742
|
+
reasm_obj_ipv4 = reasm_obj_ipv6 = reasm_obj_tcp = None
|
743
|
+
|
744
|
+
if self._ipv4:
|
745
|
+
logger.info('IPv4 reassembly enabled')
|
746
|
+
|
747
|
+
reasm_cls_ipv4 = self.__reassembly__['ipv4']
|
748
|
+
if isinstance(reasm_cls_ipv4, ModuleDescriptor):
|
749
|
+
reasm_cls_ipv4 = reasm_cls_ipv4.klass
|
750
|
+
self.__reassembly__['ipv4'] = reasm_cls_ipv4 # update mapping upon import
|
751
|
+
reasm_obj_ipv4 = cast('IPv4_Reassembly', reasm_cls_ipv4(strict=reasm_strict, store=reasm_store))
|
752
|
+
if self._ipv6:
|
753
|
+
logger.info('IPv6 reassembly enabled')
|
754
|
+
|
755
|
+
reasm_cls_ipv6 = self.__reassembly__['ipv6']
|
756
|
+
if isinstance(reasm_cls_ipv6, ModuleDescriptor):
|
757
|
+
reasm_cls_ipv6 = reasm_cls_ipv6.klass
|
758
|
+
self.__reassembly__['ipv6'] = reasm_cls_ipv6 # update mapping upon import
|
759
|
+
reasm_obj_ipv6 = cast('IPv6_Reassembly', reasm_cls_ipv6(strict=reasm_strict, store=reasm_store))
|
760
|
+
if self._tcp:
|
761
|
+
logger.info('TCP reassembly enabled')
|
762
|
+
|
763
|
+
reasm_cls_tcp = self.__reassembly__['tcp']
|
764
|
+
if isinstance(reasm_cls_tcp, ModuleDescriptor):
|
765
|
+
reasm_cls_tcp = reasm_cls_tcp.klass
|
766
|
+
self.__reassembly__['tcp'] = reasm_cls_tcp # update mapping upon import
|
767
|
+
reasm_obj_tcp = cast('TCP_Reassembly', reasm_cls_tcp(strict=reasm_strict, store=reasm_store))
|
768
|
+
|
769
|
+
self._reasm = ReassemblyManager(
|
770
|
+
ipv4=reasm_obj_ipv4,
|
771
|
+
ipv6=reasm_obj_ipv6,
|
772
|
+
tcp=reasm_obj_tcp,
|
773
|
+
)
|
774
|
+
|
775
|
+
if trace:
|
776
|
+
trace_obj_tcp = None
|
777
|
+
|
778
|
+
if self._exnam in ('pyshark',) and trace_format in ('pcap',):
|
779
|
+
warn(f"'Extractor(engine={self._exnam})' does not support 'trace_format={trace_format}'; "
|
780
|
+
"using 'trace_format=None' instead", FormatWarning, stacklevel=stacklevel())
|
781
|
+
trace_format = None
|
782
|
+
|
783
|
+
if self._tcp:
|
784
|
+
logger.info('TCP flow tracing enabled')
|
785
|
+
|
786
|
+
trace_cls_tcp = self.__traceflow__['tcp']
|
787
|
+
if isinstance(trace_cls_tcp, ModuleDescriptor):
|
788
|
+
trace_cls_tcp = trace_cls_tcp.klass
|
789
|
+
self.__traceflow__['tcp'] = trace_cls_tcp # update mapping upon import
|
790
|
+
trace_obj_tcp = cast('TCP_TraceFlow', trace_cls_tcp(fout=trace_fout, format=trace_format,
|
791
|
+
byteorder=trace_byteorder, nanosecond=trace_nanosecond))
|
792
|
+
|
793
|
+
self._trace = TraceFlowManager(
|
794
|
+
tcp=trace_obj_tcp,
|
795
|
+
)
|
796
|
+
|
797
|
+
if self._flag_s:
|
798
|
+
self._ifile = open(ifnm, 'rb') # input file # pylint: disable=unspecified-encoding,consider-using-with
|
799
|
+
else:
|
800
|
+
self._ifile = cast('BufferedReader', fin)
|
801
|
+
|
802
|
+
if not self._ifile.seekable():
|
803
|
+
self._ifile = SeekableReader(self._ifile, buffer_size, buffer_save, buffer_path,
|
804
|
+
stream_closing=not self._flag_s)
|
805
|
+
|
806
|
+
if not self._flag_q:
|
807
|
+
output, ext = self.__output__[fmt]
|
808
|
+
if ext is None:
|
809
|
+
warn(f'Unsupported output format: {fmt}; disabled file output feature',
|
810
|
+
FormatWarning, stacklevel=stacklevel())
|
811
|
+
if isinstance(output, ModuleDescriptor):
|
812
|
+
output = output.klass
|
813
|
+
self.__output__[fmt] = (output, ext) # update mapping upon import
|
814
|
+
dumper = make_dumper(output)
|
815
|
+
|
816
|
+
self._ofile = dumper if self._flag_f else dumper(ofnm) # output file
|
817
|
+
|
818
|
+
# NOTE: we use peek() to read the magic number, as the file pointer
|
819
|
+
# will not be moved after reading; however, the returned bytes object
|
820
|
+
# may not be exactly 4 bytes, so we use [:4] to get the first 4 bytes
|
821
|
+
self._magic = self._ifile.peek(4)[:4]
|
822
|
+
#self._magic = self._ifile.read(4) # magic number
|
823
|
+
#self._ifile.seek(0, os.SEEK_SET)
|
824
|
+
|
825
|
+
self.run() # start extraction
|
826
|
+
|
827
|
+
def __iter__(self) -> 'Extractor':
|
828
|
+
"""Iterate and parse PCAP frame.
|
829
|
+
|
830
|
+
Raises:
|
831
|
+
IterableError: If :attr:`self._flag_a <pcapkit.foundation.extraction.Extractor._flag_a>`
|
832
|
+
is :data:`True`, as such operation is not applicable.
|
833
|
+
|
834
|
+
"""
|
835
|
+
if not self._flag_a:
|
836
|
+
return self
|
837
|
+
raise IterableError("'Extractor(auto=True)' object is not iterable")
|
838
|
+
|
839
|
+
def __next__(self) -> '_P':
|
840
|
+
"""Iterate and parse next PCAP frame.
|
841
|
+
|
842
|
+
It will call :meth:`self._exeng.read_frame <pcapkit.foundation.engines.engine.Engine.read_frame>`
|
843
|
+
to parse next PCAP frame internally, until the EOF reached;
|
844
|
+
then it calls :meth:`self._cleanup <_cleanup>` for the aftermath.
|
845
|
+
|
846
|
+
"""
|
847
|
+
while True:
|
848
|
+
try:
|
849
|
+
return self._exeng.read_frame()
|
850
|
+
except (EOFError, StopIteration) as error:
|
851
|
+
warn('EOF reached', ExtractionWarning, stacklevel=stacklevel())
|
852
|
+
|
853
|
+
if self._flag_n:
|
854
|
+
continue
|
855
|
+
|
856
|
+
self._cleanup()
|
857
|
+
raise StopIteration from error # pylint: disable=raise-missing-from
|
858
|
+
except KeyboardInterrupt:
|
859
|
+
self._cleanup()
|
860
|
+
raise
|
861
|
+
|
862
|
+
def __call__(self) -> '_P':
|
863
|
+
"""Works as a simple wrapper for the iteration protocol.
|
864
|
+
|
865
|
+
Raises:
|
866
|
+
IterableError: If :attr:`self._flag_a <pcapkit.foundation.extraction.Extractor._flag_a>`
|
867
|
+
is :data:`True`, as iteration is not applicable.
|
868
|
+
|
869
|
+
"""
|
870
|
+
if not self._flag_a:
|
871
|
+
while True:
|
872
|
+
try:
|
873
|
+
return self._exeng.read_frame()
|
874
|
+
except (EOFError, StopIteration):
|
875
|
+
warn('EOF reached', ExtractionWarning, stacklevel=stacklevel())
|
876
|
+
|
877
|
+
if self._flag_n:
|
878
|
+
continue
|
879
|
+
|
880
|
+
self._cleanup()
|
881
|
+
raise
|
882
|
+
except KeyboardInterrupt:
|
883
|
+
self._cleanup()
|
884
|
+
raise
|
885
|
+
raise CallableError("'Extractor(auto=True)' object is not callable")
|
886
|
+
|
887
|
+
def __enter__(self) -> 'Extractor':
|
888
|
+
"""Uses :class:`Extractor` as a context manager."""
|
889
|
+
return self
|
890
|
+
|
891
|
+
def __exit__(self, exc_type: 'Type[BaseException] | None', exc_value: 'BaseException | None',
|
892
|
+
traceback: 'TracebackType | None') -> 'None': # pylint: disable=unused-argument
|
893
|
+
"""Close the input file when exits."""
|
894
|
+
self._ifile.close()
|
895
|
+
self._exeng.close()
|
896
|
+
|
897
|
+
##########################################################################
|
898
|
+
# Utilities.
|
899
|
+
##########################################################################
|
900
|
+
|
901
|
+
def _cleanup(self) -> 'None':
|
902
|
+
"""Cleanup after extraction & analysis.
|
903
|
+
|
904
|
+
The method calls :meth:`self._exeng.close <pcapkit.foundation.engines.engine.Engine.close>`,
|
905
|
+
sets :attr:`self._flag_e <pcapkit.foundation.extraction.Extractor._flag_e>`
|
906
|
+
as :data:`True` and closes the input file (if necessary).
|
907
|
+
|
908
|
+
"""
|
909
|
+
# pylint: disable=attribute-defined-outside-init
|
910
|
+
self._flag_e = True
|
911
|
+
if isinstance(self._ifile, SeekableReader):
|
912
|
+
self._ifile.close()
|
913
|
+
elif not self._flag_s:
|
914
|
+
self._ifile.close()
|
915
|
+
self._exeng.close()
|