pypcapkit 1.3.3.post1__cp313-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pcapkit/__init__.py +126 -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 +294 -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 +66 -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 +32702 -0
- pcapkit/const/reg/ethertype.py +714 -0
- pcapkit/const/reg/linktype.py +902 -0
- pcapkit/const/reg/transtype.py +523 -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 +240 -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 +361 -0
- pcapkit/protocols/internet/ipv6_frag.py +258 -0
- pcapkit/protocols/internet/ipv6_opts.py +1890 -0
- pcapkit/protocols/internet/ipv6_route.py +710 -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 +198 -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 +192 -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.3.post1.dist-info/LICENSE +29 -0
- pypcapkit-1.3.3.post1.dist-info/METADATA +236 -0
- pypcapkit-1.3.3.post1.dist-info/RECORD +466 -0
- pypcapkit-1.3.3.post1.dist-info/WHEEL +5 -0
- pypcapkit-1.3.3.post1.dist-info/entry_points.txt +3 -0
- pypcapkit-1.3.3.post1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,3025 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# mypy: disable-error-code=dict-item
|
3
|
+
"""TCP - Transmission Control Protocol
|
4
|
+
=========================================
|
5
|
+
|
6
|
+
.. module:: pcapkit.protocols.transport.tcp
|
7
|
+
|
8
|
+
:mod:`pcapkit.protocols.transport.tcp` contains
|
9
|
+
:class:`~pcapkit.protocols.transport.tcp.TCP` only,
|
10
|
+
which implements extractor for Transmission Control
|
11
|
+
Protocol (TCP) [*]_, whose structure is described as
|
12
|
+
below:
|
13
|
+
|
14
|
+
======= ========= ========================= =======================================
|
15
|
+
Octets Bits Name Description
|
16
|
+
======= ========= ========================= =======================================
|
17
|
+
0 0 ``tcp.srcport`` Source Port
|
18
|
+
2 16 ``tcp.dstport`` Destination Port
|
19
|
+
4 32 ``tcp.seq`` Sequence Number
|
20
|
+
8 64 ``tcp.ack`` Acknowledgement Number (if ACK set)
|
21
|
+
12 96 ``tcp.hdr_len`` Data Offset
|
22
|
+
12 100 Reserved (must be ``\\x00``)
|
23
|
+
12 103 ``tcp.flags.ns`` ECN Concealment Protection (NS)
|
24
|
+
13 104 ``tcp.flags.cwr`` Congestion Window Reduced (CWR)
|
25
|
+
13 105 ``tcp.flags.ece`` ECN-Echo (ECE)
|
26
|
+
13 106 ``tcp.flags.urg`` Urgent (URG)
|
27
|
+
13 107 ``tcp.flags.ack`` Acknowledgement (ACK)
|
28
|
+
13 108 ``tcp.flags.psh`` Push Function (PSH)
|
29
|
+
13 109 ``tcp.flags.rst`` Reset Connection (RST)
|
30
|
+
13 110 ``tcp.flags.syn`` Synchronize Sequence Numbers (SYN)
|
31
|
+
13 111 ``tcp.flags.fin`` Last Packet from Sender (FIN)
|
32
|
+
14 112 ``tcp.window_size`` Size of Receive Window
|
33
|
+
16 128 ``tcp.checksum`` Checksum
|
34
|
+
18 144 ``tcp.urgent_pointer`` Urgent Pointer (if URG set)
|
35
|
+
20 160 ``tcp.opt`` TCP Options (if data offset > 5)
|
36
|
+
======= ========= ========================= =======================================
|
37
|
+
|
38
|
+
.. [*] https://en.wikipedia.org/wiki/Transmission_Control_Protocol
|
39
|
+
|
40
|
+
"""
|
41
|
+
import collections
|
42
|
+
import datetime
|
43
|
+
import ipaddress
|
44
|
+
import math
|
45
|
+
from typing import TYPE_CHECKING, cast
|
46
|
+
|
47
|
+
from pcapkit.const.reg.transtype import TransType
|
48
|
+
from pcapkit.const.tcp.checksum import Checksum as Enum_Checksum
|
49
|
+
from pcapkit.const.tcp.flags import Flags as Enum_Flags
|
50
|
+
from pcapkit.const.tcp.mp_tcp_option import MPTCPOption as Enum_MPTCPOption
|
51
|
+
from pcapkit.const.tcp.option import Option as Enum_Option
|
52
|
+
from pcapkit.corekit.module import ModuleDescriptor
|
53
|
+
from pcapkit.corekit.multidict import OrderedMultiDict
|
54
|
+
from pcapkit.protocols.data.transport.tcp import CC as Data_CC
|
55
|
+
from pcapkit.protocols.data.transport.tcp import MPTCPDSS as Data_MPTCPDSS
|
56
|
+
from pcapkit.protocols.data.transport.tcp import SACK as Data_SACK
|
57
|
+
from pcapkit.protocols.data.transport.tcp import TCP as Data_TCP
|
58
|
+
from pcapkit.protocols.data.transport.tcp import AlternateChecksumData as Data_AlternateChecksumData
|
59
|
+
from pcapkit.protocols.data.transport.tcp import \
|
60
|
+
AlternateChecksumRequest as Data_AlternateChecksumRequest
|
61
|
+
from pcapkit.protocols.data.transport.tcp import Authentication as Data_Authentication
|
62
|
+
from pcapkit.protocols.data.transport.tcp import CCEcho as Data_CCEcho
|
63
|
+
from pcapkit.protocols.data.transport.tcp import CCNew as Data_CCNew
|
64
|
+
from pcapkit.protocols.data.transport.tcp import Echo as Data_Echo
|
65
|
+
from pcapkit.protocols.data.transport.tcp import EchoReply as Data_EchoReply
|
66
|
+
from pcapkit.protocols.data.transport.tcp import EndOfOptionList as Data_EndOfOptionList
|
67
|
+
from pcapkit.protocols.data.transport.tcp import FastOpenCookie as Data_FastOpenCookie
|
68
|
+
from pcapkit.protocols.data.transport.tcp import Flags as Data_Flags
|
69
|
+
from pcapkit.protocols.data.transport.tcp import MaximumSegmentSize as Data_MaximumSegmentSize
|
70
|
+
from pcapkit.protocols.data.transport.tcp import MD5Signature as Data_MD5Signature
|
71
|
+
from pcapkit.protocols.data.transport.tcp import MPTCPAddAddress as Data_MPTCPAddAddress
|
72
|
+
from pcapkit.protocols.data.transport.tcp import MPTCPCapable as Data_MPTCPCapable
|
73
|
+
from pcapkit.protocols.data.transport.tcp import MPTCPCapableFlag as Data_MPTCPCapableFlag
|
74
|
+
from pcapkit.protocols.data.transport.tcp import MPTCPFallback as Data_MPTCPFallback
|
75
|
+
from pcapkit.protocols.data.transport.tcp import MPTCPFastclose as Data_MPTCPFastclose
|
76
|
+
from pcapkit.protocols.data.transport.tcp import MPTCPJoinACK as Data_MPTCPJoinACK
|
77
|
+
from pcapkit.protocols.data.transport.tcp import MPTCPJoinSYN as Data_MPTCPJoinSYN
|
78
|
+
from pcapkit.protocols.data.transport.tcp import MPTCPJoinSYNACK as Data_MPTCPJoinSYNACK
|
79
|
+
from pcapkit.protocols.data.transport.tcp import MPTCPPriority as Data_MPTCPPriority
|
80
|
+
from pcapkit.protocols.data.transport.tcp import MPTCPRemoveAddress as Data_MPTCPRemoveAddress
|
81
|
+
from pcapkit.protocols.data.transport.tcp import MPTCPUnknown as Data_MPTCPUnknown
|
82
|
+
from pcapkit.protocols.data.transport.tcp import NoOperation as Data_NoOperation
|
83
|
+
from pcapkit.protocols.data.transport.tcp import \
|
84
|
+
PartialOrderConnectionPermitted as Data_PartialOrderConnectionPermitted
|
85
|
+
from pcapkit.protocols.data.transport.tcp import \
|
86
|
+
PartialOrderServiceProfile as Data_PartialOrderServiceProfile
|
87
|
+
from pcapkit.protocols.data.transport.tcp import QuickStartResponse as Data_QuickStartResponse
|
88
|
+
from pcapkit.protocols.data.transport.tcp import SACKBlock as Data_SACKBlock
|
89
|
+
from pcapkit.protocols.data.transport.tcp import SACKPermitted as Data_SACKPermitted
|
90
|
+
from pcapkit.protocols.data.transport.tcp import Timestamps as Data_Timestamps
|
91
|
+
from pcapkit.protocols.data.transport.tcp import UnassignedOption as Data_UnassignedOption
|
92
|
+
from pcapkit.protocols.data.transport.tcp import UserTimeout as Data_UserTimeout
|
93
|
+
from pcapkit.protocols.data.transport.tcp import WindowScale as Data_WindowScale
|
94
|
+
from pcapkit.protocols.schema.transport.tcp import CC as Schema_CC
|
95
|
+
from pcapkit.protocols.schema.transport.tcp import MPTCPDSS as Schema_MPTCPDSS
|
96
|
+
from pcapkit.protocols.schema.transport.tcp import SACK as Schema_SACK
|
97
|
+
from pcapkit.protocols.schema.transport.tcp import TCP as Schema_TCP
|
98
|
+
from pcapkit.protocols.schema.transport.tcp import \
|
99
|
+
AlternateChecksumData as Schema_AlternateChecksumData
|
100
|
+
from pcapkit.protocols.schema.transport.tcp import \
|
101
|
+
AlternateChecksumRequest as Schema_AlternateChecksumRequest
|
102
|
+
from pcapkit.protocols.schema.transport.tcp import Authentication as Schema_Authentication
|
103
|
+
from pcapkit.protocols.schema.transport.tcp import CCEcho as Schema_CCEcho
|
104
|
+
from pcapkit.protocols.schema.transport.tcp import CCNew as Schema_CCNew
|
105
|
+
from pcapkit.protocols.schema.transport.tcp import Echo as Schema_Echo
|
106
|
+
from pcapkit.protocols.schema.transport.tcp import EchoReply as Schema_EchoReply
|
107
|
+
from pcapkit.protocols.schema.transport.tcp import EndOfOptionList as Schema_EndOfOptionList
|
108
|
+
from pcapkit.protocols.schema.transport.tcp import FastOpenCookie as Schema_FastOpenCookie
|
109
|
+
from pcapkit.protocols.schema.transport.tcp import MaximumSegmentSize as Schema_MaximumSegmentSize
|
110
|
+
from pcapkit.protocols.schema.transport.tcp import MD5Signature as Schema_MD5Signature
|
111
|
+
from pcapkit.protocols.schema.transport.tcp import MPTCPAddAddress as Schema_MPTCPAddAddress
|
112
|
+
from pcapkit.protocols.schema.transport.tcp import MPTCPCapable as Schema_MPTCPCapable
|
113
|
+
from pcapkit.protocols.schema.transport.tcp import MPTCPFallback as Schema_MPTCPFallback
|
114
|
+
from pcapkit.protocols.schema.transport.tcp import MPTCPFastclose as Schema_MPTCPFastclose
|
115
|
+
from pcapkit.protocols.schema.transport.tcp import MPTCPJoinACK as Schema_MPTCPJoinACK
|
116
|
+
from pcapkit.protocols.schema.transport.tcp import MPTCPJoinSYN as Schema_MPTCPJoinSYN
|
117
|
+
from pcapkit.protocols.schema.transport.tcp import MPTCPJoinSYNACK as Schema_MPTCPJoinSYNACK
|
118
|
+
from pcapkit.protocols.schema.transport.tcp import MPTCPPriority as Schema_MPTCPPriority
|
119
|
+
from pcapkit.protocols.schema.transport.tcp import MPTCPRemoveAddress as Schema_MPTCPRemoveAddress
|
120
|
+
from pcapkit.protocols.schema.transport.tcp import MPTCPUnknown as Schema_MPTCPUnknown
|
121
|
+
from pcapkit.protocols.schema.transport.tcp import NoOperation as Schema_NoOperation
|
122
|
+
from pcapkit.protocols.schema.transport.tcp import \
|
123
|
+
PartialOrderConnectionPermitted as Schema_PartialOrderConnectionPermitted
|
124
|
+
from pcapkit.protocols.schema.transport.tcp import \
|
125
|
+
PartialOrderServiceProfile as Schema_PartialOrderServiceProfile
|
126
|
+
from pcapkit.protocols.schema.transport.tcp import QuickStartResponse as Schema_QuickStartResponse
|
127
|
+
from pcapkit.protocols.schema.transport.tcp import SACKBlock as Schema_SACKBlock
|
128
|
+
from pcapkit.protocols.schema.transport.tcp import SACKPermitted as Schema_SACKPermitted
|
129
|
+
from pcapkit.protocols.schema.transport.tcp import Timestamps as Schema_Timestamps
|
130
|
+
from pcapkit.protocols.schema.transport.tcp import UnassignedOption as Schema_UnassignedOption
|
131
|
+
from pcapkit.protocols.schema.transport.tcp import UserTimeout as Schema_UserTimeout
|
132
|
+
from pcapkit.protocols.schema.transport.tcp import WindowScale as Schema_WindowScale
|
133
|
+
from pcapkit.protocols.transport.transport import Transport
|
134
|
+
from pcapkit.utilities.exceptions import ProtocolError
|
135
|
+
from pcapkit.utilities.warnings import RegistryWarning, warn
|
136
|
+
|
137
|
+
if TYPE_CHECKING:
|
138
|
+
from datetime import timedelta
|
139
|
+
from enum import IntEnum as StdlibEnum
|
140
|
+
from ipaddress import IPv4Address, IPv6Address
|
141
|
+
from typing import Any, Callable, DefaultDict, Optional, Type
|
142
|
+
|
143
|
+
from aenum import IntEnum as AenumEnum
|
144
|
+
from mypy_extensions import DefaultArg, KwArg, NamedArg
|
145
|
+
from typing_extensions import Literal
|
146
|
+
|
147
|
+
from pcapkit.const.reg.apptype import AppType as Enum_AppType
|
148
|
+
from pcapkit.protocols.data.transport.tcp import MPTCP as Data_MPTCP
|
149
|
+
from pcapkit.protocols.data.transport.tcp import MPTCPJoin as Data_MPTCPJoin
|
150
|
+
from pcapkit.protocols.data.transport.tcp import Option as Data_Option
|
151
|
+
from pcapkit.protocols.protocol import ProtocolBase as Protocol
|
152
|
+
from pcapkit.protocols.schema.schema import Schema
|
153
|
+
from pcapkit.protocols.schema.transport.tcp import MPTCP as Schema_MPTCP
|
154
|
+
from pcapkit.protocols.schema.transport.tcp import Flags as Schema_Flags
|
155
|
+
from pcapkit.protocols.schema.transport.tcp import MPTCPJoin as Schema_MPTCPJoin
|
156
|
+
from pcapkit.protocols.schema.transport.tcp import Option as Schema_Option
|
157
|
+
|
158
|
+
Option = OrderedMultiDict[Enum_Option, Data_Option]
|
159
|
+
OptionParser = Callable[[Schema_Option, NamedArg(Option, 'options')], Data_Option]
|
160
|
+
MPOptionParser = Callable[[Schema_MPTCP, NamedArg(Option, 'options')], Data_MPTCP]
|
161
|
+
OptionConstructor = Callable[[Enum_Option, DefaultArg(Optional[Data_Option]),
|
162
|
+
KwArg(Any)], Schema_Option]
|
163
|
+
MPOptionConstructor = Callable[[Enum_MPTCPOption, DefaultArg(Optional[Data_MPTCP]),
|
164
|
+
KwArg(Any)], Schema_MPTCP]
|
165
|
+
|
166
|
+
__all__ = ['TCP']
|
167
|
+
|
168
|
+
|
169
|
+
class TCP(Transport[Data_TCP, Schema_TCP],
|
170
|
+
schema=Schema_TCP, data=Data_TCP):
|
171
|
+
"""This class implements Transmission Control Protocol.
|
172
|
+
|
173
|
+
This class currently supports parsing of the following protocols, which are
|
174
|
+
registered in the :attr:`self.__proto__ <pcapkit.protocols.transport.tcp.TCP.__proto__>`
|
175
|
+
attribute:
|
176
|
+
|
177
|
+
.. list-table::
|
178
|
+
:header-rows: 1
|
179
|
+
|
180
|
+
* - Port Number
|
181
|
+
- Protocol
|
182
|
+
* - 21
|
183
|
+
- :class:`pcapkit.protocols.application.ftp.FTP`
|
184
|
+
* - 80
|
185
|
+
- :class:`pcapkit.protocols.application.http.HTTP`
|
186
|
+
|
187
|
+
This class currently supports parsing of the following TCP options,
|
188
|
+
which are directly mapped to the :class:`pcapkit.const.tcp.option.Option`
|
189
|
+
enumeration:
|
190
|
+
|
191
|
+
.. list-table::
|
192
|
+
:header-rows: 1
|
193
|
+
|
194
|
+
* - Option Code
|
195
|
+
- Option Parser
|
196
|
+
- Option Constructor
|
197
|
+
* - :attr:`~pcapkit.const.tcp.option.Option.End_of_Option_List`
|
198
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mode_eool`
|
199
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mode_eool`
|
200
|
+
* - :attr:`~pcapkit.const.tcp.option.Option.No_Operation`
|
201
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mode_nop`
|
202
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mode_nop`
|
203
|
+
* - :attr:`~pcapkit.const.tcp.option.Option.Maximum_Segment_Size`
|
204
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mode_mss`
|
205
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mode_mss`
|
206
|
+
* - :attr:`~pcapkit.const.tcp.option.Option.Window_Scale`
|
207
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mode_ws`
|
208
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mode_ws`
|
209
|
+
* - :attr:`~pcapkit.const.tcp.option.Option.SACK_Permitted`
|
210
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mode_sackpmt`
|
211
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mode_sackpmt`
|
212
|
+
* - :attr:`~pcapkit.const.tcp.option.Option.SACK`
|
213
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mode_sack`
|
214
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mode_sack`
|
215
|
+
* - :attr:`~pcapkit.const.tcp.option.Option.Echo`
|
216
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mode_echo`
|
217
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mode_echo`
|
218
|
+
* - :attr:`~pcapkit.const.tcp.option.Option.Echo_Reply`
|
219
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mode_echore`
|
220
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mode_echore`
|
221
|
+
* - :attr:`~pcapkit.const.tcp.option.Option.Timestamps`
|
222
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mode_ts`
|
223
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mode_ts`
|
224
|
+
* - :attr:`~pcapkit.const.tcp.option.Option.Partial_Order_Connection_Permitted`
|
225
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mode_poc`
|
226
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mode_poc`
|
227
|
+
* - :attr:`~pcapkit.const.tcp.option.Option.Partial_Order_Service_Profile`
|
228
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mode_pocsp`
|
229
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mode_pocsp`
|
230
|
+
* - :attr:`~pcapkit.const.tcp.option.Option.CC`
|
231
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mode_cc`
|
232
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mode_cc`
|
233
|
+
* - :attr:`~pcapkit.const.tcp.option.Option.CC_NEW`
|
234
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mode_ccnew`
|
235
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mode_ccnew`
|
236
|
+
* - :attr:`~pcapkit.const.tcp.option.Option.CC_ECHO`
|
237
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mode_ccecho`
|
238
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mode_ccecho`
|
239
|
+
* - :attr:`~pcapkit.const.tcp.option.Option.TCP_Alternate_Checksum_Request`
|
240
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mode_chkreq`
|
241
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mode_chkreq`
|
242
|
+
* - :attr:`~pcapkit.const.tcp.option.Option.TCP_Alternate_Checksum_Data`
|
243
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mode_chksum`
|
244
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mode_chksum`
|
245
|
+
* - :attr:`~pcapkit.const.tcp.option.Option.MD5_Signature_Option`
|
246
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mode_sig`
|
247
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mode_sig`
|
248
|
+
* - :attr:`~pcapkit.const.tcp.option.Option.Quick_Start_Response`
|
249
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mode_qs`
|
250
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mode_qs`
|
251
|
+
* - :attr:`~pcapkit.const.tcp.option.Option.User_Timeout_Option`
|
252
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mode_timeout`
|
253
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mode_timeout`
|
254
|
+
* - :attr:`~pcapkit.const.tcp.option.Option.TCP_Authentication_Option`
|
255
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mode_ao`
|
256
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mode_ao`
|
257
|
+
* - :attr:`~pcapkit.const.tcp.option.Option.Multipath_TCP`
|
258
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mode_mp`
|
259
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mode_mp`
|
260
|
+
* - :attr:`~pcapkit.const.tcp.option.Option.TCP_Fast_Open_Cookie`
|
261
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mode_fastopen`
|
262
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mode_fastopen`
|
263
|
+
|
264
|
+
This class currently supports parsing of the following Multipath TCP options,
|
265
|
+
which are directly mapped to the :class:`pcapkit.const.tcp.mp_tcp_option.MPTCPOption`
|
266
|
+
enumeration:
|
267
|
+
|
268
|
+
.. list-table::
|
269
|
+
:header-rows: 1
|
270
|
+
|
271
|
+
* - Option Code
|
272
|
+
- Option Parser
|
273
|
+
- Option Constructor
|
274
|
+
* - :attr:`~pcapkit.const.tcp.mp_tcp_option.MPTCPOption.MP_CAPABLE`
|
275
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mptcp_capable`
|
276
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mptcp_capable`
|
277
|
+
* - :attr:`~pcapkit.const.tcp.mp_tcp_option.MPTCPOption.MP_JOIN`
|
278
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mptcp_join`
|
279
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mptcp_join`
|
280
|
+
* - :attr:`~pcapkit.const.tcp.mp_tcp_option.MPTCPOption.DSS`
|
281
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mptcp_dss`
|
282
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mptcp_dss`
|
283
|
+
* - :attr:`~pcapkit.const.tcp.mp_tcp_option.MPTCPOption.ADD_ADDR`
|
284
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mptcp_addaddr`
|
285
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mptcp_addaddr`
|
286
|
+
* - :attr:`~pcapkit.const.tcp.mp_tcp_option.MPTCPOption.REMOVE_ADDR`
|
287
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mptcp_remove`
|
288
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mptcp_remove`
|
289
|
+
* - :attr:`~pcapkit.const.tcp.mp_tcp_option.MPTCPOption.MP_PRIO`
|
290
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mptcp_prio`
|
291
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mptcp_prio`
|
292
|
+
* - :attr:`~pcapkit.const.tcp.mp_tcp_option.MPTCPOption.MP_FAIL`
|
293
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mptcp_fail`
|
294
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mptcp_fail`
|
295
|
+
* - :attr:`~pcapkit.const.tcp.mp_tcp_option.MPTCPOption.MP_FASTCLOSE`
|
296
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._read_mptcp_fastclose`
|
297
|
+
- :meth:`~pcapkit.protocols.transport.tcp.TCP._make_mptcp_fastclose`
|
298
|
+
|
299
|
+
"""
|
300
|
+
|
301
|
+
##########################################################################
|
302
|
+
# Defaults.
|
303
|
+
##########################################################################
|
304
|
+
|
305
|
+
#: DefaultDict[int, ModuleDescriptor[Protocol] | Type[Protocol]]: Protocol
|
306
|
+
#: index mapping for decoding next layer, c.f.
|
307
|
+
#: :meth:`self._decode_next_layer <pcapkit.protocols.transport.transport.Transport._decode_next_layer>`
|
308
|
+
#: & :meth:`self._import_next_layer <pcapkit.protocols.protocol.Protocol._import_next_layer>`.
|
309
|
+
__proto__ = collections.defaultdict(
|
310
|
+
lambda: ModuleDescriptor('pcapkit.protocols.misc.raw', 'Raw'),
|
311
|
+
{
|
312
|
+
21: ModuleDescriptor('pcapkit.protocols.application.ftp', 'FTP'), # FTP
|
313
|
+
80: ModuleDescriptor('pcapkit.protocols.application.httpv1', 'HTTP'), # HTTP/1.*
|
314
|
+
},
|
315
|
+
)
|
316
|
+
|
317
|
+
#: DefaultDict[Enum_Option, str | tuple[OptionParser, OptionConstructor]]: Option
|
318
|
+
#: code to method mapping, c.f. :meth:`_read_tcp_options` and
|
319
|
+
#: :meth:`_make_tcp_options`. Method names are expected to be referred to
|
320
|
+
#: the class by ``_read_mode_${name}`` and ``_make_mode_${name}``, and if
|
321
|
+
#: such name not found, the value should then be a method that can parse
|
322
|
+
#: the option by itself.
|
323
|
+
__option__ = collections.defaultdict(
|
324
|
+
lambda: 'donone',
|
325
|
+
{
|
326
|
+
Enum_Option.End_of_Option_List: 'eool', # [RFC 793] End of Option List
|
327
|
+
Enum_Option.No_Operation: 'nop', # [RFC 793] No-Operation
|
328
|
+
Enum_Option.Maximum_Segment_Size: 'mss', # [RFC 793] Maximum Segment Size
|
329
|
+
Enum_Option.Window_Scale: 'ws', # [RFC 7323] Window Scale
|
330
|
+
Enum_Option.SACK_Permitted: 'sackpmt', # [RFC 2018] SACK Permitted
|
331
|
+
Enum_Option.SACK: 'sack', # [RFC 2018] SACK
|
332
|
+
Enum_Option.Echo: 'echo', # [RFC 1072] Echo
|
333
|
+
Enum_Option.Echo_Reply: 'echore', # [RFC 1072] Echo Reply
|
334
|
+
Enum_Option.Timestamps: 'ts', # [RFC 7323] Timestamps
|
335
|
+
Enum_Option.Partial_Order_Connection_Permitted: 'poc', # [RFC 1693] POC Permitted
|
336
|
+
Enum_Option.Partial_Order_Service_Profile: 'pocsp', # [RFC 1693] POC-Serv Profile
|
337
|
+
Enum_Option.CC: 'cc', # [RFC 1644] Connection Count
|
338
|
+
Enum_Option.CC_NEW: 'ccnew', # [RFC 1644] CC.NEW
|
339
|
+
Enum_Option.CC_ECHO: 'ccecho', # [RFC 1644] CC.ECHO
|
340
|
+
Enum_Option.TCP_Alternate_Checksum_Request: 'chkreq', # [RFC 1146] Alt-Chksum Request
|
341
|
+
Enum_Option.TCP_Alternate_Checksum_Data: 'chksum', # [RFC 1146] Alt-Chksum Data
|
342
|
+
Enum_Option.MD5_Signature_Option: 'sig', # [RFC 2385] MD5 Signature Option
|
343
|
+
Enum_Option.Quick_Start_Response: 'qs', # [RFC 4782] Quick-Start Response
|
344
|
+
Enum_Option.User_Timeout_Option: 'timeout', # [RFC 5482] User Timeout Option
|
345
|
+
Enum_Option.TCP_Authentication_Option: 'ao', # [RFC 5925] TCP Authentication Option
|
346
|
+
Enum_Option.Multipath_TCP: 'mp', # [RFC 6824] Multipath TCP
|
347
|
+
Enum_Option.TCP_Fast_Open_Cookie: 'fastopen', # [RFC 7413] Fast Open
|
348
|
+
},
|
349
|
+
) # type: DefaultDict[int, str | tuple[OptionParser, OptionConstructor]]
|
350
|
+
|
351
|
+
#: DefaultDict[Enum_MPTCPOption, str | tuple[MPOptionParser, MPOptionConstructor]]: Option
|
352
|
+
#: code to method mapping, c.f. :meth:`_read_mode_mp` and :meth:`_make_mode_mp`.
|
353
|
+
#: Method names are expected to be referred to the class by ``_read_mptcp_${name}``
|
354
|
+
#: and ``_make_mptcp_${name}``, and if such name not found, the value should
|
355
|
+
#: then be a method that can parse the option by itself.
|
356
|
+
__mp_option__ = collections.defaultdict(
|
357
|
+
lambda: 'unknown',
|
358
|
+
{
|
359
|
+
Enum_MPTCPOption.MP_CAPABLE: 'capable',
|
360
|
+
Enum_MPTCPOption.MP_JOIN: 'join',
|
361
|
+
Enum_MPTCPOption.DSS: 'dss',
|
362
|
+
Enum_MPTCPOption.ADD_ADDR: 'addaddr',
|
363
|
+
Enum_MPTCPOption.REMOVE_ADDR: 'removeaddr',
|
364
|
+
Enum_MPTCPOption.MP_PRIO: 'prio',
|
365
|
+
Enum_MPTCPOption.MP_FAIL: 'fail',
|
366
|
+
Enum_MPTCPOption.MP_FASTCLOSE: 'fastclose',
|
367
|
+
},
|
368
|
+
) # type: DefaultDict[int, str | tuple[MPOptionParser, MPOptionConstructor]]
|
369
|
+
|
370
|
+
##########################################################################
|
371
|
+
# Properties.
|
372
|
+
##########################################################################
|
373
|
+
|
374
|
+
@property
|
375
|
+
def name(self) -> 'Literal["Transmission Control Protocol"]':
|
376
|
+
"""Name of current protocol."""
|
377
|
+
return 'Transmission Control Protocol'
|
378
|
+
|
379
|
+
@property
|
380
|
+
def length(self) -> 'int':
|
381
|
+
"""Header length of current protocol."""
|
382
|
+
return self._info.hdr_len
|
383
|
+
|
384
|
+
@property
|
385
|
+
def src(self) -> 'Enum_AppType':
|
386
|
+
"""Source port."""
|
387
|
+
return self._info.srcport
|
388
|
+
|
389
|
+
@property
|
390
|
+
def dst(self) -> 'Enum_AppType':
|
391
|
+
"""Destination port."""
|
392
|
+
return self._info.dstport
|
393
|
+
|
394
|
+
@property
|
395
|
+
def connection(self) -> 'Enum_Flags':
|
396
|
+
"""Connection flags."""
|
397
|
+
return self._flags
|
398
|
+
|
399
|
+
##########################################################################
|
400
|
+
# Methods.
|
401
|
+
##########################################################################
|
402
|
+
|
403
|
+
def read(self, length: 'Optional[int]' = None, **kwargs: 'Any') -> 'Data_TCP': # pylint: disable=unused-argument
|
404
|
+
"""Read Transmission Control Protocol (TCP).
|
405
|
+
|
406
|
+
Structure of TCP header [:rfc:`793`]::
|
407
|
+
|
408
|
+
0 1 2 3
|
409
|
+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
410
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
411
|
+
| Source Port | Destination Port |
|
412
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
413
|
+
| Sequence Number |
|
414
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
415
|
+
| Acknowledgement Number |
|
416
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
417
|
+
| Data | |U|A|P|R|S|F| |
|
418
|
+
| Offset| Reserved |R|C|S|S|Y|I| Window |
|
419
|
+
| | |G|K|H|T|N|N| |
|
420
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
421
|
+
| Checksum | Urgent Pointer |
|
422
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
423
|
+
| Options | Padding |
|
424
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
425
|
+
| data |
|
426
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
427
|
+
|
428
|
+
Args:
|
429
|
+
length: Length of packet data.
|
430
|
+
**kwargs: Arbitrary keyword arguments.
|
431
|
+
|
432
|
+
Returns:
|
433
|
+
Parsed packet data.
|
434
|
+
|
435
|
+
"""
|
436
|
+
if length is None:
|
437
|
+
length = len(self)
|
438
|
+
schema = self.__header__
|
439
|
+
|
440
|
+
tcp = Data_TCP(
|
441
|
+
srcport=schema.srcport,
|
442
|
+
dstport=schema.dstport,
|
443
|
+
seq=schema.seq,
|
444
|
+
ack=schema.ack,
|
445
|
+
hdr_len=schema.offset['offset'] * 4,
|
446
|
+
flags=Data_Flags(
|
447
|
+
#ns=bool(schema.offset['ns']),
|
448
|
+
cwr=bool(schema.flags['cwr']),
|
449
|
+
ece=bool(schema.flags['ece']),
|
450
|
+
urg=bool(schema.flags['urg']),
|
451
|
+
ack=bool(schema.flags['ack']),
|
452
|
+
psh=bool(schema.flags['psh']),
|
453
|
+
rst=bool(schema.flags['rst']),
|
454
|
+
syn=bool(schema.flags['syn']),
|
455
|
+
fin=bool(schema.flags['fin']),
|
456
|
+
),
|
457
|
+
window_size=schema.window,
|
458
|
+
checksum=schema.checksum,
|
459
|
+
urgent_pointer=schema.urgent,
|
460
|
+
)
|
461
|
+
|
462
|
+
# connection control flags
|
463
|
+
_flag = cast('Enum_Flags', 0)
|
464
|
+
for key, val in schema.flags.items():
|
465
|
+
if val == 1:
|
466
|
+
_flag |= Enum_Flags.get(key.upper())
|
467
|
+
self._flags = _flag
|
468
|
+
|
469
|
+
tcp.__update__({
|
470
|
+
'connection': self._flags,
|
471
|
+
})
|
472
|
+
|
473
|
+
_optl = tcp.hdr_len - 20
|
474
|
+
if _optl:
|
475
|
+
tcp.__update__({
|
476
|
+
'options': self._read_tcp_options(_optl),
|
477
|
+
})
|
478
|
+
|
479
|
+
return self._decode_next_layer(tcp, (tcp.srcport.port, tcp.dstport.port), length - tcp.hdr_len)
|
480
|
+
|
481
|
+
def make(self,
|
482
|
+
srcport: 'Enum_AppType | int' = 0,
|
483
|
+
dstport: 'Enum_AppType | int' = 0,
|
484
|
+
seq_no: 'int' = 0,
|
485
|
+
ack_no: 'int' = 0,
|
486
|
+
ns: 'bool' = False,
|
487
|
+
cwr: 'bool' = False,
|
488
|
+
ece: 'bool' = False,
|
489
|
+
urg: 'bool' = False,
|
490
|
+
ack: 'bool' = False,
|
491
|
+
psh: 'bool' = False,
|
492
|
+
rst: 'bool' = False,
|
493
|
+
syn: 'bool' = False,
|
494
|
+
fin: 'bool' = False,
|
495
|
+
window: 'int' = 65535, # reasonable default value
|
496
|
+
checksum: 'bytes' = b'\x00\x00',
|
497
|
+
urgent: 'int' = 0,
|
498
|
+
options: 'Optional[list[Schema_Option | tuple[Enum_Option, dict[str, Any]] | bytes] | Option]' = None, # pylint: disable=line-too-long
|
499
|
+
payload: 'bytes | Protocol | Schema' = b'',
|
500
|
+
**kwargs: 'Any') -> 'Schema_TCP':
|
501
|
+
"""Make (construct) packet data.
|
502
|
+
|
503
|
+
Args:
|
504
|
+
srcport: Source port.
|
505
|
+
dstport: Destination port.
|
506
|
+
seq_no: Sequence number.
|
507
|
+
ack_no: Acknowledgement number.
|
508
|
+
ns: ECN-nonce concealment protection.
|
509
|
+
cwr: Congestion window reduced.
|
510
|
+
ece: ECN-Echo.
|
511
|
+
urg: Urgent.
|
512
|
+
ack: Acknowledgement.
|
513
|
+
psh: Push function.
|
514
|
+
rst: Reset connection.
|
515
|
+
syn: Synchronize sequence numbers.
|
516
|
+
fin: Last packet from sender.
|
517
|
+
window: Window size.
|
518
|
+
checksum: Checksum.
|
519
|
+
urgent: Urgent pointer.
|
520
|
+
options: TCP options.
|
521
|
+
payload: Payload of the packet.
|
522
|
+
**kwargs: Arbitrary keyword arguments.
|
523
|
+
|
524
|
+
Returns:
|
525
|
+
Constructed packet data.
|
526
|
+
|
527
|
+
"""
|
528
|
+
if options is not None:
|
529
|
+
options_value, total_length = self._make_tcp_options(options)
|
530
|
+
else:
|
531
|
+
options_value, total_length = [], 0
|
532
|
+
|
533
|
+
offset = math.ceil((20 + total_length) / 4)
|
534
|
+
flags = {
|
535
|
+
'cwr': int(cwr),
|
536
|
+
'ece': int(ece),
|
537
|
+
'urg': int(urg),
|
538
|
+
'ack': int(ack),
|
539
|
+
'psh': int(psh),
|
540
|
+
'rst': int(rst),
|
541
|
+
'syn': int(syn),
|
542
|
+
'fin': int(fin),
|
543
|
+
} # type: Schema_Flags
|
544
|
+
|
545
|
+
_flag = cast('Enum_Flags', 0)
|
546
|
+
for key, val in flags.items():
|
547
|
+
if val == 1:
|
548
|
+
_flag |= Enum_Flags.get(key.upper())
|
549
|
+
self._flags = _flag
|
550
|
+
|
551
|
+
return Schema_TCP(
|
552
|
+
srcport=srcport,
|
553
|
+
dstport=dstport,
|
554
|
+
seq=seq_no,
|
555
|
+
ack=ack_no,
|
556
|
+
offset={
|
557
|
+
'offset': offset,
|
558
|
+
'ns': int(ns),
|
559
|
+
},
|
560
|
+
flags=flags,
|
561
|
+
window=window,
|
562
|
+
checksum=checksum,
|
563
|
+
urgent=urgent,
|
564
|
+
options=options_value,
|
565
|
+
payload=payload,
|
566
|
+
)
|
567
|
+
|
568
|
+
@classmethod
|
569
|
+
def register_option(cls, code: 'Enum_Option', meth: 'str | tuple[OptionParser, OptionConstructor]') -> 'None':
|
570
|
+
"""Register an option parser.
|
571
|
+
|
572
|
+
Args:
|
573
|
+
code: TCP option code.
|
574
|
+
meth: Method name or callable to parse and/or construct the option.
|
575
|
+
|
576
|
+
"""
|
577
|
+
if code in cls.__option__:
|
578
|
+
warn(f'option {code} already registered, overwriting', RegistryWarning)
|
579
|
+
cls.__option__[code] = meth
|
580
|
+
|
581
|
+
@classmethod
|
582
|
+
def register_mp_option(cls, code: 'Enum_MPTCPOption', meth: 'str | tuple[MPOptionParser, MPOptionConstructor]') -> 'None':
|
583
|
+
"""Register an MPTCP option parser.
|
584
|
+
|
585
|
+
Args:
|
586
|
+
code: MPTCP option code.
|
587
|
+
meth: Method name or callable to parse and/or construct the option.
|
588
|
+
|
589
|
+
"""
|
590
|
+
if code in cls.__mp_option__:
|
591
|
+
warn(f'option {code} already registered, overwriting', RegistryWarning)
|
592
|
+
cls.__mp_option__[code] = meth
|
593
|
+
|
594
|
+
##########################################################################
|
595
|
+
# Data models.
|
596
|
+
##########################################################################
|
597
|
+
|
598
|
+
def __length_hint__(self) -> 'Literal[20]':
|
599
|
+
"""Return an estimated length for the object."""
|
600
|
+
return 20
|
601
|
+
|
602
|
+
@classmethod
|
603
|
+
def __index__(cls) -> 'TransType': # pylint: disable=invalid-index-returned
|
604
|
+
"""Numeral registry index of the protocol.
|
605
|
+
|
606
|
+
Returns:
|
607
|
+
Numeral registry index of the protocol in `IANA`_.
|
608
|
+
|
609
|
+
.. _IANA: https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml
|
610
|
+
|
611
|
+
"""
|
612
|
+
return TransType.TCP # type: ignore[return-value]
|
613
|
+
|
614
|
+
##########################################################################
|
615
|
+
# Utilities.
|
616
|
+
##########################################################################
|
617
|
+
|
618
|
+
@classmethod
|
619
|
+
def _make_data(cls, data: 'Data_TCP') -> 'dict[str, Any]': # type: ignore[override]
|
620
|
+
"""Create key-value pairs from ``data`` for protocol construction.
|
621
|
+
|
622
|
+
Args:
|
623
|
+
data: protocol data
|
624
|
+
|
625
|
+
Returns:
|
626
|
+
Key-value pairs for protocol construction.
|
627
|
+
|
628
|
+
"""
|
629
|
+
return {
|
630
|
+
'srcport': data.srcport,
|
631
|
+
'dstport': data.dstport,
|
632
|
+
'seq_no': data.seq,
|
633
|
+
'ack_no': data.ack,
|
634
|
+
#'ns': data.flags.ns,
|
635
|
+
'cwr': data.flags.cwr,
|
636
|
+
'ece': data.flags.ece,
|
637
|
+
'urg': data.flags.urg,
|
638
|
+
'ack': data.flags.ack,
|
639
|
+
'psh': data.flags.psh,
|
640
|
+
'rst': data.flags.rst,
|
641
|
+
'syn': data.flags.syn,
|
642
|
+
'fin': data.flags.fin,
|
643
|
+
'window': data.window_size,
|
644
|
+
'checksum': data.checksum,
|
645
|
+
'urgent': data.urgent_pointer,
|
646
|
+
'options': getattr(data, 'options', None),
|
647
|
+
'payload': cls._make_payload(data),
|
648
|
+
}
|
649
|
+
|
650
|
+
def _read_tcp_options(self, size: 'int') -> 'Option':
|
651
|
+
"""Read TCP option list.
|
652
|
+
|
653
|
+
Arguments:
|
654
|
+
size: length of option list
|
655
|
+
|
656
|
+
Returns:
|
657
|
+
Extracted TCP options.
|
658
|
+
|
659
|
+
Raises:
|
660
|
+
ProtocolError: If the threshold is **NOT** matching.
|
661
|
+
|
662
|
+
"""
|
663
|
+
counter = 0 # length of read option list
|
664
|
+
options = OrderedMultiDict() # type: Option
|
665
|
+
|
666
|
+
for schema in self.__header__.options:
|
667
|
+
kind = schema.kind
|
668
|
+
name = self.__option__[kind]
|
669
|
+
|
670
|
+
if isinstance(name, str):
|
671
|
+
meth_name = f'_read_mode_{name}'
|
672
|
+
meth = cast('OptionParser',
|
673
|
+
getattr(self, meth_name, self._read_mode_donone))
|
674
|
+
else:
|
675
|
+
meth = name[0]
|
676
|
+
data = meth(schema, options=options)
|
677
|
+
|
678
|
+
# record option data
|
679
|
+
options.add(kind, data)
|
680
|
+
counter += len(schema)
|
681
|
+
|
682
|
+
# break when End of Option List (EOOL) triggered
|
683
|
+
if kind == Enum_Option.End_of_Option_List:
|
684
|
+
break
|
685
|
+
|
686
|
+
# check threshold
|
687
|
+
if counter > size:
|
688
|
+
raise ProtocolError('TCP: invalid format')
|
689
|
+
return options
|
690
|
+
|
691
|
+
def _read_mode_donone(self, schema: 'Schema_UnassignedOption', *, options: 'Option') -> 'Data_UnassignedOption': # pylint: disable=unused-argument
|
692
|
+
"""Read options request no process.
|
693
|
+
|
694
|
+
Arguments:
|
695
|
+
schema: parsed option schema
|
696
|
+
options: extracted TCP options
|
697
|
+
|
698
|
+
Returns:
|
699
|
+
Parsed option data.
|
700
|
+
|
701
|
+
"""
|
702
|
+
option = Data_UnassignedOption(
|
703
|
+
kind=schema.kind,
|
704
|
+
length=schema.length,
|
705
|
+
data=schema.data,
|
706
|
+
)
|
707
|
+
return option
|
708
|
+
|
709
|
+
def _read_mode_eool(self, schema: 'Schema_EndOfOptionList', *, options: 'Option') -> 'Data_EndOfOptionList': # pylint: disable=unused-argument
|
710
|
+
"""Read TCP End of Option List option.
|
711
|
+
|
712
|
+
Structure of TCP end of option list option [:rfc:`793`]:
|
713
|
+
|
714
|
+
.. code-block:: text
|
715
|
+
|
716
|
+
+--------+
|
717
|
+
|00000000|
|
718
|
+
+--------+
|
719
|
+
Kind=0
|
720
|
+
|
721
|
+
Arguments:
|
722
|
+
schema: parsed option schema
|
723
|
+
options: extracted TCP options
|
724
|
+
|
725
|
+
Returns:
|
726
|
+
Parsed option data.
|
727
|
+
|
728
|
+
"""
|
729
|
+
return Data_EndOfOptionList(
|
730
|
+
kind=schema.kind,
|
731
|
+
length=1,
|
732
|
+
)
|
733
|
+
|
734
|
+
def _read_mode_nop(self, schema: 'Schema_NoOperation', *, options: 'Option') -> 'Data_NoOperation': # pylint: disable=unused-argument
|
735
|
+
"""Read TCP No Operation option.
|
736
|
+
|
737
|
+
Structure of TCP maximum segment size option [:rfc:`793`]:
|
738
|
+
|
739
|
+
.. code-block:: text
|
740
|
+
|
741
|
+
+--------+
|
742
|
+
|00000001|
|
743
|
+
+--------+
|
744
|
+
Kind=1
|
745
|
+
|
746
|
+
Arguments:
|
747
|
+
schema: parsed option schema
|
748
|
+
options: extracted TCP options
|
749
|
+
|
750
|
+
Returns:
|
751
|
+
Parsed option data.
|
752
|
+
|
753
|
+
"""
|
754
|
+
return Data_NoOperation(
|
755
|
+
kind=schema.kind,
|
756
|
+
length=1,
|
757
|
+
)
|
758
|
+
|
759
|
+
def _read_mode_mss(self, schema: 'Schema_MaximumSegmentSize', *, options: 'Option') -> 'Data_MaximumSegmentSize': # pylint: disable=unused-argument
|
760
|
+
"""Read TCP max segment size option.
|
761
|
+
|
762
|
+
Structure of TCP maximum segment size option [:rfc:`793`]:
|
763
|
+
|
764
|
+
.. code-block:: text
|
765
|
+
|
766
|
+
+--------+--------+---------+--------+
|
767
|
+
|00000010|00000100| max seg size |
|
768
|
+
+--------+--------+---------+--------+
|
769
|
+
Kind=2 Length=4
|
770
|
+
|
771
|
+
Arguments:
|
772
|
+
schema: parsed option schema
|
773
|
+
options: extracted TCP options
|
774
|
+
|
775
|
+
Returns:
|
776
|
+
Parsed option data.
|
777
|
+
|
778
|
+
Raises:
|
779
|
+
ProtocolError: If length is **NOT** ``4``.
|
780
|
+
|
781
|
+
"""
|
782
|
+
if schema.length != 4:
|
783
|
+
raise ProtocolError(f'{self.alias}: [OptNo {schema.kind}] invalid format')
|
784
|
+
|
785
|
+
data = Data_MaximumSegmentSize(
|
786
|
+
kind=schema.kind,
|
787
|
+
length=schema.length,
|
788
|
+
mss=schema.mss,
|
789
|
+
)
|
790
|
+
return data
|
791
|
+
|
792
|
+
def _read_mode_ws(self, schema: 'Schema_WindowScale', *, options: 'Option') -> 'Data_WindowScale': # pylint: disable=unused-argument
|
793
|
+
"""Read TCP windows scale option.
|
794
|
+
|
795
|
+
Structure of TCP window scale option [:rfc:`7323`]:
|
796
|
+
|
797
|
+
.. code-block:: text
|
798
|
+
|
799
|
+
+---------+---------+---------+
|
800
|
+
| Kind=3 |Length=3 |shift.cnt|
|
801
|
+
+---------+---------+---------+
|
802
|
+
1 1 1
|
803
|
+
|
804
|
+
Arguments:
|
805
|
+
schema: parsed option schema
|
806
|
+
options: extracted TCP options
|
807
|
+
|
808
|
+
Returns:
|
809
|
+
Parsed option data.
|
810
|
+
|
811
|
+
Raises:
|
812
|
+
ProtocolError: If length is **NOT** ``3``.
|
813
|
+
|
814
|
+
"""
|
815
|
+
if schema.length != 3:
|
816
|
+
raise ProtocolError(f'{self.alias}: [OptNo {schema.kind}] invalid format')
|
817
|
+
|
818
|
+
data = Data_WindowScale(
|
819
|
+
kind=schema.kind,
|
820
|
+
length=schema.length,
|
821
|
+
shift=schema.shift,
|
822
|
+
)
|
823
|
+
return data
|
824
|
+
|
825
|
+
def _read_mode_sackpmt(self, schema: 'Schema_SACKPermitted', *, options: 'Option') -> 'Data_SACKPermitted': # pylint: disable=unused-argument
|
826
|
+
"""Read TCP SACK permitted option.
|
827
|
+
|
828
|
+
Structure of TCP SACK permitted option [:rfc:`2018`]:
|
829
|
+
|
830
|
+
.. code-block:: text
|
831
|
+
|
832
|
+
+---------+---------+
|
833
|
+
| Kind=4 | Length=2|
|
834
|
+
+---------+---------+
|
835
|
+
|
836
|
+
Arguments:
|
837
|
+
schema: parsed option schema
|
838
|
+
options: extracted TCP options
|
839
|
+
|
840
|
+
Returns:
|
841
|
+
Parsed option data.
|
842
|
+
|
843
|
+
Raises:
|
844
|
+
ProtocolError: If length is **NOT** ``2``.
|
845
|
+
|
846
|
+
"""
|
847
|
+
if schema.length != 2:
|
848
|
+
raise ProtocolError(f'{self.alias}: [OptNo {schema.kind}] invalid format')
|
849
|
+
|
850
|
+
return Data_SACKPermitted(
|
851
|
+
kind=schema.kind,
|
852
|
+
length=schema.length,
|
853
|
+
)
|
854
|
+
|
855
|
+
def _read_mode_sack(self, schema: 'Schema_SACK', *, options: 'Option') -> 'Data_SACK': # pylint: disable=unused-argument
|
856
|
+
"""Read TCP SACK option.
|
857
|
+
|
858
|
+
Structure of TCP SACK option [:rfc:`2018`]:
|
859
|
+
|
860
|
+
.. code-block:: text
|
861
|
+
|
862
|
+
+--------+--------+
|
863
|
+
| Kind=5 | Length |
|
864
|
+
+--------+--------+--------+--------+
|
865
|
+
| Left Edge of 1st Block |
|
866
|
+
+--------+--------+--------+--------+
|
867
|
+
| Right Edge of 1st Block |
|
868
|
+
+--------+--------+--------+--------+
|
869
|
+
| |
|
870
|
+
/ . . . /
|
871
|
+
| |
|
872
|
+
+--------+--------+--------+--------+
|
873
|
+
| Left Edge of nth Block |
|
874
|
+
+--------+--------+--------+--------+
|
875
|
+
| Right Edge of nth Block |
|
876
|
+
+--------+--------+--------+--------+
|
877
|
+
|
878
|
+
Arguments:
|
879
|
+
schema: parsed option schema
|
880
|
+
options: extracted TCP options
|
881
|
+
|
882
|
+
Returns:
|
883
|
+
Parsed option data.
|
884
|
+
|
885
|
+
Raises:
|
886
|
+
ProtocolError: If length is **NOT** multiply of ``8`` plus ``2``.
|
887
|
+
|
888
|
+
"""
|
889
|
+
data = Data_SACK(
|
890
|
+
kind=schema.kind,
|
891
|
+
length=schema.length,
|
892
|
+
sack=tuple(
|
893
|
+
Data_SACKBlock(
|
894
|
+
left=block.left,
|
895
|
+
right=block.right,
|
896
|
+
) for block in schema.sack
|
897
|
+
),
|
898
|
+
)
|
899
|
+
return data
|
900
|
+
|
901
|
+
def _read_mode_echo(self, schema: 'Schema_Echo', *, options: 'Option') -> 'Data_Echo': # pylint: disable=unused-argument
|
902
|
+
"""Read TCP echo option.
|
903
|
+
|
904
|
+
Structure of TCP echo option [:rfc:`1072`]:
|
905
|
+
|
906
|
+
.. code-block:: text
|
907
|
+
|
908
|
+
+--------+--------+--------+--------+--------+--------+
|
909
|
+
| Kind=6 | Length | 4 bytes of info to be echoed |
|
910
|
+
+--------+--------+--------+--------+--------+--------+
|
911
|
+
|
912
|
+
Arguments:
|
913
|
+
schema: parsed option schema
|
914
|
+
options: extracted TCP options
|
915
|
+
|
916
|
+
Returns:
|
917
|
+
Parsed option data.
|
918
|
+
|
919
|
+
Raises:
|
920
|
+
ProtocolError: If length is **NOT** ``6``.
|
921
|
+
|
922
|
+
"""
|
923
|
+
if schema.length != 6:
|
924
|
+
raise ProtocolError(f'{self.alias}: [OptNo {schema.kind}] invalid format')
|
925
|
+
|
926
|
+
data = Data_Echo(
|
927
|
+
kind=schema.kind,
|
928
|
+
length=schema.length,
|
929
|
+
data=schema.data,
|
930
|
+
)
|
931
|
+
return data
|
932
|
+
|
933
|
+
def _read_mode_echore(self, schema: 'Schema_EchoReply', *, options: 'Option') -> 'Data_EchoReply': # pylint: disable=unused-argument
|
934
|
+
"""Read TCP echo reply option.
|
935
|
+
|
936
|
+
Structure of TCP echo reply option [:rfc:`1072`]:
|
937
|
+
|
938
|
+
.. code-block:: text
|
939
|
+
|
940
|
+
+--------+--------+--------+--------+--------+--------+
|
941
|
+
| Kind=7 | Length | 4 bytes of echoed info |
|
942
|
+
+--------+--------+--------+--------+--------+--------+
|
943
|
+
|
944
|
+
Arguments:
|
945
|
+
schema: parsed option schema
|
946
|
+
options: extracted TCP options
|
947
|
+
|
948
|
+
Returns:
|
949
|
+
Parsed option data.
|
950
|
+
|
951
|
+
Raises:
|
952
|
+
ProtocolError: If length is **NOT** ``6``.
|
953
|
+
|
954
|
+
"""
|
955
|
+
if schema.length != 6:
|
956
|
+
raise ProtocolError(f'{self.alias}: [OptNo {schema.kind}] invalid format')
|
957
|
+
|
958
|
+
data = Data_EchoReply(
|
959
|
+
kind=schema.kind,
|
960
|
+
length=schema.length,
|
961
|
+
data=schema.data,
|
962
|
+
)
|
963
|
+
return data
|
964
|
+
|
965
|
+
def _read_mode_ts(self, schema: 'Schema_Timestamps', *, options: 'Option') -> 'Data_Timestamps': # pylint: disable=unused-argument
|
966
|
+
"""Read TCP timestamps option.
|
967
|
+
|
968
|
+
Structure of TCP timestamp option [:rfc:`7323`]:
|
969
|
+
|
970
|
+
.. code-block:: text
|
971
|
+
|
972
|
+
+-------+-------+---------------------+---------------------+
|
973
|
+
|Kind=8 | 10 | TS Value (TSval) |TS Echo Reply (TSecr)|
|
974
|
+
+-------+-------+---------------------+---------------------+
|
975
|
+
1 1 4 4
|
976
|
+
|
977
|
+
Arguments:
|
978
|
+
schema: parsed option schema
|
979
|
+
options: extracted TCP options
|
980
|
+
|
981
|
+
Returns:
|
982
|
+
Parsed option data.
|
983
|
+
|
984
|
+
Raises:
|
985
|
+
ProtocolError: If length is **NOT** ``10``.
|
986
|
+
|
987
|
+
"""
|
988
|
+
if schema.length != 10:
|
989
|
+
raise ProtocolError(f'{self.alias}: [OptNo {schema.kind}] invalid format')
|
990
|
+
|
991
|
+
data = Data_Timestamps(
|
992
|
+
kind=schema.kind,
|
993
|
+
length=schema.length,
|
994
|
+
timestamp=schema.value,
|
995
|
+
echo=schema.reply,
|
996
|
+
)
|
997
|
+
return data
|
998
|
+
|
999
|
+
def _read_mode_poc(self, schema: 'Schema_PartialOrderConnectionPermitted', *, options: 'Option') -> 'Data_PartialOrderConnectionPermitted': # pylint: disable=unused-argument
|
1000
|
+
"""Read TCP partial order connection service profile option.
|
1001
|
+
|
1002
|
+
Structure of TCP ``POC-Permitted`` option [:rfc:`1693`][:rfc:`6247`]:
|
1003
|
+
|
1004
|
+
.. code-block:: text
|
1005
|
+
|
1006
|
+
+-----------+-------------+
|
1007
|
+
| Kind=9 | Length=2 |
|
1008
|
+
+-----------+-------------+
|
1009
|
+
|
1010
|
+
Arguments:
|
1011
|
+
schema: parsed option schema
|
1012
|
+
options: extracted TCP options
|
1013
|
+
|
1014
|
+
Returns:
|
1015
|
+
Parsed option data.
|
1016
|
+
|
1017
|
+
Raises:
|
1018
|
+
ProtocolError: If length is **NOT** ``2``.
|
1019
|
+
|
1020
|
+
"""
|
1021
|
+
if schema.length != 2:
|
1022
|
+
raise ProtocolError(f'{self.alias}: [OptNo {schema.kind}] invalid format')
|
1023
|
+
|
1024
|
+
return Data_PartialOrderConnectionPermitted(
|
1025
|
+
kind=schema.kind,
|
1026
|
+
length=schema.length,
|
1027
|
+
)
|
1028
|
+
|
1029
|
+
def _read_mode_pocsp(self, schema: 'Schema_PartialOrderServiceProfile', *, options: 'Option') -> 'Data_PartialOrderServiceProfile': # pylint: disable=unused-argument
|
1030
|
+
"""Read TCP partial order connection service profile option.
|
1031
|
+
|
1032
|
+
Structure of TCP ``POC-SP`` option [:rfc:`1693`][:rfc:`6247`]:
|
1033
|
+
|
1034
|
+
.. code-block:: text
|
1035
|
+
|
1036
|
+
1 bit 1 bit 6 bits
|
1037
|
+
+----------+----------+------------+----------+--------+
|
1038
|
+
| Kind=10 | Length=3 | Start_flag | End_flag | Filler |
|
1039
|
+
+----------+----------+------------+----------+--------+
|
1040
|
+
|
1041
|
+
Arguments:
|
1042
|
+
schema: parsed option schema
|
1043
|
+
options: extracted TCP options
|
1044
|
+
|
1045
|
+
Returns:
|
1046
|
+
Parsed option data.
|
1047
|
+
|
1048
|
+
Raises:
|
1049
|
+
ProtocolError: If length is **NOT** ``3``.
|
1050
|
+
|
1051
|
+
"""
|
1052
|
+
if schema.length != 3:
|
1053
|
+
raise ProtocolError(f'{self.alias}: [OptNo {schema.kind}] invalid format')
|
1054
|
+
|
1055
|
+
data = Data_PartialOrderServiceProfile(
|
1056
|
+
kind=schema.kind,
|
1057
|
+
length=schema.length,
|
1058
|
+
start=bool(schema.profile['start']),
|
1059
|
+
end=bool(schema.profile['end']),
|
1060
|
+
)
|
1061
|
+
return data
|
1062
|
+
|
1063
|
+
def _read_mode_cc(self, schema: 'Schema_CC', *, options: 'Option') -> 'Data_CC': # pylint: disable=unused-argument
|
1064
|
+
"""Read TCP connection count option.
|
1065
|
+
|
1066
|
+
Structure of TCP ``CC`` option [:rfc:`1644`]:
|
1067
|
+
|
1068
|
+
.. code-block:: text
|
1069
|
+
|
1070
|
+
+--------+--------+--------+--------+--------+--------+
|
1071
|
+
|00001011|00000110| Connection Count: SEG.CC |
|
1072
|
+
+--------+--------+--------+--------+--------+--------+
|
1073
|
+
Kind=11 Length=6
|
1074
|
+
|
1075
|
+
Arguments:
|
1076
|
+
schema: parsed option schema
|
1077
|
+
options: extracted TCP options
|
1078
|
+
|
1079
|
+
Returns:
|
1080
|
+
Parsed option data.
|
1081
|
+
|
1082
|
+
Raises:
|
1083
|
+
ProtocolError: If length is **NOT** ``6``.
|
1084
|
+
|
1085
|
+
"""
|
1086
|
+
if schema.length != 6:
|
1087
|
+
raise ProtocolError(f'{self.alias}: [OptNo {schema.kind}] invalid format')
|
1088
|
+
|
1089
|
+
data = Data_CC(
|
1090
|
+
kind=schema.kind,
|
1091
|
+
length=schema.length,
|
1092
|
+
cc=schema.count,
|
1093
|
+
)
|
1094
|
+
return data
|
1095
|
+
|
1096
|
+
def _read_mode_ccnew(self, schema: 'Schema_CCNew', *, options: 'Option') -> 'Data_CCNew': # pylint: disable=unused-argument
|
1097
|
+
"""Read TCP connection count (new) option.
|
1098
|
+
|
1099
|
+
Structure of TCP ``CC.NEW`` option [:rfc:`1644`]:
|
1100
|
+
|
1101
|
+
.. code-block:: text
|
1102
|
+
|
1103
|
+
+--------+--------+--------+--------+--------+--------+
|
1104
|
+
|00001100|00000110| Connection Count: SEG.CC |
|
1105
|
+
+--------+--------+--------+--------+--------+--------+
|
1106
|
+
Kind=12 Length=6
|
1107
|
+
|
1108
|
+
Arguments:
|
1109
|
+
schema: parsed option schema
|
1110
|
+
options: extracted TCP options
|
1111
|
+
|
1112
|
+
Returns:
|
1113
|
+
Parsed option data.
|
1114
|
+
|
1115
|
+
Raises:
|
1116
|
+
ProtocolError: If length is **NOT** ``6``.
|
1117
|
+
|
1118
|
+
"""
|
1119
|
+
if schema.length != 6:
|
1120
|
+
raise ProtocolError(f'{self.alias}: [OptNo {schema.kind}] invalid format')
|
1121
|
+
|
1122
|
+
data = Data_CCNew(
|
1123
|
+
kind=schema.kind,
|
1124
|
+
length=schema.length,
|
1125
|
+
cc=schema.count,
|
1126
|
+
)
|
1127
|
+
return data
|
1128
|
+
|
1129
|
+
def _read_mode_ccecho(self, schema: 'Schema_CCEcho', *, options: 'Option') -> 'Data_CCEcho': # pylint: disable=unused-argument
|
1130
|
+
"""Read TCP connection count (echo) option.
|
1131
|
+
|
1132
|
+
Structure of TCP ``CC.ECHO`` option [:rfc:`1644`]:
|
1133
|
+
|
1134
|
+
.. code-block:: text
|
1135
|
+
|
1136
|
+
+--------+--------+--------+--------+--------+--------+
|
1137
|
+
|00001101|00000110| Connection Count: SEG.CC |
|
1138
|
+
+--------+--------+--------+--------+--------+--------+
|
1139
|
+
Kind=13 Length=6
|
1140
|
+
|
1141
|
+
Arguments:
|
1142
|
+
schema: parsed option schema
|
1143
|
+
options: extracted TCP options
|
1144
|
+
|
1145
|
+
Returns:
|
1146
|
+
Parsed option data.
|
1147
|
+
|
1148
|
+
Raises:
|
1149
|
+
ProtocolError: If length is **NOT** ``6``.
|
1150
|
+
|
1151
|
+
"""
|
1152
|
+
if schema.length != 6:
|
1153
|
+
raise ProtocolError(f'{self.alias}: [OptNo {schema.kind}] invalid format')
|
1154
|
+
|
1155
|
+
data = Data_CCEcho(
|
1156
|
+
kind=schema.kind,
|
1157
|
+
length=schema.length,
|
1158
|
+
cc=schema.count,
|
1159
|
+
)
|
1160
|
+
return data
|
1161
|
+
|
1162
|
+
def _read_mode_chkreq(self, schema: 'Schema_AlternateChecksumRequest', *, options: 'Option') -> 'Data_AlternateChecksumRequest': # pylint: disable=unused-argument
|
1163
|
+
"""Read TCP Alternate Checksum Request option.
|
1164
|
+
|
1165
|
+
Structure of TCP ``CHKSUM-REQ`` [:rfc:`1146`][:rfc:`6247`]:
|
1166
|
+
|
1167
|
+
.. code-block:: text
|
1168
|
+
|
1169
|
+
+----------+----------+----------+
|
1170
|
+
| Kind=14 | Length=3 | chksum |
|
1171
|
+
+----------+----------+----------+
|
1172
|
+
|
1173
|
+
Arguments:
|
1174
|
+
schema: parsed option schema
|
1175
|
+
options: extracted TCP options
|
1176
|
+
|
1177
|
+
Returns:
|
1178
|
+
Parsed option data.
|
1179
|
+
|
1180
|
+
Raises:
|
1181
|
+
ProtocolError: If length is **NOT** ``3``.
|
1182
|
+
|
1183
|
+
"""
|
1184
|
+
if schema.length != 3:
|
1185
|
+
raise ProtocolError(f'{self.alias}: [OptNo {schema.kind}] invalid format')
|
1186
|
+
|
1187
|
+
data = Data_AlternateChecksumRequest(
|
1188
|
+
kind=schema.kind,
|
1189
|
+
length=schema.length,
|
1190
|
+
chksum=schema.algorithm,
|
1191
|
+
)
|
1192
|
+
return data
|
1193
|
+
|
1194
|
+
def _read_mode_chksum(self, schema: 'Schema_AlternateChecksumData', *, options: 'Option') -> 'Data_AlternateChecksumData': # pylint: disable=unused-argument
|
1195
|
+
"""Read Alternate Checksum Data option.
|
1196
|
+
|
1197
|
+
Structure of TCP ``CHKSUM`` [:rfc:`1146`][:rfc:`6247`]:
|
1198
|
+
|
1199
|
+
.. code-block:: text
|
1200
|
+
|
1201
|
+
+---------+---------+---------+ +---------+
|
1202
|
+
| Kind=15 |Length=N | data | ... | data |
|
1203
|
+
+---------+---------+---------+ +---------+
|
1204
|
+
|
1205
|
+
Arguments:
|
1206
|
+
schema: parsed option schema
|
1207
|
+
options: extracted TCP options
|
1208
|
+
|
1209
|
+
Returns:
|
1210
|
+
Parsed option data.
|
1211
|
+
|
1212
|
+
"""
|
1213
|
+
data = Data_AlternateChecksumData(
|
1214
|
+
kind=schema.kind,
|
1215
|
+
length=schema.length,
|
1216
|
+
data=schema.data,
|
1217
|
+
)
|
1218
|
+
return data
|
1219
|
+
|
1220
|
+
def _read_mode_sig(self, schema: 'Schema_MD5Signature', *, options: 'Option') -> 'Data_MD5Signature': # pylint: disable=unused-argument
|
1221
|
+
"""Read MD5 Signature option.
|
1222
|
+
|
1223
|
+
Structure of TCP ``SIG`` option [:rfc:`2385`]:
|
1224
|
+
|
1225
|
+
.. code-block:: text
|
1226
|
+
|
1227
|
+
+---------+---------+-------------------+
|
1228
|
+
| Kind=19 |Length=18| MD5 digest... |
|
1229
|
+
+---------+---------+-------------------+
|
1230
|
+
| |
|
1231
|
+
+---------------------------------------+
|
1232
|
+
| |
|
1233
|
+
+---------------------------------------+
|
1234
|
+
| |
|
1235
|
+
+-------------------+-------------------+
|
1236
|
+
| |
|
1237
|
+
+-------------------+
|
1238
|
+
|
1239
|
+
Arguments:
|
1240
|
+
schema: parsed option schema
|
1241
|
+
options: extracted TCP options
|
1242
|
+
|
1243
|
+
Returns:
|
1244
|
+
Parsed option data.
|
1245
|
+
|
1246
|
+
Raises:
|
1247
|
+
ProtocolError: If length is **NOT** ``18``.
|
1248
|
+
|
1249
|
+
"""
|
1250
|
+
if schema.length != 18:
|
1251
|
+
raise ProtocolError(f'{self.alias}: [OptNo {schema.kind}] invalid format')
|
1252
|
+
|
1253
|
+
data = Data_MD5Signature(
|
1254
|
+
kind=schema.kind,
|
1255
|
+
length=schema.length,
|
1256
|
+
digest=schema.digest,
|
1257
|
+
)
|
1258
|
+
return data
|
1259
|
+
|
1260
|
+
def _read_mode_qs(self, schema: 'Schema_QuickStartResponse', *, options: 'Option') -> 'Data_QuickStartResponse': # pylint: disable=unused-argument
|
1261
|
+
"""Read Quick-Start Response option.
|
1262
|
+
|
1263
|
+
Structure of TCP ``QSopt`` [:rfc:`4782`]:
|
1264
|
+
|
1265
|
+
.. code-block:: text
|
1266
|
+
|
1267
|
+
0 1 2 3
|
1268
|
+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
1269
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
1270
|
+
| Kind | Length=8 | Resv. | Rate | TTL Diff |
|
1271
|
+
| | | |Request| |
|
1272
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
1273
|
+
| QS Nonce | R |
|
1274
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
1275
|
+
|
1276
|
+
Arguments:
|
1277
|
+
schema: parsed option schema
|
1278
|
+
options: extracted TCP options
|
1279
|
+
|
1280
|
+
Returns:
|
1281
|
+
Parsed option data.
|
1282
|
+
|
1283
|
+
Raises:
|
1284
|
+
ProtocolError: If length is **NOT** ``8``.
|
1285
|
+
|
1286
|
+
"""
|
1287
|
+
size = self._read_unpack(1)
|
1288
|
+
if schema.length != 8:
|
1289
|
+
raise ProtocolError(f'{self.alias}: [OptNo {schema.kind}] invalid format')
|
1290
|
+
|
1291
|
+
rate = schema.flags['rate']
|
1292
|
+
data = Data_QuickStartResponse(
|
1293
|
+
kind=schema.kind,
|
1294
|
+
length=schema.length,
|
1295
|
+
req_rate=40000 * (2 ** rate) / 1000 if rate > 0 else 0,
|
1296
|
+
ttl_diff=schema.diff,
|
1297
|
+
nonce=schema.nonce['nonce'],
|
1298
|
+
)
|
1299
|
+
return data
|
1300
|
+
|
1301
|
+
def _read_mode_timeout(self, schema: 'Schema_UserTimeout', *, options: 'Option') -> 'Data_UserTimeout': # pylint: disable=unused-argument
|
1302
|
+
"""Read User Timeout option.
|
1303
|
+
|
1304
|
+
Structure of TCP ``TIMEOUT`` [:rfc:`5482`]:
|
1305
|
+
|
1306
|
+
.. code-block:: text
|
1307
|
+
|
1308
|
+
0 1 2 3
|
1309
|
+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
1310
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
1311
|
+
| Kind = 28 | Length = 4 |G| User Timeout |
|
1312
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
1313
|
+
|
1314
|
+
Arguments:
|
1315
|
+
schema: parsed option schema
|
1316
|
+
options: extracted TCP options
|
1317
|
+
|
1318
|
+
Returns:
|
1319
|
+
Parsed option data.
|
1320
|
+
|
1321
|
+
Raises:
|
1322
|
+
ProtocolError: If length is **NOT** ``4``.
|
1323
|
+
|
1324
|
+
"""
|
1325
|
+
if schema.length != 4:
|
1326
|
+
raise ProtocolError(f'{self.alias}: [OptNo {schema.kind}] invalid format')
|
1327
|
+
|
1328
|
+
if schema.info['granularity'] == 1:
|
1329
|
+
time = datetime.timedelta(minutes=schema.info['timeout'])
|
1330
|
+
else:
|
1331
|
+
time = datetime.timedelta(seconds=schema.info['timeout'])
|
1332
|
+
|
1333
|
+
data = Data_UserTimeout(
|
1334
|
+
kind=schema.kind,
|
1335
|
+
length=schema.length,
|
1336
|
+
timeout=time,
|
1337
|
+
)
|
1338
|
+
return data
|
1339
|
+
|
1340
|
+
def _read_mode_ao(self, schema: 'Schema_Authentication', *, options: 'Option') -> 'Data_Authentication': # pylint: disable=unused-argument
|
1341
|
+
"""Read Authentication option.
|
1342
|
+
|
1343
|
+
Structure of TCP ``AOopt`` [:rfc:`5925`]:
|
1344
|
+
|
1345
|
+
.. code-block:: text
|
1346
|
+
|
1347
|
+
+------------+------------+------------+------------+
|
1348
|
+
| Kind=29 | Length | KeyID | RNextKeyID |
|
1349
|
+
+------------+------------+------------+------------+
|
1350
|
+
| MAC ...
|
1351
|
+
+-----------------------------------...
|
1352
|
+
|
1353
|
+
...-----------------+
|
1354
|
+
... MAC (con't) |
|
1355
|
+
...-----------------+
|
1356
|
+
|
1357
|
+
Arguments:
|
1358
|
+
schema: parsed option schema
|
1359
|
+
options: extracted TCP options
|
1360
|
+
|
1361
|
+
Returns:
|
1362
|
+
Parsed option data.
|
1363
|
+
|
1364
|
+
Raises:
|
1365
|
+
ProtocolError: If length is **NOT** larger than or equal to ``4``.
|
1366
|
+
|
1367
|
+
"""
|
1368
|
+
if schema.length < 4:
|
1369
|
+
raise ProtocolError(f'{self.alias}: [OptNo {schema.kind}] invalid format')
|
1370
|
+
|
1371
|
+
data = Data_Authentication(
|
1372
|
+
kind=schema.kind,
|
1373
|
+
length=schema.length,
|
1374
|
+
key_id=schema.key_id,
|
1375
|
+
next_key_id=schema.next_key_id,
|
1376
|
+
mac=schema.mac,
|
1377
|
+
)
|
1378
|
+
return data
|
1379
|
+
|
1380
|
+
def _read_mode_mp(self, schema: 'Schema_MPTCP', *, options: 'Option') -> 'Data_MPTCP': # pylint: disable=unused-argument
|
1381
|
+
"""Read Multipath TCP option.
|
1382
|
+
|
1383
|
+
Structure of ``MP-TCP`` [:rfc:`6824`]:
|
1384
|
+
|
1385
|
+
.. code-block:: text
|
1386
|
+
|
1387
|
+
1 2 3
|
1388
|
+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
1389
|
+
+---------------+---------------+-------+-----------------------+
|
1390
|
+
| Kind | Length |Subtype| |
|
1391
|
+
+---------------+---------------+-------+ |
|
1392
|
+
| Subtype-specific data |
|
1393
|
+
| (variable length) |
|
1394
|
+
+---------------------------------------------------------------+
|
1395
|
+
|
1396
|
+
Arguments:
|
1397
|
+
schema: parsed option schema
|
1398
|
+
options: extracted TCP options
|
1399
|
+
|
1400
|
+
Returns:
|
1401
|
+
Parsed option data.
|
1402
|
+
|
1403
|
+
"""
|
1404
|
+
subtype = schema.subtype
|
1405
|
+
name = self.__mp_option__[subtype]
|
1406
|
+
|
1407
|
+
if isinstance(name, str):
|
1408
|
+
meth_name = f'_read_mptcp_{name}'
|
1409
|
+
meth = cast('MPOptionParser',
|
1410
|
+
getattr(self, meth_name, self._read_mptcp_unknown))
|
1411
|
+
else:
|
1412
|
+
meth = name[0]
|
1413
|
+
|
1414
|
+
data = meth(schema, options=options)
|
1415
|
+
return data
|
1416
|
+
|
1417
|
+
def _read_mptcp_unknown(self, schema: 'Schema_MPTCPUnknown', *, options: 'Option') -> 'Data_MPTCPUnknown': # pylint: disable=unused-argument
|
1418
|
+
"""Read unknown MPTCP subtype.
|
1419
|
+
|
1420
|
+
Arguments:
|
1421
|
+
schema: parsed option schema
|
1422
|
+
options: extracted TCP options
|
1423
|
+
|
1424
|
+
Returns:
|
1425
|
+
Parsed option data.
|
1426
|
+
|
1427
|
+
"""
|
1428
|
+
data = Data_MPTCPUnknown(
|
1429
|
+
kind=Enum_Option.Multipath_TCP, # type: ignore[arg-type]
|
1430
|
+
length=schema.length,
|
1431
|
+
subtype=schema.subtype,
|
1432
|
+
data=schema.test['data'].to_bytes(1, 'big', signed=False) + schema.data,
|
1433
|
+
)
|
1434
|
+
return data
|
1435
|
+
|
1436
|
+
def _read_mptcp_capable(self, schema: 'Schema_MPTCPCapable', *, options: 'Option') -> 'Data_MPTCPCapable': # pylint: disable=unused-argument
|
1437
|
+
"""Read Multipath Capable option.
|
1438
|
+
|
1439
|
+
Structure of ``MP_CAPABLE`` [:rfc:`6824`]:
|
1440
|
+
|
1441
|
+
.. code-block:: text
|
1442
|
+
|
1443
|
+
1 2 3
|
1444
|
+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
1445
|
+
+---------------+---------------+-------+-------+---------------+
|
1446
|
+
| Kind | Length |Subtype|Version|A|B|C|D|E|F|G|H|
|
1447
|
+
+---------------+---------------+-------+-------+---------------+
|
1448
|
+
| Option Sender's Key (64 bits) |
|
1449
|
+
| |
|
1450
|
+
| |
|
1451
|
+
+---------------------------------------------------------------+
|
1452
|
+
| Option Receiver's Key (64 bits) |
|
1453
|
+
| (if option Length == 20) |
|
1454
|
+
| |
|
1455
|
+
+---------------------------------------------------------------+
|
1456
|
+
|
1457
|
+
Arguments:
|
1458
|
+
schema: parsed option schema
|
1459
|
+
options: extracted TCP options
|
1460
|
+
|
1461
|
+
Returns:
|
1462
|
+
Parsed option data.
|
1463
|
+
|
1464
|
+
Raises:
|
1465
|
+
ProtocolError: If length is **NOT** ``20`` or ``32``.
|
1466
|
+
|
1467
|
+
"""
|
1468
|
+
if schema.length not in (20, 32):
|
1469
|
+
raise ProtocolError(f'{self.alias}: [OptNo {schema.kind}] invalid format')
|
1470
|
+
|
1471
|
+
data = Data_MPTCPCapable(
|
1472
|
+
kind=Enum_Option.Multipath_TCP, # type: ignore[arg-type]
|
1473
|
+
length=schema.length,
|
1474
|
+
subtype=schema.subtype,
|
1475
|
+
version=schema.test['version'],
|
1476
|
+
flags=Data_MPTCPCapableFlag(
|
1477
|
+
req=bool(schema.flags['req']),
|
1478
|
+
ext=bool(schema.flags['ext']),
|
1479
|
+
hsa=bool(schema.flags['hsa']),
|
1480
|
+
),
|
1481
|
+
skey=schema.skey,
|
1482
|
+
rkey=schema.rkey if schema.length == 32 else None,
|
1483
|
+
)
|
1484
|
+
return data
|
1485
|
+
|
1486
|
+
def _read_mptcp_join(self, schema: 'Schema_MPTCPJoin', *, options: 'Option') -> 'Data_MPTCPJoin':
|
1487
|
+
"""Read Join Connection option.
|
1488
|
+
|
1489
|
+
Arguments:
|
1490
|
+
schema: parsed option schema
|
1491
|
+
options: extracted TCP options
|
1492
|
+
|
1493
|
+
Returns:
|
1494
|
+
Parsed option data.
|
1495
|
+
|
1496
|
+
Raises:
|
1497
|
+
ProtocolError: If the option is not given on a valid SYN/ACK packet.
|
1498
|
+
|
1499
|
+
"""
|
1500
|
+
if Enum_Flags.SYN in self._flags and Enum_Flags.ACK not in self._flags: # MP_JOIN-SYN
|
1501
|
+
return self._read_join_syn(schema, options=options) # type: ignore[arg-type]
|
1502
|
+
if Enum_Flags.SYN in self._flags and Enum_Flags.ACK in self._flags: # MP_JOIN-SYN/ACK
|
1503
|
+
return self._read_join_synack(schema, options=options) # type: ignore[arg-type]
|
1504
|
+
if Enum_Flags.SYN not in self._flags and Enum_Flags.ACK in self._flags: # MP_JOIN-ACK
|
1505
|
+
return self._read_join_ack(schema, options=options) # type: ignore[arg-type]
|
1506
|
+
raise ProtocolError(f'{self.alias}: : [OptNo {schema.kind}] {schema.subtype}: invalid flags combination')
|
1507
|
+
|
1508
|
+
def _read_join_syn(self, schema: 'Schema_MPTCPJoinSYN', *, options: 'Option') -> 'Data_MPTCPJoinSYN': # pylint: disable=unused-argument
|
1509
|
+
"""Read Join Connection option for Initial SYN.
|
1510
|
+
|
1511
|
+
Structure of ``MP_JOIN-SYN`` [:rfc:`6824`]:
|
1512
|
+
|
1513
|
+
.. code-block:: text
|
1514
|
+
|
1515
|
+
1 2 3
|
1516
|
+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
1517
|
+
+---------------+---------------+-------+-----+-+---------------+
|
1518
|
+
| Kind | Length = 12 |Subtype| |B| Address ID |
|
1519
|
+
+---------------+---------------+-------+-----+-+---------------+
|
1520
|
+
| Receiver's Token (32 bits) |
|
1521
|
+
+---------------------------------------------------------------+
|
1522
|
+
| Sender's Random Number (32 bits) |
|
1523
|
+
+---------------------------------------------------------------+
|
1524
|
+
|
1525
|
+
Arguments:
|
1526
|
+
schema: parsed option schema
|
1527
|
+
options: extracted TCP options
|
1528
|
+
|
1529
|
+
Returns:
|
1530
|
+
Parsed option data.
|
1531
|
+
|
1532
|
+
Raises:
|
1533
|
+
ProtocolError: If length is **NOT** ``12``.
|
1534
|
+
|
1535
|
+
"""
|
1536
|
+
if schema.length != 12:
|
1537
|
+
raise ProtocolError(f'{self.alias}: [OptNo {schema.kind}] invalid format')
|
1538
|
+
|
1539
|
+
data = Data_MPTCPJoinSYN(
|
1540
|
+
kind=Enum_Option.Multipath_TCP, # type: ignore[arg-type]
|
1541
|
+
length=schema.length,
|
1542
|
+
subtype=schema.subtype,
|
1543
|
+
connection=Enum_Flags.SYN, # type: ignore[arg-type]
|
1544
|
+
backup=bool(schema.test['backup']),
|
1545
|
+
addr_id=schema.addr_id,
|
1546
|
+
token=schema.token,
|
1547
|
+
nonce=schema.nonce,
|
1548
|
+
)
|
1549
|
+
return data
|
1550
|
+
|
1551
|
+
def _read_join_synack(self, schema: 'Schema_MPTCPJoinSYNACK', options: 'Option') -> 'Data_MPTCPJoinSYNACK': # pylint: disable=unused-argument
|
1552
|
+
"""Read Join Connection option for Responding SYN/ACK.
|
1553
|
+
|
1554
|
+
Structure of ``MP_JOIN-SYN/ACK`` [:rfc:`6824`]:
|
1555
|
+
|
1556
|
+
.. code-block:: text
|
1557
|
+
|
1558
|
+
1 2 3
|
1559
|
+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
1560
|
+
+---------------+---------------+-------+-----+-+---------------+
|
1561
|
+
| Kind | Length = 16 |Subtype| |B| Address ID |
|
1562
|
+
+---------------+---------------+-------+-----+-+---------------+
|
1563
|
+
| |
|
1564
|
+
| Sender's Truncated HMAC (64 bits) |
|
1565
|
+
| |
|
1566
|
+
+---------------------------------------------------------------+
|
1567
|
+
| Sender's Random Number (32 bits) |
|
1568
|
+
+---------------------------------------------------------------+
|
1569
|
+
|
1570
|
+
Arguments:
|
1571
|
+
schema: parsed option schema
|
1572
|
+
options: extracted TCP options
|
1573
|
+
|
1574
|
+
Returns:
|
1575
|
+
Parsed option data.
|
1576
|
+
|
1577
|
+
Raises:
|
1578
|
+
ProtocolError: If length is **NOT** ``20``.
|
1579
|
+
|
1580
|
+
"""
|
1581
|
+
if schema.length != 20:
|
1582
|
+
raise ProtocolError(f'{self.alias}: [OptNo {schema.kind}] invalid format')
|
1583
|
+
|
1584
|
+
data = Data_MPTCPJoinSYNACK(
|
1585
|
+
kind=Enum_Option.Multipath_TCP, # type: ignore[arg-type]
|
1586
|
+
length=schema.length,
|
1587
|
+
subtype=schema.subtype,
|
1588
|
+
connection=Enum_Flags.SYN | Enum_Flags.ACK, # type: ignore[arg-type]
|
1589
|
+
backup=bool(schema.test['backup']),
|
1590
|
+
addr_id=schema.addr_id,
|
1591
|
+
hmac=schema.hmac,
|
1592
|
+
nonce=schema.nonce,
|
1593
|
+
)
|
1594
|
+
return data
|
1595
|
+
|
1596
|
+
def _read_join_ack(self, schema: 'Schema_MPTCPJoinACK', *, options: 'Option') -> 'Data_MPTCPJoinACK': # pylint: disable=unused-argument
|
1597
|
+
"""Read Join Connection option for Third ACK.
|
1598
|
+
|
1599
|
+
Structure of ``MP_JOIN-ACK`` [:rfc:`6824`]:
|
1600
|
+
|
1601
|
+
.. code-block:: text
|
1602
|
+
|
1603
|
+
1 2 3
|
1604
|
+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
1605
|
+
+---------------+---------------+-------+-----------------------+
|
1606
|
+
| Kind | Length = 24 |Subtype| (reserved) |
|
1607
|
+
+---------------+---------------+-------+-----------------------+
|
1608
|
+
| |
|
1609
|
+
| |
|
1610
|
+
| Sender's HMAC (160 bits) |
|
1611
|
+
| |
|
1612
|
+
| |
|
1613
|
+
+---------------------------------------------------------------+
|
1614
|
+
|
1615
|
+
Arguments:
|
1616
|
+
schema: parsed option schema
|
1617
|
+
options: extracted TCP options
|
1618
|
+
|
1619
|
+
Returns:
|
1620
|
+
Parsed option data.
|
1621
|
+
|
1622
|
+
Raises:
|
1623
|
+
ProtocolError: If length is **NOT** ``24``.
|
1624
|
+
|
1625
|
+
"""
|
1626
|
+
if schema.length != 24:
|
1627
|
+
raise ProtocolError(f'{self.alias}: [OptNo {schema.kind}] invalid format')
|
1628
|
+
|
1629
|
+
data = Data_MPTCPJoinACK(
|
1630
|
+
kind=Enum_Option.Multipath_TCP, # type: ignore[arg-type]
|
1631
|
+
length=schema.length,
|
1632
|
+
subtype=schema.subtype,
|
1633
|
+
connection=Enum_Flags.ACK, # type: ignore[arg-type]
|
1634
|
+
hmac=schema.hmac,
|
1635
|
+
)
|
1636
|
+
return data
|
1637
|
+
|
1638
|
+
def _read_mptcp_dss(self, schema: 'Schema_MPTCPDSS', *, options: 'Option') -> 'Data_MPTCPDSS': # pylint: disable=unused-argument
|
1639
|
+
"""Read Data Sequence Signal (Data ACK and Data Sequence Mapping) option.
|
1640
|
+
|
1641
|
+
Structure of ``DSS`` [:rfc:`6824`]:
|
1642
|
+
|
1643
|
+
.. code-block:: text
|
1644
|
+
|
1645
|
+
1 2 3
|
1646
|
+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
1647
|
+
+---------------+---------------+-------+----------------------+
|
1648
|
+
| Kind | Length |Subtype| (reserved) |F|m|M|a|A|
|
1649
|
+
+---------------+---------------+-------+----------------------+
|
1650
|
+
| |
|
1651
|
+
| Data ACK (4 or 8 octets, depending on flags) |
|
1652
|
+
| |
|
1653
|
+
+--------------------------------------------------------------+
|
1654
|
+
| |
|
1655
|
+
| Data sequence number (4 or 8 octets, depending on flags) |
|
1656
|
+
| |
|
1657
|
+
+--------------------------------------------------------------+
|
1658
|
+
| Subflow Sequence Number (4 octets) |
|
1659
|
+
+-------------------------------+------------------------------+
|
1660
|
+
| Data-Level Length (2 octets) | Checksum (2 octets) |
|
1661
|
+
+-------------------------------+------------------------------+
|
1662
|
+
|
1663
|
+
Arguments:
|
1664
|
+
schema: parsed option schema
|
1665
|
+
options: extracted TCP options
|
1666
|
+
|
1667
|
+
Returns:
|
1668
|
+
Parsed option data.
|
1669
|
+
|
1670
|
+
"""
|
1671
|
+
data = Data_MPTCPDSS(
|
1672
|
+
kind=Enum_Option.Multipath_TCP, # type: ignore[arg-type]
|
1673
|
+
length=schema.length,
|
1674
|
+
subtype=schema.subtype,
|
1675
|
+
data_fin=bool(schema.flags['F']),
|
1676
|
+
ack=schema.ack,
|
1677
|
+
dsn=schema.dsn,
|
1678
|
+
ssn=schema.ssn,
|
1679
|
+
dl_len=schema.dl_len,
|
1680
|
+
checksum=schema.checksum,
|
1681
|
+
)
|
1682
|
+
return data
|
1683
|
+
|
1684
|
+
def _read_mptcp_addaddr(self, schema: 'Schema_MPTCPAddAddress', *, options: 'Option') -> 'Data_MPTCPAddAddress': # pylint: disable=unused-argument
|
1685
|
+
"""Read Add Address option.
|
1686
|
+
|
1687
|
+
Structure of ``ADD_ADDR`` [:rfc:`6824`]:
|
1688
|
+
|
1689
|
+
.. code-block:: text
|
1690
|
+
|
1691
|
+
1 2 3
|
1692
|
+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
1693
|
+
+---------------+---------------+-------+-------+---------------+
|
1694
|
+
| Kind | Length |Subtype| IPVer | Address ID |
|
1695
|
+
+---------------+---------------+-------+-------+---------------+
|
1696
|
+
| Address (TCP - 4 octets / IPv6 - 16 octets) |
|
1697
|
+
+-------------------------------+-------------------------------+
|
1698
|
+
| Port (2 octets, optional) |
|
1699
|
+
+-------------------------------+
|
1700
|
+
|
1701
|
+
Arguments:
|
1702
|
+
schema: parsed option schema
|
1703
|
+
options: extracted TCP options
|
1704
|
+
|
1705
|
+
Returns:
|
1706
|
+
Parsed option data.
|
1707
|
+
|
1708
|
+
Raises:
|
1709
|
+
ProtocolError: Invalid IP version and/or addresses.
|
1710
|
+
|
1711
|
+
"""
|
1712
|
+
if schema.test['version'] not in (4, 6):
|
1713
|
+
raise ProtocolError(f'{self.alias}: [OptNo {schema.kind}] invalid IP version')
|
1714
|
+
|
1715
|
+
data = Data_MPTCPAddAddress(
|
1716
|
+
kind=Enum_Option.Multipath_TCP, # type: ignore[arg-type]
|
1717
|
+
length=schema.length,
|
1718
|
+
subtype=schema.subtype,
|
1719
|
+
version=schema.test['version'],
|
1720
|
+
addr_id=schema.addr_id,
|
1721
|
+
addr=schema.address,
|
1722
|
+
port=schema.port,
|
1723
|
+
)
|
1724
|
+
return data
|
1725
|
+
|
1726
|
+
def _read_mptcp_remove(self, schema: 'Schema_MPTCPRemoveAddress', *, options: 'Option') -> 'Data_MPTCPRemoveAddress': # pylint: disable=unused-argument
|
1727
|
+
"""Read Remove Address option.
|
1728
|
+
|
1729
|
+
Structure of ``REMOVE_ADDR`` [:rfc:`6824`]:
|
1730
|
+
|
1731
|
+
.. code-block:: text
|
1732
|
+
|
1733
|
+
1 2 3
|
1734
|
+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
1735
|
+
+---------------+---------------+-------+-------+---------------+
|
1736
|
+
| Kind | Length = 3+n |Subtype|(resvd)| Address ID | ...
|
1737
|
+
+---------------+---------------+-------+-------+---------------+
|
1738
|
+
(followed by n-1 Address IDs, if required)
|
1739
|
+
|
1740
|
+
Arguments:
|
1741
|
+
schema: parsed option schema
|
1742
|
+
options: extracted TCP options
|
1743
|
+
|
1744
|
+
Returns:
|
1745
|
+
Parsed option data.
|
1746
|
+
|
1747
|
+
Raises:
|
1748
|
+
ProtocolError: If the length is smaller than **3**.
|
1749
|
+
|
1750
|
+
"""
|
1751
|
+
if schema.length < 3:
|
1752
|
+
raise ProtocolError(f'{self.alias}: [OptNo {schema.kind}] invalid format')
|
1753
|
+
|
1754
|
+
data = Data_MPTCPRemoveAddress(
|
1755
|
+
kind=Enum_Option.Multipath_TCP, # type: ignore[arg-type]
|
1756
|
+
length=schema.length,
|
1757
|
+
subtype=schema.subtype,
|
1758
|
+
addr_id=tuple(schema.addr_id),
|
1759
|
+
)
|
1760
|
+
|
1761
|
+
return data
|
1762
|
+
|
1763
|
+
def _read_mptcp_prio(self, schema: 'Schema_MPTCPPriority', *, options: 'Option') -> 'Data_MPTCPPriority': # pylint: disable=unused-argument
|
1764
|
+
"""Read Change Subflow Priority option.
|
1765
|
+
|
1766
|
+
Structure of ``MP_PRIO`` [RFC 6824]:
|
1767
|
+
|
1768
|
+
.. code-block:: text
|
1769
|
+
|
1770
|
+
1 2 3
|
1771
|
+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
1772
|
+
+---------------+---------------+-------+-----+-+--------------+
|
1773
|
+
| Kind | Length |Subtype| |B| AddrID (opt) |
|
1774
|
+
+---------------+---------------+-------+-----+-+--------------+
|
1775
|
+
|
1776
|
+
Arguments:
|
1777
|
+
schema: parsed option schema
|
1778
|
+
options: extracted TCP options
|
1779
|
+
|
1780
|
+
Returns:
|
1781
|
+
Parsed option data.
|
1782
|
+
|
1783
|
+
Raises:
|
1784
|
+
ProtocolError: If the length is smaller than **3**.
|
1785
|
+
|
1786
|
+
"""
|
1787
|
+
if schema.length not in (3, 4):
|
1788
|
+
raise ProtocolError(f'{self.alias}: [OptNo {schema.kind}] invalid format')
|
1789
|
+
|
1790
|
+
data = Data_MPTCPPriority(
|
1791
|
+
kind=Enum_Option.Multipath_TCP, # type: ignore[arg-type]
|
1792
|
+
length=schema.length,
|
1793
|
+
subtype=schema.subtype,
|
1794
|
+
backup=bool(schema.test['backup']),
|
1795
|
+
addr_id=schema.addr_id,
|
1796
|
+
)
|
1797
|
+
|
1798
|
+
return data
|
1799
|
+
|
1800
|
+
def _read_mptcp_fail(self, schema: 'Schema_MPTCPFallback', *, options: 'Option') -> 'Data_MPTCPFallback': # pylint: disable=unused-argument
|
1801
|
+
"""Read Fallback option.
|
1802
|
+
|
1803
|
+
Structure of ``MP_FAIL`` [:rfc:`6824`]:
|
1804
|
+
|
1805
|
+
.. code-block:: text
|
1806
|
+
|
1807
|
+
1 2 3
|
1808
|
+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
1809
|
+
+---------------+---------------+-------+----------------------+
|
1810
|
+
| Kind | Length=12 |Subtype| (reserved) |
|
1811
|
+
+---------------+---------------+-------+----------------------+
|
1812
|
+
| |
|
1813
|
+
| Data Sequence Number (8 octets) |
|
1814
|
+
| |
|
1815
|
+
+--------------------------------------------------------------+
|
1816
|
+
|
1817
|
+
Arguments:
|
1818
|
+
schema: parsed option schema
|
1819
|
+
options: extracted TCP options
|
1820
|
+
|
1821
|
+
Returns:
|
1822
|
+
Parsed option data.
|
1823
|
+
|
1824
|
+
Raises:
|
1825
|
+
ProtocolError: If the length is **NOT** 12.
|
1826
|
+
|
1827
|
+
"""
|
1828
|
+
if schema.length != 12:
|
1829
|
+
raise ProtocolError(f'{self.alias}: [OptNo {schema.kind}] invalid format')
|
1830
|
+
|
1831
|
+
data = Data_MPTCPFallback(
|
1832
|
+
kind=Enum_Option.Multipath_TCP, # type: ignore[arg-type]
|
1833
|
+
length=schema.length,
|
1834
|
+
subtype=schema.subtype,
|
1835
|
+
dsn=schema.dsn,
|
1836
|
+
)
|
1837
|
+
return data
|
1838
|
+
|
1839
|
+
def _read_mptcp_fastclose(self, schema: 'Schema_MPTCPFastclose', options: 'Option') -> 'Data_MPTCPFastclose': # pylint: disable=unused-argument
|
1840
|
+
"""Read Fast Close option.
|
1841
|
+
|
1842
|
+
Structure of ``MP_FASTCLOSE`` [RFC 6824]:
|
1843
|
+
|
1844
|
+
.. code-block:: text
|
1845
|
+
|
1846
|
+
1 2 3
|
1847
|
+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
1848
|
+
+---------------+---------------+-------+-----------------------+
|
1849
|
+
| Kind | Length |Subtype| (reserved) |
|
1850
|
+
+---------------+---------------+-------+-----------------------+
|
1851
|
+
| Option Receiver's Key |
|
1852
|
+
| (64 bits) |
|
1853
|
+
| |
|
1854
|
+
+---------------------------------------------------------------+
|
1855
|
+
|
1856
|
+
Arguments:
|
1857
|
+
schema: parsed option schema
|
1858
|
+
options: extracted TCP options
|
1859
|
+
|
1860
|
+
Returns:
|
1861
|
+
Parsed option data.
|
1862
|
+
|
1863
|
+
Raises:
|
1864
|
+
ProtocolError: If the length is **NOT** 16.
|
1865
|
+
|
1866
|
+
"""
|
1867
|
+
if schema.length != 16:
|
1868
|
+
raise ProtocolError(f'{self.alias}: [OptNo {schema.kind}] invalid format')
|
1869
|
+
|
1870
|
+
data = Data_MPTCPFastclose(
|
1871
|
+
kind=Enum_Option.Multipath_TCP, # type: ignore[arg-type]
|
1872
|
+
length=schema.length,
|
1873
|
+
subtype=schema.subtype,
|
1874
|
+
rkey=schema.key,
|
1875
|
+
)
|
1876
|
+
return data
|
1877
|
+
|
1878
|
+
def _read_mode_fastopen(self, schema: 'Schema_FastOpenCookie', *, options: 'Option') -> 'Data_FastOpenCookie': # pylint: disable=unused-argument
|
1879
|
+
"""Read Fast Open option.
|
1880
|
+
|
1881
|
+
Structure of TCP ``FASTOPEN`` [:rfc:`7413`]:
|
1882
|
+
|
1883
|
+
.. code-block:: text
|
1884
|
+
|
1885
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
1886
|
+
| Kind | Length |
|
1887
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
1888
|
+
| |
|
1889
|
+
~ Cookie ~
|
1890
|
+
| |
|
1891
|
+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
1892
|
+
|
1893
|
+
Arguments:
|
1894
|
+
schema: parsed option schema
|
1895
|
+
options: extracted TCP options
|
1896
|
+
|
1897
|
+
Returns:
|
1898
|
+
Parsed option data.
|
1899
|
+
|
1900
|
+
Raises:
|
1901
|
+
ProtocolError: If length is **NOT** valid.
|
1902
|
+
|
1903
|
+
"""
|
1904
|
+
if not (6 <= schema.length <= 18 or schema.length == 2) and schema.length % 2 != 0:
|
1905
|
+
raise ProtocolError(f'{self.alias}: [OptNo {schema.kind}] invalid format')
|
1906
|
+
|
1907
|
+
data = Data_FastOpenCookie(
|
1908
|
+
kind=schema.kind,
|
1909
|
+
length=schema.length,
|
1910
|
+
cookie=schema.cookie,
|
1911
|
+
)
|
1912
|
+
return data
|
1913
|
+
|
1914
|
+
def _make_tcp_options(self, options: 'list[Schema_Option | tuple[Enum_Option, dict[str, Any]] | bytes] | Option') -> 'tuple[list[Schema_Option | bytes], int]':
|
1915
|
+
"""Make options for TCP.
|
1916
|
+
|
1917
|
+
Args:
|
1918
|
+
options: TCP options
|
1919
|
+
|
1920
|
+
Returns:
|
1921
|
+
Tuple of options and total length of options.
|
1922
|
+
|
1923
|
+
"""
|
1924
|
+
total_length = 0
|
1925
|
+
if isinstance(options, list):
|
1926
|
+
options_list = [] # type: list[Schema_Option | bytes]
|
1927
|
+
for schema in options:
|
1928
|
+
if isinstance(schema, bytes):
|
1929
|
+
code = Enum_Option.get(schema[0])
|
1930
|
+
if code in (Enum_Option.No_Operation, Enum_Option.End_of_Option_List): # ignore padding options by default
|
1931
|
+
continue
|
1932
|
+
|
1933
|
+
data = schema # type: Schema_Option | bytes
|
1934
|
+
data_len = len(data)
|
1935
|
+
elif isinstance(schema, Schema):
|
1936
|
+
code = schema.type
|
1937
|
+
if code in (Enum_Option.No_Operation, Enum_Option.End_of_Option_List): # ignore padding options by default
|
1938
|
+
continue
|
1939
|
+
|
1940
|
+
data = schema
|
1941
|
+
data_len = len(schema.pack())
|
1942
|
+
else:
|
1943
|
+
code, args = cast('tuple[Enum_Option, dict[str, Any]]', schema)
|
1944
|
+
if code in (Enum_Option.No_Operation, Enum_Option.End_of_Option_List): # ignore padding options by default
|
1945
|
+
continue
|
1946
|
+
|
1947
|
+
name = self.__option__[code]
|
1948
|
+
if isinstance(name, str):
|
1949
|
+
meth_name = f'_make_mode_{name}'
|
1950
|
+
meth = cast('OptionConstructor',
|
1951
|
+
getattr(self, meth_name, self._make_mode_donone))
|
1952
|
+
else:
|
1953
|
+
meth = name[1]
|
1954
|
+
|
1955
|
+
data = meth(code, **args)
|
1956
|
+
data_len = len(data.pack())
|
1957
|
+
|
1958
|
+
options_list.append(data)
|
1959
|
+
total_length += data_len
|
1960
|
+
|
1961
|
+
# force alignment to 32-bit boundary
|
1962
|
+
if data_len % 4:
|
1963
|
+
pad_len = 4 - (data_len % 4)
|
1964
|
+
pad_opt = self._make_mode_nop(Enum_Option.No_Operation) # type: ignore[arg-type]
|
1965
|
+
total_length += pad_len
|
1966
|
+
|
1967
|
+
for _ in range(pad_len - 1):
|
1968
|
+
options_list.append(pad_opt)
|
1969
|
+
options_list.append(self._make_mode_eool(Enum_Option.End_of_Option_List)) # type: ignore[arg-type]
|
1970
|
+
return options_list, total_length
|
1971
|
+
|
1972
|
+
options_list = []
|
1973
|
+
for code, option in options.items(multi=True):
|
1974
|
+
# ignore padding options by default
|
1975
|
+
if code in (Enum_Option.No_Operation, Enum_Option.End_of_Option_List):
|
1976
|
+
continue
|
1977
|
+
|
1978
|
+
name = self.__option__[code]
|
1979
|
+
if isinstance(name, str):
|
1980
|
+
meth_name = f'_make_mode_{name}'
|
1981
|
+
meth = cast('OptionConstructor',
|
1982
|
+
getattr(self, meth_name, self._make_mode_donone))
|
1983
|
+
else:
|
1984
|
+
meth = name[1]
|
1985
|
+
|
1986
|
+
data = meth(code, option)
|
1987
|
+
data_len = len(data.pack())
|
1988
|
+
|
1989
|
+
options_list.append(data)
|
1990
|
+
total_length += data_len
|
1991
|
+
|
1992
|
+
# force alignment to 32-bit boundary
|
1993
|
+
if data_len % 4:
|
1994
|
+
pad_len = 4 - (data_len % 4)
|
1995
|
+
pad_opt = self._make_mode_nop(Enum_Option.No_Operation) # type: ignore[arg-type]
|
1996
|
+
total_length += pad_len
|
1997
|
+
|
1998
|
+
for _ in range(pad_len - 1):
|
1999
|
+
options_list.append(pad_opt)
|
2000
|
+
options_list.append(self._make_mode_eool(Enum_Option.End_of_Option_List)) # type: ignore[arg-type]
|
2001
|
+
return options_list, total_length
|
2002
|
+
|
2003
|
+
def _make_mode_donone(self, code: 'Enum_Option', opt: 'Optional[Data_UnassignedOption]' = None, *,
|
2004
|
+
data: 'bytes' = b'',
|
2005
|
+
**kwargs: 'Any') -> 'Schema_UnassignedOption':
|
2006
|
+
"""Make TCP unassigned option.
|
2007
|
+
|
2008
|
+
Args:
|
2009
|
+
code: option code
|
2010
|
+
opt: option data
|
2011
|
+
data: option payload in :obj:`bytes`
|
2012
|
+
**kwargs: arbitrary keyword arguments
|
2013
|
+
|
2014
|
+
Returns:
|
2015
|
+
Constructed option schema.
|
2016
|
+
|
2017
|
+
"""
|
2018
|
+
if opt is not None:
|
2019
|
+
data = opt.data
|
2020
|
+
|
2021
|
+
return Schema_UnassignedOption(
|
2022
|
+
kind=code,
|
2023
|
+
length=len(data) + 2,
|
2024
|
+
data=data,
|
2025
|
+
)
|
2026
|
+
|
2027
|
+
def _make_mode_eool(self, code: 'Enum_Option', opt: 'Optional[Data_EndOfOptionList]' = None, **kwargs: 'Any') -> 'Schema_EndOfOptionList':
|
2028
|
+
"""Make TCP End of Option List option.
|
2029
|
+
|
2030
|
+
Args:
|
2031
|
+
code: option code
|
2032
|
+
opt: option data
|
2033
|
+
**kwargs: arbitrary keyword arguments
|
2034
|
+
|
2035
|
+
Returns:
|
2036
|
+
Constructed option schema.
|
2037
|
+
|
2038
|
+
"""
|
2039
|
+
return Schema_EndOfOptionList(
|
2040
|
+
kind=code,
|
2041
|
+
length=1,
|
2042
|
+
)
|
2043
|
+
|
2044
|
+
def _make_mode_nop(self, code: 'Enum_Option', opt: 'Optional[Data_NoOperation]' = None, **kwargs: 'Any') -> 'Schema_NoOperation':
|
2045
|
+
"""Make TCP NoOperation option.
|
2046
|
+
|
2047
|
+
Args:
|
2048
|
+
code: option code
|
2049
|
+
opt: option data
|
2050
|
+
**kwargs: arbitrary keyword arguments
|
2051
|
+
|
2052
|
+
Returns:
|
2053
|
+
Constructed option schema.
|
2054
|
+
|
2055
|
+
"""
|
2056
|
+
return Schema_NoOperation(
|
2057
|
+
kind=code,
|
2058
|
+
length=1,
|
2059
|
+
)
|
2060
|
+
|
2061
|
+
def _make_mode_mss(self, code: 'Enum_Option', opt: 'Optional[Data_MaximumSegmentSize]' = None, *,
|
2062
|
+
mss: 'int' = 65535, # reasonable default value
|
2063
|
+
**kwargs: 'Any') -> 'Schema_MaximumSegmentSize':
|
2064
|
+
"""Make TCP maximum segment size option.
|
2065
|
+
|
2066
|
+
Args:
|
2067
|
+
code: option code
|
2068
|
+
opt: option data
|
2069
|
+
mss: maximum segment size
|
2070
|
+
**kwargs: arbitrary keyword arguments
|
2071
|
+
|
2072
|
+
Returns:
|
2073
|
+
Constructed option schema.
|
2074
|
+
|
2075
|
+
"""
|
2076
|
+
if opt is not None:
|
2077
|
+
mss = opt.mss
|
2078
|
+
|
2079
|
+
return Schema_MaximumSegmentSize(
|
2080
|
+
kind=code,
|
2081
|
+
length=4,
|
2082
|
+
mss=mss,
|
2083
|
+
)
|
2084
|
+
|
2085
|
+
def _make_mode_ws(self, code: 'Enum_Option', opt: 'Optional[Data_WindowScale]' = None, *,
|
2086
|
+
shift: 'int' = 0, # reasonable default value
|
2087
|
+
**kwargs: 'Any') -> 'Schema_WindowScale':
|
2088
|
+
"""Make TCP window scale option.
|
2089
|
+
|
2090
|
+
Args:
|
2091
|
+
code: option code
|
2092
|
+
opt: option data
|
2093
|
+
shift: window scale shift count
|
2094
|
+
**kwargs: arbitrary keyword arguments
|
2095
|
+
|
2096
|
+
Returns:
|
2097
|
+
Constructed option schema.
|
2098
|
+
|
2099
|
+
"""
|
2100
|
+
if opt is not None:
|
2101
|
+
shift = opt.shift
|
2102
|
+
|
2103
|
+
return Schema_WindowScale(
|
2104
|
+
kind=code,
|
2105
|
+
length=3,
|
2106
|
+
scale=shift,
|
2107
|
+
)
|
2108
|
+
|
2109
|
+
def _make_mode_sackpmt(self, code: 'Enum_Option', opt: 'Optional[Data_SACKPermitted]' = None,
|
2110
|
+
**kwargs: 'Any') -> 'Schema_SACKPermitted':
|
2111
|
+
"""Make TCP SACK permitted option.
|
2112
|
+
|
2113
|
+
Args:
|
2114
|
+
code: option code
|
2115
|
+
opt: option data
|
2116
|
+
**kwargs: arbitrary keyword arguments
|
2117
|
+
|
2118
|
+
Returns:
|
2119
|
+
Constructed option schema.
|
2120
|
+
|
2121
|
+
"""
|
2122
|
+
return Schema_SACKPermitted(
|
2123
|
+
kind=code,
|
2124
|
+
length=2,
|
2125
|
+
)
|
2126
|
+
|
2127
|
+
def _make_mode_sack(self, code: 'Enum_Option', opt: 'Optional[Data_SACK]' = None, *,
|
2128
|
+
sack: 'Optional[list[tuple[int, int]]]' = None,
|
2129
|
+
**kwargs: 'Any') -> 'Schema_SACK':
|
2130
|
+
"""Make TCP SACK option.
|
2131
|
+
|
2132
|
+
Args:
|
2133
|
+
code: option code
|
2134
|
+
opt: option data
|
2135
|
+
sack: SACK blocks
|
2136
|
+
**kwargs: arbitrary keyword arguments
|
2137
|
+
|
2138
|
+
Returns:
|
2139
|
+
Constructed option schema.
|
2140
|
+
|
2141
|
+
"""
|
2142
|
+
if opt is not None:
|
2143
|
+
sack_val = [Schema_SACKBlock(
|
2144
|
+
left=block.left,
|
2145
|
+
right=block.right,
|
2146
|
+
) for block in opt.sack]
|
2147
|
+
else:
|
2148
|
+
sack_val = []
|
2149
|
+
|
2150
|
+
if sack is not None:
|
2151
|
+
for left, right in sack:
|
2152
|
+
sack_val.append(Schema_SACKBlock(
|
2153
|
+
left=left,
|
2154
|
+
right=right,
|
2155
|
+
))
|
2156
|
+
|
2157
|
+
return Schema_SACK(
|
2158
|
+
kind=code,
|
2159
|
+
length=2 + (len(sack_val) * 8),
|
2160
|
+
sack=sack_val,
|
2161
|
+
)
|
2162
|
+
|
2163
|
+
def _make_mode_echo(self, code: 'Enum_Option', opt: 'Optional[Data_Echo]' = None, *,
|
2164
|
+
data: 'bytes' = b'\x00\x00\x00\x00',
|
2165
|
+
**kwargs: 'Any') -> 'Schema_Echo':
|
2166
|
+
"""Make TCP echo option.
|
2167
|
+
|
2168
|
+
Args:
|
2169
|
+
code: option code
|
2170
|
+
opt: option data
|
2171
|
+
data: 4 bytes of info to be echoed
|
2172
|
+
**kwargs: arbitrary keyword arguments
|
2173
|
+
|
2174
|
+
Returns:
|
2175
|
+
Constructed option schema.
|
2176
|
+
|
2177
|
+
"""
|
2178
|
+
if opt is not None:
|
2179
|
+
data = opt.data
|
2180
|
+
|
2181
|
+
return Schema_Echo(
|
2182
|
+
kind=code,
|
2183
|
+
length=6,
|
2184
|
+
data=data,
|
2185
|
+
)
|
2186
|
+
|
2187
|
+
def _make_mode_echore(self, code: 'Enum_Option', opt: 'Optional[Data_EchoReply]' = None, *,
|
2188
|
+
data: 'bytes' = b'\x00\x00\x00\x00',
|
2189
|
+
**kwargs: 'Any') -> 'Schema_EchoReply':
|
2190
|
+
"""Make TCP echo reply option.
|
2191
|
+
|
2192
|
+
Args:
|
2193
|
+
code: option code
|
2194
|
+
opt: option data
|
2195
|
+
data: 4 bytes of echoed info
|
2196
|
+
**kwargs: arbitrary keyword arguments
|
2197
|
+
|
2198
|
+
Returns:
|
2199
|
+
Constructed option schema.
|
2200
|
+
|
2201
|
+
"""
|
2202
|
+
if opt is not None:
|
2203
|
+
data = opt.data
|
2204
|
+
|
2205
|
+
return Schema_EchoReply(
|
2206
|
+
kind=code,
|
2207
|
+
length=6,
|
2208
|
+
data=data,
|
2209
|
+
)
|
2210
|
+
|
2211
|
+
def _make_mode_ts(self, code: 'Enum_Option', opt: 'Optional[Data_Timestamps]' = None, *,
|
2212
|
+
tsval: 'int' = 0,
|
2213
|
+
tsecr: 'int' = 0,
|
2214
|
+
**kwargs: 'Any') -> 'Schema_Timestamps':
|
2215
|
+
"""Make TCP timestamps option.
|
2216
|
+
|
2217
|
+
Args:
|
2218
|
+
code: option code
|
2219
|
+
opt: option data
|
2220
|
+
tsval: timestamp value
|
2221
|
+
tsecr: timestamp echo reply
|
2222
|
+
**kwargs: arbitrary keyword arguments
|
2223
|
+
|
2224
|
+
Returns:
|
2225
|
+
Constructed option schema.
|
2226
|
+
|
2227
|
+
"""
|
2228
|
+
if opt is not None:
|
2229
|
+
tsval = opt.timestamp
|
2230
|
+
tsecr = opt.echo
|
2231
|
+
|
2232
|
+
return Schema_Timestamps(
|
2233
|
+
kind=code,
|
2234
|
+
length=10,
|
2235
|
+
value=tsval,
|
2236
|
+
reply=tsecr,
|
2237
|
+
)
|
2238
|
+
|
2239
|
+
def _make_mode_poc(self, code: 'Enum_Option', opt: 'Optional[Data_PartialOrderConnectionPermitted]' = None,
|
2240
|
+
**kwargs: 'Any') -> 'Schema_PartialOrderConnectionPermitted':
|
2241
|
+
"""Make TCP partial order connection option.
|
2242
|
+
|
2243
|
+
Args:
|
2244
|
+
code: option code
|
2245
|
+
opt: option data
|
2246
|
+
**kwargs: arbitrary keyword arguments
|
2247
|
+
|
2248
|
+
Returns:
|
2249
|
+
Constructed option schema.
|
2250
|
+
|
2251
|
+
"""
|
2252
|
+
return Schema_PartialOrderConnectionPermitted(
|
2253
|
+
kind=code,
|
2254
|
+
length=2,
|
2255
|
+
)
|
2256
|
+
|
2257
|
+
def _make_mode_pocsp(self, code: 'Enum_Option', opt: 'Optional[Data_PartialOrderServiceProfile]' = None, *,
|
2258
|
+
start: 'bool' = False,
|
2259
|
+
end: 'bool' = False,
|
2260
|
+
**kwargs: 'Any') -> 'Schema_PartialOrderServiceProfile':
|
2261
|
+
"""Make TCP partial order connection service profile option.
|
2262
|
+
|
2263
|
+
Args:
|
2264
|
+
code: option code
|
2265
|
+
opt: option data
|
2266
|
+
start: start partial order connection
|
2267
|
+
end: end partial order connection
|
2268
|
+
**kwargs: arbitrary keyword arguments
|
2269
|
+
|
2270
|
+
Returns:
|
2271
|
+
Constructed option schema.
|
2272
|
+
|
2273
|
+
"""
|
2274
|
+
if opt is not None:
|
2275
|
+
start = opt.start
|
2276
|
+
end = opt.end
|
2277
|
+
|
2278
|
+
return Schema_PartialOrderServiceProfile(
|
2279
|
+
kind=code,
|
2280
|
+
length=3,
|
2281
|
+
profile={
|
2282
|
+
'start': start,
|
2283
|
+
'end': end,
|
2284
|
+
},
|
2285
|
+
)
|
2286
|
+
|
2287
|
+
def _make_mode_cc(self, code: 'Enum_Option', opt: 'Optional[Data_CC]' = None, *,
|
2288
|
+
count: 'int' = 0,
|
2289
|
+
**kwargs: 'Any') -> 'Schema_CC':
|
2290
|
+
"""Make TCP connection count option.
|
2291
|
+
|
2292
|
+
Args:
|
2293
|
+
code: option code
|
2294
|
+
opt: option data
|
2295
|
+
count: connection count
|
2296
|
+
**kwargs: arbitrary keyword arguments
|
2297
|
+
|
2298
|
+
Returns:
|
2299
|
+
Constructed option schema.
|
2300
|
+
|
2301
|
+
"""
|
2302
|
+
if opt is not None:
|
2303
|
+
count = opt.cc
|
2304
|
+
|
2305
|
+
return Schema_CC(
|
2306
|
+
kind=code,
|
2307
|
+
length=6,
|
2308
|
+
count=count,
|
2309
|
+
)
|
2310
|
+
|
2311
|
+
def _make_mode_ccnew(self, code: 'Enum_Option', opt: 'Optional[Data_CCNew]' = None, *,
|
2312
|
+
count: 'int' = 0,
|
2313
|
+
**kwargs: 'Any') -> 'Schema_CCNew':
|
2314
|
+
"""Make TCP connection count new option.
|
2315
|
+
|
2316
|
+
Args:
|
2317
|
+
code: option code
|
2318
|
+
opt: option data
|
2319
|
+
count: connection count
|
2320
|
+
**kwargs: arbitrary keyword arguments
|
2321
|
+
|
2322
|
+
Returns:
|
2323
|
+
Constructed option schema.
|
2324
|
+
|
2325
|
+
"""
|
2326
|
+
if opt is not None:
|
2327
|
+
count = opt.cc
|
2328
|
+
|
2329
|
+
return Schema_CCNew(
|
2330
|
+
kind=code,
|
2331
|
+
length=6,
|
2332
|
+
count=count,
|
2333
|
+
)
|
2334
|
+
|
2335
|
+
def _make_mode_ccecho(self, code: 'Enum_Option', opt: 'Optional[Data_CCEcho]' = None, *,
|
2336
|
+
count: 'int' = 0,
|
2337
|
+
**kwargs: 'Any') -> 'Schema_CCEcho':
|
2338
|
+
"""Make TCP connection count echo option.
|
2339
|
+
|
2340
|
+
Args:
|
2341
|
+
code: option code
|
2342
|
+
opt: option data
|
2343
|
+
count: connection count
|
2344
|
+
**kwargs: arbitrary keyword arguments
|
2345
|
+
|
2346
|
+
Returns:
|
2347
|
+
Constructed option schema.
|
2348
|
+
|
2349
|
+
"""
|
2350
|
+
if opt is not None:
|
2351
|
+
count = opt.cc
|
2352
|
+
|
2353
|
+
return Schema_CCEcho(
|
2354
|
+
kind=code,
|
2355
|
+
length=6,
|
2356
|
+
count=count,
|
2357
|
+
)
|
2358
|
+
|
2359
|
+
def _make_mode_chkreq(self, code: 'Enum_Option', opt: 'Optional[Data_AlternateChecksumRequest]' = None, *,
|
2360
|
+
algorithm: 'Enum_Checksum | StdlibEnum | AenumEnum | int | str' = Enum_Checksum.TCP_checksum,
|
2361
|
+
algorithm_default: 'Optional[int]' = None,
|
2362
|
+
algorithm_namespace: 'Optional[dict[str, int] | dict[int, str] | Type[StdlibEnum] | Type[AenumEnum]]' = None, # pylint: disable=line-too-long
|
2363
|
+
algorithm_reversed: 'bool' = False,
|
2364
|
+
**kwargs: 'Any') -> 'Schema_AlternateChecksumRequest':
|
2365
|
+
"""Make TCP alternate checksum request option.
|
2366
|
+
|
2367
|
+
Args:
|
2368
|
+
code: option code
|
2369
|
+
opt: option data
|
2370
|
+
algorithm: checksum algorithm
|
2371
|
+
algorithm_default: default value for checksum algorithm
|
2372
|
+
algorithm_namespace: namespace for checksum algorithm
|
2373
|
+
algorithm_reversed: reversed flag for checksum algorithm
|
2374
|
+
**kwargs: arbitrary keyword arguments
|
2375
|
+
|
2376
|
+
Returns:
|
2377
|
+
Constructed option schema.
|
2378
|
+
|
2379
|
+
"""
|
2380
|
+
if opt is not None:
|
2381
|
+
algorithm_val = opt.chksum
|
2382
|
+
else:
|
2383
|
+
algorithm_val = self._make_index(algorithm, algorithm_default, namespace=algorithm_namespace, # type: ignore[assignment]
|
2384
|
+
reversed=algorithm_reversed, pack=False)
|
2385
|
+
|
2386
|
+
return Schema_AlternateChecksumRequest(
|
2387
|
+
kind=code,
|
2388
|
+
length=3,
|
2389
|
+
algorithm=algorithm_val,
|
2390
|
+
)
|
2391
|
+
|
2392
|
+
def _make_mode_chksum(self, code: 'Enum_Option', opt: 'Optional[Data_AlternateChecksumData]' = None, *,
|
2393
|
+
data: 'bytes' = b'',
|
2394
|
+
**kwargs: 'Any') -> 'Schema_AlternateChecksumData':
|
2395
|
+
"""Make TCP alternate checksum data option.
|
2396
|
+
|
2397
|
+
Args:
|
2398
|
+
code: option code
|
2399
|
+
opt: option data
|
2400
|
+
data: checksum data
|
2401
|
+
**kwargs: arbitrary keyword arguments
|
2402
|
+
|
2403
|
+
Returns:
|
2404
|
+
Constructed option schema.
|
2405
|
+
|
2406
|
+
"""
|
2407
|
+
if opt is not None:
|
2408
|
+
data = opt.data
|
2409
|
+
|
2410
|
+
return Schema_AlternateChecksumData(
|
2411
|
+
kind=code,
|
2412
|
+
length=2 + len(data),
|
2413
|
+
data=data,
|
2414
|
+
)
|
2415
|
+
|
2416
|
+
def _make_mode_sig(self, code: 'Enum_Option', opt: 'Optional[Data_MD5Signature]' = None, *,
|
2417
|
+
digest: 'bytes' = bytes(16),
|
2418
|
+
**kwargs: 'Any') -> 'Schema_MD5Signature':
|
2419
|
+
"""Make TCP MD5 signature option.
|
2420
|
+
|
2421
|
+
Args:
|
2422
|
+
code: option code
|
2423
|
+
opt: option data
|
2424
|
+
digest: digest
|
2425
|
+
**kwargs: arbitrary keyword arguments
|
2426
|
+
|
2427
|
+
Returns:
|
2428
|
+
Constructed option schema.
|
2429
|
+
|
2430
|
+
"""
|
2431
|
+
if opt is not None:
|
2432
|
+
digest = opt.digest
|
2433
|
+
|
2434
|
+
return Schema_MD5Signature(
|
2435
|
+
kind=code,
|
2436
|
+
length=18,
|
2437
|
+
digest=digest,
|
2438
|
+
)
|
2439
|
+
|
2440
|
+
def _make_mode_qs(self, code: 'Enum_Option', opt: 'Optional[Data_QuickStartResponse]' = None, *,
|
2441
|
+
rate: 'int' = 0,
|
2442
|
+
diff: 'timedelta | int' = 0,
|
2443
|
+
nonce: 'int' = 0,
|
2444
|
+
**kwargs: 'Any') -> 'Schema_QuickStartResponse':
|
2445
|
+
"""Make TCP quick start response option.
|
2446
|
+
|
2447
|
+
Args:
|
2448
|
+
code: option code
|
2449
|
+
opt: option data
|
2450
|
+
rate: rate (in kbps)
|
2451
|
+
diff: time to live (in seconds) difference
|
2452
|
+
nonce: nonce value
|
2453
|
+
**kwargs: arbitrary keyword arguments
|
2454
|
+
|
2455
|
+
Returns:
|
2456
|
+
Constructed option schema.
|
2457
|
+
|
2458
|
+
"""
|
2459
|
+
if opt is not None:
|
2460
|
+
rate = opt.req_rate
|
2461
|
+
diff = opt.ttl_diff
|
2462
|
+
nonce = opt.nonce
|
2463
|
+
|
2464
|
+
rate_val = math.floor(math.log2(rate * 1000 / 40000)) if rate > 0 else 0
|
2465
|
+
diff_val = diff if isinstance(diff, int) else math.floor(diff.total_seconds())
|
2466
|
+
|
2467
|
+
return Schema_QuickStartResponse(
|
2468
|
+
kind=code,
|
2469
|
+
length=8,
|
2470
|
+
flags={
|
2471
|
+
'rate': rate_val,
|
2472
|
+
},
|
2473
|
+
diff=diff_val,
|
2474
|
+
nonce={
|
2475
|
+
'nonce': nonce,
|
2476
|
+
},
|
2477
|
+
)
|
2478
|
+
|
2479
|
+
def _make_mode_timeout(self, code: 'Enum_Option', opt: 'Optional[Data_UserTimeout]' = None, *,
|
2480
|
+
timeout: 'timedelta | int' = 0,
|
2481
|
+
**kwargs: 'Any') -> 'Schema_UserTimeout':
|
2482
|
+
"""Make TCP user timeout option.
|
2483
|
+
|
2484
|
+
Args:
|
2485
|
+
code: option code
|
2486
|
+
opt: option data
|
2487
|
+
timeout: timeout value
|
2488
|
+
**kwargs: arbitrary keyword arguments
|
2489
|
+
|
2490
|
+
Returns:
|
2491
|
+
Constructed option schema.
|
2492
|
+
|
2493
|
+
"""
|
2494
|
+
if opt is not None:
|
2495
|
+
timeout_val = math.floor(opt.timeout.total_seconds())
|
2496
|
+
else:
|
2497
|
+
timeout_val = timeout if isinstance(timeout, int) else math.floor(timeout.total_seconds())
|
2498
|
+
|
2499
|
+
granularity = timeout_val.bit_length() > 15
|
2500
|
+
timeout_val = math.floor(timeout_val / 60) if granularity else timeout_val
|
2501
|
+
|
2502
|
+
if timeout_val.bit_length() > 15:
|
2503
|
+
raise ProtocolError(f'TCP: [OptNo {code}] timeout value too large: {timeout}')
|
2504
|
+
|
2505
|
+
return Schema_UserTimeout(
|
2506
|
+
kind=code,
|
2507
|
+
length=3,
|
2508
|
+
info={
|
2509
|
+
'granularity': granularity,
|
2510
|
+
'timeout': timeout_val,
|
2511
|
+
},
|
2512
|
+
)
|
2513
|
+
|
2514
|
+
def _make_mode_ao(self, code: 'Enum_Option', opt: 'Optional[Data_Authentication]' = None, *,
|
2515
|
+
key_id: 'int' = 0,
|
2516
|
+
next_key_id: 'int' = 0,
|
2517
|
+
mac: 'bytes' = b'',
|
2518
|
+
**kwargs: 'Any') -> 'Schema_Authentication':
|
2519
|
+
"""Make TCP authentication option.
|
2520
|
+
|
2521
|
+
Args:
|
2522
|
+
code: option code
|
2523
|
+
opt: option data
|
2524
|
+
key_id: key ID
|
2525
|
+
next_key_id: next key ID
|
2526
|
+
mac: MAC value
|
2527
|
+
**kwargs: arbitrary keyword arguments
|
2528
|
+
|
2529
|
+
Returns:
|
2530
|
+
Constructed option schema.
|
2531
|
+
|
2532
|
+
"""
|
2533
|
+
if opt is not None:
|
2534
|
+
key_id = opt.key_id
|
2535
|
+
next_key_id = opt.next_key_id
|
2536
|
+
mac = opt.mac
|
2537
|
+
|
2538
|
+
return Schema_Authentication(
|
2539
|
+
kind=code,
|
2540
|
+
length=4 + len(mac),
|
2541
|
+
key_id=key_id,
|
2542
|
+
next_key_id=next_key_id,
|
2543
|
+
mac=mac,
|
2544
|
+
)
|
2545
|
+
|
2546
|
+
def _make_mode_mp(self, code: 'Enum_Option', opt: 'Optional[Data_MPTCP]' = None, *,
|
2547
|
+
subtype: 'Enum_MPTCPOption | StdlibEnum | AenumEnum | int | str' = Enum_MPTCPOption.MP_CAPABLE,
|
2548
|
+
subtype_default: 'Optional[int]' = None,
|
2549
|
+
subtype_namespace: 'Optional[dict[str, int] | dict[int, str] | Type[StdlibEnum] | Type[AenumEnum]]' = None, # pylint: disable=line-too-long
|
2550
|
+
subtype_reversed: 'bool' = False,
|
2551
|
+
**kwargs: 'Any') -> 'Schema_MPTCP':
|
2552
|
+
"""Make multipath TCP option.
|
2553
|
+
|
2554
|
+
Args:
|
2555
|
+
code: option code
|
2556
|
+
opt: option data
|
2557
|
+
subtype: MPTCP subtype
|
2558
|
+
subtype_default: default value for MPTCP subtype
|
2559
|
+
subtype_namespace: namespace for MPTCP subtype
|
2560
|
+
subtype_reversed: reversed flag for MPTCP subtype
|
2561
|
+
**kwargs: arbitrary keyword arguments
|
2562
|
+
|
2563
|
+
Returns:
|
2564
|
+
Constructed option schema.
|
2565
|
+
|
2566
|
+
"""
|
2567
|
+
if opt is not None:
|
2568
|
+
subtype_val = opt.subtype
|
2569
|
+
else:
|
2570
|
+
subtype_val = self._make_index(subtype, subtype_default, namespace=subtype_namespace, # type: ignore[assignment]
|
2571
|
+
reversed=subtype_reversed, pack=False)
|
2572
|
+
|
2573
|
+
name = self.__mp_option__[subtype_val]
|
2574
|
+
if isinstance(name, str):
|
2575
|
+
meth_name = f'_make_mptcp_{name}'
|
2576
|
+
meth = cast('MPOptionConstructor',
|
2577
|
+
getattr(self, meth_name, self._make_mptcp_unknown))
|
2578
|
+
else:
|
2579
|
+
meth = name[1]
|
2580
|
+
|
2581
|
+
schema = meth(subtype_val, opt, **kwargs)
|
2582
|
+
return schema
|
2583
|
+
|
2584
|
+
def _make_mptcp_unknown(self, subtype: 'Enum_MPTCPOption', opt: 'Optional[Data_MPTCPUnknown]' = None, *,
|
2585
|
+
data: 'bytes' = b'\x00',
|
2586
|
+
**kwargs: 'Any') -> 'Schema_MPTCPUnknown':
|
2587
|
+
"""Make unknown multipath TCP option.
|
2588
|
+
|
2589
|
+
Args:
|
2590
|
+
subtype: MPTCP subtype
|
2591
|
+
opt: option data
|
2592
|
+
data: option payload data
|
2593
|
+
**kwargs: arbitrary keyword arguments
|
2594
|
+
|
2595
|
+
Returns:
|
2596
|
+
Constructed option schema.
|
2597
|
+
|
2598
|
+
"""
|
2599
|
+
if opt is not None:
|
2600
|
+
data = opt.data
|
2601
|
+
|
2602
|
+
return Schema_MPTCPUnknown(
|
2603
|
+
kind=Enum_Option.MPTCP,
|
2604
|
+
length=2 + len(data),
|
2605
|
+
test={
|
2606
|
+
'subtype': subtype.value,
|
2607
|
+
'data': data[0] & 0x0F if data else 0,
|
2608
|
+
},
|
2609
|
+
data=data[1:],
|
2610
|
+
)
|
2611
|
+
|
2612
|
+
def _make_mptcp_capable(self, subtype: 'Enum_MPTCPOption', opt: 'Optional[Data_MPTCPCapable]' = None, *,
|
2613
|
+
version: 'int' = 0,
|
2614
|
+
flag_req: 'bool' = False,
|
2615
|
+
flag_ext: 'bool' = False,
|
2616
|
+
flag_hsa: 'bool' = False,
|
2617
|
+
skey: 'int' = 0,
|
2618
|
+
rkey: 'Optional[int]' = 0,
|
2619
|
+
**kwargs: 'Any') -> 'Schema_MPTCPCapable':
|
2620
|
+
"""Make multipath TCP capable option.
|
2621
|
+
|
2622
|
+
Args:
|
2623
|
+
subtype: MPTCP subtype
|
2624
|
+
opt: option data
|
2625
|
+
version: MPTCP version
|
2626
|
+
flag_req: checksum required flag
|
2627
|
+
flag_ext: extensability flag
|
2628
|
+
flag_hsa: use of HMAC-SHA1 flag
|
2629
|
+
skey: option sender's key
|
2630
|
+
rkey: option receiver's key
|
2631
|
+
**kwargs: arbitrary keyword arguments
|
2632
|
+
|
2633
|
+
Returns:
|
2634
|
+
Constructed option schema.
|
2635
|
+
|
2636
|
+
"""
|
2637
|
+
if opt is not None:
|
2638
|
+
version = opt.version
|
2639
|
+
flag_req = opt.flags.req
|
2640
|
+
flag_ext = opt.flags.ext
|
2641
|
+
flag_hsa = opt.flags.hsa
|
2642
|
+
skey = opt.skey
|
2643
|
+
rkey = opt.rkey
|
2644
|
+
|
2645
|
+
return Schema_MPTCPCapable(
|
2646
|
+
kind=Enum_Option.MPTCP,
|
2647
|
+
length=20 if rkey is None else 32,
|
2648
|
+
test={
|
2649
|
+
'subtype': subtype.value,
|
2650
|
+
'version': version,
|
2651
|
+
},
|
2652
|
+
flags={
|
2653
|
+
'req': flag_req,
|
2654
|
+
'ext': flag_ext,
|
2655
|
+
'hsa': flag_hsa,
|
2656
|
+
},
|
2657
|
+
skey=skey,
|
2658
|
+
rkey=rkey,
|
2659
|
+
)
|
2660
|
+
|
2661
|
+
def _make_mptcp_join(self, subtype: 'Enum_MPTCPOption', opt: 'Optional[Data_MPTCPJoin]' = None, **kwargs: 'Any') -> 'Schema_MPTCPJoin':
|
2662
|
+
"""Make multipath TCP join option.
|
2663
|
+
|
2664
|
+
Args:
|
2665
|
+
subtype: MPTCP subtype
|
2666
|
+
opt: option data
|
2667
|
+
**kwargs: arbitrary keyword arguments
|
2668
|
+
|
2669
|
+
Returns:
|
2670
|
+
Constructed option schema.
|
2671
|
+
|
2672
|
+
"""
|
2673
|
+
if Enum_Flags.SYN in self._flags and Enum_Flags.ACK not in self._flags: # MP_JOIN-SYN
|
2674
|
+
return self._make_join_syn(subtype, opt, **kwargs) # type: ignore[arg-type]
|
2675
|
+
if Enum_Flags.SYN in self._flags and Enum_Flags.ACK in self._flags: # MP_JOIN-SYN/ACK
|
2676
|
+
return self._make_join_synack(subtype, opt, **kwargs) # type: ignore[arg-type]
|
2677
|
+
if Enum_Flags.SYN not in self._flags and Enum_Flags.ACK in self._flags: # MP_JOIN-ACK
|
2678
|
+
return self._make_join_ack(subtype, opt, **kwargs) # type: ignore[arg-type]
|
2679
|
+
raise ProtocolError(f'{self.alias}: : [OptNo {Enum_Option.Multipath_TCP}] {subtype}: invalid flags combination')
|
2680
|
+
|
2681
|
+
def _make_join_syn(self, subtype: 'Enum_MPTCPOption', opt: 'Optional[Data_MPTCPJoinSYN]' = None, *,
|
2682
|
+
backup: 'bool' = False,
|
2683
|
+
addr_id: 'int' = 0,
|
2684
|
+
token: 'int' = 0,
|
2685
|
+
nonce: 'int' = 0,
|
2686
|
+
**kwargs: 'Any') -> 'Schema_MPTCPJoinSYN':
|
2687
|
+
"""Make multipath TCP join SYN option.
|
2688
|
+
|
2689
|
+
Args:
|
2690
|
+
subtype: MPTCP subtype
|
2691
|
+
opt: option data
|
2692
|
+
backup: backup flag
|
2693
|
+
addr_id: address ID
|
2694
|
+
token: receiver's token
|
2695
|
+
nonce: sender's random number
|
2696
|
+
**kwargs: arbitrary keyword arguments
|
2697
|
+
|
2698
|
+
Returns:
|
2699
|
+
Constructed option schema.
|
2700
|
+
|
2701
|
+
"""
|
2702
|
+
if opt is not None:
|
2703
|
+
backup = opt.backup
|
2704
|
+
addr_id = opt.addr_id
|
2705
|
+
token = opt.token
|
2706
|
+
nonce = opt.nonce
|
2707
|
+
|
2708
|
+
return Schema_MPTCPJoinSYN(
|
2709
|
+
kind=Enum_Option.MPTCP,
|
2710
|
+
length=12,
|
2711
|
+
test={
|
2712
|
+
'subtype': subtype.value,
|
2713
|
+
'backup': backup,
|
2714
|
+
},
|
2715
|
+
addr_id=addr_id,
|
2716
|
+
token=token,
|
2717
|
+
nonce=nonce,
|
2718
|
+
)
|
2719
|
+
|
2720
|
+
def _make_join_synack(self, subtype: 'Enum_MPTCPOption', opt: 'Optional[Data_MPTCPJoinSYNACK]' = None, *,
|
2721
|
+
backup: 'bool' = False,
|
2722
|
+
addr_id: 'int' = 0,
|
2723
|
+
hmac: 'bytes' = bytes(8),
|
2724
|
+
nonce: 'int' = 0,
|
2725
|
+
**kwargs: 'Any') -> 'Schema_MPTCPJoinSYNACK':
|
2726
|
+
"""Make multipath TCP join SYN/ACK option.
|
2727
|
+
|
2728
|
+
Args:
|
2729
|
+
subtype: MPTCP subtype
|
2730
|
+
opt: option data
|
2731
|
+
backup: backup flag
|
2732
|
+
addr_id: address ID
|
2733
|
+
hmac: sender's truncated HMAC
|
2734
|
+
nonce: sender's random number
|
2735
|
+
**kwargs: arbitrary keyword arguments
|
2736
|
+
|
2737
|
+
Returns:
|
2738
|
+
Constructed option schema.
|
2739
|
+
|
2740
|
+
"""
|
2741
|
+
if opt is not None:
|
2742
|
+
backup = opt.backup
|
2743
|
+
addr_id = opt.addr_id
|
2744
|
+
nonce = opt.nonce
|
2745
|
+
nonce = opt.nonce
|
2746
|
+
|
2747
|
+
return Schema_MPTCPJoinSYNACK(
|
2748
|
+
kind=Enum_Option.MPTCP,
|
2749
|
+
length=12,
|
2750
|
+
test={
|
2751
|
+
'subtype': subtype.value,
|
2752
|
+
'backup': backup,
|
2753
|
+
},
|
2754
|
+
addr_id=addr_id,
|
2755
|
+
hmac=hmac,
|
2756
|
+
nonce=nonce,
|
2757
|
+
)
|
2758
|
+
|
2759
|
+
def _make_join_ack(self, subtype: 'Enum_MPTCPOption', opt: 'Optional[Data_MPTCPJoinACK]' = None, *,
|
2760
|
+
hmac: 'bytes' = bytes(20),
|
2761
|
+
**kwargs: 'Any') -> 'Schema_MPTCPJoinACK':
|
2762
|
+
"""Make multipath TCP join ACK option.
|
2763
|
+
|
2764
|
+
Args:
|
2765
|
+
subtype: MPTCP subtype
|
2766
|
+
opt: option data
|
2767
|
+
hmac: sender's HMAC
|
2768
|
+
**kwargs: arbitrary keyword arguments
|
2769
|
+
|
2770
|
+
Returns:
|
2771
|
+
Constructed option schema.
|
2772
|
+
|
2773
|
+
"""
|
2774
|
+
if opt is not None:
|
2775
|
+
hmac = opt.hmac
|
2776
|
+
|
2777
|
+
return Schema_MPTCPJoinACK(
|
2778
|
+
kind=Enum_Option.MPTCP,
|
2779
|
+
length=8,
|
2780
|
+
test={
|
2781
|
+
'subtype': subtype.value,
|
2782
|
+
},
|
2783
|
+
hmac=hmac,
|
2784
|
+
)
|
2785
|
+
|
2786
|
+
def _make_mptcp_dss(self, subtype: 'Enum_MPTCPOption', opt: 'Optional[Data_MPTCPDSS]' = None, *,
|
2787
|
+
data_fin: 'bool' = False,
|
2788
|
+
ack: 'Optional[int]' = None,
|
2789
|
+
dsn: 'Optional[int]' = None,
|
2790
|
+
ssn: 'Optional[int]' = None,
|
2791
|
+
dl_len: 'Optional[int]' = None,
|
2792
|
+
checksum: 'Optional[bytes]' = None,
|
2793
|
+
**kwargs: 'Any') -> 'Schema_MPTCPDSS':
|
2794
|
+
"""Make multipath TCP DSS option.
|
2795
|
+
|
2796
|
+
Args:
|
2797
|
+
subtype: MPTCP subtype
|
2798
|
+
opt: option data
|
2799
|
+
data_fin: ``DATA_FIN`` flag
|
2800
|
+
ack: Data ACK
|
2801
|
+
dsn: data sequence number
|
2802
|
+
ssn: subflow sequence number
|
2803
|
+
dl_len: data-level length
|
2804
|
+
checksum: checksum
|
2805
|
+
**kwargs: arbitrary keyword arguments
|
2806
|
+
|
2807
|
+
Returns:
|
2808
|
+
Constructed option schema.
|
2809
|
+
|
2810
|
+
"""
|
2811
|
+
if opt is not None:
|
2812
|
+
data_fin = opt.data_fin
|
2813
|
+
ack = opt.ack
|
2814
|
+
dsn = opt.dsn
|
2815
|
+
ssn = opt.ssn
|
2816
|
+
dl_len = opt.dl_len
|
2817
|
+
checksum = opt.checksum
|
2818
|
+
|
2819
|
+
flag_A = ack is not None
|
2820
|
+
flag_a = cast('int', ack).bit_length() > 32 if flag_A else False
|
2821
|
+
|
2822
|
+
flag_M = dsn is not None
|
2823
|
+
flag_m = cast('int', dsn).bit_length() > 32 if flag_M else False
|
2824
|
+
|
2825
|
+
if flag_M and (ssn is None or dl_len is None or checksum is None):
|
2826
|
+
raise ProtocolError(f'{self.alias}: : [OptNo {Enum_Option.Multipath_TCP}] {subtype}: missing required fields')
|
2827
|
+
if not flag_M and (ssn is not None or dl_len is not None or checksum is not None):
|
2828
|
+
raise ProtocolError(f'{self.alias}: : [OptNo {Enum_Option.Multipath_TCP}] {subtype}: missing required fields')
|
2829
|
+
|
2830
|
+
return Schema_MPTCPDSS(
|
2831
|
+
kind=Enum_Option.MPTCP,
|
2832
|
+
length=4 + (4 if flag_A else 0) + (4 if flag_a else 0) + (12 if flag_M else 0) + (4 if flag_m else 0),
|
2833
|
+
test={
|
2834
|
+
'subtype': subtype.value,
|
2835
|
+
},
|
2836
|
+
flags={
|
2837
|
+
'F': data_fin,
|
2838
|
+
'A': flag_A,
|
2839
|
+
'm': flag_m,
|
2840
|
+
'M': flag_M,
|
2841
|
+
'a': flag_a,
|
2842
|
+
'A': flag_A,
|
2843
|
+
},
|
2844
|
+
ack=ack,
|
2845
|
+
dsn=dsn,
|
2846
|
+
ssn=ssn,
|
2847
|
+
dl_len=dl_len,
|
2848
|
+
checksum=checksum,
|
2849
|
+
)
|
2850
|
+
|
2851
|
+
def _make_mptcp_addaddr(self, subtype: 'Enum_MPTCPOption', opt: 'Optional[Data_MPTCPAddAddress]' = None, *,
|
2852
|
+
addr_id: 'int' = 0,
|
2853
|
+
addr: 'IPv4Address | IPv6Address | int | bytes | str' = '0.0.0.0', # nosec: B104
|
2854
|
+
port: 'Optional[int]' = None,
|
2855
|
+
**kwargs: 'Any') -> 'Schema_MPTCPAddAddress':
|
2856
|
+
"""Make multipath TCP add address option.
|
2857
|
+
|
2858
|
+
Args:
|
2859
|
+
subtype: MPTCP subtype
|
2860
|
+
opt: option data
|
2861
|
+
addr_id: address ID
|
2862
|
+
addr: address
|
2863
|
+
port: port number
|
2864
|
+
**kwargs: arbitrary keyword arguments
|
2865
|
+
|
2866
|
+
Returns:
|
2867
|
+
Constructed option schema.
|
2868
|
+
|
2869
|
+
"""
|
2870
|
+
if opt is not None:
|
2871
|
+
addr_id = opt.addr_id
|
2872
|
+
addr_val = opt.addr
|
2873
|
+
port = opt.port
|
2874
|
+
else:
|
2875
|
+
addr_val = ipaddress.ip_address(addr)
|
2876
|
+
version = addr_val.version
|
2877
|
+
|
2878
|
+
return Schema_MPTCPAddAddress(
|
2879
|
+
kind=Enum_Option.MPTCP,
|
2880
|
+
length=4 + (4 if version == 4 else 16) + (2 if port is not None else 0),
|
2881
|
+
test={
|
2882
|
+
'subtype': subtype.value,
|
2883
|
+
'version': version,
|
2884
|
+
},
|
2885
|
+
addr_id=addr_id,
|
2886
|
+
address=addr_val,
|
2887
|
+
port=port,
|
2888
|
+
)
|
2889
|
+
|
2890
|
+
def _make_mptcp_remove(self, subtype: 'Enum_MPTCPOption', opt: 'Optional[Data_MPTCPRemoveAddress]' = None, *,
|
2891
|
+
addr_id: 'Optional[list[int]]' = None,
|
2892
|
+
**kwargs: 'Any') -> 'Schema_MPTCPRemoveAddress':
|
2893
|
+
"""Make multipath TCP remove address option.
|
2894
|
+
|
2895
|
+
Args:
|
2896
|
+
subtype: MPTCP subtype
|
2897
|
+
opt: option data
|
2898
|
+
addr_id: address ID list
|
2899
|
+
**kwargs: arbitrary keyword arguments
|
2900
|
+
|
2901
|
+
Returns:
|
2902
|
+
Constructed option schema.
|
2903
|
+
|
2904
|
+
"""
|
2905
|
+
if opt is not None:
|
2906
|
+
addr_id_list = cast('list[int]', opt.addr_id)
|
2907
|
+
else:
|
2908
|
+
addr_id_list = addr_id if addr_id is not None else []
|
2909
|
+
|
2910
|
+
return Schema_MPTCPRemoveAddress(
|
2911
|
+
kind=Enum_Option.MPTCP,
|
2912
|
+
length=4,
|
2913
|
+
test={
|
2914
|
+
'subtype': subtype.value,
|
2915
|
+
},
|
2916
|
+
addr_id=addr_id_list,
|
2917
|
+
)
|
2918
|
+
|
2919
|
+
def _make_mptcp_prio(self, subtype: 'Enum_MPTCPOption', opt: 'Optional[Data_MPTCPPriority]' = None, *,
|
2920
|
+
backup: 'bool' = False,
|
2921
|
+
addr_id: 'Optional[int]' = None,
|
2922
|
+
**kwargs: 'Any') -> 'Schema_MPTCPPriority':
|
2923
|
+
"""Make multipath TCP priority option.
|
2924
|
+
|
2925
|
+
Args:
|
2926
|
+
subtype: MPTCP subtype
|
2927
|
+
opt: option data
|
2928
|
+
backup: backup flag
|
2929
|
+
addr_id: address ID
|
2930
|
+
**kwargs: arbitrary keyword arguments
|
2931
|
+
|
2932
|
+
Returns:
|
2933
|
+
Constructed option schema.
|
2934
|
+
|
2935
|
+
"""
|
2936
|
+
if opt is not None:
|
2937
|
+
addr_id = opt.addr_id
|
2938
|
+
|
2939
|
+
return Schema_MPTCPPriority(
|
2940
|
+
kind=Enum_Option.MPTCP,
|
2941
|
+
length=4,
|
2942
|
+
test={
|
2943
|
+
'subtype': subtype.value,
|
2944
|
+
'backup': backup,
|
2945
|
+
},
|
2946
|
+
addr_id=addr_id,
|
2947
|
+
)
|
2948
|
+
|
2949
|
+
def _make_mptcp_fail(self, subtype: 'Enum_MPTCPOption', opt: 'Optional[Data_MPTCPFallback]' = None, *,
|
2950
|
+
dsn: 'int' = 0,
|
2951
|
+
**kwargs: 'Any') -> 'Schema_MPTCPFallback':
|
2952
|
+
"""Make multipath TCP fail option.
|
2953
|
+
|
2954
|
+
Args:
|
2955
|
+
subtype: MPTCP subtype
|
2956
|
+
opt: option data
|
2957
|
+
dsn: data sequence number
|
2958
|
+
**kwargs: arbitrary keyword arguments
|
2959
|
+
|
2960
|
+
Returns:
|
2961
|
+
Constructed option schema.
|
2962
|
+
|
2963
|
+
"""
|
2964
|
+
if opt is not None:
|
2965
|
+
dsn = opt.dsn
|
2966
|
+
|
2967
|
+
return Schema_MPTCPFallback(
|
2968
|
+
kind=Enum_Option.MPTCP,
|
2969
|
+
length=12,
|
2970
|
+
test={
|
2971
|
+
'subtype': subtype.value,
|
2972
|
+
},
|
2973
|
+
dsn=dsn,
|
2974
|
+
)
|
2975
|
+
|
2976
|
+
def _make_mptcp_fastclose(self, subtype: 'Enum_MPTCPOption', opt: 'Optional[Data_MPTCPFastclose]' = None, *,
|
2977
|
+
key: 'int' = 0,
|
2978
|
+
**kwargs: 'Any') -> 'Schema_MPTCPFastclose':
|
2979
|
+
"""Make multipath TCP fastclose option.
|
2980
|
+
|
2981
|
+
Args:
|
2982
|
+
subtype: MPTCP subtype
|
2983
|
+
opt: option data
|
2984
|
+
key: option receiver's key
|
2985
|
+
**kwargs: arbitrary keyword arguments
|
2986
|
+
|
2987
|
+
Returns:
|
2988
|
+
Constructed option schema.
|
2989
|
+
|
2990
|
+
"""
|
2991
|
+
if opt is not None:
|
2992
|
+
key = opt.rkey
|
2993
|
+
|
2994
|
+
return Schema_MPTCPFastclose(
|
2995
|
+
kind=Enum_Option.MPTCP,
|
2996
|
+
length=12,
|
2997
|
+
test={
|
2998
|
+
'subtype': subtype.value,
|
2999
|
+
},
|
3000
|
+
key=key,
|
3001
|
+
)
|
3002
|
+
|
3003
|
+
def _make_mode_fastopen(self, code: 'Enum_Option', opt: 'Optional[Data_FastOpenCookie]' = None, *,
|
3004
|
+
cookie: 'Optional[bytes]' = None,
|
3005
|
+
**kwargs: 'Any') -> 'Schema_FastOpenCookie':
|
3006
|
+
"""Make TCP Fast Open option.
|
3007
|
+
|
3008
|
+
Args:
|
3009
|
+
code: option code
|
3010
|
+
opt: option data
|
3011
|
+
cookie: fast open cookie
|
3012
|
+
**kwargs: arbitrary keyword arguments
|
3013
|
+
|
3014
|
+
Returns:
|
3015
|
+
Constructed option schema.
|
3016
|
+
|
3017
|
+
"""
|
3018
|
+
if opt is not None:
|
3019
|
+
cookie = opt.cookie
|
3020
|
+
|
3021
|
+
return Schema_FastOpenCookie(
|
3022
|
+
kind=code,
|
3023
|
+
length=2 + (len(cookie) if cookie is not None else 0),
|
3024
|
+
cookie=cookie,
|
3025
|
+
)
|