stackforge 0.6.0__tar.gz → 0.6.2__tar.gz
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.
- {stackforge-0.6.0 → stackforge-0.6.2}/Cargo.lock +71 -3
- {stackforge-0.6.0 → stackforge-0.6.2}/Cargo.toml +3 -1
- {stackforge-0.6.0 → stackforge-0.6.2}/PKG-INFO +63 -11
- {stackforge-0.6.0 → stackforge-0.6.2}/README.md +62 -10
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/Cargo.toml +2 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/flow/config.rs +8 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/flow/error.rs +3 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/flow/mod.rs +44 -1
- stackforge-0.6.2/crates/stackforge-core/src/flow/spill.rs +315 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/flow/state.rs +24 -3
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/flow/table.rs +57 -1
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/flow/tcp_reassembly.rs +57 -22
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/mqttsn/builder.rs +1 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/lib.rs +4 -2
- stackforge-0.6.2/crates/stackforge-core/src/pcap/mod.rs +67 -0
- stackforge-0.6.2/crates/stackforge-core/src/pcap/reader.rs +496 -0
- stackforge-0.6.2/crates/stackforge-core/src/pcap/writer.rs +419 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/python/stackforge/__init__.py +2 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/src/lib.rs +99 -16
- stackforge-0.6.2/tests/python/test_pcapng.py +201 -0
- stackforge-0.6.2/tests/python/test_streaming_flows.py +136 -0
- stackforge-0.6.0/crates/stackforge-core/src/pcap/mod.rs +0 -42
- stackforge-0.6.0/crates/stackforge-core/src/pcap/reader.rs +0 -172
- stackforge-0.6.0/crates/stackforge-core/src/pcap/writer.rs +0 -207
- {stackforge-0.6.0 → stackforge-0.6.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/.github/workflows/release.yml +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/.github/workflows/test.yml +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/.gitignore +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/.pre-commit-config.yaml +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/.python-version +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/CLAUDE.md +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/CODE_OF_CONDUCT.md +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/CONTRIBUTING.md +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/LICENSE +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/cliff.toml +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/cog.toml +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-automata/Cargo.toml +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-automata/src/lib.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/error.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/flow/icmp_state.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/flow/key.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/flow/tcp_state.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/flow/udp_state.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/arp.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/bindings.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/dns/bitmap.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/dns/builder.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/dns/edns.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/dns/header.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/dns/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/dns/query.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/dns/rdata.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/dns/rr.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/dns/svcb.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/dns/types.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/dot11/builder.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/dot11/control.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/dot11/data.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/dot11/ie.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/dot11/management.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/dot11/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/dot11/radiotap.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/dot11/security.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/dot11/types.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/dot15d4/beacon.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/dot15d4/builder.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/dot15d4/command.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/dot15d4/crc.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/dot15d4/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/dot15d4/security.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/dot15d4/types.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/ethernet.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/field.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/field_ext.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/ftp/builder.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/ftp/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/generic/builder.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/generic/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/http/builder.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/http/detection.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/http/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/http/request.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/http/response.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/http2/builder.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/http2/frames.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/http2/hpack.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/http2/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/icmp/builder.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/icmp/checksum.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/icmp/error.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/icmp/extensions.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/icmp/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/icmp/types.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/icmpv6/builder.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/icmpv6/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/imap/builder.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/imap/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/ipv4/builder.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/ipv4/checksum.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/ipv4/fragmentation.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/ipv4/header.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/ipv4/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/ipv4/options.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/ipv4/protocol.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/ipv4/routing.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/ipv4/ttl.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/ipv6/builder.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/ipv6/ext_headers.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/ipv6/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/l2tp/builder.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/l2tp/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/modbus/builder.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/modbus/crc.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/modbus/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/mqtt/builder.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/mqtt/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/mqttsn/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/neighbor.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/pop3/builder.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/pop3/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/quic/builder.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/quic/frames.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/quic/headers.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/quic/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/quic/varint.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/raw.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/smtp/builder.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/smtp/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/ssh/builder.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/ssh/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/stack.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tcp/builder.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tcp/checksum.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tcp/flags.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tcp/header.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tcp/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tcp/options.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tcp/services.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tftp/builder.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tftp/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/builder.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/cert.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/crypto/cipher_aead.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/crypto/cipher_block.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/crypto/cipher_stream.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/crypto/compression.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/crypto/groups.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/crypto/hash.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/crypto/hkdf_tls13.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/crypto/hmac_tls.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/crypto/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/crypto/prf.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/crypto/suites.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/extensions/common.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/extensions/key_share.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/extensions/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/extensions/signature_algorithms.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/extensions/sni.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/extensions/supported_versions.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/handshake/certificate.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/handshake/client_hello.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/handshake/finished.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/handshake/key_exchange.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/handshake/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/handshake/server_hello.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/keyexchange/ecdhe.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/keyexchange/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/record.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/session.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/sslv2/handshake.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/sslv2/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/sslv2/record.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/tls/types.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/udp/builder.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/udp/checksum.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/udp/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/zwave/builder.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/layer/zwave/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/packet.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/utils/bits.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/utils/checksum.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/utils/compare.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/utils/hex.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/utils/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/utils/padding.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/crates/stackforge-core/src/utils/random.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/pyproject.toml +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/python/stackforge/custom.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/rust-toolchain.toml +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/rustfmt.toml +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/arp.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/compat_tests/arp_compat.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/compat_tests/ethernet_compat.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/compat_tests/icmp_compat.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/compat_tests/ipv4_compat.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/compat_tests/mod.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/compat_tests/ssh_compat.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/compat_tests/tcp_compat.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/compat_tests/tls_compat.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/compat_tests/udp_compat.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/dns.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/dot11.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/dot15d4.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/ethernet.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/field.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/ftp.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/http.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/http2.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/icmpv6.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/imap.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/ipv6.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/layer.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/main.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/modbus.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/mqtt.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/packet.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/pop3.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/quic.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/smtp.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/ssh.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/tftp.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/tls.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/util.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/integration/zwave.rs +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/scapy_compat/__init__.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/scapy_compat/conftest.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/scapy_compat/test_arp_compat.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/scapy_compat/test_checksums_compat.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/scapy_compat/test_edge_cases_compat.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/scapy_compat/test_ethernet_compat.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/scapy_compat/test_icmp_compat.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/scapy_compat/test_ipv4_compat.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/scapy_compat/test_pcap_compat.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/scapy_compat/test_stacking_compat.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/scapy_compat/test_tcp_compat.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/scapy_compat/test_udp_compat.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/scapy_compat/test_uts_integration.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_core.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_custom.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_dns.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_dot11.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_dot15d4.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_flow.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_ftp.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_http.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_icmpv6.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_imap.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_ipv6.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_l2tp.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_max_packet_flow_len.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_modbus.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_mqtt.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_mqttsn.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_pcap.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_pop3.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_quic.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_smtp.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_ssh.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_tftp.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_tls.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_udp_icmp.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_uts_ftp.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_uts_http.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_uts_http2.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_uts_imap.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_uts_ipv6.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_uts_l2tp.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_uts_modbus.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_uts_mqtt.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_uts_mqttsn.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_uts_pop3.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_uts_quic.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_uts_smtp.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_uts_tftp.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_uts_zwave.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/python/test_zwave.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/sample_pcap/http2_h2c.pcap +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/sample_pcap/http_chunk.pcap +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/sample_pcap/http_compressed-brotli.pcap +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/sample_pcap/http_compressed-zstd.pcap +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/sample_pcap/http_compressed.pcap +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/sample_pcap/http_content_length.pcap +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/sample_pcap/http_head.pcapng +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/sample_pcap/http_tcp_psh.pcap +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/sample_pcap/ssh_ed25519.pcap +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/sample_pcap/tcprelay/PCAP.md +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/sample_pcap/tcprelay/smallFlows.pcap +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/sample_pcap/tcprelay/test.pcap +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/scripts/compare_packets.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/scripts/generate_scapy_fixtures.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/dns.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/dns_dnssec.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/dns_edns0.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/dot11.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/dot15d4.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/fields.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/ftp.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/http.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/http2.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/imap.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/inet.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/inet6 copy.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/inet6.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/l2.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/l2tp.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/modbus.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/mqtt.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/mqttsn.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/pop3.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/quic.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/smtp.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/ssh.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/tftp.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/tls/__init__.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/tls/cert.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/tls/example_client.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/tls/example_server.py +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/tls/pki/README.md +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/tls/pki/ca_cert.pem +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/tls/pki/ca_key.pem +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/tls/pki/cli_cert.pem +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/tls/pki/cli_key.pem +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/tls/pki/srv_cert.pem +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/tls/pki/srv_cert_ed25519.pem +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/tls/pki/srv_key.pem +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/tls/pki/srv_key_ed25519.pem +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/tls/sslv2.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/tls/tls.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/tls/tls13.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/tls/tlsclientserver.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/tests/uts/zwave.uts +0 -0
- {stackforge-0.6.0 → stackforge-0.6.2}/uv.lock +0 -0
|
@@ -377,6 +377,22 @@ dependencies = [
|
|
|
377
377
|
"zeroize",
|
|
378
378
|
]
|
|
379
379
|
|
|
380
|
+
[[package]]
|
|
381
|
+
name = "errno"
|
|
382
|
+
version = "0.3.14"
|
|
383
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
384
|
+
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
|
385
|
+
dependencies = [
|
|
386
|
+
"libc",
|
|
387
|
+
"windows-sys",
|
|
388
|
+
]
|
|
389
|
+
|
|
390
|
+
[[package]]
|
|
391
|
+
name = "fastrand"
|
|
392
|
+
version = "2.3.0"
|
|
393
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
394
|
+
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
|
395
|
+
|
|
380
396
|
[[package]]
|
|
381
397
|
name = "ff"
|
|
382
398
|
version = "0.13.1"
|
|
@@ -512,6 +528,12 @@ version = "0.2.178"
|
|
|
512
528
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
513
529
|
checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091"
|
|
514
530
|
|
|
531
|
+
[[package]]
|
|
532
|
+
name = "linux-raw-sys"
|
|
533
|
+
version = "0.11.0"
|
|
534
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
535
|
+
checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
|
|
536
|
+
|
|
515
537
|
[[package]]
|
|
516
538
|
name = "lock_api"
|
|
517
539
|
version = "0.4.14"
|
|
@@ -543,6 +565,15 @@ version = "0.1.0"
|
|
|
543
565
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
544
566
|
checksum = "df39d232f5c40b0891c10216992c2f250c054105cb1e56f0fc9032db6203ecc1"
|
|
545
567
|
|
|
568
|
+
[[package]]
|
|
569
|
+
name = "memmap2"
|
|
570
|
+
version = "0.9.10"
|
|
571
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
572
|
+
checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3"
|
|
573
|
+
dependencies = [
|
|
574
|
+
"libc",
|
|
575
|
+
]
|
|
576
|
+
|
|
546
577
|
[[package]]
|
|
547
578
|
name = "memoffset"
|
|
548
579
|
version = "0.9.1"
|
|
@@ -918,6 +949,19 @@ dependencies = [
|
|
|
918
949
|
"semver",
|
|
919
950
|
]
|
|
920
951
|
|
|
952
|
+
[[package]]
|
|
953
|
+
name = "rustix"
|
|
954
|
+
version = "1.1.3"
|
|
955
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
956
|
+
checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34"
|
|
957
|
+
dependencies = [
|
|
958
|
+
"bitflags 2.11.0",
|
|
959
|
+
"errno",
|
|
960
|
+
"libc",
|
|
961
|
+
"linux-raw-sys",
|
|
962
|
+
"windows-sys",
|
|
963
|
+
]
|
|
964
|
+
|
|
921
965
|
[[package]]
|
|
922
966
|
name = "rustversion"
|
|
923
967
|
version = "1.0.22"
|
|
@@ -1030,7 +1074,7 @@ dependencies = [
|
|
|
1030
1074
|
|
|
1031
1075
|
[[package]]
|
|
1032
1076
|
name = "stackforge"
|
|
1033
|
-
version = "0.6.
|
|
1077
|
+
version = "0.6.2"
|
|
1034
1078
|
dependencies = [
|
|
1035
1079
|
"pyo3",
|
|
1036
1080
|
"stackforge-automata",
|
|
@@ -1039,7 +1083,7 @@ dependencies = [
|
|
|
1039
1083
|
|
|
1040
1084
|
[[package]]
|
|
1041
1085
|
name = "stackforge-automata"
|
|
1042
|
-
version = "0.6.
|
|
1086
|
+
version = "0.6.2"
|
|
1043
1087
|
dependencies = [
|
|
1044
1088
|
"bytes",
|
|
1045
1089
|
"stackforge-core",
|
|
@@ -1047,7 +1091,7 @@ dependencies = [
|
|
|
1047
1091
|
|
|
1048
1092
|
[[package]]
|
|
1049
1093
|
name = "stackforge-core"
|
|
1050
|
-
version = "0.6.
|
|
1094
|
+
version = "0.6.2"
|
|
1051
1095
|
dependencies = [
|
|
1052
1096
|
"aes",
|
|
1053
1097
|
"aes-gcm",
|
|
@@ -1061,6 +1105,7 @@ dependencies = [
|
|
|
1061
1105
|
"hkdf",
|
|
1062
1106
|
"hmac",
|
|
1063
1107
|
"md-5",
|
|
1108
|
+
"memmap2",
|
|
1064
1109
|
"p256",
|
|
1065
1110
|
"pcap-file",
|
|
1066
1111
|
"pnet_datalink",
|
|
@@ -1069,6 +1114,7 @@ dependencies = [
|
|
|
1069
1114
|
"sha1",
|
|
1070
1115
|
"sha2",
|
|
1071
1116
|
"smallvec",
|
|
1117
|
+
"tempfile",
|
|
1072
1118
|
"thiserror 2.0.17",
|
|
1073
1119
|
"x25519-dalek",
|
|
1074
1120
|
]
|
|
@@ -1128,6 +1174,19 @@ version = "0.13.4"
|
|
|
1128
1174
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1129
1175
|
checksum = "b1dd07eb858a2067e2f3c7155d54e929265c264e6f37efe3ee7a8d1b5a1dd0ba"
|
|
1130
1176
|
|
|
1177
|
+
[[package]]
|
|
1178
|
+
name = "tempfile"
|
|
1179
|
+
version = "3.25.0"
|
|
1180
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1181
|
+
checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1"
|
|
1182
|
+
dependencies = [
|
|
1183
|
+
"fastrand",
|
|
1184
|
+
"getrandom 0.3.4",
|
|
1185
|
+
"once_cell",
|
|
1186
|
+
"rustix",
|
|
1187
|
+
"windows-sys",
|
|
1188
|
+
]
|
|
1189
|
+
|
|
1131
1190
|
[[package]]
|
|
1132
1191
|
name = "thiserror"
|
|
1133
1192
|
version = "1.0.69"
|
|
@@ -1254,6 +1313,15 @@ version = "0.2.1"
|
|
|
1254
1313
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1255
1314
|
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
|
1256
1315
|
|
|
1316
|
+
[[package]]
|
|
1317
|
+
name = "windows-sys"
|
|
1318
|
+
version = "0.61.2"
|
|
1319
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1320
|
+
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
|
1321
|
+
dependencies = [
|
|
1322
|
+
"windows-link",
|
|
1323
|
+
]
|
|
1324
|
+
|
|
1257
1325
|
[[package]]
|
|
1258
1326
|
name = "windows-targets"
|
|
1259
1327
|
version = "0.48.5"
|
|
@@ -21,7 +21,7 @@ shared-version = true
|
|
|
21
21
|
tag-name = "v{{version}}"
|
|
22
22
|
|
|
23
23
|
[workspace.package]
|
|
24
|
-
version = "0.6.
|
|
24
|
+
version = "0.6.2"
|
|
25
25
|
edition = "2024"
|
|
26
26
|
license = "GPL-3.0-only"
|
|
27
27
|
authors = ["Stackforge Contributors"]
|
|
@@ -32,6 +32,8 @@ bytes = "1.11.0"
|
|
|
32
32
|
smallvec = "1.15.1"
|
|
33
33
|
thiserror = "2.0.17"
|
|
34
34
|
dashmap = "6.1"
|
|
35
|
+
memmap2 = "0.9"
|
|
36
|
+
tempfile = "3"
|
|
35
37
|
stackforge-core = { path = "crates/stackforge-core" }
|
|
36
38
|
stackforge-automata = { path = "crates/stackforge-automata" }
|
|
37
39
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: stackforge
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.2
|
|
4
4
|
Classifier: Development Status :: 3 - Alpha
|
|
5
5
|
Classifier: Intended Audience :: Developers
|
|
6
6
|
Classifier: Intended Audience :: System Administrators
|
|
@@ -35,9 +35,10 @@ Project-URL: Repository, https://github.com/LaBackDoor/stackforge
|
|
|
35
35
|
|
|
36
36
|
- **Scapy-style API** — Stack layers with `Ether() / IP() / TCP()`, set fields with keyword arguments
|
|
37
37
|
- **High Performance** — Core logic in Rust, zero-copy parsing, copy-on-write mutation
|
|
38
|
-
- **Broad Protocol Support** — Ethernet, ARP, IPv4/IPv6, TCP, UDP, ICMP/ICMPv6 (with echo correlation), DNS, HTTP/1.x, HTTP/2, QUIC, L2TP, 802.11 (Wi-Fi), 802.15.4 (Zigbee), and custom protocols
|
|
39
|
-
- **Stateful Flow Extraction** — Extract bidirectional conversations from PCAP files with TCP state tracking, stream reassembly, UDP timeout handling, and optional max packet/flow length tracking
|
|
40
|
-
- **
|
|
38
|
+
- **Broad Protocol Support** — Ethernet, ARP, IPv4/IPv6, TCP, UDP, ICMP/ICMPv6 (with echo correlation), DNS, HTTP/1.x, HTTP/2, QUIC, L2TP, MQTT, MQTT-SN, Modbus, Z-Wave, FTP, TFTP, SMTP, POP3, IMAP, 802.11 (Wi-Fi), 802.15.4 (Zigbee), and custom protocols
|
|
39
|
+
- **Stateful Flow Extraction** — Extract bidirectional conversations from PCAP/PcapNG files with TCP state tracking, stream reassembly, UDP timeout handling, and optional max packet/flow length tracking
|
|
40
|
+
- **Memory-Budgeted Streaming** — Process gigabyte-sized captures without loading everything into RAM; set a memory budget and reassembly buffers automatically spill to memory-mapped temp files
|
|
41
|
+
- **PCAP & PcapNG I/O** — Read and write both classic PCAP and PcapNG files with auto-detection via `rdpcap()` / `wrpcap()` / `wrpcapng()`
|
|
41
42
|
- **Python Bindings** — Seamless integration via PyO3/maturin
|
|
42
43
|
- **Custom Protocols** — Define runtime protocols with `CustomLayer` and typed fields
|
|
43
44
|
|
|
@@ -101,10 +102,10 @@ print(pkt.summary()) # "Ethernet / IPv4 / TCP"
|
|
|
101
102
|
print(pkt.show()) # detailed layer view
|
|
102
103
|
```
|
|
103
104
|
|
|
104
|
-
### Read and write PCAP files
|
|
105
|
+
### Read and write PCAP / PcapNG files
|
|
105
106
|
|
|
106
107
|
```python
|
|
107
|
-
from stackforge import rdpcap, wrpcap, PcapReader, Ether, IP, TCP
|
|
108
|
+
from stackforge import rdpcap, wrpcap, wrpcapng, PcapReader, Ether, IP, TCP
|
|
108
109
|
|
|
109
110
|
# Write packets to a pcap file
|
|
110
111
|
packets = [
|
|
@@ -113,13 +114,20 @@ packets = [
|
|
|
113
114
|
]
|
|
114
115
|
wrpcap("capture.pcap", packets)
|
|
115
116
|
|
|
116
|
-
#
|
|
117
|
-
|
|
117
|
+
# Write PcapNG format explicitly
|
|
118
|
+
wrpcapng("capture.pcapng", packets)
|
|
119
|
+
|
|
120
|
+
# wrpcap auto-detects format from extension
|
|
121
|
+
wrpcap("capture.pcapng", packets) # writes PcapNG
|
|
122
|
+
|
|
123
|
+
# Read any format (auto-detected)
|
|
124
|
+
packets = rdpcap("capture.pcap") # classic PCAP
|
|
125
|
+
packets = rdpcap("capture.pcapng") # PcapNG — same API
|
|
118
126
|
for pkt in packets:
|
|
119
127
|
print(pkt.summary())
|
|
120
128
|
|
|
121
|
-
# Stream large
|
|
122
|
-
for pkt in PcapReader("large_capture.
|
|
129
|
+
# Stream large captures (works with both formats)
|
|
130
|
+
for pkt in PcapReader("large_capture.pcapng"):
|
|
123
131
|
print(pkt.summary())
|
|
124
132
|
```
|
|
125
133
|
|
|
@@ -281,6 +289,36 @@ pkt.parse()
|
|
|
281
289
|
print(pkt.has_layer(LayerKind.L2tp))
|
|
282
290
|
```
|
|
283
291
|
|
|
292
|
+
### IoT Protocols
|
|
293
|
+
|
|
294
|
+
```python
|
|
295
|
+
from stackforge import MQTT, MQTTSN, Modbus, ZWave
|
|
296
|
+
|
|
297
|
+
# MQTT (auto-detected on TCP port 1883)
|
|
298
|
+
pkt = Ether() / IP() / TCP(dport=1883) / MQTT(msg_type=1) # CONNECT
|
|
299
|
+
|
|
300
|
+
# MQTT-SN (auto-detected on UDP port 1883)
|
|
301
|
+
pkt = Ether() / IP() / UDP(dport=1883) / MQTTSN(msg_type=0x04) # PUBLISH
|
|
302
|
+
|
|
303
|
+
# Modbus TCP (auto-detected on TCP port 502)
|
|
304
|
+
pkt = Ether() / IP() / TCP(dport=502) / Modbus(func_code=3, data=b"\x00\x01\x00\x0a")
|
|
305
|
+
|
|
306
|
+
# Z-Wave (wireless, not auto-detected over TCP/UDP)
|
|
307
|
+
pkt = ZWave(home_id=0x12345678, src=1, dst=2, cmd_class=0x25, cmd=0x01)
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Email & File Transfer Protocols
|
|
311
|
+
|
|
312
|
+
```python
|
|
313
|
+
from stackforge import FTP, TFTP, SMTP, POP3, IMAP
|
|
314
|
+
|
|
315
|
+
# FTP (TCP port 21), SMTP (TCP ports 25/587/465), POP3 (TCP port 110), IMAP (TCP port 143)
|
|
316
|
+
# All auto-detected during packet parsing
|
|
317
|
+
|
|
318
|
+
# TFTP (UDP port 69)
|
|
319
|
+
pkt = Ether() / IP() / UDP(dport=69) / TFTP(opcode=1, filename="test.txt", mode="octet")
|
|
320
|
+
```
|
|
321
|
+
|
|
284
322
|
### Stateful Flow Extraction
|
|
285
323
|
|
|
286
324
|
Extract bidirectional conversations from PCAP captures with full TCP state machine tracking, stream reassembly, and UDP timeout-based flow grouping.
|
|
@@ -316,7 +354,7 @@ packets = rdpcap("capture.pcap")
|
|
|
316
354
|
conversations = extract_flows_from_packets(packets)
|
|
317
355
|
```
|
|
318
356
|
|
|
319
|
-
Customize timeouts
|
|
357
|
+
Customize timeouts, buffer limits, and memory budget with `FlowConfig`:
|
|
320
358
|
|
|
321
359
|
```python
|
|
322
360
|
config = FlowConfig(
|
|
@@ -327,6 +365,20 @@ config = FlowConfig(
|
|
|
327
365
|
conversations = extract_flows("capture.pcap", config=config)
|
|
328
366
|
```
|
|
329
367
|
|
|
368
|
+
#### Memory-Budgeted Flow Extraction
|
|
369
|
+
|
|
370
|
+
For large captures, set a memory budget so reassembly buffers automatically spill to disk when RAM is tight:
|
|
371
|
+
|
|
372
|
+
```python
|
|
373
|
+
config = FlowConfig(
|
|
374
|
+
memory_budget=256 * 1024 * 1024, # 256 MB RAM budget
|
|
375
|
+
spill_dir="/tmp/stackforge-spill", # optional custom spill directory
|
|
376
|
+
)
|
|
377
|
+
conversations = extract_flows("large_capture.pcapng", config=config)
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
Packets stream from disk one at a time (never loaded all at once). When TCP reassembly buffers exceed the budget, the largest buffers are transparently spilled to memory-mapped temp files and read back on demand. Temp files are automatically cleaned up via RAII.
|
|
381
|
+
|
|
330
382
|
Optional: Track maximum packet sizes during flow extraction:
|
|
331
383
|
|
|
332
384
|
```python
|
|
@@ -11,9 +11,10 @@
|
|
|
11
11
|
|
|
12
12
|
- **Scapy-style API** — Stack layers with `Ether() / IP() / TCP()`, set fields with keyword arguments
|
|
13
13
|
- **High Performance** — Core logic in Rust, zero-copy parsing, copy-on-write mutation
|
|
14
|
-
- **Broad Protocol Support** — Ethernet, ARP, IPv4/IPv6, TCP, UDP, ICMP/ICMPv6 (with echo correlation), DNS, HTTP/1.x, HTTP/2, QUIC, L2TP, 802.11 (Wi-Fi), 802.15.4 (Zigbee), and custom protocols
|
|
15
|
-
- **Stateful Flow Extraction** — Extract bidirectional conversations from PCAP files with TCP state tracking, stream reassembly, UDP timeout handling, and optional max packet/flow length tracking
|
|
16
|
-
- **
|
|
14
|
+
- **Broad Protocol Support** — Ethernet, ARP, IPv4/IPv6, TCP, UDP, ICMP/ICMPv6 (with echo correlation), DNS, HTTP/1.x, HTTP/2, QUIC, L2TP, MQTT, MQTT-SN, Modbus, Z-Wave, FTP, TFTP, SMTP, POP3, IMAP, 802.11 (Wi-Fi), 802.15.4 (Zigbee), and custom protocols
|
|
15
|
+
- **Stateful Flow Extraction** — Extract bidirectional conversations from PCAP/PcapNG files with TCP state tracking, stream reassembly, UDP timeout handling, and optional max packet/flow length tracking
|
|
16
|
+
- **Memory-Budgeted Streaming** — Process gigabyte-sized captures without loading everything into RAM; set a memory budget and reassembly buffers automatically spill to memory-mapped temp files
|
|
17
|
+
- **PCAP & PcapNG I/O** — Read and write both classic PCAP and PcapNG files with auto-detection via `rdpcap()` / `wrpcap()` / `wrpcapng()`
|
|
17
18
|
- **Python Bindings** — Seamless integration via PyO3/maturin
|
|
18
19
|
- **Custom Protocols** — Define runtime protocols with `CustomLayer` and typed fields
|
|
19
20
|
|
|
@@ -77,10 +78,10 @@ print(pkt.summary()) # "Ethernet / IPv4 / TCP"
|
|
|
77
78
|
print(pkt.show()) # detailed layer view
|
|
78
79
|
```
|
|
79
80
|
|
|
80
|
-
### Read and write PCAP files
|
|
81
|
+
### Read and write PCAP / PcapNG files
|
|
81
82
|
|
|
82
83
|
```python
|
|
83
|
-
from stackforge import rdpcap, wrpcap, PcapReader, Ether, IP, TCP
|
|
84
|
+
from stackforge import rdpcap, wrpcap, wrpcapng, PcapReader, Ether, IP, TCP
|
|
84
85
|
|
|
85
86
|
# Write packets to a pcap file
|
|
86
87
|
packets = [
|
|
@@ -89,13 +90,20 @@ packets = [
|
|
|
89
90
|
]
|
|
90
91
|
wrpcap("capture.pcap", packets)
|
|
91
92
|
|
|
92
|
-
#
|
|
93
|
-
|
|
93
|
+
# Write PcapNG format explicitly
|
|
94
|
+
wrpcapng("capture.pcapng", packets)
|
|
95
|
+
|
|
96
|
+
# wrpcap auto-detects format from extension
|
|
97
|
+
wrpcap("capture.pcapng", packets) # writes PcapNG
|
|
98
|
+
|
|
99
|
+
# Read any format (auto-detected)
|
|
100
|
+
packets = rdpcap("capture.pcap") # classic PCAP
|
|
101
|
+
packets = rdpcap("capture.pcapng") # PcapNG — same API
|
|
94
102
|
for pkt in packets:
|
|
95
103
|
print(pkt.summary())
|
|
96
104
|
|
|
97
|
-
# Stream large
|
|
98
|
-
for pkt in PcapReader("large_capture.
|
|
105
|
+
# Stream large captures (works with both formats)
|
|
106
|
+
for pkt in PcapReader("large_capture.pcapng"):
|
|
99
107
|
print(pkt.summary())
|
|
100
108
|
```
|
|
101
109
|
|
|
@@ -257,6 +265,36 @@ pkt.parse()
|
|
|
257
265
|
print(pkt.has_layer(LayerKind.L2tp))
|
|
258
266
|
```
|
|
259
267
|
|
|
268
|
+
### IoT Protocols
|
|
269
|
+
|
|
270
|
+
```python
|
|
271
|
+
from stackforge import MQTT, MQTTSN, Modbus, ZWave
|
|
272
|
+
|
|
273
|
+
# MQTT (auto-detected on TCP port 1883)
|
|
274
|
+
pkt = Ether() / IP() / TCP(dport=1883) / MQTT(msg_type=1) # CONNECT
|
|
275
|
+
|
|
276
|
+
# MQTT-SN (auto-detected on UDP port 1883)
|
|
277
|
+
pkt = Ether() / IP() / UDP(dport=1883) / MQTTSN(msg_type=0x04) # PUBLISH
|
|
278
|
+
|
|
279
|
+
# Modbus TCP (auto-detected on TCP port 502)
|
|
280
|
+
pkt = Ether() / IP() / TCP(dport=502) / Modbus(func_code=3, data=b"\x00\x01\x00\x0a")
|
|
281
|
+
|
|
282
|
+
# Z-Wave (wireless, not auto-detected over TCP/UDP)
|
|
283
|
+
pkt = ZWave(home_id=0x12345678, src=1, dst=2, cmd_class=0x25, cmd=0x01)
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Email & File Transfer Protocols
|
|
287
|
+
|
|
288
|
+
```python
|
|
289
|
+
from stackforge import FTP, TFTP, SMTP, POP3, IMAP
|
|
290
|
+
|
|
291
|
+
# FTP (TCP port 21), SMTP (TCP ports 25/587/465), POP3 (TCP port 110), IMAP (TCP port 143)
|
|
292
|
+
# All auto-detected during packet parsing
|
|
293
|
+
|
|
294
|
+
# TFTP (UDP port 69)
|
|
295
|
+
pkt = Ether() / IP() / UDP(dport=69) / TFTP(opcode=1, filename="test.txt", mode="octet")
|
|
296
|
+
```
|
|
297
|
+
|
|
260
298
|
### Stateful Flow Extraction
|
|
261
299
|
|
|
262
300
|
Extract bidirectional conversations from PCAP captures with full TCP state machine tracking, stream reassembly, and UDP timeout-based flow grouping.
|
|
@@ -292,7 +330,7 @@ packets = rdpcap("capture.pcap")
|
|
|
292
330
|
conversations = extract_flows_from_packets(packets)
|
|
293
331
|
```
|
|
294
332
|
|
|
295
|
-
Customize timeouts
|
|
333
|
+
Customize timeouts, buffer limits, and memory budget with `FlowConfig`:
|
|
296
334
|
|
|
297
335
|
```python
|
|
298
336
|
config = FlowConfig(
|
|
@@ -303,6 +341,20 @@ config = FlowConfig(
|
|
|
303
341
|
conversations = extract_flows("capture.pcap", config=config)
|
|
304
342
|
```
|
|
305
343
|
|
|
344
|
+
#### Memory-Budgeted Flow Extraction
|
|
345
|
+
|
|
346
|
+
For large captures, set a memory budget so reassembly buffers automatically spill to disk when RAM is tight:
|
|
347
|
+
|
|
348
|
+
```python
|
|
349
|
+
config = FlowConfig(
|
|
350
|
+
memory_budget=256 * 1024 * 1024, # 256 MB RAM budget
|
|
351
|
+
spill_dir="/tmp/stackforge-spill", # optional custom spill directory
|
|
352
|
+
)
|
|
353
|
+
conversations = extract_flows("large_capture.pcapng", config=config)
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
Packets stream from disk one at a time (never loaded all at once). When TCP reassembly buffers exceed the budget, the largest buffers are transparently spilled to memory-mapped temp files and read back on demand. Temp files are automatically cleaned up via RAII.
|
|
357
|
+
|
|
306
358
|
Optional: Track maximum packet sizes during flow extraction:
|
|
307
359
|
|
|
308
360
|
```python
|
|
@@ -15,6 +15,8 @@ default-net = "0.22.0"
|
|
|
15
15
|
rand = { version = "0.9.2", optional = true }
|
|
16
16
|
pcap-file = "2"
|
|
17
17
|
dashmap = { workspace = true }
|
|
18
|
+
memmap2 = { workspace = true }
|
|
19
|
+
tempfile = { workspace = true }
|
|
18
20
|
|
|
19
21
|
# TLS crypto dependencies
|
|
20
22
|
hmac = { version = "0.12", optional = true }
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
use std::path::PathBuf;
|
|
1
2
|
use std::time::Duration;
|
|
2
3
|
|
|
3
4
|
/// Configuration for the flow extraction engine.
|
|
@@ -24,6 +25,11 @@ pub struct FlowConfig {
|
|
|
24
25
|
pub track_max_packet_len: bool,
|
|
25
26
|
/// Track maximum flow length per direction (default: false).
|
|
26
27
|
pub track_max_flow_len: bool,
|
|
28
|
+
/// Total RAM budget for flow extraction (None = unlimited).
|
|
29
|
+
/// When set, reassembly buffers will be spilled to disk when exceeded.
|
|
30
|
+
pub memory_budget: Option<usize>,
|
|
31
|
+
/// Directory for spill files (None = system temp dir).
|
|
32
|
+
pub spill_dir: Option<PathBuf>,
|
|
27
33
|
}
|
|
28
34
|
|
|
29
35
|
impl Default for FlowConfig {
|
|
@@ -38,6 +44,8 @@ impl Default for FlowConfig {
|
|
|
38
44
|
eviction_interval: Duration::from_secs(30),
|
|
39
45
|
track_max_packet_len: false,
|
|
40
46
|
track_max_flow_len: false,
|
|
47
|
+
memory_budget: None,
|
|
48
|
+
spill_dir: None,
|
|
41
49
|
}
|
|
42
50
|
}
|
|
43
51
|
}
|
|
@@ -20,6 +20,9 @@ pub enum FlowError {
|
|
|
20
20
|
#[error("too many discontinuous fragments ({count}, limit {limit})")]
|
|
21
21
|
TooManyFragments { count: usize, limit: usize },
|
|
22
22
|
|
|
23
|
+
#[error("disk spill I/O error: {0}")]
|
|
24
|
+
SpillError(String),
|
|
25
|
+
|
|
23
26
|
#[error(transparent)]
|
|
24
27
|
PacketError(#[from] PacketError),
|
|
25
28
|
}
|
|
@@ -29,6 +29,7 @@ pub mod config;
|
|
|
29
29
|
pub mod error;
|
|
30
30
|
pub mod icmp_state;
|
|
31
31
|
pub mod key;
|
|
32
|
+
pub mod spill;
|
|
32
33
|
pub mod state;
|
|
33
34
|
pub mod table;
|
|
34
35
|
pub mod tcp_reassembly;
|
|
@@ -51,9 +52,11 @@ pub use tcp_state::{TcpConnectionState, TcpConversationState, TcpEndpointState};
|
|
|
51
52
|
pub use udp_state::UdpFlowState;
|
|
52
53
|
|
|
53
54
|
use std::collections::HashMap;
|
|
55
|
+
use std::path::Path;
|
|
54
56
|
|
|
57
|
+
use crate::error::PacketError;
|
|
55
58
|
use crate::layer::LayerKind;
|
|
56
|
-
use crate::pcap::CapturedPacket;
|
|
59
|
+
use crate::pcap::{CaptureIterator, CapturedPacket};
|
|
57
60
|
|
|
58
61
|
/// Extract bidirectional conversations from a list of captured packets.
|
|
59
62
|
///
|
|
@@ -82,6 +85,45 @@ pub fn extract_flows_with_config(
|
|
|
82
85
|
Ok(table.into_conversations())
|
|
83
86
|
}
|
|
84
87
|
|
|
88
|
+
/// Extract flows from a streaming packet source (iterator).
|
|
89
|
+
///
|
|
90
|
+
/// Does not require all packets in memory simultaneously — each packet is
|
|
91
|
+
/// processed and then dropped. Only conversation state (metadata + reassembly
|
|
92
|
+
/// buffers) is retained.
|
|
93
|
+
///
|
|
94
|
+
/// If `config.memory_budget` is set, reassembly buffers will be spilled to
|
|
95
|
+
/// disk when the budget is exceeded.
|
|
96
|
+
pub fn extract_flows_streaming<I>(
|
|
97
|
+
packets: I,
|
|
98
|
+
config: FlowConfig,
|
|
99
|
+
) -> Result<Vec<ConversationState>, FlowError>
|
|
100
|
+
where
|
|
101
|
+
I: Iterator<Item = Result<CapturedPacket, PacketError>>,
|
|
102
|
+
{
|
|
103
|
+
let table = ConversationTable::new(config);
|
|
104
|
+
|
|
105
|
+
for (index, result) in packets.enumerate() {
|
|
106
|
+
let captured = result.map_err(FlowError::PacketError)?;
|
|
107
|
+
let timestamp = captured.metadata.timestamp;
|
|
108
|
+
table.ingest_packet(&captured.packet, timestamp, index)?;
|
|
109
|
+
// `captured` is dropped here — packet memory freed immediately
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
Ok(table.into_conversations())
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/// Extract flows directly from a capture file (PCAP or PcapNG).
|
|
116
|
+
///
|
|
117
|
+
/// Streams packets from disk — never loads the entire file into memory.
|
|
118
|
+
/// The file format is auto-detected from magic bytes.
|
|
119
|
+
pub fn extract_flows_from_file(
|
|
120
|
+
path: impl AsRef<Path>,
|
|
121
|
+
config: FlowConfig,
|
|
122
|
+
) -> Result<Vec<ConversationState>, FlowError> {
|
|
123
|
+
let iter = CaptureIterator::open(path).map_err(FlowError::PacketError)?;
|
|
124
|
+
extract_flows_streaming(iter, config)
|
|
125
|
+
}
|
|
126
|
+
|
|
85
127
|
/// Extract Z-Wave conversations from a list of captured packets.
|
|
86
128
|
///
|
|
87
129
|
/// Z-Wave is a wireless protocol not carried over IP, so it needs its own
|
|
@@ -155,6 +197,7 @@ mod tests {
|
|
|
155
197
|
metadata: PcapMetadata {
|
|
156
198
|
timestamp: Duration::from_secs(timestamp_secs),
|
|
157
199
|
orig_len: 0,
|
|
200
|
+
..Default::default()
|
|
158
201
|
},
|
|
159
202
|
}
|
|
160
203
|
}
|