├── .github └── workflows │ ├── coverage.yml │ └── main.yml ├── .gitignore ├── .gitlab-ci.yml ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── README.tpl ├── changelog.md ├── coverage ├── README.md └── coverage.bash ├── etherparse ├── Cargo.toml ├── ensure_no_std │ ├── .gitignore │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── examples │ ├── ip_defrag.rs │ ├── read_by_slicing.rs │ ├── write_ipv4_udp.rs │ ├── write_tcp.rs │ └── write_udp.rs ├── proptest-regressions │ ├── compositions_tests.txt │ ├── internet │ │ ├── internet_slice.txt │ │ ├── ip_auth_header.txt │ │ ├── ip_auth_header_slice.txt │ │ ├── ip_header.txt │ │ ├── ip_slice.txt │ │ ├── ipv4_dscp.txt │ │ ├── ipv4_exts.txt │ │ ├── ipv4_header.txt │ │ ├── ipv4_header_slice.txt │ │ ├── ipv4_slice.txt │ │ ├── ipv6_exts.txt │ │ ├── ipv6_exts_slice.txt │ │ ├── ipv6_fragment_header.txt │ │ ├── ipv6_header.txt │ │ ├── ipv6_header_slice.txt │ │ ├── ipv6_raw_ext_header.txt │ │ ├── ipv6_slice.txt │ │ ├── lax_ip_slice.txt │ │ ├── lax_ipv4_slice.txt │ │ └── lax_ipv6_slice.txt │ ├── link │ │ ├── double_vlan_slice.txt │ │ ├── ethernet2_header.txt │ │ ├── ethernet2_slice.txt │ │ ├── lax_link_ext_slice.txt │ │ ├── lax_macsec_slice.txt │ │ ├── link_ext_slice.txt │ │ ├── linux_sll_header_slice.txt │ │ ├── mac_sec_an.txt │ │ ├── mac_sec_header.txt │ │ ├── mac_sec_sl.txt │ │ ├── macsec_header.txt │ │ ├── macsec_header_slice.txt │ │ ├── macsec_slice.txt │ │ ├── single_vlan_header.txt │ │ ├── single_vlan_slice.txt │ │ ├── vlan_id.txt │ │ ├── vlan_pcp.txt │ │ └── vlan_slice.txt │ ├── net │ │ ├── arp_eth_ipv4_packet.txt │ │ ├── arp_packet.txt │ │ ├── arp_packet_slice.txt │ │ └── ipv4_header.txt │ ├── packet_filters.rs.txt │ ├── sliced_packet.txt │ └── transport │ │ ├── icmpv4_header.txt │ │ ├── icmpv6_header.txt │ │ ├── tcp_header.txt │ │ ├── tcp_header_slice.txt │ │ ├── tcp_options.txt │ │ ├── tcp_slice.txt │ │ ├── transport_header.txt │ │ ├── udp_header.txt │ │ └── udp_slice.txt ├── src │ ├── checksum.rs │ ├── compositions_tests.rs │ ├── defrag │ │ ├── ip_defrag_buf.rs │ │ ├── ip_defrag_error.rs │ │ ├── ip_defrag_payload_vec.rs │ │ ├── ip_defrag_pool.rs │ │ ├── ip_frag_id.rs │ │ ├── ip_frag_range.rs │ │ ├── ip_frag_version_spec_id.rs │ │ └── mod.rs │ ├── err │ │ ├── arp │ │ │ ├── arp_eth_ipv4_from_error.rs │ │ │ ├── arp_hw_addr_error.rs │ │ │ ├── arp_new_error.rs │ │ │ ├── arp_proto_addr_error.rs │ │ │ └── mod.rs │ │ ├── from_slice_error.rs │ │ ├── io │ │ │ ├── limited_read_error.rs │ │ │ └── mod.rs │ │ ├── ip │ │ │ ├── header_error.rs │ │ │ ├── headers_error.rs │ │ │ ├── headers_read_error.rs │ │ │ ├── headers_slice_error.rs │ │ │ ├── headers_write_error.rs │ │ │ ├── ip_dscp_unknown_value_error.rs │ │ │ ├── lax_header_slice_error.rs │ │ │ ├── mod.rs │ │ │ └── slice_error.rs │ │ ├── ip_auth │ │ │ ├── header_error.rs │ │ │ ├── header_limited_read_error.rs │ │ │ ├── header_read_error.rs │ │ │ ├── header_slice_error.rs │ │ │ ├── icv_len_error.rs │ │ │ └── mod.rs │ │ ├── ip_exts │ │ │ ├── exts_walk_error.rs │ │ │ ├── header_error.rs │ │ │ ├── headers_slice_error.rs │ │ │ └── mod.rs │ │ ├── ipv4 │ │ │ ├── bad_options_len.rs │ │ │ ├── header_error.rs │ │ │ ├── header_read_error.rs │ │ │ ├── header_slice_error.rs │ │ │ ├── mod.rs │ │ │ └── slice_error.rs │ │ ├── ipv4_exts │ │ │ ├── exts_walk_error.rs │ │ │ ├── header_write_error.rs │ │ │ └── mod.rs │ │ ├── ipv6 │ │ │ ├── header_error.rs │ │ │ ├── header_read_error.rs │ │ │ ├── header_slice_error.rs │ │ │ ├── mod.rs │ │ │ └── slice_error.rs │ │ ├── ipv6_exts │ │ │ ├── ext_payload_len_error.rs │ │ │ ├── exts_walk_error.rs │ │ │ ├── header_error.rs │ │ │ ├── header_limited_read_error.rs │ │ │ ├── header_read_error.rs │ │ │ ├── header_slice_error.rs │ │ │ ├── header_write_error.rs │ │ │ └── mod.rs │ │ ├── layer.rs │ │ ├── len_error.rs │ │ ├── linux_sll │ │ │ ├── header_error.rs │ │ │ ├── header_read_error.rs │ │ │ ├── header_slice_error.rs │ │ │ └── mod.rs │ │ ├── macsec │ │ │ ├── header_error.rs │ │ │ ├── header_read_error.rs │ │ │ ├── header_slice_error.rs │ │ │ └── mod.rs │ │ ├── mod.rs │ │ ├── net │ │ │ ├── mod.rs │ │ │ └── net_set_next_header_error.rs │ │ ├── packet │ │ │ ├── build_write_error.rs │ │ │ ├── mod.rs │ │ │ ├── slice_error.rs │ │ │ └── transport_checksum_error.rs │ │ ├── read_error.rs │ │ ├── slice_write_space_error.rs │ │ ├── tcp │ │ │ ├── header_error.rs │ │ │ ├── header_read_error.rs │ │ │ ├── header_slice_error.rs │ │ │ └── mod.rs │ │ ├── value_too_big_error.rs │ │ └── value_type.rs │ ├── helpers.rs │ ├── io │ │ ├── limited_reader.rs │ │ └── mod.rs │ ├── lax_packet_headers.rs │ ├── lax_payload_slice.rs │ ├── lax_sliced_packet.rs │ ├── lax_sliced_packet_cursor.rs │ ├── len_source.rs │ ├── lib.rs │ ├── link │ │ ├── double_vlan_header.rs │ │ ├── double_vlan_slice.rs │ │ ├── ether_payload_slice.rs │ │ ├── ether_type_impl.rs │ │ ├── ethernet2_header.rs │ │ ├── ethernet2_header_slice.rs │ │ ├── ethernet2_slice.rs │ │ ├── lax_ether_payload_slice.rs │ │ ├── lax_link_ext_slice.rs │ │ ├── lax_macsec_payload_slice.rs │ │ ├── lax_macsec_slice.rs │ │ ├── link_ext_header.rs │ │ ├── link_ext_slice.rs │ │ ├── link_header.rs │ │ ├── link_slice.rs │ │ ├── linux_nonstandard_ether_type.rs │ │ ├── linux_sll_header.rs │ │ ├── linux_sll_header_slice.rs │ │ ├── linux_sll_packet_type.rs │ │ ├── linux_sll_payload_slice.rs │ │ ├── linux_sll_protocol_type.rs │ │ ├── linux_sll_slice.rs │ │ ├── macsec_an.rs │ │ ├── macsec_header.rs │ │ ├── macsec_header_slice.rs │ │ ├── macsec_payload_slice.rs │ │ ├── macsec_ptype.rs │ │ ├── macsec_short_len.rs │ │ ├── macsec_slice.rs │ │ ├── mod.rs │ │ ├── single_vlan_header.rs │ │ ├── single_vlan_header_slice.rs │ │ ├── single_vlan_slice.rs │ │ ├── vlan_header.rs │ │ ├── vlan_id.rs │ │ ├── vlan_pcp.rs │ │ └── vlan_slice.rs │ ├── net │ │ ├── arp_eth_ipv4_packet.rs │ │ ├── arp_hardware_id.rs │ │ ├── arp_operation.rs │ │ ├── arp_packet.rs │ │ ├── arp_packet_slice.rs │ │ ├── ip_auth_header.rs │ │ ├── ip_auth_header_slice.rs │ │ ├── ip_dscp.rs │ │ ├── ip_dscp_known.rs │ │ ├── ip_ecn.rs │ │ ├── ip_frag_offset.rs │ │ ├── ip_headers.rs │ │ ├── ip_number_impl.rs │ │ ├── ip_payload_slice.rs │ │ ├── ip_slice.rs │ │ ├── ipv4_exts.rs │ │ ├── ipv4_exts_slice.rs │ │ ├── ipv4_header.rs │ │ ├── ipv4_header_slice.rs │ │ ├── ipv4_options.rs │ │ ├── ipv4_slice.rs │ │ ├── ipv6_ext_slice.rs │ │ ├── ipv6_ext_slice_iter.rs │ │ ├── ipv6_exts.rs │ │ ├── ipv6_exts_slice.rs │ │ ├── ipv6_flow_label.rs │ │ ├── ipv6_fragment_header.rs │ │ ├── ipv6_fragment_header_slice.rs │ │ ├── ipv6_header.rs │ │ ├── ipv6_header_slice.rs │ │ ├── ipv6_raw_ext_header.rs │ │ ├── ipv6_raw_ext_header_slice.rs │ │ ├── ipv6_routing_exts.rs │ │ ├── ipv6_slice.rs │ │ ├── lax_ip_payload_slice.rs │ │ ├── lax_ip_slice.rs │ │ ├── lax_ipv4_slice.rs │ │ ├── lax_ipv6_slice.rs │ │ ├── lax_net_slice.rs │ │ ├── mod.rs │ │ ├── net_headers.rs │ │ └── net_slice.rs │ ├── packet_builder.rs │ ├── packet_headers.rs │ ├── payload_slice.rs │ ├── sliced_packet.rs │ ├── sliced_packet_cursor.rs │ ├── test_gens │ │ └── mod.rs │ ├── test_packet.rs │ └── transport │ │ ├── icmp_echo_header.rs │ │ ├── icmpv4 │ │ ├── dest_unreachable_header.rs │ │ ├── mod.rs │ │ ├── parameter_problem_header.rs │ │ ├── redirect_code.rs │ │ ├── redirect_header.rs │ │ ├── time_exceeded_code.rs │ │ └── timestamp_message.rs │ │ ├── icmpv4_header.rs │ │ ├── icmpv4_slice.rs │ │ ├── icmpv4_type.rs │ │ ├── icmpv6 │ │ ├── dest_unreachable_code.rs │ │ ├── mod.rs │ │ ├── parameter_problem_code.rs │ │ ├── parameter_problem_header.rs │ │ └── time_exceeded_code.rs │ │ ├── icmpv6_header.rs │ │ ├── icmpv6_slice.rs │ │ ├── icmpv6_type.rs │ │ ├── mod.rs │ │ ├── tcp_header.rs │ │ ├── tcp_header_slice.rs │ │ ├── tcp_option_element.rs │ │ ├── tcp_option_impl.rs │ │ ├── tcp_option_read_error.rs │ │ ├── tcp_option_write_error.rs │ │ ├── tcp_options.rs │ │ ├── tcp_options_iterator.rs │ │ ├── tcp_slice.rs │ │ ├── transport_header.rs │ │ ├── transport_slice.rs │ │ ├── udp_header.rs │ │ ├── udp_header_slice.rs │ │ └── udp_slice.rs └── tests │ ├── transport │ ├── icmpv4.rs │ ├── icmpv6.rs │ └── mod.rs │ └── unit-tests.rs └── etherparse_proptest_generators ├── Cargo.toml └── src └── lib.rs /.github/workflows/coverage.yml: -------------------------------------------------------------------------------- 1 | name: codecoverage 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - master 8 | 9 | jobs: 10 | codecoverage_test: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | - uses: actions-rs/toolchain@v1 16 | with: 17 | toolchain: stable 18 | override: true 19 | components: llvm-tools-preview 20 | - uses: actions-rs/cargo@v1 21 | with: 22 | command: install 23 | args: cargo-binutils rustfilt 24 | - name: Install jq 25 | run: sudo apt install jq 26 | - name: Determine coverage 27 | run: coverage/coverage.bash 28 | shell: bash 29 | - name: Codecov 30 | uses: codecov/codecov-action@v4 31 | with: 32 | files: target/coverage/export.lcov.txt 33 | fail_ci_if_error: true 34 | token: ${{ secrets.CODECOV_TOKEN }} 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target 3 | **/*.rs.bk 4 | Cargo.lock 5 | /.vscode 6 | /.idea 7 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | # Official language image. Look for the different tagged releases at: 2 | # https://hub.docker.com/r/library/rust/tags/ 3 | image: "rust:latest" 4 | 5 | # Optional: Pick zero or more services to be used on all builds. 6 | # Only needed when using a docker container to run your tests in. 7 | # Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-a-service 8 | #services: 9 | # - mysql:latest 10 | # - redis:latest 11 | # - postgres:latest 12 | 13 | # Optional: Install a C compiler, cmake and git into the container. 14 | # You will often need this when you (or any of your dependencies) depends on C code. 15 | #before_script: 16 | #- apt-get update -yqq 17 | #- apt-get install -yqq --no-install-recommends build-essential 18 | 19 | # Use cargo to test the project 20 | test:cargo: 21 | script: 22 | - rustc --version && cargo --version # Print version info for debugging 23 | - cargo test --all --verbose 24 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | members = [ 4 | "etherparse", 5 | "etherparse_proptest_generators", 6 | ] 7 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Julian Schmid 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.tpl: -------------------------------------------------------------------------------- 1 | [![Crates.io](https://img.shields.io/crates/v/etherparse.svg)](https://crates.io/crates/etherparse) 2 | [![docs.rs](https://docs.rs/etherparse/badge.svg)](https://docs.rs/etherparse) 3 | [![Build Status Github](https://github.com/JulianSchmid/etherparse/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/JulianSchmid/etherparse/actions/workflows/main.yml) 4 | [![Build Status Gitlab](https://gitlab.com/julian.schmid/etherparse/badges/master/pipeline.svg)](https://gitlab.com/julian.schmid/etherparse/-/commits/master) 5 | [![Codecov](https://codecov.io/gh/JulianSchmid/etherparse/branch/master/graph/badge.svg?token=yjfRLgScR6)](https://codecov.io/gh/JulianSchmid/etherparse) 6 | 7 | # {{crate}} 8 | 9 | {{readme}} 10 | 11 | ## License 12 | Licensed under either of Apache License, Version 2.0 or MIT license at your option. The corresponding license texts can be found in the LICENSE-APACHE file and the LICENSE-MIT file. 13 | 14 | ### Contribution 15 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you shall be licensed as above, without any additional terms or conditions. -------------------------------------------------------------------------------- /coverage/README.md: -------------------------------------------------------------------------------- 1 | # Scripts 2 | 3 | This folder contains some helpfull scripts that can be helpfull during development. 4 | 5 | ## Pre-Requirements 6 | 7 | To run the scripts in this folder you have to install a few tools on your system. You can use the following script to install the required tools (just replace `brew` with the packet manager of your choice). 8 | 9 | ```sh 10 | # nightly toolchain 11 | rustup toolchain install stable 12 | 13 | # llvm toolchain for nightly 14 | rustup component add llvm-tools-preview 15 | 16 | # cargo-binutils and rustfilt for nightly 17 | cargo install cargo-binutils rustfilt 18 | 19 | # jq from your package manager of choice (just replace brew with apt or a similar manager) 20 | brew install jq 21 | ``` 22 | 23 | ## coverage.bash 24 | 25 | `coverage.bash` calculates the region & line based code coverage of the tests. Just execute it and it will write the reports to `target/coverage`. 26 | 27 | Note: When executing this script `cargo clean` be executed and previous coverage data will be deleted. 28 | -------------------------------------------------------------------------------- /etherparse/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "etherparse" 3 | version = "0.18.0" 4 | authors = ["Julian Schmid "] 5 | edition = "2021" 6 | repository = "https://github.com/JulianSchmid/etherparse" 7 | description = "A library for parsing & writing a bunch of packet based protocols (EthernetII, IPv4, IPv6, UDP, TCP ...)." 8 | categories = ["network-programming", "parser-implementations", "no-std", "no-std::no-alloc"] 9 | keywords = ["ipv4", "ipv6", "vlan", "udp", "tcp"] 10 | license = "MIT OR Apache-2.0" 11 | readme = "../README.md" 12 | exclude = [ 13 | ".gitignore", 14 | ".travis.yml", 15 | ".github/*", 16 | ".gitlab-ci.yml", 17 | ".travis/*", 18 | "appveyor.yml" 19 | ] 20 | rust-version = "1.83.0" 21 | 22 | [features] 23 | default = ["std"] 24 | std = ["arrayvec/std"] 25 | 26 | [dependencies] 27 | arrayvec = { version = "0.7.2", default-features = false } 28 | 29 | [dev-dependencies] 30 | proptest = "1.4.0" 31 | 32 | [package.metadata.docs.rs] 33 | all-features = true 34 | rustdoc-args = ["--cfg", "docsrs"] 35 | -------------------------------------------------------------------------------- /etherparse/ensure_no_std/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | /.vscode 5 | /.idea 6 | -------------------------------------------------------------------------------- /etherparse/ensure_no_std/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ensure_no_std" 3 | version = "0.1.0" 4 | edition = "2021" 5 | publish = false 6 | 7 | [dependencies] 8 | etherparse = { path = "..", default-features = false } 9 | 10 | [profile.dev] 11 | panic = "abort" 12 | 13 | [profile.release] 14 | panic = "abort" 15 | 16 | [workspace] -------------------------------------------------------------------------------- /etherparse/ensure_no_std/README.md: -------------------------------------------------------------------------------- 1 | # ensure_no_std 2 | 3 | This a helper project to test if `etherparse` compiled in `no_std` 4 | mode does not contain any references to `std` or `alloc`. 5 | 6 | ## Prerequisite 7 | 8 | You have to have a toolchain installed for `no_std` testing: 9 | 10 | ``` 11 | rustup target add x86_64-unknown-none 12 | ``` 13 | 14 | ## How to test there are no `std` or `alloc` dependencies? 15 | 16 | ```sh 17 | cd /etherparse/ensure_no_std 18 | cargo build --target x86_64-unknown-none 19 | ``` 20 | 21 | If the build passes you are good. -------------------------------------------------------------------------------- /etherparse/ensure_no_std/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use core::panic::PanicInfo; 5 | 6 | /// This function is called on panic. 7 | #[panic_handler] 8 | fn panic(_info: &PanicInfo) -> ! { 9 | loop {} 10 | } 11 | 12 | #[no_mangle] 13 | pub extern "C" fn _start() -> ! { 14 | loop {} 15 | } 16 | -------------------------------------------------------------------------------- /etherparse/examples/ip_defrag.rs: -------------------------------------------------------------------------------- 1 | use etherparse::*; 2 | 3 | fn main() { 4 | // setup some network data to parse 5 | let builder = PacketBuilder::ethernet2( 6 | // source mac 7 | [1, 2, 3, 4, 5, 6], 8 | // destination mac 9 | [7, 8, 9, 10, 11, 12], 10 | ) 11 | .ip(IpHeaders::Ipv4( 12 | Ipv4Header { 13 | total_len: 0, // will be overwritten by builder 14 | identification: 1234, 15 | dont_fragment: false, 16 | more_fragments: true, 17 | fragment_offset: IpFragOffset::try_new(1024 / 8).unwrap(), 18 | time_to_live: 20, 19 | protocol: IpNumber::UDP, 20 | header_checksum: 0, // will be overwritten by builder 21 | source: [1, 2, 3, 4], 22 | destination: [2, 3, 4, 5], 23 | ..Default::default() 24 | }, 25 | Default::default(), 26 | )) 27 | .udp( 28 | 21, // source port 29 | 1234, // desitnation port 30 | ); 31 | 32 | // payload of the udp packet 33 | let payload = [1, 2, 3, 4, 5, 6, 7, 8]; 34 | 35 | // get some memory to store the serialized data 36 | let mut serialized = Vec::::with_capacity(builder.size(payload.len())); 37 | builder.write(&mut serialized, &payload).unwrap(); 38 | 39 | // pool that manages the different fragmented packets & the different memory buffers for re-assembly 40 | let mut ip_defrag_pool = defrag::IpDefragPool::<(), ()>::new(); 41 | 42 | // slice the packet into the different header components 43 | let sliced_packet = match SlicedPacket::from_ethernet(&serialized) { 44 | Err(err) => { 45 | println!("Err {:?}", err); 46 | return; 47 | } 48 | Ok(v) => v, 49 | }; 50 | 51 | // constructed 52 | if sliced_packet.is_ip_payload_fragmented() { 53 | let defrag_result = ip_defrag_pool.process_sliced_packet(&sliced_packet, (), ()); 54 | match defrag_result { 55 | Ok(Some(finished)) => { 56 | println!( 57 | "Successfully reconstructed fragmented IP packet ({} bytes, protocol {:?})", 58 | finished.payload.len(), 59 | finished.ip_number, 60 | ); 61 | 62 | // continue parsing the payload 63 | // ... fill in your code here 64 | 65 | // IMPORTANT: After done return the finished packet buffer to avoid unneeded allocations 66 | ip_defrag_pool.return_buf(finished); 67 | } 68 | Ok(None) => { 69 | println!( 70 | "Received a fragmented packet, but the reconstruction was not yet finished" 71 | ); 72 | } 73 | Err(err) => { 74 | println!("Error reconstructing fragmented IPv4 packet: {err}"); 75 | } 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /etherparse/examples/write_ipv4_udp.rs: -------------------------------------------------------------------------------- 1 | use etherparse::*; 2 | use std::io::Write; 3 | 4 | fn main() { 5 | let with_udp_checksum = true; 6 | 7 | //Any struct implementing the "Write" trait can be used to write to (e.g. File). 8 | //For this example lets use a simple Vec as it implements the write trait. 9 | let mut out = Vec::::with_capacity( 10 | //lets reserve enough memory to avoid unnecessary allocations 11 | Ethernet2Header::LEN + Ipv4Header::MAX_LEN + UdpHeader::LEN + 8, //payload 12 | ); 13 | 14 | //setup the actual payload of the udp packet 15 | let udp_payload = [1, 2, 3, 4, 5, 6, 7, 8]; 16 | 17 | //Lets start out with an ethernet II header containing the mac addresses 18 | Ethernet2Header { 19 | destination: [1, 2, 3, 4, 5, 6], 20 | source: [11, 12, 13, 14, 15, 16], 21 | ether_type: ether_type::IPV4, 22 | } 23 | .write(&mut out) 24 | .unwrap(); 25 | 26 | //create the ipv4 header with the helper function 27 | //Note: It is also possible to define the rest of the header values via Ipv4Header {...} 28 | let ip_header = Ipv4Header::new( 29 | //payload length 30 | (UdpHeader::LEN + udp_payload.len()) as u16, 31 | 20, //time to live 32 | ip_number::UDP, //contained protocol is udp 33 | [192, 168, 1, 42], //source ip address 34 | [192, 168, 1, 1], //destination ip address 35 | ) 36 | .unwrap(); 37 | 38 | //write the ipv4 header 39 | // 40 | //The "write" call automatically calculates the ipv4 checksum. 41 | //Alternatively "write_raw" can be used to skip the checksum 42 | //calculation and just write out the checksum set in the header. 43 | ip_header.write(&mut out).unwrap(); 44 | 45 | //write the udp header 46 | // 47 | //There is the option to write it with a checksum or without. 48 | //If yes, the ipv4 header & payload are needed to calculate the header 49 | if with_udp_checksum { 50 | UdpHeader::with_ipv4_checksum( 51 | 0, //source port 52 | 42, //destination port 53 | &ip_header, //ip header 54 | &udp_payload, //udp payload 55 | ) 56 | .unwrap() 57 | .write(&mut out) 58 | .unwrap(); 59 | } else { 60 | //write the header with the checksum disabled 61 | UdpHeader::without_ipv4_checksum( 62 | 0, //source port 63 | 42, //destination port 64 | udp_payload.len(), //payload length 65 | ) 66 | .unwrap() 67 | .write(&mut out) 68 | .unwrap(); 69 | } 70 | 71 | out.write_all(&udp_payload).unwrap(); 72 | 73 | println!("{:?}", &out); 74 | } 75 | -------------------------------------------------------------------------------- /etherparse/examples/write_tcp.rs: -------------------------------------------------------------------------------- 1 | use etherparse::*; 2 | 3 | fn main() { 4 | //setup the packet headers 5 | let builder = PacketBuilder::ethernet2( 6 | [1, 2, 3, 4, 5, 6], //source mac 7 | [7, 8, 9, 10, 11, 12], //destination mac 8 | ) 9 | .ipv4( 10 | [192, 168, 1, 1], //source ip 11 | [192, 168, 1, 2], //destination ip 12 | 20, //time to life 13 | ) 14 | .tcp( 15 | 21, //source port 16 | 1234, //desitnation port 17 | 1, //sequence number 18 | 26180, //window size 19 | ) 20 | //set additional tcp header fields 21 | //supported flags: ns(), fin(), syn(), rst(), psh(), ece(), cwr() 22 | .ns() //set the ns flag 23 | .ack(123) //ack flag + the ack number 24 | .urg(23) //urg flag + urgent pointer 25 | //tcp header options 26 | .options(&[ 27 | TcpOptionElement::Noop, 28 | TcpOptionElement::MaximumSegmentSize(1234), 29 | ]) 30 | .unwrap(); 31 | 32 | //payload of the tcp packet 33 | let payload = [1, 2, 3, 4, 5, 6, 7, 8]; 34 | 35 | //get some memory to store the result 36 | let mut result = Vec::::with_capacity(builder.size(payload.len())); 37 | 38 | //serialize 39 | //this will automatically set all length fields, checksums and identifiers (ethertype & protocol) 40 | builder.write(&mut result, &payload).unwrap(); 41 | println!("{:?}", result); 42 | } 43 | -------------------------------------------------------------------------------- /etherparse/examples/write_udp.rs: -------------------------------------------------------------------------------- 1 | use etherparse::*; 2 | 3 | fn main() { 4 | //setup the packet headers 5 | let builder = PacketBuilder::ethernet2( 6 | [1, 2, 3, 4, 5, 6], //source mac 7 | [7, 8, 9, 10, 11, 12], //destination mac 8 | ) 9 | .ipv4( 10 | [192, 168, 1, 1], //source ip 11 | [192, 168, 1, 2], //destination ip 12 | 20, //time to life 13 | ) 14 | .udp( 15 | 21, //source port 16 | 1234, //desitnation port 17 | ); 18 | 19 | //payload of the udp packet 20 | let payload = [1, 2, 3, 4, 5, 6, 7, 8]; 21 | 22 | //get some memory to store the result 23 | let mut result = Vec::::with_capacity(builder.size(payload.len())); 24 | 25 | //serialize 26 | //this will automatically set all length fields, checksums and identifiers (ethertype & protocol) 27 | builder.write(&mut result, &payload).unwrap(); 28 | println!("{:?}", result); 29 | } 30 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/internet/internet_slice.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc 97770562c27d77b6712b809b566ffe400df2b2ca3046e643e5f2166090f4a327 # shrinks to ipv4_header = Ipv4Header { ihl: 7, differentiated_services_code_point: 0, explicit_congestion_notification: 0, payload_len: 0, identification: 0, dont_fragment: false, more_fragments: false, fragments_offset: IpFragOffset(0), time_to_live: 0, protocol: 68 (any distributed file system), header_checksum: 0, source: [0, 0, 0, 0], destination: [0, 0, 0, 0], options: [0, 0, 0, 0, 0, 0, 0, 0] }, ipv4_exts = Ipv4Extensions { auth: None }, ipv6_header = Ipv6Header { traffic_class: 22, flow_label: 395206, payload_length: 37958, next_header: 172, hop_limit: 137, source: [99, 186, 12, 226, 117, 70, 74, 128, 47, 61, 103, 116, 125, 57, 68, 219], destination: [98, 36, 139, 184, 238, 110, 147, 161, 222, 44, 184, 124, 31, 106, 87, 248] }, mut ipv6_exts = Ipv6Extensions { hop_by_hop_options: None, destination_options: None, routing: None, fragment: Some(Ipv6FragmentHeader { next_header: 51 (AH - Authentication Header), fragment_offset: IpFragOffset(3576), more_fragments: false, identification: 1363142016 }), auth: Some(IpAuthHeader { next_header: 17 (UDP - User Datagram), spi: 1791610029, sequence_number: 2584472886, raw_icv: [7, 228, 240, 72, 15, 159, 71, 243, 221, 88, 254, 85, 113, 158, 208, 119, 138, 203, 182, 77, 92, 141, 251, 112, 9, 236, 219, 62, 192, 216, 161, 123, 217, 224, 41, 71, 237, 94, 1, 168, 60, 169, 86, 194, 107, 100, 14, 14, 216, 69, 195, 15, 26, 202, 77, 165, 218, 96, 70, 196, 205, 188, 187, 22, 118, 245, 83, 55, 19, 84, 36, 109, 57, 159, 76, 130, 254, 218, 187, 15, 47, 25, 146, 206, 196, 30, 109, 191, 120, 59, 67, 90, 203, 164, 2, 89, 23, 70, 31, 117, 83, 183, 66, 100, 71, 159, 205, 94, 88, 228, 189, 28, 71, 187, 44, 122, 166, 87, 26, 203, 191, 13, 205, 81, 3, 195, 92, 205, 71, 152, 182, 219, 223, 44, 135, 213, 153, 71, 3, 156, 71, 101, 176, 142, 8, 51, 101, 88, 147, 0, 198, 251, 50, 170, 117, 197, 39, 183, 212, 96, 213, 114, 128, 23, 99, 182, 244, 184, 141, 178, 127, 231, 219, 255, 135, 224, 53, 223, 160, 249, 204, 18, 49, 17, 167, 182, 34, 238, 124, 231, 68, 235, 124, 216, 57, 194, 68, 93, 109, 7, 166, 144, 41, 33, 118, 246, 195, 215, 237, 108, 241, 45, 37, 45, 46, 245, 234, 14, 153, 180, 4, 67, 225, 223, 19, 111, 164, 165, 86, 221, 202, 231, 73, 24, 34, 227, 36, 57, 164, 167, 169, 39, 171, 13, 76, 109, 191, 249, 199, 3, 239, 109, 230, 59, 142, 234, 28, 2, 145, 43, 57, 212, 46, 71, 167, 171, 195, 237, 52, 106, 173, 173, 128, 143, 207, 75, 171, 183, 130, 79, 107, 218, 3, 174, 90, 173, 137, 182, 64, 85, 227, 103, 149, 209, 113, 20, 191, 39, 124, 223, 204, 112, 204, 242, 239, 100, 156, 214, 5, 164, 125, 77, 196, 79, 209, 199, 11, 20, 185, 242, 42, 203, 168, 236, 99, 79, 112, 107, 2, 166, 74, 213, 92, 175, 209, 72, 117, 85, 1, 155, 116, 53, 191, 107] }) } 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/internet/ip_auth_header.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc 159267836a648eca852fb99cd2e2035279bb389560c8c24dd3ab89d94137459f # shrinks to header = IpAuthHeader { next_header: 207, spi: 0, sequence_number: 0, raw_icv: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 128, 239, 235, 139, 103, 67, 20, 232, 165, 130, 99, 126, 233, 46, 188, 157, 107, 12, 135, 213, 227, 67, 185, 217, 225, 211, 10, 234, 108, 88, 143, 27, 101, 85, 25, 92, 97, 90, 125, 18, 226, 33, 191, 38, 57, 63, 224, 218, 67, 173, 204, 203, 213, 167, 137, 211, 87, 3, 149, 118, 79, 53, 73, 34, 170, 244, 128, 65, 21, 49, 16, 91, 187, 241, 224, 110, 29, 151, 0, 174, 142, 125, 43, 53, 95, 30, 148, 62, 172, 243, 223, 244, 83, 131, 178, 10, 125, 228, 74, 122, 193, 13, 222, 196, 119, 215, 151, 164, 14, 149, 253, 206, 249, 144, 225, 65, 169, 119, 176, 199, 35, 211, 24, 157, 187, 131, 241, 184, 158, 0, 89, 56, 207, 171, 12, 233, 155, 247, 101, 15, 81, 134, 249, 223, 162, 64, 15, 78, 222, 241, 92, 92, 231, 154, 51, 90, 82, 139, 19, 54, 72, 54, 204, 37, 27, 51, 125, 119, 254, 131, 186, 145, 217, 206, 225, 227, 205, 224, 192, 167, 205, 210, 214, 45, 165, 151, 225, 171, 198, 21, 83, 32, 226, 220, 123, 56, 138, 64, 240, 51, 174, 209, 59, 185, 3, 66, 159, 218, 131, 10, 110, 35, 122, 187, 187, 62, 231, 57, 54, 38, 81, 126, 164, 232, 5, 190, 95, 80, 68, 215, 213, 187, 159, 124, 227, 13, 147, 192, 41, 97, 30, 48, 130, 9, 215, 89, 146, 233, 40, 234, 76, 182, 6, 70, 54, 83, 102, 242, 111, 10, 5, 7, 54, 218, 29, 204, 1, 54, 68, 65, 231, 59, 235, 64, 209, 185, 14, 201, 254, 125, 89, 29, 245, 116, 77, 3, 18, 241, 167, 140, 96, 254, 227, 67, 141, 225, 244, 22, 78, 116, 20, 245, 244, 30, 47, 5, 172, 214, 93, 191, 222, 96, 209, 179, 174, 184, 179, 197, 169, 243, 33, 71, 23, 228, 160, 52, 224, 150, 231, 196, 64, 76, 69, 115, 115, 108, 250, 224, 62, 252, 128, 141, 47, 210, 158, 54, 102, 30, 22, 50, 38, 198, 153, 162, 211, 148, 196, 196, 4, 9, 76, 42, 202, 27, 208, 23, 250, 53, 119, 9, 255, 36, 194, 72] } 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/internet/ip_auth_header_slice.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc e2f998d6f63804db73d82a7f750bcd3c47c81935f754dbc47d64acb87f1c00e8 # shrinks to header = IpAuthHeader { next_header: 128, spi: 0, sequence_number: 0, raw_icv: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 173, 194, 175, 193, 118, 185, 243, 139, 122, 246, 253, 120, 31, 19, 106, 172, 133, 161, 33, 155, 46, 31, 50, 82, 231, 196, 145, 146, 254, 199, 90, 48, 88, 37, 48, 190, 211, 116, 107, 4, 150, 61, 162, 89, 14, 122, 171, 194, 58, 155, 205, 154, 3, 178, 52, 214, 149, 254, 78, 192, 223, 65, 99, 101, 121, 22, 93, 236, 160, 133, 247, 103, 15, 114, 190, 37, 193, 248, 62, 16, 102, 31, 7, 180, 88, 17, 222, 108, 178, 93, 22, 240, 243, 13, 43, 255, 217, 78, 151, 146, 70, 221, 244, 88, 94, 218, 152, 86, 177, 236, 33, 0, 96, 184, 34, 245, 220, 172, 38, 208, 104, 147, 170, 58, 111, 87, 191, 112, 142, 253, 144, 15, 17, 241, 233, 242, 53, 116, 7, 6, 69, 14, 197, 155, 101, 16, 194, 206, 191, 41, 134, 123, 210, 70, 56, 110, 137, 175, 8, 123, 61, 87, 53, 40, 67, 179, 148, 228, 183, 212, 89, 127, 26, 65, 37, 7, 205, 183, 136, 213, 197, 133, 181, 226, 170, 242, 209, 79, 213, 173, 160, 85, 193, 250, 30, 146, 243, 236, 150, 9, 40, 220, 110, 104, 188, 13, 246, 75, 136, 1, 185, 158, 23, 3, 72, 199, 177, 177, 95, 195, 74, 135, 102, 40, 99, 87, 242, 176, 249, 115, 31, 140, 49, 53, 5, 42, 10, 104, 167, 46, 36, 215, 206, 33, 99, 162, 47, 223, 223, 162, 246, 207, 78, 101, 245, 201, 72, 5, 105, 231, 121, 18, 132, 252, 224, 201, 166, 148, 243, 204, 23, 102, 201, 48, 122, 141, 67, 188, 214, 235, 19, 40, 103, 138, 75, 220, 3, 31, 205, 30, 80, 195, 6, 182, 100, 239, 166, 151, 191, 141, 104, 200, 242, 250, 13, 137, 237, 15, 127, 251, 174, 164, 49, 176, 101, 201, 170, 183, 189, 15, 209, 103, 164, 141, 17, 121, 62, 27, 24, 70, 130, 174, 35, 218, 64, 216, 101, 130, 28, 125, 47, 129, 126, 199, 111, 170, 45, 21, 79, 72, 124, 59, 213, 22, 62, 160, 247, 8, 183, 2, 102, 151, 53, 36, 221, 194, 163, 93, 65, 108, 166, 202, 87, 189, 105, 95, 161, 160, 92, 113, 172, 100, 14, 220, 100, 249, 54, 255, 159, 225, 45, 13, 164, 165, 197, 119, 206, 27, 145, 1, 56, 140, 212, 134, 54, 33, 118, 16, 117, 242, 233, 143, 50, 121, 172, 30, 62, 70, 181, 196, 149, 254, 204, 11, 149, 129, 26, 156, 157, 137, 167, 222, 215, 99, 211, 178, 96, 125, 216, 45, 198, 130, 78, 47, 219, 186, 128, 69, 9, 10, 100, 247, 129, 29, 144, 48, 106, 62, 119, 214, 200, 78, 182, 54, 175, 88, 36, 203, 78, 12, 131, 254, 29, 209, 32, 197, 70, 141, 110, 12, 243, 128, 194, 36, 153, 212, 38, 165, 168, 58, 193, 56, 18, 100, 153, 245, 45, 148, 167, 83, 191, 112, 0, 114, 26, 164, 101, 184, 105, 104, 142, 247, 136, 2, 178, 71, 110, 7, 138, 240, 211, 189, 246, 119, 201, 226, 69, 162, 222, 233, 197, 40, 223, 73, 38, 9, 180, 139, 201, 23, 90, 47, 12, 178, 102, 109, 177, 150, 103, 95, 30, 99, 2, 121, 197, 231, 170, 177, 66, 211, 59, 233, 179, 82, 231, 237, 245, 139, 255, 45, 250, 203, 138, 79, 37, 87, 253, 195, 211, 235, 201, 227, 75, 159, 23, 43, 45, 87, 134, 19, 94, 53, 192, 30, 221, 201, 197] } 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/internet/ipv4_dscp.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc 5b030cccbf007850504f9893ee7f26cdf0897ddc3f98e23a3c337eeee2066467 # shrinks to valid_value = 0, invalid_value = 64 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/internet/ipv4_exts.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc 437386ca2a231427893f72679446650276d0b4913d7a8a27c4d792a864806647 # shrinks to auth = IpAuthHeader { next_header: 38 (IDPR-CMTP - IDPR Control Message Transport Proto), spi: 0, sequence_number: 0, raw_icv: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 97, 221, 214, 171, 240, 40, 121, 63, 60, 128, 84, 176, 126, 51, 89, 111, 186, 144, 173, 18, 139, 65, 203, 201, 92, 255, 180, 14, 203, 163, 11, 179, 7, 7, 44, 142, 26, 247, 206, 130, 175, 158, 169, 170, 53, 78, 236, 79, 248, 144, 107, 85, 25, 231, 37, 222, 117, 244, 14, 164, 136, 68, 30, 9, 152, 134, 8, 107, 211, 118, 102, 203, 44, 90, 247, 6, 60, 144, 125, 230, 101, 125, 199, 47, 9, 219, 201, 123, 113, 85, 150, 243, 215, 176, 57, 142, 140, 220, 179, 126, 63, 100, 189, 58, 92, 213, 238, 109, 145, 122, 108, 13, 84, 177, 150, 236, 215, 245, 9, 236, 61, 38, 196, 191, 11, 4, 67, 249, 253, 248, 93, 155, 186, 11, 233, 120, 56, 0, 75, 188, 241, 134, 41, 24, 140, 124, 243, 63, 181, 106, 63, 178, 153, 228, 48, 183, 170, 194, 182, 78, 79, 158, 164, 174, 233, 241, 186, 105, 165, 182, 78, 161, 58, 0, 79, 190, 201, 77, 133, 75, 123, 169, 93, 88, 95, 173, 136, 6, 211, 97, 219, 238, 252, 206, 235, 86, 16, 179, 250, 233, 55, 239, 251, 241, 196, 226, 20, 203, 78, 133, 131, 236, 204, 2, 121, 79, 195, 197, 60, 168, 16, 195, 122, 1, 229, 178, 15, 53, 93, 72, 88, 163, 136, 58, 109, 44, 22, 76, 79, 213, 168, 141, 197, 110, 56, 32, 240, 253, 168, 147, 28, 171, 238, 239, 95, 88, 31, 181, 5, 66, 31, 44, 246, 201, 112, 20, 187, 46, 14, 171, 193, 142, 27, 73, 2, 56, 93, 251, 147, 55, 30, 194, 37, 102, 65, 85, 131, 113, 130, 109, 209, 13, 198, 168, 176, 241, 218, 70, 210, 178, 12, 184, 184, 234, 122, 128, 217, 237, 101, 102, 209, 68, 46, 108, 100, 178, 85, 21, 143, 224, 206, 231, 236, 204, 153, 111, 31, 253, 141, 148, 181, 154, 120, 66, 0, 177, 29, 166, 179, 187, 53, 219, 42, 136, 217, 95, 213, 205, 151, 236, 1, 52, 56, 11, 164, 146, 137, 40, 41, 50, 137, 154, 113, 175, 199, 151, 18, 168, 211, 205, 230, 131, 171, 214, 157, 21, 228, 116, 32, 91, 216, 181, 48, 223, 154, 94, 146, 193, 114, 113, 44, 212, 98, 69, 134, 119, 74, 173, 173, 119, 49, 130, 23, 28, 207, 167, 180, 86, 13, 109, 36, 84, 194, 113, 36, 33, 161, 221, 172, 19, 75, 16, 108, 51, 255, 118, 74, 101, 172, 238, 105, 45, 12, 101, 28, 108, 77, 234, 251, 196, 233, 187, 40, 176, 220, 4, 59, 128, 48, 95, 49, 123, 37, 224, 62, 36, 217, 103, 12, 152, 162, 26, 49, 148, 82, 50, 63, 64, 7, 102, 185, 45, 71, 41, 184, 55, 195, 172, 80, 217, 251, 38, 5, 194, 139, 67, 61, 160, 52, 15, 173, 116, 153, 111, 222, 228, 145, 193, 14, 134, 6, 28, 66, 148, 163, 111, 107, 15, 94, 157, 48, 154, 36, 145, 41, 15, 3, 7, 208, 168, 153, 239, 109, 16, 117, 90, 254, 130, 187, 186, 72, 40, 194, 27, 25, 115, 31, 248, 20, 19, 145, 123, 27, 39, 30, 141, 189, 30, 229, 102, 208, 174, 249, 221, 170, 241, 156, 193, 138, 20, 26, 65, 228, 31, 99, 163, 213, 50, 225, 17, 227, 96, 47, 136, 8, 118, 176, 216, 181, 24, 32, 139, 41, 78, 179, 212, 101, 15, 124, 188, 33, 86, 175, 129, 121, 246, 11, 25, 121, 184, 144, 12, 108, 177, 9, 113, 108, 82, 214, 207, 215, 118, 239, 129, 56] } 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/internet/ipv4_header.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc 1873fa00d9b4f0af87861f075c5ba29e74d7dac118637e4c1a33d41a3009a28f # shrinks to ref base_header = Ipv4Header { ihl: 7, differentiated_services_code_point: 0, explicit_congestion_notification: 0, payload_len: 0, identification: 0, dont_fragment: false, more_fragments: false, fragments_offset: 0, time_to_live: 0, protocol: 145, header_checksum: 0, source: [0, 0, 0, 0], destination: [0, 0, 0, 0], options: [0, 0, 0, 0, 0, 0, 0, 0] } 8 | cc 13666c027d7ea3b1272e605857d2a4f6532e92dd8509f6003e9b2124cdb0387e # shrinks to header = Ipv4Header { ihl: 5, differentiated_services_code_point: 0, explicit_congestion_notification: 0, payload_len: 0, identification: 0, dont_fragment: false, more_fragments: false, fragments_offset: 0, time_to_live: 0, protocol: 233, header_checksum: 0, source: [0, 0, 0, 0], destination: [0, 0, 0, 0], options: [] } 9 | cc f85bc62081cbee15e8029eb6aca54a2495c572e0652775898c1309c17cda3b95 # shrinks to base_header = Ipv4Header { ihl: 8, differentiated_services_code_point: 0, explicit_congestion_notification: 0, payload_len: 0, identification: 0, dont_fragment: false, more_fragments: false, fragments_offset: 0, time_to_live: 0, protocol: 127, header_checksum: 0, source: [0, 0, 0, 0], destination: [0, 0, 0, 0], options: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 85] }, bad_dscp = 169, bad_ecn = 48, bad_frag_offset = 7337 10 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/internet/ipv4_header_slice.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc 4cc24fab1e703ab4a8d4563e9d3f4ca100aa7611386914d66993eb37d7c3fcd6 # shrinks to header = Ipv4Header { ihl: 6, differentiated_services_code_point: 0, explicit_congestion_notification: 0, payload_len: 0, identification: 0, dont_fragment: false, more_fragments: false, fragments_offset: 0, time_to_live: 0, protocol: 252, header_checksum: 0, source: [0, 0, 0, 0], destination: [0, 0, 0, 0], options: [0, 0, 0, 0] } 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/internet/ipv6_exts.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc 8241e4aed6355dae62ebffd014e532bc315a4795977336d48b8ed9b83ae04d6f # shrinks to header_size = 0, post_header = 1 (ICMP - Internet Control Message) 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/internet/ipv6_exts_slice.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc 925b9a2a0ec5a0f366aebbadd60534e57feb06ff69477bf7d18e5fa85168aee3 # shrinks to header_size = 0, post_header = 52 (I-NLSP - Integrated Net Layer Security TUBA) 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/internet/ipv6_fragment_header.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc 69bfd2a19e0bfc33810009e0e3aa8266194847913d0bab87102f5864cf620d56 # shrinks to input = Ipv6FragmentHeader { next_header: 0 (HOPOPT - IPv6 Hop-by-Hop Option), fragment_offset: 0, more_fragments: false, identification: 0 } 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/internet/ipv6_header_slice.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc 10a03f9d86ad9fc6a192d9086246d29f800e3d0b526f3835a44babeeca3085dc # shrinks to header = Ipv6Header { traffic_class: 163, flow_label: 522586, payload_length: 32529, next_header: 18, hop_limit: 5, source: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], destination: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 37, 225] } 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/link/double_vlan_slice.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc fd2ee3e3872d2ded38124f5a6352bfd29738db63731eab08d738e1a32a036b86 # shrinks to vlan = DoubleVlanHeader { outer: SingleVlanHeader { pcp: VlanPcp(0), drop_eligible_indicator: false, vlan_id: VlanId(0), ether_type: 0x8100 (Customer VLAN Tag (C-TAG) as defined in IEEE Std 802.1Q) }, inner: SingleVlanHeader { pcp: VlanPcp(0), drop_eligible_indicator: false, vlan_id: VlanId(0), ether_type: 0x0000 } }, ether_type_non_vlan = 0x0000 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/link/ethernet2_header.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc e3e72f2a0f7782b605dc416d2a8186c3f04d32f54f9d72069497b71dec1d96d9 # shrinks to input = Ethernet2Header { source: [0, 0, 0, 38, 213, 2], destination: [248, 77, 92, 15, 164, 253], ether_type: 11 } 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/link/ethernet2_slice.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc 0313dcb8757d7c15ecd8a3af4a0489043408c891a7fb87e6caf643ec7bde8e7d # shrinks to eth = Ethernet2Header { source: [0, 2, 50, 70, 120, 132], destination: [225, 162, 116, 209, 135, 44], ether_type: 0x0001 } 8 | cc c4709ecdb8cc8ad815bd2e4e5d31d149c4a29c0e9ad2bd5e64164df59c42b871 # shrinks to eth = Ethernet2Header { source: [0, 0, 0, 0, 0, 0], destination: [0, 0, 0, 7, 128, 191], ether_type: 0x0001 } 9 | cc 51e35db4df6e551682b7047b57e72d8e884a9c61b3f3738c6ec65f0277515337 # shrinks to eth = Ethernet2Header { source: [3, 10, 170, 46, 204, 204], destination: [94, 67, 48, 133, 64, 179], ether_type: 0x0001 } 10 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/link/lax_link_ext_slice.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc d6c35d4295255dbddecc82e6fa137d7a138d869cdade93165b972bd23217edfa # shrinks to vlan = SingleVlanHeader { pcp: VlanPcp(0), drop_eligible_indicator: false, vlan_id: VlanId(0), ether_type: 0x0000 }, macsec = MacsecHeader { ptype: Unmodified(0x0000), endstation_id: false, scb: false, an: MacsecAn(0), short_len: MacsecShortLen(0), packet_nr: 0, sci: None }, ethertype = 0x0000 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/link/lax_macsec_slice.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc 445d2cb2bb5b24a1094bb52f109956b7608ba2910bdd11bb8e32115976398660 # shrinks to macsec = MacsecHeader { ptype: Unmodified(0x0000), endstation_id: false, scb: false, an: MacsecAn(0), short_len: MacsecShortLen(0), packet_nr: 0, sci: None } 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/link/link_ext_slice.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc b9680cab0923704b74563ac762bf321510faf67286af3ba221f6ca1537dd69b9 # shrinks to vlan = SingleVlanHeader { pcp: VlanPcp(0), drop_eligible_indicator: false, vlan_id: VlanId(0), ether_type: 0x0000 }, macsec = MacsecHeader { ptype: Unmodified(0x0000), endstation_id: false, scb: false, an: MacsecAn(0), short_len: MacsecShortLen(0), packet_nr: 0, sci: Some(0) }, ether_type = 0x0000 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/link/linux_sll_header_slice.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc e14e4c7280be51164b675912e97895f4919b07792e7fd41ab8c9bad5356465e1 # shrinks to input = LinuxSllHeader { packet_type: 0 (Sent to us), arp_hrd_type: 824 (Netlink header), sender_address_valid_length: 0, sender_address: [0, 0, 0, 0, 0, 0, 0, 0], protocol_type: NetlinkProtocolType(0) } 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/link/mac_sec_an.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc bede3366c70950fac8a449294adc500d9f5ee5c956c66896ab6ea14c1b0bef45 # shrinks to valid_value = 4 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/link/mac_sec_header.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc 66ab8c1dc7f1c333bd90c5289bdef647537372b1b9ce894d34b3a23422abc54f # shrinks to header = MacSecHeader { ptype: Unmodified(0x0001), endstation_id: false, scb: false, an: MacSecAn(0), short_len: MacSecShortLen(0), packet_nr: 0, sci: None } 8 | cc 604f124b27176f7ff3c97f86d16e36928f51f7daa79c30eea702e5248f9f2abe # shrinks to header = MacSecHeader { ptype: Unmodified(0x0001), endstation_id: false, scb: false, an: MacSecAn(0), short_len: MacSecShortLen(0), packet_nr: 0, sci: None } 9 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/link/mac_sec_sl.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc f970f91fec10c3eed54d6eb268b9e5cf6e32e19a5dff1586bf78ca99362a7b23 # shrinks to valid_value = 0, invalid_value = 8 8 | cc 614402f8cc83702195d27bfee2bc8b56aaf904f8dd858773cb9f9d6c093d426a # shrinks to valid_value = 0, invalid_value = 8 9 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/link/macsec_header.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc d15fc6bd85097c58f9ba998fc10940a19ab7307798cb469b426460228be06ab2 # shrinks to header = MacsecHeader { ptype: Unmodified(0x0000), endstation_id: false, scb: false, an: MacsecAn(0), short_len: MacsecShortLen(0), packet_nr: 0, sci: None }, ether_type = 0x0000, valid_unmodified_len = 2, invalid_unmodified_len_0 = 0, invalid_unmodified_len_1 = 64, valid_modified_len = 1, invalid_modified_len = 64 8 | cc 5c365eb47d1c5896957cd70b55708aab545924c84dba5de6d1d8ae7855a850f4 # shrinks to header = MacsecHeader { ptype: Unmodified(0x0000), endstation_id: false, scb: false, an: MacsecAn(0), short_len: MacsecShortLen(1), packet_nr: 0, sci: None } 9 | cc f5537f4646b939dfa8168d93a1be25c58d326acda8604af3ae382fbf14fd0a2f # shrinks to header = MacsecHeader { ptype: Unmodified(0x0000), endstation_id: false, scb: false, an: MacsecAn(0), short_len: MacsecShortLen(0), packet_nr: 0, sci: None }, ether_type = 0x0000, valid_unmodified_len = 62, invalid_unmodified_len = 64, valid_modified_len = 1, invalid_modified_len = 64 10 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/link/macsec_header_slice.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc 4a82fa88308d823cc3bb0d7da35d367c7475990dc8daaa4c1a5455445ccd41ff # shrinks to macsec = MacsecHeader { ptype: Unmodified(0x0000), endstation_id: false, scb: false, an: MacsecAn(0), short_len: MacsecShortLen(0), packet_nr: 0, sci: None }, ethertype = 0x0000, sci = 0 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/link/macsec_slice.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc 32e7fe8e0e32be55152e2d893aff9099856ba4f19b1babb9a767fb4b44979167 # shrinks to macsec = MacsecHeader { ptype: Unmodified(0x0000), endstation_id: false, scb: false, an: MacsecAn(0), short_len: MacsecShortLen(0), packet_nr: 0, sci: None }, ethertype = 0x0000, non_zero_sl = 1 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/link/single_vlan_header.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc d15330847f35a69e5da65860dd0c00af1e689f6bb3c5c59c5cc03e5f2f0a2158 # shrinks to input = SingleVlanHeader { priority_code_point: 0, drop_eligible_indicator: false, vlan_identifier: VlanId(0), ether_type: 0x0000 } 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/link/single_vlan_slice.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc 9fa5be0c50535dff951c67f43c46b17fe04de3d9f044c08c9112f4991fc1dbfb # shrinks to vlan = SingleVlanHeader { pcp: VlanPcp(0), drop_eligible_indicator: false, vlan_id: VlanId(0), ether_type: 0x0000 } 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/link/vlan_id.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc a28ca5d0468d174393786b905277642e5bd1c6438a8410a79c09c4cc14158f1f # shrinks to valid_value = 0, invalid_value = 256 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/link/vlan_pcp.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc c46f85fbef3083dce84c9912bbe5a07c271579fe1016fc80a257a4e621f103ca # shrinks to valid_value = 0, invalid_value = 8 8 | cc a8c6efb3f79060e61109ba5289b334c5bdd6216b40165b516e15bfa52bcce137 # shrinks to valid_value = 0, invalid_value = 8 9 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/link/vlan_slice.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc dadc8babb24c7b9b8eaf2e0c4e75312dd9704c267a33c8a68906ccec14fa8b92 # shrinks to single = SingleVlanHeader { pcp: VlanPcp(0), drop_eligible_indicator: false, vlan_id: VlanId(0), ether_type: 0x0000 }, double = DoubleVlanHeader { outer: SingleVlanHeader { pcp: VlanPcp(0), drop_eligible_indicator: false, vlan_id: VlanId(61), ether_type: 0x88A8 (IEEE Std 802.1Q - Service VLAN tag identifier (S-Tag)) }, inner: SingleVlanHeader { pcp: VlanPcp(2), drop_eligible_indicator: true, vlan_id: VlanId(472), ether_type: 0x0001 } } 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/net/arp_eth_ipv4_packet.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc 586bfcca48a89809a557b83c703e64b33458a7b99e492937dc9d27cd15f12884 # shrinks to arp = ArpEthIpv4Packet { operation: ArpOperation(0), sender_mac: [0, 0, 0, 0, 0, 0], sender_ipv4: [0, 0, 0, 0], target_mac: [0, 0, 0, 0, 0, 0], target_ipv4: [0, 0, 0, 0] } 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/net/arp_packet.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc 851d44d91acc679380cc543da5c9c124ada08859a988834338417d6e186c45bc # shrinks to arp_eth_ipv4 = ArpEthIpv4Packet { operation: ArpOperation(0), sender_mac: [0, 0, 0, 0, 0, 0], sender_ipv4: [0, 0, 0, 0], target_mac: [0, 0, 0, 0, 0, 0], target_ipv4: [0, 0, 0, 0] } 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/net/arp_packet_slice.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc 1a4c5722fbe8b2c58d2ebb4f140cb4655407ddbc5972f4b14f50f743ef72a03b # shrinks to packet = ArpPacket { hw_addr_type: 0 (from KA9Q: NET/ROM pseudo), proto_addr_type: 0x0000, hw_addr_size: 211, proto_addr_size: 74, operation: ArpOperation(0), sender_hw_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 202, 150, 216, 12, 76, 238, 98, 229, 121, 39, 172, 59, 94, 140, 211, 148, 188, 50, 18, 80, 41, 153, 167, 119, 35, 140, 120, 152, 201, 226, 208, 223, 192, 247, 79, 30, 145, 16, 135, 44, 22, 146, 117, 102, 57, 159, 179, 81, 83, 74, 49, 97, 20, 237, 86, 202, 21, 122, 12, 146, 146, 252, 253, 218, 153, 94, 71, 147, 137, 188, 54], sender_protocol_addr: [237, 238, 108, 127, 141, 251, 105, 6, 10, 128, 214, 186, 26, 165, 196, 137, 202, 142, 53, 175, 48, 169, 149, 76, 22, 140, 61, 223, 245, 75, 180, 131, 219, 57, 64, 35, 165, 205, 38, 212, 168, 70, 247, 208, 172, 207, 47, 145, 65, 19, 165, 171, 7, 197, 135, 227, 209, 37, 29, 37, 67, 8, 93, 201, 250, 131, 20, 22, 157, 238, 56, 156, 86, 115], target_hw_addr: [29, 254, 122, 18, 135, 228, 147, 190, 154, 52, 156, 255, 94, 78, 80, 14, 239, 11, 128, 100, 202, 250, 166, 103, 210, 14, 9, 195, 75, 199, 69, 33, 198, 87, 125, 118, 21, 151, 253, 121, 246, 50, 3, 196, 25, 38, 210, 101, 25, 232, 171, 65, 110, 233, 57, 62, 53, 8, 13, 125, 248, 185, 13, 237, 152, 249, 246, 236, 147, 230, 143, 82, 0, 220, 177, 106, 162, 237, 217, 30, 58, 31, 39, 244, 191, 33, 248, 201, 46, 153, 38, 20, 120, 124, 215, 93, 65, 91, 242, 45, 184, 248, 243, 64, 93, 158, 214, 244, 77, 247, 76, 85, 3, 146, 203, 79, 111, 82, 87, 72, 118, 100, 215, 186, 155, 139, 241, 162, 13, 55, 24, 114, 238, 27, 180, 101, 35, 50, 161, 46, 242, 17, 29, 20, 38, 66, 252, 226, 110, 92, 99, 177, 207, 108, 188, 169, 193, 51, 42, 107, 157, 73, 217, 229, 141, 89, 215, 149, 139, 196, 30, 24, 242, 220, 164, 5, 86, 191, 128, 177, 177, 99, 37, 198, 20, 102, 185, 163, 245, 25, 178, 210, 196, 156, 240, 65, 218, 127, 254, 20, 240, 41, 137, 29, 241, 160, 198, 218, 50, 61, 131], target_protocol_addr: [66, 87, 247, 183, 139, 227, 187, 185, 147, 188, 228, 171, 89, 50, 198, 181, 249, 92, 139, 114, 49, 17, 111, 191, 145, 5, 84, 204, 190, 174, 36, 0, 224, 9, 76, 117, 226, 198, 32, 247, 238, 245, 182, 73, 7, 239, 26, 25, 14, 62, 110, 34, 88, 156, 78, 118, 223, 127, 36, 229, 50, 96, 248, 145, 41, 80, 135, 169, 195, 101, 215, 24, 8, 24] } 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/net/ipv4_header.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc fc12b54abbe610c4344c9f792ab4c501830e658c699e926cebafc50e5c156975 # shrinks to source_ip = [0, 0, 0, 0], dest_ip = [0, 0, 0, 0], ttl = 0, ok_payload_len = 0, err_payload_len = 65516 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/packet_filters.rs.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc 0fd0278a04b30a10d618763c0c03f610dbeaec3661b8f264590f673be5363846 # shrinks to ref ipv4 = Ipv4Header { ihl: 11, differentiated_services_code_point: 0, explicit_congestion_notification: 0, payload_len: 0, identification: 0, dont_fragment: false, more_fragments: false, fragments_offset: 0, time_to_live: 0, protocol: 49, header_checksum: 0, source: [0, 0, 0, 0], destination: [0, 0, 0, 0], options: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 238, 161, 238, 54, 33, 252, 165, 192, 37] }, ref ipv6 = Ipv6Header { traffic_class: 233, flow_label: 974616, payload_length: 44475, next_header: 235, hop_limit: 186, source: [145, 233, 192, 110, 139, 99, 37, 92, 244, 136, 22, 106, 192, 236, 204, 158], destination: [217, 167, 1, 43, 51, 177, 255, 124, 199, 126, 68, 131, 107, 116, 242, 151] } 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/sliced_packet.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc b196b71d1fd361e0dc02078dcedaa8e67bb496f2cb76ceddd1fa51ce90c70f6d # shrinks to ref eth = Ethernet2Header { source: [0, 0, 0, 0, 0, 0], destination: [0, 0, 0, 0, 0, 0], ether_type: 0x0000 }, ref linux_sll = LinuxSllHeader { packet_type: 0 (Sent to us), arp_hrd_type: 824 (Netlink header), sender_address_valid_length: 0, sender_address: [0, 0, 0, 0, 0, 0, 0, 0], protocol_type: NetlinkProtocolType(0) }, ref vlan_outer = SingleVlanHeader { pcp: VlanPcp(0), drop_eligible_indicator: false, vlan_id: VlanId(0), ether_type: 0x0000 }, ref vlan_inner = SingleVlanHeader { pcp: VlanPcp(0), drop_eligible_indicator: false, vlan_id: VlanId(0), ether_type: 0x0000 }, ref ipv4 = Ipv4Header { dscp: Ipv4Dscp(0), ecn: Ipv4Ecn(0), total_len: 60781, identification: 0, dont_fragment: false, more_fragments: false, fragment_offset: IpFragOffset(0), time_to_live: 0, protocol: 253 (Use for experimentation and testing), header_checksum: 128, source: [0, 0, 0, 0], destination: [0, 0, 0, 0], options: [] }, ref udp = UdpHeader { source_port: 24402, destination_port: 23948, length: 49051, checksum: 43062 } 8 | cc c9232de04a5ac1b216ee2a446fc52503748be2b45c1d1622e9775e408e371b05 # shrinks to ref eth = Ethernet2Header { source: [0, 0, 0, 0, 0, 0], destination: [0, 0, 0, 0, 0, 0], ether_type: 0x0000 }, ref linux_sll = LinuxSllHeader { packet_type: 0 (Sent to us), arp_hrd_type: 824 (Netlink header), sender_address_valid_length: 0, sender_address: [0, 0, 0, 0, 0, 0, 0, 0], protocol_type: NetlinkProtocolType(0) }, ref vlan_outer = SingleVlanHeader { pcp: VlanPcp(0), drop_eligible_indicator: false, vlan_id: VlanId(0), ether_type: 0x0000 }, ref vlan_inner = SingleVlanHeader { pcp: VlanPcp(0), drop_eligible_indicator: false, vlan_id: VlanId(0), ether_type: 0x88E5 (IEEE Std 802.1AE - Media Access Control Security) }, ref ipv4 = Ipv4Header { dscp: Ipv4Dscp(0), ecn: Ipv4Ecn(0), total_len: 116, identification: 0, dont_fragment: false, more_fragments: false, fragment_offset: IpFragOffset(0), time_to_live: 0, protocol: 249, header_checksum: 0, source: [0, 0, 0, 0], destination: [0, 0, 0, 0], options: [] }, ref udp = UdpHeader { source_port: 31477, destination_port: 47928, length: 514, checksum: 40807 } 9 | cc c63a66c0c25668d61d2b797e8999efbb3b360389e87888b75b713bffee230ae4 # shrinks to ref eth = Ethernet2Header { source: [0, 0, 0, 0, 0, 0], destination: [0, 0, 0, 0, 0, 0], ether_type: 0x0000 }, ether_type = 0x0001, ref linux_sll = LinuxSllHeader { packet_type: 0 (Sent to us), arp_hrd_type: 824 (Netlink header), sender_address_valid_length: 0, sender_address: [0, 0, 0, 0, 0, 0, 0, 0], protocol_type: NetlinkProtocolType(0) }, ref vlan_outer = SingleVlanHeader { pcp: VlanPcp(0), drop_eligible_indicator: false, vlan_id: VlanId(0), ether_type: 0x0000 }, ref vlan_inner = SingleVlanHeader { pcp: VlanPcp(0), drop_eligible_indicator: false, vlan_id: VlanId(0), ether_type: 0x0000 }, ref macsec = MacsecHeader { ptype: Unmodified(0x0000), endstation_id: false, scb: false, an: MacsecAn(0), short_len: MacsecShortLen(0), packet_nr: 0, sci: None }, ref ipv4 = Ipv4Header { dscp: Ipv4Dscp(0), ecn: Ipv4Ecn(0), total_len: 42578, identification: 0, dont_fragment: true, more_fragments: true, fragment_offset: IpFragOffset(8186), time_to_live: 4, protocol: 245, header_checksum: 48900, source: [0, 0, 0, 0], destination: [0, 0, 0, 0], options: [] }, ref udp = UdpHeader { source_port: 6925, destination_port: 44508, length: 6037, checksum: 64107 } 10 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/transport/icmpv4_header.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc bc7b6196699451faa703284f9b393d235597bea7e4f33f227699c1e9e528af37 # shrinks to icmpv4_type = EchoReply(IcmpEchoHeader { id: 0, seq: 0 }), checksum = 0, payload = [] 8 | cc 42e7dbb3e46ac694fc7e996489af2d734b30e753db2fee99cda10dc8e570f4aa # shrinks to icmpv4_type = TimestampRequest(TimestampMessage { id: 0, seq: 0, originate_timestamp: 0, receive_timestamp: 0, transmit_timestamp: 0 }), checksum = 0, payload = [] 9 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/transport/icmpv6_header.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc ffd752a46c404037c472aa01b1a5c7f98b20118e42015c09b100a9b9b64d8696 # shrinks to ip_header = Ipv6Header { traffic_class: 217, flow_label: Ipv6FlowLabel(981108), payload_length: 16434, next_header: 2 (IGMP - Internet Group Management), hop_limit: 189, source: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], destination: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 137, 251, 239] }, icmp_type = Unknown { type_u8: 244, code_u8: 110, bytes5to8: [15, 190, 118, 169] }, start_checksum = 18835, bad_len = 5027843371569756216, payload = [98, 191, 45, 21, 55, 95, 238, 218, 192, 43, 50, 110, 99, 18, 104, 210, 39, 176, 84, 62, 205, 10, 202, 59, 83, 156, 164, 3, 99, 232, 248, 212, 137, 55, 198, 189, 93, 54, 126, 216, 216, 112, 234, 255, 79, 53, 65, 252, 183, 175, 168, 92, 8, 21] 8 | cc 2765acd850616df4c2fce5d30cb2eba2465db3359ca143e22a1c34f37ce9f14a # shrinks to ip_header = Ipv6Header { traffic_class: 127, flow_label: Ipv6FlowLabel(773565), payload_length: 40939, next_header: 8 (EGP - Exterior Gateway Protocol), hop_limit: 223, source: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], destination: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 65] }, icmp_type = Unknown { type_u8: 181, code_u8: 54, bytes5to8: [152, 109, 154, 4] }, bad_len = 17253463390686651414, payload = [4, 100, 149, 243, 177, 68, 90, 66, 162, 111, 235, 43, 130, 47, 18, 75, 75, 244, 74, 42, 208, 50, 192, 194, 35, 174, 201, 34, 99, 203, 50, 1, 87, 66, 238, 121, 228, 230, 15, 124, 26, 66, 167, 19, 73, 173, 172, 196, 20, 53, 244, 164, 169, 155, 204, 201, 220, 171, 185, 245, 156, 140, 53, 193, 238, 220, 37, 132, 104, 228, 195, 184, 205, 24, 188, 69, 169, 199, 36, 123, 24, 249, 34, 194, 54, 48, 43, 137, 108, 171, 0, 209, 145, 37, 196, 27, 231, 131, 142, 238, 222, 27, 209, 103, 206, 7, 165, 230, 242, 110, 189, 42, 151, 105, 173, 14, 172, 89, 234, 33, 140, 8, 227, 254, 190, 211, 211, 128, 162, 230, 80, 229, 58, 113, 66, 122, 27, 159, 17, 52, 72, 169, 113, 254, 142, 123, 67, 160, 194, 231, 166, 17, 33, 158, 224, 99, 160, 134, 141, 4, 134, 208, 213, 67, 26, 171, 252, 238, 112, 210, 12, 218, 99, 84, 208, 190, 251, 77, 116, 214, 232, 41, 183, 78, 23, 21, 178, 76, 206, 167, 127, 129, 62, 161, 114, 17, 201, 126, 68, 126, 145, 66, 100, 65, 94, 88, 184, 100, 12, 93, 73, 231, 120, 225, 255, 155, 80, 109, 77, 43, 164, 180, 121, 91, 118, 48, 226, 90, 25, 181, 17, 175, 123, 132, 65, 208, 171, 15, 72, 75, 79, 69, 160, 100, 160, 49, 211, 126, 251, 136, 191, 204, 64, 63, 49, 204, 72, 115, 75, 141, 191, 187, 13, 159, 178, 133, 6, 236, 173, 230, 42, 255, 133, 22, 35, 159, 19, 27, 89, 17, 233, 91, 217, 223, 247, 230, 26, 67, 246, 79, 74, 147, 68, 206, 203, 203, 9, 228, 108, 239, 208, 221, 52, 15, 126, 69, 153, 81, 45, 139, 203, 103, 204, 226, 214, 203, 122, 98, 18, 245, 131, 33, 89, 204, 187, 23, 39, 30, 158, 16, 223, 254, 162, 105, 71, 101, 156, 24, 28, 79, 158, 90, 28, 127, 130, 238, 26, 81, 225, 162, 132, 125] 9 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/transport/tcp_header.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc 31b0fb089633c48a18726ea1da4fe4e9163f6e2921fdc1499a9bba9f37feaf4d # shrinks to header = TcpHeader { source_port: 0, destination_port: 0, sequence_number: 0, acknowledgment_number: 0, data_offset: 6, ns: false, fin: false, syn: false, rst: false, psh: false, ack: false, urg: false, ece: false, cwr: false, window_size: 0, checksum: 11, urgent_pointer: 16871, options: [Err(UnknownId(152))] } 8 | cc d2a8fca62107cbf941adb1976c9dce7a75c0191dd8c36c55032136867b1ab282 # shrinks to header = TcpHeader { source_port: 0, destination_port: 0, sequence_number: 0, acknowledgment_number: 2, data_offset: 6, ns: false, fin: true, syn: true, rst: false, psh: true, ack: false, urg: true, ece: false, cwr: false, window_size: 36889, checksum: 6852, urgent_pointer: 48998, options: [Err(UnknownId(60))] } 9 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/transport/tcp_header_slice.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc e7c41816b38346ff44b21bdc756a29f36f2e1d38d62cabb90566f350949817c4 # shrinks to header = TcpHeader { source_port: 0, destination_port: 0, sequence_number: 394338, acknowledgment_number: 2141047503, ns: false, fin: false, syn: false, rst: false, psh: true, ack: false, urg: false, ece: false, cwr: true, window_size: 30412, checksum: 30779, urgent_pointer: 12128, options: [] } 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/transport/tcp_options.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc 16837f46966cc3eb7b6c37c8fe755bc83b89533f9489b42983d8f4e2f25ca913 # shrinks to options = [] 8 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/transport/tcp_slice.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc 3429dff6dbc595ae082d1cc437e3798ffde5f09424b9f1e3b2c496b70a5009f7 # shrinks to tcp = TcpHeader { source_port: 0, destination_port: 0, sequence_number: 0, acknowledgment_number: 0, ns: false, fin: false, syn: false, rst: false, psh: false, ack: false, urg: false, ece: false, cwr: false, window_size: 0, checksum: 0, urgent_pointer: 0, options: [] } 8 | cc 3a4466de4451685da5af95d84271cf94711e9f349721c2e535c3cfb8dfcce42b # shrinks to tcp = TcpHeader { source_port: 0, destination_port: 0, sequence_number: 0, acknowledgment_number: 0, ns: false, fin: false, syn: false, rst: false, psh: false, ack: false, urg: false, ece: false, cwr: false, window_size: 0, checksum: 0, urgent_pointer: 0, options: [] } 9 | cc 36e04f7e28d57b5b7c5b56bffe5cfef4108cb48c3406267b9f7ac6e59c9d154d # shrinks to tcp = TcpHeader { source_port: 0, destination_port: 0, sequence_number: 0, acknowledgment_number: 0, ns: false, fin: false, syn: false, rst: false, psh: false, ack: false, urg: false, ece: false, cwr: false, window_size: 0, checksum: 0, urgent_pointer: 0, options: [] } 10 | cc eab44d2ba159a270c4d6efede60141d39b52c55225c27ee475235df1314c2751 # shrinks to tcp = TcpHeader { source_port: 0, destination_port: 0, sequence_number: 0, acknowledgment_number: 0, ns: false, fin: false, syn: false, rst: false, psh: false, ack: false, urg: false, ece: false, cwr: false, window_size: 0, checksum: 0, urgent_pointer: 0, options: [] } 11 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/transport/transport_header.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc bea28b0e26af0e201236a15cd393aca1f8a94b70de66dd675cb35283abbba161 # shrinks to ipv4 = Ipv4Header { dscp: Ipv4Dscp(44), ecn: Ipv4Ecn(2), total_len: 35493, identification: 38923, dont_fragment: false, more_fragments: false, fragment_offset: IpFragOffset(4491), time_to_live: 157, protocol: 95 (MICP (deprecated) - Mobile Internetworking Control Pro.), header_checksum: 42512, source: [0, 0, 0, 0], destination: [5, 90, 100, 61], options: [] }, udp = UdpHeader { source_port: 28436, destination_port: 576, length: 42868, checksum: 57008 }, tcp = TcpHeader { source_port: 33227, destination_port: 16188, sequence_number: 2098146184, acknowledgment_number: 963144137, data_offset: 5, ns: true, fin: true, syn: false, rst: false, psh: false, ack: true, urg: false, ece: false, cwr: true, window_size: 17323, checksum: 15303, urgent_pointer: 22752, options: [] }, icmpv4 = Icmpv4Header { icmp_type: Unknown { type_u8: 252, code_u8: 154, bytes5to8: [196, 196, 233, 94] }, checksum: 61125 }, icmpv6 = Icmpv6Header { icmp_type: Unknown { type_u8: 187, code_u8: 225, bytes5to8: [172, 176, 129, 161] }, checksum: 53431 } 8 | cc a2e9a50ed8bae611d487c399db98a675694df83e5d3d706a84a3c68abc90c303 # shrinks to ipv6 = Ipv6Header { traffic_class: 148, flow_label: Ipv6FlowLabel(494246), payload_length: 8442, next_header: 20 (HMP - Host Monitoring), hop_limit: 228, source: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], destination: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1] }, udp = UdpHeader { source_port: 24006, destination_port: 15797, length: 46422, checksum: 30229 }, tcp = TcpHeader { source_port: 48728, destination_port: 46298, sequence_number: 4167087310, acknowledgment_number: 3560287757, data_offset: 13, ns: true, fin: false, syn: true, rst: true, psh: false, ack: true, urg: false, ece: true, cwr: true, window_size: 28234, checksum: 27234, urgent_pointer: 49127, options: [Err(UnknownId(118))] }, icmpv4 = Icmpv4Header { icmp_type: Unknown { type_u8: 9, code_u8: 191, bytes5to8: [200, 204, 140, 178] }, checksum: 24840 }, icmpv6 = Icmpv6Header { icmp_type: Unknown { type_u8: 35, code_u8: 74, bytes5to8: [138, 73, 230, 137] }, checksum: 63947 } 9 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/transport/udp_header.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc 33a7fb51312ea17d9481182a3c9ac5b79b768564ee007129565e05b1af374cda # shrinks to source_port = 0, destination_port = 0, dummy_checksum = 0, ipv4 = Ipv4Header { dscp: Ipv4Dscp(27), ecn: Ipv4Ecn(2), total_len: 2020, identification: 17171, dont_fragment: false, more_fragments: false, fragment_offset: IpFragOffset(5617), time_to_live: 43, protocol: 223, header_checksum: 55616, source: [199, 143, 81, 185], destination: [178, 183, 108, 161], options: [] }, payload = [50, 40, 103, 182, 130, 191, 69, 120, 36, 125, 61, 174, 10, 18, 139, 72, 223, 100, 31], bad_len = 2705066850224624139 8 | cc 292410f71c257b6ae77f9b3a4ee37003b2447999e104b371d42bffb4f9cb0edb # shrinks to source_port = 0, destination_port = 0, dummy_checksum = 0, ipv6 = Ipv6Header { traffic_class: 192, flow_label: Ipv6FlowLabel(272844), payload_length: 35736, next_header: 19 (DCN-MEAS - DCN Measurement Subsystems), hop_limit: 24, source: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], destination: [0, 0, 0, 0, 0, 1, 104, 215, 211, 202, 179, 244, 153, 59, 51, 20] }, payload = [241, 32, 93, 159, 140, 158, 174, 121, 38, 113, 42, 223, 24], bad_len = 17475589487341371523 9 | -------------------------------------------------------------------------------- /etherparse/proptest-regressions/transport/udp_slice.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc 32283d8802a47cec4259af38383590cd01e11af6dce16c620b67ea18f433eceb # shrinks to udp_base = UdpHeader { source_port: 0, destination_port: 0, length: 0, checksum: 0 } 8 | -------------------------------------------------------------------------------- /etherparse/src/defrag/ip_defrag_payload_vec.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | use std::vec::Vec; 3 | 4 | /// Payload of an IP packet. 5 | #[derive(Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)] 6 | pub struct IpDefragPayloadVec { 7 | /// Identifying content of the payload. 8 | pub ip_number: IpNumber, 9 | 10 | /// Length field that was used to determine the length 11 | /// of the payload (e.g. IPv6 "payload_length" field). 12 | pub len_source: LenSource, 13 | 14 | /// Payload 15 | pub payload: Vec, 16 | } 17 | 18 | #[cfg(test)] 19 | mod test { 20 | use super::*; 21 | use std::{format, vec}; 22 | 23 | #[test] 24 | fn debug() { 25 | let s = IpDefragPayloadVec { 26 | ip_number: IpNumber::UDP, 27 | len_source: LenSource::Slice, 28 | payload: vec![], 29 | }; 30 | assert_eq!( 31 | format!( 32 | "IpDefragPayloadVec {{ ip_number: {:?}, len_source: {:?}, payload: {:?} }}", 33 | s.ip_number, s.len_source, s.payload 34 | ), 35 | format!("{:?}", s) 36 | ); 37 | } 38 | 39 | #[test] 40 | fn clone_eq_hash_ord() { 41 | let s = IpDefragPayloadVec { 42 | ip_number: IpNumber::UDP, 43 | len_source: LenSource::Slice, 44 | payload: vec![], 45 | }; 46 | assert_eq!(s.clone(), s); 47 | 48 | use std::collections::hash_map::DefaultHasher; 49 | use std::hash::{Hash, Hasher}; 50 | 51 | let a_hash = { 52 | let mut hasher = DefaultHasher::new(); 53 | s.hash(&mut hasher); 54 | hasher.finish() 55 | }; 56 | let b_hash = { 57 | let mut hasher = DefaultHasher::new(); 58 | s.clone().hash(&mut hasher); 59 | hasher.finish() 60 | }; 61 | assert_eq!(a_hash, b_hash); 62 | 63 | use std::cmp::Ordering; 64 | assert_eq!(s.clone().cmp(&s), Ordering::Equal); 65 | assert_eq!(s.clone().partial_cmp(&s), Some(Ordering::Equal)); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /etherparse/src/defrag/ip_frag_id.rs: -------------------------------------------------------------------------------- 1 | use crate::{defrag::*, *}; 2 | use arrayvec::ArrayVec; 3 | 4 | /// Values identifying a fragmented packet. 5 | #[derive(Debug, Clone, Hash, Eq, PartialEq)] 6 | pub struct IpFragId 7 | where 8 | CustomChannelId: core::hash::Hash + Eq + PartialEq + Clone + Sized, 9 | { 10 | /// VLAN id's of the original packets. 11 | pub vlan_ids: ArrayVec, 12 | 13 | /// IP source & destination address & identifaction field. 14 | pub ip: IpFragVersionSpecId, 15 | 16 | /// IP number of the payload. 17 | pub payload_ip_number: IpNumber, 18 | 19 | /// Custom user defined channel identifier (can be used to differentiate packet 20 | /// sources if the normal ethernet packets identifier are not enough). 21 | pub channel_id: CustomChannelId, 22 | } 23 | -------------------------------------------------------------------------------- /etherparse/src/defrag/ip_frag_range.rs: -------------------------------------------------------------------------------- 1 | /// Describing the range of reconstructed data. 2 | #[derive(Debug, Copy, Clone, Eq, Hash, PartialEq, Ord, PartialOrd)] 3 | pub struct IpFragRange { 4 | /// Offset of section 5 | pub start: u16, 6 | /// Offset + length of section 7 | pub end: u16, 8 | } 9 | 10 | impl IpFragRange { 11 | /// Return if the value is contained within the section. 12 | fn is_value_connected(&self, value: u16) -> bool { 13 | self.start <= value && self.end >= value 14 | } 15 | 16 | /// Combine both sections if possible. 17 | pub fn merge(&self, other: IpFragRange) -> Option { 18 | if self.is_value_connected(other.start) 19 | || self.is_value_connected(other.end) 20 | || other.is_value_connected(self.start) 21 | || other.is_value_connected(self.end) 22 | { 23 | Some(IpFragRange { 24 | start: core::cmp::min(self.start, other.start), 25 | end: core::cmp::max(self.end, other.end), 26 | }) 27 | } else { 28 | None 29 | } 30 | } 31 | } 32 | 33 | #[cfg(test)] 34 | mod test { 35 | use super::*; 36 | use alloc::format; 37 | 38 | #[test] 39 | fn debug_clone_eq() { 40 | let section = IpFragRange { start: 1, end: 2 }; 41 | let _ = format!("{:?}", section); 42 | assert_eq!(section, section.clone()); 43 | assert_eq!(section.cmp(§ion), core::cmp::Ordering::Equal); 44 | assert_eq!( 45 | section.partial_cmp(§ion), 46 | Some(core::cmp::Ordering::Equal) 47 | ); 48 | 49 | use core::hash::{Hash, Hasher}; 50 | use std::collections::hash_map::DefaultHasher; 51 | let h1 = { 52 | let mut h = DefaultHasher::new(); 53 | section.hash(&mut h); 54 | h.finish() 55 | }; 56 | let h2 = { 57 | let mut h = DefaultHasher::new(); 58 | section.clone().hash(&mut h); 59 | h.finish() 60 | }; 61 | assert_eq!(h1, h2); 62 | } 63 | 64 | #[test] 65 | fn is_value_connected() { 66 | let s = IpFragRange { start: 5, end: 9 }; 67 | assert_eq!(false, s.is_value_connected(3)); 68 | assert_eq!(false, s.is_value_connected(4)); 69 | assert!(s.is_value_connected(5)); 70 | assert!(s.is_value_connected(6)); 71 | assert!(s.is_value_connected(7)); 72 | assert!(s.is_value_connected(8)); 73 | assert!(s.is_value_connected(9)); 74 | assert_eq!(false, s.is_value_connected(10)); 75 | assert_eq!(false, s.is_value_connected(11)); 76 | } 77 | 78 | #[test] 79 | fn merge() { 80 | let tests = [ 81 | ((0, 1), (1, 2), Some((0, 2))), 82 | ((0, 1), (2, 3), None), 83 | ((3, 7), (1, 2), None), 84 | ((3, 7), (1, 3), Some((1, 7))), 85 | ((3, 7), (1, 4), Some((1, 7))), 86 | ((3, 7), (1, 5), Some((1, 7))), 87 | ((3, 7), (1, 6), Some((1, 7))), 88 | ((3, 7), (1, 7), Some((1, 7))), 89 | ((3, 7), (1, 8), Some((1, 8))), 90 | ]; 91 | for t in tests { 92 | let a = IpFragRange { 93 | start: t.0 .0, 94 | end: t.0 .1, 95 | }; 96 | let b = IpFragRange { 97 | start: t.1 .0, 98 | end: t.1 .1, 99 | }; 100 | let expected = t.2.map(|v| IpFragRange { 101 | start: v.0, 102 | end: v.1, 103 | }); 104 | assert_eq!(a.merge(b), expected); 105 | assert_eq!(b.merge(a), expected); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /etherparse/src/defrag/ip_frag_version_spec_id.rs: -------------------------------------------------------------------------------- 1 | /// IPv4 & IPv6 specific fragment identifying information. 2 | #[derive(Debug, Clone, Hash, Eq, PartialEq)] 3 | pub enum IpFragVersionSpecId { 4 | /// IPv4 specific data. 5 | Ipv4 { 6 | source: [u8; 4], 7 | destination: [u8; 4], 8 | identification: u16, 9 | }, 10 | /// IPv6 specific data. 11 | Ipv6 { 12 | source: [u8; 16], 13 | destination: [u8; 16], 14 | identification: u32, 15 | }, 16 | } 17 | -------------------------------------------------------------------------------- /etherparse/src/defrag/mod.rs: -------------------------------------------------------------------------------- 1 | mod ip_defrag_buf; 2 | pub use ip_defrag_buf::*; 3 | 4 | mod ip_defrag_error; 5 | pub use ip_defrag_error::*; 6 | 7 | mod ip_defrag_payload_vec; 8 | pub use ip_defrag_payload_vec::*; 9 | 10 | mod ip_defrag_pool; 11 | pub use ip_defrag_pool::*; 12 | 13 | mod ip_frag_id; 14 | pub use ip_frag_id::*; 15 | 16 | mod ip_frag_range; 17 | pub use ip_frag_range::*; 18 | 19 | mod ip_frag_version_spec_id; 20 | pub use ip_frag_version_spec_id::*; 21 | 22 | /// Maximum length of a defragmented packet as [`u16`]. 23 | pub const MAX_IP_DEFRAG_LEN_U16: u16 = u16::MAX; 24 | 25 | /// Maximum length of a defragmented packet as [`usize`]. 26 | pub const MAX_IP_DEFRAG_LEN: usize = MAX_IP_DEFRAG_LEN_U16 as usize; 27 | -------------------------------------------------------------------------------- /etherparse/src/err/arp/arp_eth_ipv4_from_error.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | 3 | /// Error while converting an [`crate::ArpPacket`] to an [`crate::ArpEthIpv4Packet`]. 4 | #[derive(Debug, Clone, Eq, PartialEq, Hash)] 5 | pub enum ArpEthIpv4FromError { 6 | /// Error if `hw_addr_type` is not [`crate::ArpHardwareId::ETHERNET`]. 7 | NonMatchingHwType(ArpHardwareId), 8 | 9 | /// Error if `proto_addr_type` is not [`crate::EtherType::IPV4`]. 10 | NonMatchingProtocolType(EtherType), 11 | 12 | /// Error if `hw_addr_size` is not `6` 13 | NonMatchingHwAddrSize(u8), 14 | 15 | /// Error if `hw_addr_size` is not `6` 16 | NonMatchingProtoAddrSize(u8), 17 | } 18 | 19 | impl core::fmt::Display for ArpEthIpv4FromError { 20 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 21 | match self { 22 | ArpEthIpv4FromError::NonMatchingHwType(t) => 23 | write!(f, "Hardware address type is expected to have the type '1 (Ethernet)' but is '{t:?}'"), 24 | ArpEthIpv4FromError::NonMatchingProtocolType(t) => 25 | write!(f, "Protocol address type is expected to have the type '0x0800 (Internet Protocol version 4 (IPv4))' but is '{t:?}'"), 26 | ArpEthIpv4FromError::NonMatchingHwAddrSize(len) => 27 | write!(f, "Hardware address size is expected to be 6 but is {len}"), 28 | ArpEthIpv4FromError::NonMatchingProtoAddrSize(len) => 29 | write!(f, "Protocol address size is expected to be 4 but is {len}"), 30 | } 31 | } 32 | } 33 | 34 | #[cfg(feature = "std")] 35 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 36 | impl std::error::Error for ArpEthIpv4FromError { 37 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 38 | None 39 | } 40 | } 41 | 42 | #[cfg(test)] 43 | mod tests { 44 | use super::{ArpEthIpv4FromError::*, ArpHardwareId, EtherType}; 45 | use alloc::format; 46 | use std::{ 47 | collections::hash_map::DefaultHasher, 48 | error::Error, 49 | hash::{Hash, Hasher}, 50 | }; 51 | 52 | #[test] 53 | fn debug() { 54 | assert_eq!( 55 | "NonMatchingProtoAddrSize(3)", 56 | format!("{:?}", NonMatchingProtoAddrSize(3)) 57 | ); 58 | } 59 | 60 | #[test] 61 | fn clone_eq_hash() { 62 | let err = NonMatchingProtoAddrSize(3); 63 | assert_eq!(err, err.clone()); 64 | let hash_a = { 65 | let mut hasher = DefaultHasher::new(); 66 | err.hash(&mut hasher); 67 | hasher.finish() 68 | }; 69 | let hash_b = { 70 | let mut hasher = DefaultHasher::new(); 71 | err.clone().hash(&mut hasher); 72 | hasher.finish() 73 | }; 74 | assert_eq!(hash_a, hash_b); 75 | } 76 | 77 | #[test] 78 | fn fmt() { 79 | let tests = [ 80 | (NonMatchingHwType(ArpHardwareId::CHAOS), "Hardware address type is expected to have the type '1 (Ethernet)' but is '5 (Chaosnet)'"), 81 | (NonMatchingProtocolType(EtherType::IPV6), "Protocol address type is expected to have the type '0x0800 (Internet Protocol version 4 (IPv4))' but is '0x86DD (Internet Protocol Version 6 (IPV6))'"), 82 | (NonMatchingHwAddrSize(21), "Hardware address size is expected to be 6 but is 21"), 83 | (NonMatchingProtoAddrSize(22), "Protocol address size is expected to be 4 but is 22") 84 | ]; 85 | for test in tests { 86 | assert_eq!(format!("{}", test.0), test.1); 87 | } 88 | } 89 | 90 | #[cfg(feature = "std")] 91 | #[test] 92 | fn source() { 93 | assert!(NonMatchingProtoAddrSize(3).source().is_none()); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /etherparse/src/err/arp/arp_hw_addr_error.rs: -------------------------------------------------------------------------------- 1 | /// Error in the hardware addresses when creating an [`crate::ArpPacket`] or 2 | /// changing the hardware addresses in an [`crate::ArpPacket`]. 3 | #[derive(Debug, Clone, Eq, PartialEq, Hash)] 4 | pub enum ArpHwAddrError { 5 | /// Error if the given hardware address is longer than 6 | /// the maximum of 255 bytes/octets. 7 | LenTooBig(usize), 8 | 9 | /// Hardware address lengths of sender and target differ. 10 | LenNonMatching(usize, usize), 11 | } 12 | 13 | impl core::fmt::Display for ArpHwAddrError { 14 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 15 | match self { 16 | ArpHwAddrError::LenTooBig(len) => 17 | write!(f, "ARP Hardware Address Error: Given hardware address has a length of {len} which is greater then the maximum of 255."), 18 | ArpHwAddrError::LenNonMatching(len_sender, len_target) => 19 | write!(f, "ARP Hardware Address Error: Given sender & target hardware addresses have differing lengths of {len_sender} & {len_target} (must be matching)."), 20 | } 21 | } 22 | } 23 | 24 | #[cfg(feature = "std")] 25 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 26 | impl std::error::Error for ArpHwAddrError { 27 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 28 | None 29 | } 30 | } 31 | 32 | #[cfg(test)] 33 | mod tests { 34 | use super::ArpHwAddrError::*; 35 | use alloc::format; 36 | use std::{ 37 | collections::hash_map::DefaultHasher, 38 | error::Error, 39 | hash::{Hash, Hasher}, 40 | }; 41 | 42 | #[test] 43 | fn debug() { 44 | assert_eq!("LenTooBig(300)", format!("{:?}", LenTooBig(300))); 45 | } 46 | 47 | #[test] 48 | fn clone_eq_hash() { 49 | let err = LenTooBig(300); 50 | assert_eq!(err, err.clone()); 51 | let hash_a = { 52 | let mut hasher = DefaultHasher::new(); 53 | err.hash(&mut hasher); 54 | hasher.finish() 55 | }; 56 | let hash_b = { 57 | let mut hasher = DefaultHasher::new(); 58 | err.clone().hash(&mut hasher); 59 | hasher.finish() 60 | }; 61 | assert_eq!(hash_a, hash_b); 62 | } 63 | 64 | #[test] 65 | fn fmt() { 66 | let tests = [ 67 | (LenTooBig(300), "ARP Hardware Address Error: Given hardware address has a length of 300 which is greater then the maximum of 255."), 68 | (LenNonMatching(21, 22), "ARP Hardware Address Error: Given sender & target hardware addresses have differing lengths of 21 & 22 (must be matching)."), 69 | ]; 70 | for test in tests { 71 | assert_eq!(format!("{}", test.0), test.1); 72 | } 73 | } 74 | 75 | #[cfg(feature = "std")] 76 | #[test] 77 | fn source() { 78 | assert!(LenTooBig(300).source().is_none()); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /etherparse/src/err/arp/arp_new_error.rs: -------------------------------------------------------------------------------- 1 | use super::{ArpHwAddrError, ArpProtoAddrError}; 2 | 3 | /// Error while creating a new [`crate::ArpPacket`]. 4 | #[derive(Debug, Clone, Eq, PartialEq, Hash)] 5 | pub enum ArpNewError { 6 | /// Error in the given hardware addresses. 7 | HwAddr(ArpHwAddrError), 8 | 9 | /// Error in the given protocol addresses. 10 | ProtoAddr(ArpProtoAddrError), 11 | } 12 | 13 | impl core::fmt::Display for ArpNewError { 14 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 15 | match self { 16 | ArpNewError::HwAddr(err) => err.fmt(f), 17 | ArpNewError::ProtoAddr(err) => err.fmt(f), 18 | } 19 | } 20 | } 21 | 22 | #[cfg(feature = "std")] 23 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 24 | impl std::error::Error for ArpNewError { 25 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 26 | None 27 | } 28 | } 29 | 30 | #[cfg(test)] 31 | mod tests { 32 | use crate::err::arp::{ArpHwAddrError, ArpProtoAddrError}; 33 | 34 | use super::ArpNewError::*; 35 | use alloc::format; 36 | use std::{ 37 | collections::hash_map::DefaultHasher, 38 | error::Error, 39 | hash::{Hash, Hasher}, 40 | }; 41 | 42 | #[test] 43 | fn debug() { 44 | assert_eq!( 45 | "HwAddr(LenTooBig(300))", 46 | format!("{:?}", HwAddr(ArpHwAddrError::LenTooBig(300))) 47 | ); 48 | } 49 | 50 | #[test] 51 | fn clone_eq_hash() { 52 | let err = HwAddr(ArpHwAddrError::LenTooBig(300)); 53 | assert_eq!(err, err.clone()); 54 | let hash_a = { 55 | let mut hasher = DefaultHasher::new(); 56 | err.hash(&mut hasher); 57 | hasher.finish() 58 | }; 59 | let hash_b = { 60 | let mut hasher = DefaultHasher::new(); 61 | err.clone().hash(&mut hasher); 62 | hasher.finish() 63 | }; 64 | assert_eq!(hash_a, hash_b); 65 | } 66 | 67 | #[test] 68 | fn fmt() { 69 | let tests = [ 70 | (HwAddr(ArpHwAddrError::LenTooBig(300)), "ARP Hardware Address Error: Given hardware address has a length of 300 which is greater then the maximum of 255."), 71 | (ProtoAddr(ArpProtoAddrError::LenTooBig(301)), "ARP Protocol Address Error: Given protocol address has a length of 301 which is greater then the maximum of 255."), 72 | (HwAddr(ArpHwAddrError::LenNonMatching(21, 22)), "ARP Hardware Address Error: Given sender & target hardware addresses have differing lengths of 21 & 22 (must be matching)."), 73 | (ProtoAddr(ArpProtoAddrError::LenNonMatching(23, 24)), "ARP Protocol Address Error: Given sender & target protocol addresses have differing lengths of 23 & 24 (must be matching).") 74 | ]; 75 | for test in tests { 76 | assert_eq!(format!("{}", test.0), test.1); 77 | } 78 | } 79 | 80 | #[cfg(feature = "std")] 81 | #[test] 82 | fn source() { 83 | assert!(HwAddr(ArpHwAddrError::LenTooBig(300)).source().is_none()); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /etherparse/src/err/arp/arp_proto_addr_error.rs: -------------------------------------------------------------------------------- 1 | /// Error in the protocol addresses when creating an [`crate::ArpPacket`] or 2 | /// changing the protocol addresses in an [`crate::ArpPacket`]. 3 | #[derive(Debug, Clone, Eq, PartialEq, Hash)] 4 | pub enum ArpProtoAddrError { 5 | /// Error if the given protocol address is longer than 6 | /// the maximum of 255 bytes/octets. 7 | LenTooBig(usize), 8 | 9 | /// Protocol address lengths of sender and target differ. 10 | LenNonMatching(usize, usize), 11 | } 12 | 13 | impl core::fmt::Display for ArpProtoAddrError { 14 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 15 | match self { 16 | ArpProtoAddrError::LenTooBig(len) => 17 | write!(f, "ARP Protocol Address Error: Given protocol address has a length of {len} which is greater then the maximum of 255."), 18 | ArpProtoAddrError::LenNonMatching(len_sender, len_target) => 19 | write!(f, "ARP Protocol Address Error: Given sender & target protocol addresses have differing lengths of {len_sender} & {len_target} (must be matching)."), 20 | } 21 | } 22 | } 23 | 24 | #[cfg(feature = "std")] 25 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 26 | impl std::error::Error for ArpProtoAddrError { 27 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 28 | None 29 | } 30 | } 31 | 32 | #[cfg(test)] 33 | mod tests { 34 | use super::ArpProtoAddrError::*; 35 | use alloc::format; 36 | use std::{ 37 | collections::hash_map::DefaultHasher, 38 | error::Error, 39 | hash::{Hash, Hasher}, 40 | }; 41 | 42 | #[test] 43 | fn debug() { 44 | assert_eq!("LenTooBig(300)", format!("{:?}", LenTooBig(300))); 45 | } 46 | 47 | #[test] 48 | fn clone_eq_hash() { 49 | let err = LenTooBig(300); 50 | assert_eq!(err, err.clone()); 51 | let hash_a = { 52 | let mut hasher = DefaultHasher::new(); 53 | err.hash(&mut hasher); 54 | hasher.finish() 55 | }; 56 | let hash_b = { 57 | let mut hasher = DefaultHasher::new(); 58 | err.clone().hash(&mut hasher); 59 | hasher.finish() 60 | }; 61 | assert_eq!(hash_a, hash_b); 62 | } 63 | 64 | #[test] 65 | fn fmt() { 66 | let tests = [ 67 | (LenTooBig(301), "ARP Protocol Address Error: Given protocol address has a length of 301 which is greater then the maximum of 255."), 68 | (LenNonMatching(23, 24), "ARP Protocol Address Error: Given sender & target protocol addresses have differing lengths of 23 & 24 (must be matching).") 69 | ]; 70 | for test in tests { 71 | assert_eq!(format!("{}", test.0), test.1); 72 | } 73 | } 74 | 75 | #[cfg(feature = "std")] 76 | #[test] 77 | fn source() { 78 | assert!(LenTooBig(300).source().is_none()); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /etherparse/src/err/arp/mod.rs: -------------------------------------------------------------------------------- 1 | mod arp_eth_ipv4_from_error; 2 | pub use arp_eth_ipv4_from_error::*; 3 | 4 | mod arp_hw_addr_error; 5 | pub use arp_hw_addr_error::*; 6 | 7 | mod arp_new_error; 8 | pub use arp_new_error::*; 9 | 10 | mod arp_proto_addr_error; 11 | pub use arp_proto_addr_error::*; 12 | -------------------------------------------------------------------------------- /etherparse/src/err/io/mod.rs: -------------------------------------------------------------------------------- 1 | mod limited_read_error; 2 | pub use limited_read_error::*; 3 | -------------------------------------------------------------------------------- /etherparse/src/err/ip/ip_dscp_unknown_value_error.rs: -------------------------------------------------------------------------------- 1 | use core::{cmp::Eq, cmp::PartialEq, fmt::Debug, hash::Hash}; 2 | 3 | /// Error if an unknown value is passed to [`crate::IpDscpKnown::try_from_ip_dscp`]. 4 | #[derive(Clone, Debug, Eq, PartialEq, Hash)] 5 | pub struct IpDscpUnknownValueError { 6 | /// Unknown DSCP value that caused the error. 7 | pub value: u8, 8 | } 9 | 10 | impl core::fmt::Display for IpDscpUnknownValueError { 11 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 12 | write!(f, "Error DSCP value '{}' is not known.", self.value) 13 | } 14 | } 15 | 16 | #[cfg(feature = "std")] 17 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 18 | impl std::error::Error for IpDscpUnknownValueError { 19 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 20 | None 21 | } 22 | } 23 | 24 | #[cfg(test)] 25 | mod test { 26 | use super::*; 27 | use std::{collections::hash_map::DefaultHasher, error::Error, format, hash::Hasher}; 28 | 29 | #[test] 30 | fn fmt() { 31 | assert_eq!( 32 | format!("{}", IpDscpUnknownValueError { value: 3 }), 33 | "Error DSCP value '3' is not known." 34 | ); 35 | } 36 | 37 | #[test] 38 | fn dbg() { 39 | assert_eq!( 40 | format!("{:?}", IpDscpUnknownValueError { value: 3 }), 41 | format!("IpDscpUnknownValueError {{ value: {} }}", 3) 42 | ); 43 | } 44 | 45 | #[test] 46 | fn clone_eq_hash() { 47 | let err = IpDscpUnknownValueError { value: 3 }; 48 | assert_eq!(err, err.clone()); 49 | let hash_a = { 50 | let mut hasher = DefaultHasher::new(); 51 | err.hash(&mut hasher); 52 | hasher.finish() 53 | }; 54 | let hash_b = { 55 | let mut hasher = DefaultHasher::new(); 56 | err.clone().hash(&mut hasher); 57 | hasher.finish() 58 | }; 59 | assert_eq!(hash_a, hash_b); 60 | } 61 | 62 | #[cfg(feature = "std")] 63 | #[test] 64 | fn source() { 65 | assert!(IpDscpUnknownValueError { value: 3 }.source().is_none()); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /etherparse/src/err/ip/mod.rs: -------------------------------------------------------------------------------- 1 | mod header_error; 2 | pub use header_error::*; 3 | 4 | mod headers_error; 5 | pub use headers_error::*; 6 | 7 | #[cfg(feature = "std")] 8 | mod headers_read_error; 9 | #[cfg(feature = "std")] 10 | pub use headers_read_error::*; 11 | 12 | mod headers_slice_error; 13 | pub use headers_slice_error::*; 14 | 15 | #[cfg(feature = "std")] 16 | mod headers_write_error; 17 | #[cfg(feature = "std")] 18 | pub use headers_write_error::*; 19 | 20 | pub mod ip_dscp_unknown_value_error; 21 | pub use ip_dscp_unknown_value_error::*; 22 | 23 | mod lax_header_slice_error; 24 | pub use lax_header_slice_error::*; 25 | 26 | mod slice_error; 27 | pub use slice_error::*; 28 | -------------------------------------------------------------------------------- /etherparse/src/err/ip/slice_error.rs: -------------------------------------------------------------------------------- 1 | use crate::err::{ip, LenError}; 2 | 3 | /// Errors that can occur when slicing the IP part of a packet. 4 | #[derive(Clone, Debug, Eq, PartialEq, Hash)] 5 | pub enum SliceError { 6 | /// Length related errors (e.g. not enough data in slice). 7 | Len(LenError), 8 | 9 | /// Error when decoding an IP header or IP extension header. 10 | IpHeaders(ip::HeadersError), 11 | } 12 | 13 | impl core::fmt::Display for SliceError { 14 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 15 | use SliceError::*; 16 | match self { 17 | Len(err) => err.fmt(f), 18 | IpHeaders(err) => err.fmt(f), 19 | } 20 | } 21 | } 22 | 23 | #[cfg(feature = "std")] 24 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 25 | impl std::error::Error for SliceError { 26 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 27 | use SliceError::*; 28 | match self { 29 | Len(err) => Some(err), 30 | IpHeaders(err) => Some(err), 31 | } 32 | } 33 | } 34 | 35 | #[cfg(test)] 36 | mod tests { 37 | use super::{ 38 | super::{HeaderError::*, HeadersError::*}, 39 | SliceError::*, 40 | }; 41 | use crate::{ 42 | err::{Layer, LenError}, 43 | LenSource, 44 | }; 45 | use alloc::format; 46 | use std::{ 47 | collections::hash_map::DefaultHasher, 48 | error::Error, 49 | hash::{Hash, Hasher}, 50 | }; 51 | 52 | #[test] 53 | fn debug() { 54 | let err = Ip(UnsupportedIpVersion { version_number: 6 }); 55 | assert_eq!( 56 | format!("IpHeaders({:?})", err.clone()), 57 | format!("{:?}", IpHeaders(err)) 58 | ); 59 | } 60 | 61 | #[test] 62 | fn clone_eq_hash() { 63 | let err = IpHeaders(Ip(UnsupportedIpVersion { version_number: 6 })); 64 | assert_eq!(err, err.clone()); 65 | let hash_a = { 66 | let mut hasher = DefaultHasher::new(); 67 | err.hash(&mut hasher); 68 | hasher.finish() 69 | }; 70 | let hash_b = { 71 | let mut hasher = DefaultHasher::new(); 72 | err.clone().hash(&mut hasher); 73 | hasher.finish() 74 | }; 75 | assert_eq!(hash_a, hash_b); 76 | } 77 | 78 | #[test] 79 | fn fmt() { 80 | // len 81 | { 82 | let err = LenError { 83 | required_len: 1, 84 | layer: Layer::Ipv4Packet, 85 | len: 2, 86 | len_source: LenSource::Slice, 87 | layer_start_offset: 3, 88 | }; 89 | assert_eq!(format!("{}", &err), format!("{}", Len(err))); 90 | } 91 | // header 92 | { 93 | let err = Ip(UnsupportedIpVersion { version_number: 6 }); 94 | assert_eq!(format!("{}", &err), format!("{}", IpHeaders(err.clone()))); 95 | } 96 | } 97 | 98 | #[cfg(feature = "std")] 99 | #[test] 100 | fn source() { 101 | assert!(Len(LenError { 102 | required_len: 1, 103 | layer: Layer::Ipv4Packet, 104 | len: 2, 105 | len_source: LenSource::Slice, 106 | layer_start_offset: 3 107 | }) 108 | .source() 109 | .is_some()); 110 | assert!(IpHeaders(Ip(UnsupportedIpVersion { version_number: 6 })) 111 | .source() 112 | .is_some()); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /etherparse/src/err/ip_auth/header_error.rs: -------------------------------------------------------------------------------- 1 | /// Errors that can be encountered while decoding an IP 2 | /// authentication header. 3 | #[derive(Clone, Debug, Eq, PartialEq, Hash)] 4 | pub enum HeaderError { 5 | /// Error when the payload length is zero and therefor 6 | /// too small to contain the minimum fields of the IP 7 | /// authentication itself. 8 | ZeroPayloadLen, 9 | } 10 | 11 | impl core::fmt::Display for HeaderError { 12 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 13 | use HeaderError::*; 14 | match self { 15 | ZeroPayloadLen => write!(f, "IP Authentication Header Error: Payload Length too small (0). The payload length must be at least 1."), 16 | } 17 | } 18 | } 19 | 20 | #[cfg(feature = "std")] 21 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 22 | impl std::error::Error for HeaderError { 23 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 24 | None 25 | } 26 | } 27 | 28 | #[cfg(test)] 29 | mod tests { 30 | use super::HeaderError::*; 31 | use alloc::format; 32 | use std::{ 33 | collections::hash_map::DefaultHasher, 34 | error::Error, 35 | hash::{Hash, Hasher}, 36 | }; 37 | 38 | #[test] 39 | fn debug() { 40 | assert_eq!("ZeroPayloadLen", format!("{:?}", ZeroPayloadLen)); 41 | } 42 | 43 | #[test] 44 | fn clone_eq_hash() { 45 | let err = ZeroPayloadLen; 46 | assert_eq!(err, err.clone()); 47 | let hash_a = { 48 | let mut hasher = DefaultHasher::new(); 49 | err.hash(&mut hasher); 50 | hasher.finish() 51 | }; 52 | let hash_b = { 53 | let mut hasher = DefaultHasher::new(); 54 | err.clone().hash(&mut hasher); 55 | hasher.finish() 56 | }; 57 | assert_eq!(hash_a, hash_b); 58 | } 59 | 60 | #[test] 61 | fn fmt() { 62 | assert_eq!( 63 | "IP Authentication Header Error: Payload Length too small (0). The payload length must be at least 1.", 64 | format!("{}", ZeroPayloadLen) 65 | ); 66 | } 67 | 68 | #[cfg(feature = "std")] 69 | #[test] 70 | fn source() { 71 | assert!(ZeroPayloadLen.source().is_none()); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /etherparse/src/err/ip_auth/icv_len_error.rs: -------------------------------------------------------------------------------- 1 | /// Error when creating an [`crate::IpAuthHeader`] and the 2 | /// length of the raw ICV is non representable in an IP authentication 3 | /// header. 4 | #[derive(Clone, Debug, Eq, PartialEq, Hash)] 5 | pub enum IcvLenError { 6 | /// Error when the payload length is bigger then 7 | /// [`crate::IpAuthHeader::MAX_ICV_LEN`] (1016). 8 | TooBig(usize), 9 | 10 | /// Error when the ICV length can not be represented 11 | /// as a multiple of 4-bytes in the authentication header 12 | /// (`0 == raw_icv.len() % 4` is not fulfilled). 13 | Unaligned(usize), 14 | } 15 | 16 | impl core::fmt::Display for IcvLenError { 17 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 18 | use IcvLenError::*; 19 | match self { 20 | TooBig(size) => 21 | write!(f, "Error the IP authentication header ICV length is too large. The ICV size ({} bytes) is larger then what can be be represented by the 'payload len' field in an IP authentication header.", size), 22 | Unaligned(size) => 23 | write!(f, "Error the IP authentication header ICV length of {} bytes is not a multiple of 4. This is required as the payload length field can only express lengths in multiple of 4 bytes.", size), 24 | } 25 | } 26 | } 27 | 28 | #[cfg(feature = "std")] 29 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 30 | impl std::error::Error for IcvLenError { 31 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 32 | None 33 | } 34 | } 35 | 36 | #[cfg(test)] 37 | mod tests { 38 | use super::IcvLenError::*; 39 | use crate::*; 40 | use alloc::format; 41 | use std::{ 42 | collections::hash_map::DefaultHasher, 43 | error::Error, 44 | hash::{Hash, Hasher}, 45 | }; 46 | 47 | #[test] 48 | fn debug() { 49 | assert_eq!("TooBig(3000)", format!("{:?}", TooBig(3000))); 50 | } 51 | 52 | #[test] 53 | fn clone_eq_hash() { 54 | let err = TooBig(5000); 55 | assert_eq!(err, err.clone()); 56 | let hash_a = { 57 | let mut hasher = DefaultHasher::new(); 58 | err.hash(&mut hasher); 59 | hasher.finish() 60 | }; 61 | let hash_b = { 62 | let mut hasher = DefaultHasher::new(); 63 | err.clone().hash(&mut hasher); 64 | hasher.finish() 65 | }; 66 | assert_eq!(hash_a, hash_b); 67 | } 68 | 69 | #[test] 70 | fn fmt() { 71 | assert_eq!( 72 | "Error the IP authentication header ICV length is too large. The ICV size (4000 bytes) is larger then what can be be represented by the 'payload len' field in an IP authentication header.", 73 | format!("{}", TooBig(4000)) 74 | ); 75 | assert_eq!( 76 | "Error the IP authentication header ICV length of 12 bytes is not a multiple of 4. This is required as the payload length field can only express lengths in multiple of 4 bytes.", 77 | format!("{}", Unaligned(12)) 78 | ); 79 | } 80 | 81 | #[cfg(feature = "std")] 82 | #[test] 83 | fn source() { 84 | assert!(TooBig(4000).source().is_none()); 85 | assert!(Unaligned(12).source().is_none()); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /etherparse/src/err/ip_auth/mod.rs: -------------------------------------------------------------------------------- 1 | mod header_error; 2 | pub use header_error::*; 3 | 4 | #[cfg(feature = "std")] 5 | mod header_read_error; 6 | #[cfg(feature = "std")] 7 | pub use header_read_error::*; 8 | 9 | #[cfg(feature = "std")] 10 | mod header_limited_read_error; 11 | #[cfg(feature = "std")] 12 | pub use header_limited_read_error::*; 13 | 14 | mod header_slice_error; 15 | pub use header_slice_error::*; 16 | 17 | mod icv_len_error; 18 | pub use icv_len_error::*; 19 | -------------------------------------------------------------------------------- /etherparse/src/err/ip_exts/exts_walk_error.rs: -------------------------------------------------------------------------------- 1 | use crate::err::{ipv4_exts, ipv6_exts}; 2 | 3 | /// Errors while serializing or determining the next_header of 4 | /// an [`crate::IpHeaders`]. 5 | #[derive(Clone, Debug, Eq, PartialEq, Hash)] 6 | pub enum ExtsWalkError { 7 | /// Error within the IPv4 extensions headers. 8 | Ipv4Exts(ipv4_exts::ExtsWalkError), 9 | 10 | /// Error within the IPv6 extensions headers. 11 | Ipv6Exts(ipv6_exts::ExtsWalkError), 12 | } 13 | 14 | impl core::fmt::Display for ExtsWalkError { 15 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 16 | use ExtsWalkError::*; 17 | match self { 18 | Ipv4Exts(err) => err.fmt(f), 19 | Ipv6Exts(err) => err.fmt(f), 20 | } 21 | } 22 | } 23 | 24 | #[cfg(feature = "std")] 25 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 26 | impl std::error::Error for ExtsWalkError { 27 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 28 | use ExtsWalkError::*; 29 | match self { 30 | Ipv4Exts(err) => Some(err), 31 | Ipv6Exts(err) => Some(err), 32 | } 33 | } 34 | } 35 | 36 | #[cfg(test)] 37 | mod tests { 38 | use super::{ExtsWalkError::*, *}; 39 | use crate::IpNumber; 40 | use alloc::format; 41 | use std::{ 42 | collections::hash_map::DefaultHasher, 43 | error::Error, 44 | hash::{Hash, Hasher}, 45 | }; 46 | 47 | #[test] 48 | fn debug() { 49 | let err = ipv6_exts::ExtsWalkError::HopByHopNotAtStart; 50 | assert_eq!( 51 | format!("Ipv6Exts({:?})", err.clone()), 52 | format!("{:?}", Ipv6Exts(err)) 53 | ); 54 | } 55 | 56 | #[test] 57 | fn clone_eq_hash() { 58 | let err = Ipv6Exts(ipv6_exts::ExtsWalkError::HopByHopNotAtStart); 59 | assert_eq!(err, err.clone()); 60 | let hash_a = { 61 | let mut hasher = DefaultHasher::new(); 62 | err.hash(&mut hasher); 63 | hasher.finish() 64 | }; 65 | let hash_b = { 66 | let mut hasher = DefaultHasher::new(); 67 | err.clone().hash(&mut hasher); 68 | hasher.finish() 69 | }; 70 | assert_eq!(hash_a, hash_b); 71 | } 72 | 73 | #[test] 74 | fn fmt() { 75 | // Ipv4Exts 76 | { 77 | let err = ipv4_exts::ExtsWalkError::ExtNotReferenced { 78 | missing_ext: IpNumber::AUTHENTICATION_HEADER, 79 | }; 80 | assert_eq!(format!("{}", &err), format!("{}", Ipv4Exts(err))); 81 | } 82 | // Ipv6Exts 83 | { 84 | let err = ipv6_exts::ExtsWalkError::HopByHopNotAtStart; 85 | assert_eq!(format!("{}", &err), format!("{}", Ipv6Exts(err.clone()))); 86 | } 87 | } 88 | 89 | #[cfg(feature = "std")] 90 | #[test] 91 | fn source() { 92 | assert!(Ipv4Exts(ipv4_exts::ExtsWalkError::ExtNotReferenced { 93 | missing_ext: IpNumber::AUTHENTICATION_HEADER 94 | }) 95 | .source() 96 | .is_some()); 97 | assert!(Ipv6Exts(ipv6_exts::ExtsWalkError::HopByHopNotAtStart) 98 | .source() 99 | .is_some()); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /etherparse/src/err/ip_exts/header_error.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | 3 | /// Error when decoding the IP extension header. 4 | #[derive(Clone, Debug, Eq, PartialEq, Hash)] 5 | pub enum HeaderError { 6 | /// Error in the IPv4 extension headers (only authentication header). 7 | Ipv4Ext(err::ip_auth::HeaderError), 8 | 9 | /// Error in the IPv6 extension headers. 10 | Ipv6Ext(err::ipv6_exts::HeaderError), 11 | } 12 | 13 | impl core::fmt::Display for HeaderError { 14 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 15 | use HeaderError::*; 16 | match self { 17 | Ipv4Ext(err) => err.fmt(f), 18 | Ipv6Ext(err) => err.fmt(f), 19 | } 20 | } 21 | } 22 | 23 | #[cfg(feature = "std")] 24 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 25 | impl std::error::Error for HeaderError { 26 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 27 | use HeaderError::*; 28 | match self { 29 | Ipv4Ext(err) => Some(err), 30 | Ipv6Ext(err) => Some(err), 31 | } 32 | } 33 | } 34 | 35 | #[cfg(test)] 36 | mod tests { 37 | use super::{super::HeaderError::*, *}; 38 | use alloc::format; 39 | use std::{ 40 | collections::hash_map::DefaultHasher, 41 | error::Error, 42 | hash::{Hash, Hasher}, 43 | }; 44 | 45 | #[test] 46 | fn debug() { 47 | assert_eq!( 48 | "Ipv4Ext(ZeroPayloadLen)", 49 | format!("{:?}", Ipv4Ext(err::ip_auth::HeaderError::ZeroPayloadLen)) 50 | ); 51 | } 52 | 53 | #[test] 54 | fn clone_eq_hash() { 55 | let err = Ipv4Ext(err::ip_auth::HeaderError::ZeroPayloadLen); 56 | assert_eq!(err, err.clone()); 57 | let hash_a = { 58 | let mut hasher = DefaultHasher::new(); 59 | err.hash(&mut hasher); 60 | hasher.finish() 61 | }; 62 | let hash_b = { 63 | let mut hasher = DefaultHasher::new(); 64 | err.clone().hash(&mut hasher); 65 | hasher.finish() 66 | }; 67 | assert_eq!(hash_a, hash_b); 68 | } 69 | 70 | #[test] 71 | fn fmt() { 72 | { 73 | let err = err::ip_auth::HeaderError::ZeroPayloadLen; 74 | assert_eq!(format!("{}", Ipv4Ext(err.clone())), format!("{}", err)); 75 | } 76 | { 77 | let err = err::ipv6_exts::HeaderError::HopByHopNotAtStart; 78 | assert_eq!(format!("{}", Ipv6Ext(err.clone())), format!("{}", err)); 79 | } 80 | } 81 | 82 | #[cfg(feature = "std")] 83 | #[test] 84 | fn source() { 85 | let values = [ 86 | Ipv4Ext(err::ip_auth::HeaderError::ZeroPayloadLen), 87 | Ipv6Ext(err::ipv6_exts::HeaderError::HopByHopNotAtStart), 88 | ]; 89 | for v in values { 90 | assert!(v.source().is_some()); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /etherparse/src/err/ip_exts/mod.rs: -------------------------------------------------------------------------------- 1 | mod exts_walk_error; 2 | pub use exts_walk_error::*; 3 | 4 | mod header_error; 5 | pub use header_error::*; 6 | 7 | mod headers_slice_error; 8 | pub use headers_slice_error::*; 9 | -------------------------------------------------------------------------------- /etherparse/src/err/ipv4/bad_options_len.rs: -------------------------------------------------------------------------------- 1 | /// Error if a slice can not be used as options data in 2 | /// [`crate::Ipv4Options`] as then length is non compatible. 3 | /// 4 | /// The length for options in an IPv4 header 5 | #[derive(Clone, Debug, Eq, PartialEq, Hash)] 6 | pub struct BadOptionsLen { 7 | /// Invalid length. 8 | pub bad_len: usize, 9 | } 10 | 11 | impl core::fmt::Display for BadOptionsLen { 12 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 13 | write!(f, "Slice of length {} cannot be set as IPv4 header options. The length must be a multiple of 4 and at maximum 40.", self.bad_len) 14 | } 15 | } 16 | 17 | #[cfg(feature = "std")] 18 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 19 | impl std::error::Error for BadOptionsLen { 20 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 21 | None 22 | } 23 | } 24 | 25 | #[cfg(test)] 26 | mod tests { 27 | use super::*; 28 | use alloc::format; 29 | use std::{ 30 | collections::hash_map::DefaultHasher, 31 | error::Error, 32 | hash::{Hash, Hasher}, 33 | }; 34 | 35 | #[test] 36 | fn debug() { 37 | assert_eq!( 38 | "BadOptionsLen { bad_len: 123 }", 39 | format!("{:?}", BadOptionsLen { bad_len: 123 }) 40 | ); 41 | } 42 | 43 | #[test] 44 | fn clone_eq_hash() { 45 | let err = BadOptionsLen { bad_len: 123 }; 46 | assert_eq!(err, err.clone()); 47 | let hash_a = { 48 | let mut hasher = DefaultHasher::new(); 49 | err.hash(&mut hasher); 50 | hasher.finish() 51 | }; 52 | let hash_b = { 53 | let mut hasher = DefaultHasher::new(); 54 | err.clone().hash(&mut hasher); 55 | hasher.finish() 56 | }; 57 | assert_eq!(hash_a, hash_b); 58 | } 59 | 60 | #[test] 61 | fn fmt() { 62 | let err = BadOptionsLen { bad_len: 123 }; 63 | assert_eq!( 64 | format!("{}", err), 65 | "Slice of length 123 cannot be set as IPv4 header options. The length must be a multiple of 4 and at maximum 40." 66 | ); 67 | } 68 | 69 | #[cfg(feature = "std")] 70 | #[test] 71 | fn source() { 72 | assert!(BadOptionsLen { bad_len: 123 }.source().is_none()); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /etherparse/src/err/ipv4/header_error.rs: -------------------------------------------------------------------------------- 1 | /// Error when decoding the IPv4 part of a message. 2 | #[derive(Clone, Debug, Eq, PartialEq, Hash)] 3 | pub enum HeaderError { 4 | /// Error when the IPv4 header version field is not equal to 4. 5 | UnexpectedVersion { 6 | /// The unexpected version number in the IPv4 header. 7 | version_number: u8, 8 | }, 9 | 10 | /// Error when the ipv4 internet header length is smaller then the header itself (5). 11 | HeaderLengthSmallerThanHeader { 12 | /// The internet header length that was too small. 13 | ihl: u8, 14 | }, 15 | } 16 | 17 | impl core::fmt::Display for HeaderError { 18 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 19 | use HeaderError::*; 20 | match self { 21 | UnexpectedVersion { version_number } => write!(f, "IPv4 Header Error: Encountered '{}' as IP version number in the IPv4 header (must be '4' in an IPv4 header).", version_number), 22 | HeaderLengthSmallerThanHeader { ihl } => write!(f, "IPv4 Header Error: The 'internet header length' value '{}' present in the IPv4 header is smaller than the minimum size of an IPv4 header. The minimum allowed value is '5'.", ihl), 23 | } 24 | } 25 | } 26 | 27 | #[cfg(feature = "std")] 28 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 29 | impl std::error::Error for HeaderError { 30 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 31 | None 32 | } 33 | } 34 | 35 | #[cfg(test)] 36 | mod tests { 37 | use super::{HeaderError::*, *}; 38 | use alloc::format; 39 | use std::{ 40 | collections::hash_map::DefaultHasher, 41 | error::Error, 42 | hash::{Hash, Hasher}, 43 | }; 44 | 45 | #[test] 46 | fn debug() { 47 | assert_eq!( 48 | "UnexpectedVersion { version_number: 6 }", 49 | format!("{:?}", UnexpectedVersion { version_number: 6 }) 50 | ); 51 | } 52 | 53 | #[test] 54 | fn clone_eq_hash() { 55 | let err = HeaderError::UnexpectedVersion { version_number: 6 }; 56 | assert_eq!(err, err.clone()); 57 | let hash_a = { 58 | let mut hasher = DefaultHasher::new(); 59 | err.hash(&mut hasher); 60 | hasher.finish() 61 | }; 62 | let hash_b = { 63 | let mut hasher = DefaultHasher::new(); 64 | err.clone().hash(&mut hasher); 65 | hasher.finish() 66 | }; 67 | assert_eq!(hash_a, hash_b); 68 | } 69 | 70 | #[test] 71 | fn fmt() { 72 | assert_eq!( 73 | "IPv4 Header Error: Encountered '1' as IP version number in the IPv4 header (must be '4' in an IPv4 header).", 74 | format!("{}", UnexpectedVersion{ version_number: 1 }) 75 | ); 76 | assert_eq!( 77 | "IPv4 Header Error: The 'internet header length' value '2' present in the IPv4 header is smaller than the minimum size of an IPv4 header. The minimum allowed value is '5'.", 78 | format!("{}", HeaderLengthSmallerThanHeader{ ihl: 2 }) 79 | ); 80 | } 81 | 82 | #[cfg(feature = "std")] 83 | #[test] 84 | fn source() { 85 | let values = [ 86 | UnexpectedVersion { version_number: 0 }, 87 | HeaderLengthSmallerThanHeader { ihl: 0 }, 88 | ]; 89 | for v in values { 90 | assert!(v.source().is_none()); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /etherparse/src/err/ipv4/mod.rs: -------------------------------------------------------------------------------- 1 | mod bad_options_len; 2 | pub use bad_options_len::*; 3 | 4 | mod header_error; 5 | pub use header_error::*; 6 | 7 | #[cfg(feature = "std")] 8 | mod header_read_error; 9 | #[cfg(feature = "std")] 10 | pub use header_read_error::*; 11 | 12 | mod header_slice_error; 13 | pub use header_slice_error::*; 14 | 15 | mod slice_error; 16 | pub use slice_error::*; 17 | -------------------------------------------------------------------------------- /etherparse/src/err/ipv4_exts/exts_walk_error.rs: -------------------------------------------------------------------------------- 1 | use crate::IpNumber; 2 | 3 | /// Errors in content of IPv4 header extensions that prevent serialization 4 | /// or determining the next header. 5 | #[derive(Clone, Debug, Eq, PartialEq, Hash)] 6 | pub enum ExtsWalkError { 7 | /// Error when a header in [`crate::Ipv4Extensions`] is never referenced even 8 | /// though it is present in the [`crate::Ipv4Extensions`]. 9 | /// 10 | /// This can occur when calculating the "next header" value or when 11 | /// trying to write [crate::Ipv4Extensions`]. 12 | ExtNotReferenced { 13 | /// IpNumber of the header which was not referenced. 14 | missing_ext: IpNumber, 15 | }, 16 | } 17 | 18 | impl core::fmt::Display for ExtsWalkError { 19 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 20 | use ExtsWalkError::*; 21 | match self { 22 | ExtNotReferenced{ missing_ext } => write!( 23 | f, 24 | "IPv4 extensions '{:?}' is defined but is not referenced by the 'protocol' the IPv4 header.", 25 | missing_ext 26 | ), 27 | } 28 | } 29 | } 30 | 31 | #[cfg(feature = "std")] 32 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 33 | impl std::error::Error for ExtsWalkError { 34 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 35 | use ExtsWalkError::*; 36 | match self { 37 | ExtNotReferenced { missing_ext: _ } => None, 38 | } 39 | } 40 | } 41 | 42 | #[cfg(test)] 43 | mod tests { 44 | use super::ExtsWalkError::*; 45 | use crate::*; 46 | use alloc::format; 47 | use std::{ 48 | collections::hash_map::DefaultHasher, 49 | error::Error, 50 | hash::{Hash, Hasher}, 51 | }; 52 | 53 | #[test] 54 | fn debug() { 55 | assert_eq!( 56 | format!( 57 | "ExtNotReferenced {{ missing_ext: {:?} }}", 58 | IpNumber::AUTHENTICATION_HEADER, 59 | ), 60 | format!( 61 | "{:?}", 62 | ExtNotReferenced { 63 | missing_ext: IpNumber::AUTHENTICATION_HEADER 64 | } 65 | ) 66 | ); 67 | } 68 | 69 | #[test] 70 | fn clone_eq_hash() { 71 | let err = ExtNotReferenced { 72 | missing_ext: IpNumber::AUTHENTICATION_HEADER, 73 | }; 74 | assert_eq!(err, err.clone()); 75 | let hash_a = { 76 | let mut hasher = DefaultHasher::new(); 77 | err.hash(&mut hasher); 78 | hasher.finish() 79 | }; 80 | let hash_b = { 81 | let mut hasher = DefaultHasher::new(); 82 | err.clone().hash(&mut hasher); 83 | hasher.finish() 84 | }; 85 | assert_eq!(hash_a, hash_b); 86 | } 87 | 88 | #[test] 89 | fn fmt() { 90 | assert_eq!( 91 | "IPv4 extensions '51 (AH - Authentication Header)' is defined but is not referenced by the 'protocol' the IPv4 header.", 92 | format!("{}", ExtNotReferenced{ 93 | missing_ext: IpNumber::AUTHENTICATION_HEADER, 94 | }) 95 | ); 96 | } 97 | 98 | #[cfg(feature = "std")] 99 | #[test] 100 | fn source() { 101 | assert!(ExtNotReferenced { 102 | missing_ext: IpNumber::IPV6_FRAGMENTATION_HEADER 103 | } 104 | .source() 105 | .is_none()); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /etherparse/src/err/ipv4_exts/mod.rs: -------------------------------------------------------------------------------- 1 | mod exts_walk_error; 2 | pub use exts_walk_error::*; 3 | 4 | #[cfg(feature = "std")] 5 | mod header_write_error; 6 | #[cfg(feature = "std")] 7 | pub use header_write_error::*; 8 | -------------------------------------------------------------------------------- /etherparse/src/err/ipv6/header_error.rs: -------------------------------------------------------------------------------- 1 | /// Error when decoding the IPv6 header. 2 | #[derive(Clone, Debug, Eq, PartialEq, Hash)] 3 | pub enum HeaderError { 4 | /// Error when the IPv6 header version field is not equal to 6. 5 | UnexpectedVersion { 6 | /// The unexpected version number in the IPv6 header. 7 | version_number: u8, 8 | }, 9 | } 10 | 11 | impl core::fmt::Display for HeaderError { 12 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 13 | use HeaderError::*; 14 | match self { 15 | UnexpectedVersion { version_number } => write!(f, "IPv6 Header Error: Encountered '{}' as IP version number in the IPv6 header (must be '6' in an IPv6 header).", version_number), 16 | } 17 | } 18 | } 19 | 20 | #[cfg(feature = "std")] 21 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 22 | impl std::error::Error for HeaderError { 23 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 24 | None 25 | } 26 | } 27 | 28 | #[cfg(test)] 29 | mod tests { 30 | use super::{HeaderError::*, *}; 31 | use alloc::format; 32 | use std::{ 33 | collections::hash_map::DefaultHasher, 34 | error::Error, 35 | hash::{Hash, Hasher}, 36 | }; 37 | 38 | #[test] 39 | fn debug() { 40 | assert_eq!( 41 | "UnexpectedVersion { version_number: 1 }", 42 | format!("{:?}", UnexpectedVersion { version_number: 1 }) 43 | ); 44 | } 45 | 46 | #[test] 47 | fn clone_eq_hash() { 48 | let err = HeaderError::UnexpectedVersion { version_number: 6 }; 49 | assert_eq!(err, err.clone()); 50 | let hash_a = { 51 | let mut hasher = DefaultHasher::new(); 52 | err.hash(&mut hasher); 53 | hasher.finish() 54 | }; 55 | let hash_b = { 56 | let mut hasher = DefaultHasher::new(); 57 | err.clone().hash(&mut hasher); 58 | hasher.finish() 59 | }; 60 | assert_eq!(hash_a, hash_b); 61 | } 62 | 63 | #[test] 64 | fn fmt() { 65 | assert_eq!( 66 | "IPv6 Header Error: Encountered '1' as IP version number in the IPv6 header (must be '6' in an IPv6 header).", 67 | format!("{}", UnexpectedVersion{ version_number: 1 }) 68 | ); 69 | } 70 | 71 | #[cfg(feature = "std")] 72 | #[test] 73 | fn source() { 74 | let values = [UnexpectedVersion { version_number: 0 }]; 75 | for v in values { 76 | assert!(v.source().is_none()); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /etherparse/src/err/ipv6/mod.rs: -------------------------------------------------------------------------------- 1 | mod header_error; 2 | pub use header_error::*; 3 | 4 | #[cfg(feature = "std")] 5 | mod header_read_error; 6 | #[cfg(feature = "std")] 7 | pub use header_read_error::*; 8 | 9 | mod header_slice_error; 10 | pub use header_slice_error::*; 11 | 12 | mod slice_error; 13 | pub use slice_error::*; 14 | -------------------------------------------------------------------------------- /etherparse/src/err/ipv6_exts/exts_walk_error.rs: -------------------------------------------------------------------------------- 1 | use crate::IpNumber; 2 | 3 | /// Errors in content of IPv6 header extensions that prevent serialization. 4 | #[derive(Clone, Debug, Eq, PartialEq, Hash)] 5 | pub enum ExtsWalkError { 6 | /// Error when a hop-by-hop header is not referenced as the 7 | /// first header after the ipv6 header but as a later extension 8 | /// header. 9 | HopByHopNotAtStart, 10 | 11 | /// Error when a header in [`crate::Ipv6Extensions`] is never written 12 | /// as it is never referenced by any of the other `next_header` 13 | /// fields or the initial ip number. 14 | ExtNotReferenced { 15 | /// IpNumber of the header which was not referenced. 16 | missing_ext: IpNumber, 17 | }, 18 | } 19 | 20 | impl core::fmt::Display for ExtsWalkError { 21 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 22 | match self { 23 | ExtsWalkError::HopByHopNotAtStart => 24 | write!(f, "IPv6 extensions hop-by-hop is not located directly after the IPv6 header (required by IPv6)."), 25 | ExtsWalkError::ExtNotReferenced{ missing_ext } => 26 | write!(f, "IPv6 extensions '{:?}' is defined but is not referenced by any of the 'next_header' of the other extension headers or the IPv6 header.", missing_ext), 27 | } 28 | } 29 | } 30 | 31 | #[cfg(feature = "std")] 32 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 33 | impl std::error::Error for ExtsWalkError { 34 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 35 | None 36 | } 37 | } 38 | 39 | #[cfg(test)] 40 | mod tests { 41 | use super::ExtsWalkError::*; 42 | use crate::*; 43 | use alloc::format; 44 | use std::{ 45 | collections::hash_map::DefaultHasher, 46 | error::Error, 47 | hash::{Hash, Hasher}, 48 | }; 49 | 50 | #[test] 51 | fn debug() { 52 | assert_eq!("HopByHopNotAtStart", format!("{:?}", HopByHopNotAtStart)); 53 | } 54 | 55 | #[test] 56 | fn clone_eq_hash() { 57 | let err = HopByHopNotAtStart; 58 | assert_eq!(err, err.clone()); 59 | let hash_a = { 60 | let mut hasher = DefaultHasher::new(); 61 | err.hash(&mut hasher); 62 | hasher.finish() 63 | }; 64 | let hash_b = { 65 | let mut hasher = DefaultHasher::new(); 66 | err.clone().hash(&mut hasher); 67 | hasher.finish() 68 | }; 69 | assert_eq!(hash_a, hash_b); 70 | } 71 | 72 | #[test] 73 | fn fmt() { 74 | assert_eq!( 75 | "IPv6 extensions hop-by-hop is not located directly after the IPv6 header (required by IPv6).", 76 | format!("{}", HopByHopNotAtStart) 77 | ); 78 | assert_eq!( 79 | "IPv6 extensions '44 (IPv6-Frag - Fragment Header for IPv6)' is defined but is not referenced by any of the 'next_header' of the other extension headers or the IPv6 header.", 80 | format!("{}", ExtNotReferenced{ missing_ext: IpNumber::IPV6_FRAGMENTATION_HEADER }) 81 | ); 82 | } 83 | 84 | #[cfg(feature = "std")] 85 | #[test] 86 | fn source() { 87 | assert!(HopByHopNotAtStart.source().is_none()); 88 | assert!(ExtNotReferenced { 89 | missing_ext: IpNumber::IPV6_FRAGMENTATION_HEADER 90 | } 91 | .source() 92 | .is_none()); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /etherparse/src/err/ipv6_exts/header_error.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | 3 | /// Error when decoding IPv6 extension headers. 4 | #[derive(Clone, Debug, Eq, PartialEq, Hash)] 5 | pub enum HeaderError { 6 | /// Error if the ipv6 hop by hop header does not occur directly after the ipv6 header (see rfc8200 chapter 4.1.) 7 | HopByHopNotAtStart, 8 | 9 | /// Error in the ip authentication header. 10 | IpAuth(err::ip_auth::HeaderError), 11 | } 12 | 13 | impl core::fmt::Display for HeaderError { 14 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 15 | use HeaderError::*; 16 | match self { 17 | HopByHopNotAtStart => write!(f, "IPv6 Extension Header Error: Encountered an IPv6 hop-by-hop header not directly after the IPv6 header. This is not allowed according to RFC 8200."), 18 | IpAuth(err) => err.fmt(f), 19 | } 20 | } 21 | } 22 | 23 | #[cfg(feature = "std")] 24 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 25 | impl std::error::Error for HeaderError { 26 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 27 | use HeaderError::*; 28 | match self { 29 | HopByHopNotAtStart => None, 30 | IpAuth(err) => Some(err), 31 | } 32 | } 33 | } 34 | 35 | #[cfg(test)] 36 | mod tests { 37 | use super::HeaderError::*; 38 | use crate::*; 39 | use alloc::format; 40 | use std::{ 41 | collections::hash_map::DefaultHasher, 42 | error::Error, 43 | hash::{Hash, Hasher}, 44 | }; 45 | 46 | #[test] 47 | fn debug() { 48 | assert_eq!("HopByHopNotAtStart", format!("{:?}", HopByHopNotAtStart)); 49 | } 50 | 51 | #[test] 52 | fn clone_eq_hash() { 53 | let err = HopByHopNotAtStart; 54 | assert_eq!(err, err.clone()); 55 | let hash_a = { 56 | let mut hasher = DefaultHasher::new(); 57 | err.hash(&mut hasher); 58 | hasher.finish() 59 | }; 60 | let hash_b = { 61 | let mut hasher = DefaultHasher::new(); 62 | err.clone().hash(&mut hasher); 63 | hasher.finish() 64 | }; 65 | assert_eq!(hash_a, hash_b); 66 | } 67 | 68 | #[test] 69 | fn fmt() { 70 | assert_eq!( 71 | "IPv6 Extension Header Error: Encountered an IPv6 hop-by-hop header not directly after the IPv6 header. This is not allowed according to RFC 8200.", 72 | format!("{}", HopByHopNotAtStart) 73 | ); 74 | { 75 | let err = err::ip_auth::HeaderError::ZeroPayloadLen; 76 | assert_eq!(format!("{}", err), format!("{}", IpAuth(err))); 77 | } 78 | } 79 | 80 | #[cfg(feature = "std")] 81 | #[test] 82 | fn source() { 83 | use err::ip_auth::HeaderError::ZeroPayloadLen; 84 | 85 | assert!(HopByHopNotAtStart.source().is_none()); 86 | assert!(IpAuth(ZeroPayloadLen).source().is_some()); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /etherparse/src/err/ipv6_exts/mod.rs: -------------------------------------------------------------------------------- 1 | mod ext_payload_len_error; 2 | pub use ext_payload_len_error::*; 3 | 4 | mod header_error; 5 | pub use header_error::*; 6 | 7 | #[cfg(feature = "std")] 8 | mod header_limited_read_error; 9 | #[cfg(feature = "std")] 10 | pub use header_limited_read_error::*; 11 | 12 | #[cfg(feature = "std")] 13 | mod header_read_error; 14 | #[cfg(feature = "std")] 15 | pub use header_read_error::*; 16 | 17 | mod exts_walk_error; 18 | pub use exts_walk_error::*; 19 | 20 | mod header_slice_error; 21 | pub use header_slice_error::*; 22 | 23 | #[cfg(feature = "std")] 24 | mod header_write_error; 25 | #[cfg(feature = "std")] 26 | pub use header_write_error::*; 27 | -------------------------------------------------------------------------------- /etherparse/src/err/linux_sll/header_error.rs: -------------------------------------------------------------------------------- 1 | use crate::ArpHardwareId; 2 | 3 | /// Errors in an Linux Cooked Capture header encountered while decoding it. 4 | #[derive(Clone, Debug, Eq, PartialEq, Hash)] 5 | pub enum HeaderError { 6 | /// Error when the "packet byte" field is not one of the known ones 7 | UnsupportedPacketTypeField { 8 | // The unexpected packet type number in the SLL header 9 | packet_type: u16, 10 | }, 11 | /// Error when the arp hardware type field is not one of the known ones 12 | UnsupportedArpHardwareId { arp_hardware_type: ArpHardwareId }, 13 | } 14 | 15 | impl core::fmt::Display for HeaderError { 16 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 17 | use HeaderError::*; 18 | match self { 19 | UnsupportedPacketTypeField { packet_type } => write!(f, "Linux cooked capture v1 (SLL) Header Error: Encountered '{}' as the packet type, but its not supported.", packet_type), 20 | UnsupportedArpHardwareId { arp_hardware_type } => write!(f, "Linux cooked capture v1 (SLL) Header Error: Encountered '{:?}' as the ARP harware type, but its not supported.", arp_hardware_type), 21 | } 22 | } 23 | } 24 | 25 | #[cfg(feature = "std")] 26 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 27 | impl std::error::Error for HeaderError { 28 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 29 | use HeaderError::*; 30 | match self { 31 | UnsupportedPacketTypeField { packet_type: _ } => None, 32 | UnsupportedArpHardwareId { 33 | arp_hardware_type: _, 34 | } => None, 35 | } 36 | } 37 | } 38 | 39 | #[cfg(test)] 40 | mod tests { 41 | use super::{HeaderError::*, *}; 42 | use alloc::format; 43 | use std::{ 44 | collections::hash_map::DefaultHasher, 45 | error::Error, 46 | hash::{Hash, Hasher}, 47 | }; 48 | 49 | #[test] 50 | fn debug() { 51 | assert_eq!( 52 | "UnsupportedPacketTypeField { packet_type: 6 }", 53 | format!("{:?}", UnsupportedPacketTypeField { packet_type: 6 }) 54 | ); 55 | } 56 | 57 | #[test] 58 | fn clone_eq_hash() { 59 | let err = HeaderError::UnsupportedPacketTypeField { packet_type: 6 }; 60 | assert_eq!(err, err.clone()); 61 | let hash_a = { 62 | let mut hasher = DefaultHasher::new(); 63 | err.hash(&mut hasher); 64 | hasher.finish() 65 | }; 66 | let hash_b = { 67 | let mut hasher = DefaultHasher::new(); 68 | err.clone().hash(&mut hasher); 69 | hasher.finish() 70 | }; 71 | assert_eq!(hash_a, hash_b); 72 | } 73 | 74 | #[test] 75 | fn fmt() { 76 | assert_eq!( 77 | "Linux cooked capture v1 (SLL) Header Error: Encountered '6' as the packet type, but its not supported.", 78 | format!("{}", UnsupportedPacketTypeField{ packet_type: 6 }) 79 | ); 80 | assert_eq!( 81 | "Linux cooked capture v1 (SLL) Header Error: Encountered '1 (Ethernet)' as the ARP harware type, but its not supported.", 82 | format!("{}", UnsupportedArpHardwareId{ arp_hardware_type: ArpHardwareId::ETHERNET }) 83 | ); 84 | } 85 | 86 | #[cfg(feature = "std")] 87 | #[test] 88 | fn source() { 89 | let values = [ 90 | UnsupportedPacketTypeField { packet_type: 6 }, 91 | UnsupportedArpHardwareId { 92 | arp_hardware_type: ArpHardwareId::ETHERNET, 93 | }, 94 | ]; 95 | for v in values { 96 | assert!(v.source().is_none()); 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /etherparse/src/err/linux_sll/mod.rs: -------------------------------------------------------------------------------- 1 | mod header_error; 2 | pub use header_error::*; 3 | 4 | #[cfg(feature = "std")] 5 | mod header_read_error; 6 | #[cfg(feature = "std")] 7 | pub use header_read_error::*; 8 | 9 | mod header_slice_error; 10 | pub use header_slice_error::*; 11 | -------------------------------------------------------------------------------- /etherparse/src/err/macsec/header_error.rs: -------------------------------------------------------------------------------- 1 | /// Error when decoding a MACsec header. 2 | #[derive(Clone, Debug, Eq, PartialEq, Hash)] 3 | pub enum HeaderError { 4 | /// Error when the MACsec header version field is not equal 0. 5 | UnexpectedVersion, 6 | 7 | /// Error if the short len is 1 when it should be at least 2 8 | /// (for the next ether type). 9 | InvalidUnmodifiedShortLen, 10 | } 11 | 12 | impl core::fmt::Display for HeaderError { 13 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 14 | use HeaderError::*; 15 | match self { 16 | UnexpectedVersion => write!(f, "MACsec Header Error: Encountered '1' as MACsec version in the MACsec SecTag header (must be '0')."), 17 | InvalidUnmodifiedShortLen => write!(f, "MACsec Header Error: Encountered '1' as MACsec short len in an unmodified packet (must be '0' or '2' or greater)."), 18 | } 19 | } 20 | } 21 | 22 | #[cfg(feature = "std")] 23 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 24 | impl std::error::Error for HeaderError { 25 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 26 | None 27 | } 28 | } 29 | 30 | #[cfg(test)] 31 | mod tests { 32 | use super::{HeaderError::*, *}; 33 | use alloc::format; 34 | use std::{ 35 | collections::hash_map::DefaultHasher, 36 | error::Error, 37 | hash::{Hash, Hasher}, 38 | }; 39 | 40 | #[test] 41 | fn debug() { 42 | assert_eq!("UnexpectedVersion", format!("{:?}", UnexpectedVersion)); 43 | } 44 | 45 | #[test] 46 | fn clone_eq_hash() { 47 | let err = HeaderError::UnexpectedVersion; 48 | assert_eq!(err, err.clone()); 49 | let hash_a = { 50 | let mut hasher = DefaultHasher::new(); 51 | err.hash(&mut hasher); 52 | hasher.finish() 53 | }; 54 | let hash_b = { 55 | let mut hasher = DefaultHasher::new(); 56 | err.clone().hash(&mut hasher); 57 | hasher.finish() 58 | }; 59 | assert_eq!(hash_a, hash_b); 60 | } 61 | 62 | #[test] 63 | fn fmt() { 64 | assert_eq!( 65 | "MACsec Header Error: Encountered '1' as MACsec version in the MACsec SecTag header (must be '0').", 66 | format!("{}", UnexpectedVersion) 67 | ); 68 | assert_eq!( 69 | "MACsec Header Error: Encountered '1' as MACsec short len in an unmodified packet (must be '0' or '2' or greater).", 70 | format!("{}", InvalidUnmodifiedShortLen) 71 | ); 72 | } 73 | 74 | #[cfg(feature = "std")] 75 | #[test] 76 | fn source() { 77 | let values = [UnexpectedVersion, InvalidUnmodifiedShortLen]; 78 | for v in values { 79 | assert!(v.source().is_none()); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /etherparse/src/err/macsec/mod.rs: -------------------------------------------------------------------------------- 1 | mod header_error; 2 | pub use header_error::*; 3 | 4 | #[cfg(feature = "std")] 5 | mod header_read_error; 6 | #[cfg(feature = "std")] 7 | pub use header_read_error::*; 8 | 9 | mod header_slice_error; 10 | pub use header_slice_error::*; 11 | -------------------------------------------------------------------------------- /etherparse/src/err/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod arp; 2 | #[cfg(feature = "std")] 3 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 4 | pub mod io; 5 | pub mod ip; 6 | pub mod ip_auth; 7 | pub mod ip_exts; 8 | pub mod ipv4; 9 | pub mod ipv4_exts; 10 | pub mod ipv6; 11 | pub mod ipv6_exts; 12 | pub mod linux_sll; 13 | pub mod macsec; 14 | pub mod net; 15 | pub mod packet; 16 | pub mod tcp; 17 | 18 | mod value_type; 19 | pub use value_type::*; 20 | 21 | mod from_slice_error; 22 | pub use from_slice_error::*; 23 | 24 | mod layer; 25 | pub use layer::*; 26 | 27 | mod len_error; 28 | pub use len_error::*; 29 | 30 | mod value_too_big_error; 31 | pub use value_too_big_error::*; 32 | 33 | #[cfg(feature = "std")] 34 | mod read_error; 35 | #[cfg(feature = "std")] 36 | pub use read_error::*; 37 | 38 | mod slice_write_space_error; 39 | pub use slice_write_space_error::*; 40 | -------------------------------------------------------------------------------- /etherparse/src/err/net/mod.rs: -------------------------------------------------------------------------------- 1 | mod net_set_next_header_error; 2 | pub use net_set_next_header_error::*; 3 | -------------------------------------------------------------------------------- /etherparse/src/err/net/net_set_next_header_error.rs: -------------------------------------------------------------------------------- 1 | /// Errors when setting the next header IP number. 2 | #[derive(Clone, Debug, Eq, PartialEq, Hash)] 3 | pub enum NetSetNextHeaderError { 4 | /// It is possible to set the ip_number in an ARP header. 5 | ArpHeader, 6 | } 7 | 8 | impl core::fmt::Display for NetSetNextHeaderError { 9 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 10 | use NetSetNextHeaderError::*; 11 | match self { 12 | ArpHeader => write!( 13 | f, 14 | "It is not possible to set the payload 'IP number' for an ARP header." 15 | ), 16 | } 17 | } 18 | } 19 | 20 | #[cfg(feature = "std")] 21 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 22 | impl std::error::Error for NetSetNextHeaderError { 23 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 24 | None 25 | } 26 | } 27 | 28 | #[cfg(test)] 29 | mod tests { 30 | use super::*; 31 | use alloc::format; 32 | use std::{ 33 | collections::hash_map::DefaultHasher, 34 | error::Error, 35 | hash::{Hash, Hasher}, 36 | }; 37 | 38 | #[test] 39 | fn debug() { 40 | assert_eq!( 41 | "ArpHeader", 42 | format!("{:?}", NetSetNextHeaderError::ArpHeader) 43 | ); 44 | } 45 | 46 | #[test] 47 | fn clone_eq_hash() { 48 | let err = NetSetNextHeaderError::ArpHeader; 49 | assert_eq!(err, err.clone()); 50 | let hash_a = { 51 | let mut hasher = DefaultHasher::new(); 52 | err.hash(&mut hasher); 53 | hasher.finish() 54 | }; 55 | let hash_b = { 56 | let mut hasher = DefaultHasher::new(); 57 | err.clone().hash(&mut hasher); 58 | hasher.finish() 59 | }; 60 | assert_eq!(hash_a, hash_b); 61 | } 62 | 63 | #[test] 64 | fn fmt() { 65 | assert_eq!( 66 | "It is not possible to set the payload 'IP number' for an ARP header.", 67 | format!("{}", NetSetNextHeaderError::ArpHeader) 68 | ); 69 | } 70 | 71 | #[cfg(feature = "std")] 72 | #[test] 73 | fn source() { 74 | let values = [NetSetNextHeaderError::ArpHeader]; 75 | for v in values { 76 | assert!(v.source().is_none()); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /etherparse/src/err/packet/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "std")] 2 | mod build_write_error; 3 | #[cfg(feature = "std")] 4 | pub use build_write_error::*; 5 | 6 | mod slice_error; 7 | pub use slice_error::*; 8 | 9 | mod transport_checksum_error; 10 | pub use transport_checksum_error::*; 11 | -------------------------------------------------------------------------------- /etherparse/src/err/packet/transport_checksum_error.rs: -------------------------------------------------------------------------------- 1 | use crate::err::ValueTooBigError; 2 | 3 | /// Error while calculating the checksum in a transport header. 4 | #[derive(Clone, Debug, Eq, PartialEq, Hash)] 5 | pub enum TransportChecksumError { 6 | /// Error if the length of the payload is too 7 | /// big to be representable by the length fields. 8 | PayloadLen(ValueTooBigError), 9 | 10 | /// Error when an Icmpv6 payload is found in an IPv4 packet. 11 | Icmpv6InIpv4, 12 | } 13 | 14 | impl core::fmt::Display for TransportChecksumError { 15 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 16 | use TransportChecksumError::*; 17 | match self { 18 | PayloadLen(err) => err.fmt(f), 19 | Icmpv6InIpv4 => write!(f, "Error: ICMPv6 can not be combined with an IPv4 headers (checksum can not be calculated)."), 20 | } 21 | } 22 | } 23 | 24 | #[cfg(feature = "std")] 25 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 26 | impl std::error::Error for TransportChecksumError { 27 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 28 | use TransportChecksumError::*; 29 | match self { 30 | PayloadLen(err) => Some(err), 31 | Icmpv6InIpv4 => None, 32 | } 33 | } 34 | } 35 | 36 | #[cfg(test)] 37 | mod tests { 38 | use super::{TransportChecksumError::*, *}; 39 | use crate::err::ValueType; 40 | use alloc::format; 41 | use std::{ 42 | collections::hash_map::DefaultHasher, 43 | error::Error, 44 | hash::{Hash, Hasher}, 45 | }; 46 | 47 | #[test] 48 | fn debug() { 49 | assert_eq!("Icmpv6InIpv4", format!("{:?}", Icmpv6InIpv4)); 50 | } 51 | 52 | #[test] 53 | fn clone_eq_hash() { 54 | let err = Icmpv6InIpv4; 55 | assert_eq!(err, err.clone()); 56 | let hash_a = { 57 | let mut hasher = DefaultHasher::new(); 58 | err.hash(&mut hasher); 59 | hasher.finish() 60 | }; 61 | let hash_b = { 62 | let mut hasher = DefaultHasher::new(); 63 | err.clone().hash(&mut hasher); 64 | hasher.finish() 65 | }; 66 | assert_eq!(hash_a, hash_b); 67 | } 68 | 69 | #[test] 70 | fn fmt() { 71 | // PayloadLen 72 | { 73 | let err = ValueTooBigError { 74 | actual: 1, 75 | max_allowed: 2, 76 | value_type: ValueType::TcpPayloadLengthIpv6, 77 | }; 78 | assert_eq!(format!("{}", &err), format!("{}", PayloadLen(err))); 79 | } 80 | 81 | // Icmpv6InIpv4 82 | assert_eq!( 83 | format!("{}", Icmpv6InIpv4), 84 | "Error: ICMPv6 can not be combined with an IPv4 headers (checksum can not be calculated)." 85 | ); 86 | } 87 | 88 | #[cfg(feature = "std")] 89 | #[test] 90 | fn source() { 91 | // Len 92 | { 93 | let err = ValueTooBigError { 94 | actual: 1, 95 | max_allowed: 2, 96 | value_type: ValueType::TcpPayloadLengthIpv6, 97 | }; 98 | assert!(PayloadLen(err).source().is_some()); 99 | } 100 | 101 | // IpHeader 102 | assert!(Icmpv6InIpv4.source().is_none()); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /etherparse/src/err/tcp/header_error.rs: -------------------------------------------------------------------------------- 1 | /// Errors that can be encountered while decoding a TCP header. 2 | #[derive(Clone, Debug, Eq, PartialEq, Hash)] 3 | pub enum HeaderError { 4 | /// Error when the data_offset is so small that the data would 5 | /// start within the TCP header itself. 6 | DataOffsetTooSmall { data_offset: u8 }, 7 | } 8 | 9 | impl core::fmt::Display for HeaderError { 10 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 11 | use HeaderError::*; 12 | match self { 13 | DataOffsetTooSmall{ data_offset } => write!( 14 | f, 15 | "TCP Header Error: 'data offset' too small ({}). The 'data offset' must be at least 5 so the data is not overlapping with the TCP header itself.", 16 | data_offset 17 | ), 18 | } 19 | } 20 | } 21 | 22 | #[cfg(feature = "std")] 23 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 24 | impl std::error::Error for HeaderError { 25 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 26 | None 27 | } 28 | } 29 | 30 | #[cfg(test)] 31 | mod tests { 32 | use super::HeaderError::*; 33 | use alloc::format; 34 | use std::{ 35 | collections::hash_map::DefaultHasher, 36 | error::Error, 37 | hash::{Hash, Hasher}, 38 | }; 39 | 40 | #[test] 41 | fn debug() { 42 | assert_eq!( 43 | "DataOffsetTooSmall { data_offset: 1 }", 44 | format!("{:?}", DataOffsetTooSmall { data_offset: 1 }) 45 | ); 46 | } 47 | 48 | #[test] 49 | fn clone_eq_hash() { 50 | let err = DataOffsetTooSmall { data_offset: 1 }; 51 | assert_eq!(err, err.clone()); 52 | let hash_a = { 53 | let mut hasher = DefaultHasher::new(); 54 | err.hash(&mut hasher); 55 | hasher.finish() 56 | }; 57 | let hash_b = { 58 | let mut hasher = DefaultHasher::new(); 59 | err.clone().hash(&mut hasher); 60 | hasher.finish() 61 | }; 62 | assert_eq!(hash_a, hash_b); 63 | } 64 | 65 | #[test] 66 | fn fmt() { 67 | assert_eq!( 68 | "TCP Header Error: 'data offset' too small (1). The 'data offset' must be at least 5 so the data is not overlapping with the TCP header itself.", 69 | format!("{}", DataOffsetTooSmall{ data_offset: 1 }) 70 | ); 71 | } 72 | 73 | #[cfg(feature = "std")] 74 | #[test] 75 | fn source() { 76 | assert!(DataOffsetTooSmall { data_offset: 0 }.source().is_none()); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /etherparse/src/err/tcp/mod.rs: -------------------------------------------------------------------------------- 1 | mod header_error; 2 | pub use header_error::*; 3 | 4 | #[cfg(feature = "std")] 5 | mod header_read_error; 6 | #[cfg(feature = "std")] 7 | pub use header_read_error::*; 8 | 9 | mod header_slice_error; 10 | pub use header_slice_error::*; 11 | -------------------------------------------------------------------------------- /etherparse/src/err/value_too_big_error.rs: -------------------------------------------------------------------------------- 1 | use crate::err; 2 | use core::{cmp::Eq, cmp::PartialEq, fmt::Debug, fmt::Display, hash::Hash}; 3 | 4 | /// Error if a value exceeds the maximum allowed value. 5 | #[derive(Clone, Debug, Eq, PartialEq, Hash)] 6 | pub struct ValueTooBigError { 7 | /// Value that was disallowed. 8 | pub actual: T, 9 | 10 | /// Maximum allowed value (inclusive). 11 | pub max_allowed: T, 12 | 13 | /// Type of value. 14 | pub value_type: err::ValueType, 15 | } 16 | 17 | impl core::fmt::Display for ValueTooBigError 18 | where 19 | T: Sized + Clone + Display + Debug + Eq + PartialEq + Hash, 20 | { 21 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 22 | write!( 23 | f, 24 | "Error '{}' is too big to be a '{}' (maximum allowed value is '{}')", 25 | self.actual, self.value_type, self.max_allowed 26 | ) 27 | } 28 | } 29 | 30 | #[cfg(feature = "std")] 31 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 32 | impl std::error::Error for ValueTooBigError 33 | where 34 | T: Sized + Clone + Display + Debug + Eq + PartialEq + Hash, 35 | { 36 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 37 | None 38 | } 39 | } 40 | 41 | #[cfg(test)] 42 | mod test { 43 | use super::*; 44 | use std::{collections::hash_map::DefaultHasher, error::Error, format, hash::Hasher}; 45 | 46 | #[test] 47 | fn fmt() { 48 | assert_eq!( 49 | format!( 50 | "{}", 51 | ValueTooBigError { 52 | actual: 3, 53 | max_allowed: 2, 54 | value_type: err::ValueType::IpFragmentOffset 55 | } 56 | ), 57 | "Error '3' is too big to be a 'IP Fragment Offset' (maximum allowed value is '2')" 58 | ); 59 | } 60 | 61 | #[test] 62 | fn dbg() { 63 | assert_eq!( 64 | format!( 65 | "{:?}", 66 | ValueTooBigError { 67 | actual: 3, 68 | max_allowed: 2, 69 | value_type: err::ValueType::IpFragmentOffset 70 | } 71 | ), 72 | format!( 73 | "ValueTooBigError {{ actual: {}, max_allowed: {}, value_type: {:?} }}", 74 | 3, 75 | 2, 76 | err::ValueType::IpFragmentOffset 77 | ) 78 | ); 79 | } 80 | 81 | #[test] 82 | fn clone_eq_hash() { 83 | let err = ValueTooBigError { 84 | actual: 3, 85 | max_allowed: 2, 86 | value_type: err::ValueType::IpFragmentOffset, 87 | }; 88 | assert_eq!(err, err.clone()); 89 | let hash_a = { 90 | let mut hasher = DefaultHasher::new(); 91 | err.hash(&mut hasher); 92 | hasher.finish() 93 | }; 94 | let hash_b = { 95 | let mut hasher = DefaultHasher::new(); 96 | err.clone().hash(&mut hasher); 97 | hasher.finish() 98 | }; 99 | assert_eq!(hash_a, hash_b); 100 | } 101 | 102 | #[cfg(feature = "std")] 103 | #[test] 104 | fn source() { 105 | assert!(ValueTooBigError { 106 | actual: 3, 107 | max_allowed: 2, 108 | value_type: err::ValueType::IpFragmentOffset 109 | } 110 | .source() 111 | .is_none()); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /etherparse/src/helpers.rs: -------------------------------------------------------------------------------- 1 | /// Helper function for reading big endian u16 values from a ptr unchecked. 2 | /// 3 | /// # Safety 4 | /// 5 | /// It is in the responsibility of the caller to ensure there are at least 2 6 | /// bytes accessable via the ptr. If this is not the case undefined behavior 7 | /// will be triggered. 8 | #[inline] 9 | pub(crate) unsafe fn get_unchecked_be_u16(ptr: *const u8) -> u16 { 10 | u16::from_be_bytes([*ptr, *ptr.add(1)]) 11 | } 12 | 13 | /// Helper function for reading big endian u32 values from a ptr unchecked. 14 | /// 15 | /// # Safety 16 | /// 17 | /// It is in the responsibility of the caller to ensure there are at least 4 18 | /// bytes accessable via the ptr. If this is not the case undefined behavior 19 | /// will be triggered. 20 | #[inline] 21 | pub(crate) unsafe fn get_unchecked_be_u32(ptr: *const u8) -> u32 { 22 | u32::from_be_bytes([*ptr, *ptr.add(1), *ptr.add(2), *ptr.add(3)]) 23 | } 24 | 25 | /// Helper function for reading a 4 byte fixed-size array. 26 | /// 27 | /// # Safety 28 | /// 29 | /// It is in the responsibility of the caller to ensure there are at least 4 30 | /// bytes accessable via the ptr. If this is not the case undefined behavior 31 | /// will be triggered. 32 | #[inline] 33 | pub(crate) unsafe fn get_unchecked_4_byte_array(ptr: *const u8) -> [u8; 4] { 34 | [*ptr, *ptr.add(1), *ptr.add(2), *ptr.add(3)] 35 | } 36 | 37 | /// Helper function for reading a 6 byte fixed-size array. 38 | /// 39 | /// # Safety 40 | /// 41 | /// It is in the responsibility of the caller to ensure there are at least 6 42 | /// bytes accessable via the ptr. If this is not the case undefined behavior 43 | /// will be triggered. 44 | #[inline] 45 | pub(crate) unsafe fn get_unchecked_6_byte_array(ptr: *const u8) -> [u8; 6] { 46 | [ 47 | *ptr, 48 | *ptr.add(1), 49 | *ptr.add(2), 50 | *ptr.add(3), 51 | *ptr.add(4), 52 | *ptr.add(5), 53 | ] 54 | } 55 | 56 | /// Helper function for reading a 8 byte fixed-size array. 57 | /// 58 | /// # Safety 59 | /// 60 | /// It is in the responsibility of the caller to ensure there are at least 6 61 | /// bytes accessable via the ptr. If this is not the case undefined behavior 62 | /// will be triggered. 63 | #[inline] 64 | pub(crate) unsafe fn get_unchecked_8_byte_array(ptr: *const u8) -> [u8; 8] { 65 | [ 66 | *ptr, 67 | *ptr.add(1), 68 | *ptr.add(2), 69 | *ptr.add(3), 70 | *ptr.add(4), 71 | *ptr.add(5), 72 | *ptr.add(6), 73 | *ptr.add(7), 74 | ] 75 | } 76 | 77 | /// Helper function for reading a 16 byte fixed-size array. 78 | /// 79 | /// # Safety 80 | /// 81 | /// It is in the responsibility of the caller to ensure there are at least 16 82 | /// bytes accessable via the ptr. If this is not the case undefined behavior 83 | /// will be triggered. 84 | #[inline] 85 | pub(crate) unsafe fn get_unchecked_16_byte_array(ptr: *const u8) -> [u8; 16] { 86 | [ 87 | *ptr, 88 | *ptr.add(1), 89 | *ptr.add(2), 90 | *ptr.add(3), 91 | *ptr.add(4), 92 | *ptr.add(5), 93 | *ptr.add(6), 94 | *ptr.add(7), 95 | *ptr.add(8), 96 | *ptr.add(9), 97 | *ptr.add(10), 98 | *ptr.add(11), 99 | *ptr.add(12), 100 | *ptr.add(13), 101 | *ptr.add(14), 102 | *ptr.add(15), 103 | ] 104 | } 105 | -------------------------------------------------------------------------------- /etherparse/src/io/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "std")] 2 | mod limited_reader; 3 | #[cfg(feature = "std")] 4 | pub use limited_reader::*; 5 | -------------------------------------------------------------------------------- /etherparse/src/len_source.rs: -------------------------------------------------------------------------------- 1 | /// Sources of length limiting values (e.g. "ipv6 payload length field"). 2 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] 3 | pub enum LenSource { 4 | /// Limiting length was the slice length (we don't know what determined 5 | /// that one originally). 6 | Slice, 7 | /// Short length field in the MACsec header. 8 | MacsecShortLength, 9 | /// Length 10 | Ipv4HeaderTotalLen, 11 | /// Error occurred in the IPv6 layer. 12 | Ipv6HeaderPayloadLen, 13 | /// Error occurred while decoding an UDP header. 14 | UdpHeaderLen, 15 | /// Error occurred while decoding a TCP header. 16 | TcpHeaderLen, 17 | /// Error occurred while decoding a ARP packet. 18 | ArpAddrLengths, 19 | } 20 | 21 | #[cfg(test)] 22 | mod test { 23 | use super::LenSource::*; 24 | use alloc::format; 25 | use std::{ 26 | cmp::Ordering, 27 | collections::hash_map::DefaultHasher, 28 | hash::{Hash, Hasher}, 29 | }; 30 | 31 | #[test] 32 | fn debug() { 33 | assert_eq!("Slice", format!("{:?}", Slice)); 34 | } 35 | 36 | #[test] 37 | fn clone_eq_hash_ord() { 38 | let layer = Slice; 39 | assert_eq!(layer, layer.clone()); 40 | let hash_a = { 41 | let mut hasher = DefaultHasher::new(); 42 | layer.hash(&mut hasher); 43 | hasher.finish() 44 | }; 45 | let hash_b = { 46 | let mut hasher = DefaultHasher::new(); 47 | layer.clone().hash(&mut hasher); 48 | hasher.finish() 49 | }; 50 | assert_eq!(hash_a, hash_b); 51 | assert_eq!(Ordering::Equal, layer.cmp(&layer)); 52 | assert_eq!(Some(Ordering::Equal), layer.partial_cmp(&layer)); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /etherparse/src/link/double_vlan_header.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | 3 | /// IEEE 802.1Q double VLAN Tagging Header (helper struct to 4 | /// check vlan tagging values in a [crate::`PacketHeaders`]). 5 | /// 6 | /// Note that it is NOT guranteed that the two VLAN headers 7 | /// will directly follow each other. In the original packet 8 | /// there could be another LinkExt header present in between 9 | /// them (e.g. MacSec Security Tag). 10 | #[derive(Clone, Debug, Eq, PartialEq)] 11 | pub struct DoubleVlanHeader { 12 | /// The outer vlan tagging header 13 | pub outer: SingleVlanHeader, 14 | /// The inner vlan tagging header 15 | pub inner: SingleVlanHeader, 16 | } 17 | 18 | impl Default for DoubleVlanHeader { 19 | fn default() -> Self { 20 | DoubleVlanHeader { 21 | outer: SingleVlanHeader { 22 | pcp: VlanPcp::ZERO, 23 | drop_eligible_indicator: false, 24 | vlan_id: Default::default(), 25 | ether_type: ether_type::VLAN_TAGGED_FRAME, 26 | }, 27 | inner: Default::default(), 28 | } 29 | } 30 | } 31 | 32 | #[cfg(test)] 33 | mod test { 34 | use crate::{test_gens::*, *}; 35 | use alloc::format; 36 | use proptest::prelude::*; 37 | 38 | #[test] 39 | fn default() { 40 | let actual: DoubleVlanHeader = Default::default(); 41 | assert_eq!(actual.outer, { 42 | let mut outer: SingleVlanHeader = Default::default(); 43 | outer.ether_type = ether_type::VLAN_TAGGED_FRAME; 44 | outer 45 | }); 46 | assert_eq!(actual.inner, Default::default()); 47 | } 48 | 49 | proptest! { 50 | #[test] 51 | fn clone_eq(input in vlan_double_any()) { 52 | assert_eq!(input, input.clone()); 53 | } 54 | } 55 | 56 | proptest! { 57 | #[test] 58 | fn dbg(input in vlan_double_any()) { 59 | assert_eq!( 60 | &format!( 61 | "DoubleVlanHeader {{ outer: {:?}, inner: {:?} }}", 62 | input.outer, 63 | input.inner, 64 | ), 65 | &format!("{:?}", input) 66 | ); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /etherparse/src/link/ether_payload_slice.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | 3 | /// Payload of an link layer packet. 4 | #[derive(Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)] 5 | pub struct EtherPayloadSlice<'a> { 6 | /// Identifying content of the payload. 7 | pub ether_type: EtherType, 8 | 9 | /// Length field that was used to determine the length 10 | /// of the payload (e.g. MACsec "short length" field). 11 | pub len_source: LenSource, 12 | 13 | /// Payload 14 | pub payload: &'a [u8], 15 | } 16 | 17 | #[cfg(test)] 18 | mod test { 19 | use super::*; 20 | use alloc::format; 21 | 22 | #[test] 23 | fn debug() { 24 | let s = EtherPayloadSlice { 25 | ether_type: EtherType::IPV4, 26 | payload: &[], 27 | len_source: LenSource::MacsecShortLength, 28 | }; 29 | assert_eq!( 30 | format!( 31 | "EtherPayloadSlice {{ ether_type: {:?}, len_source: {:?}, payload: {:?} }}", 32 | s.ether_type, s.len_source, s.payload 33 | ), 34 | format!("{:?}", s) 35 | ); 36 | } 37 | 38 | #[test] 39 | fn clone_eq_hash_ord() { 40 | let s = EtherPayloadSlice { 41 | ether_type: EtherType::IPV4, 42 | payload: &[], 43 | len_source: LenSource::MacsecShortLength, 44 | }; 45 | assert_eq!(s.clone(), s); 46 | 47 | use std::collections::hash_map::DefaultHasher; 48 | use std::hash::{Hash, Hasher}; 49 | 50 | let a_hash = { 51 | let mut hasher = DefaultHasher::new(); 52 | s.hash(&mut hasher); 53 | hasher.finish() 54 | }; 55 | let b_hash = { 56 | let mut hasher = DefaultHasher::new(); 57 | s.clone().hash(&mut hasher); 58 | hasher.finish() 59 | }; 60 | assert_eq!(a_hash, b_hash); 61 | 62 | use std::cmp::Ordering; 63 | assert_eq!(s.clone().cmp(&s), Ordering::Equal); 64 | assert_eq!(s.clone().partial_cmp(&s), Some(Ordering::Equal)); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /etherparse/src/link/lax_ether_payload_slice.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | 3 | /// Laxly identified payload of an link layer packet (potentially incomplete). 4 | /// 5 | /// To check if the payload is complete check the `incomplete` field. 6 | #[derive(Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)] 7 | pub struct LaxEtherPayloadSlice<'a> { 8 | /// True if the length field in the link header (e.g. MACsec short length) 9 | /// indicates more data should be present but it was not (aka the packet 10 | /// data is cut off). 11 | pub incomplete: bool, 12 | 13 | /// Identifying content of the payload. 14 | pub ether_type: EtherType, 15 | 16 | /// Length field that was used to determine the length 17 | /// of the payload (e.g. MACsec "short length" field). 18 | pub len_source: LenSource, 19 | 20 | /// Payload 21 | pub payload: &'a [u8], 22 | } 23 | -------------------------------------------------------------------------------- /etherparse/src/link/lax_macsec_payload_slice.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | 3 | #[derive(Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)] 4 | pub enum LaxMacsecPayloadSlice<'a> { 5 | /// Unencrypted unmodified ether payload. 6 | Unmodified(LaxEtherPayloadSlice<'a>), 7 | 8 | /// Modified payload (either by encryption or other algorithm). 9 | Modified { incomplete: bool, payload: &'a [u8] }, 10 | } 11 | -------------------------------------------------------------------------------- /etherparse/src/link/link_ext_header.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | /// The possible headers on the link layer 4 | #[derive(Clone, Debug, Eq, PartialEq)] 5 | pub enum LinkExtHeader { 6 | /// VLAN header. 7 | Vlan(SingleVlanHeader), 8 | 9 | /// MACsec header (SecTag + next ether type if available). 10 | Macsec(MacsecHeader), 11 | } 12 | 13 | impl LinkExtHeader { 14 | /// Returns the header length of the link extension. 15 | pub fn header_len(&self) -> usize { 16 | match self { 17 | LinkExtHeader::Vlan(s) => s.header_len(), 18 | LinkExtHeader::Macsec(m) => m.header_len(), 19 | } 20 | } 21 | } 22 | 23 | #[cfg(test)] 24 | mod tests { 25 | use super::*; 26 | use crate::test_gens::*; 27 | use alloc::format; 28 | use proptest::prelude::*; 29 | 30 | proptest! { 31 | #[test] 32 | fn debug_clone_eq(ref vlan in vlan_single_any()) { 33 | let header = LinkExtHeader::Vlan(vlan.clone()); 34 | 35 | // clone & eq 36 | assert_eq!(header.clone(), header); 37 | 38 | // debug 39 | assert_eq!( 40 | format!("{:?}", header), 41 | format!("Vlan({:?})", vlan), 42 | ); 43 | } 44 | } 45 | 46 | proptest! { 47 | #[test] 48 | fn header_len( 49 | vlan in vlan_single_any(), 50 | macsec in macsec_any() 51 | ) { 52 | // vlan 53 | { 54 | let header = LinkExtHeader::Vlan(vlan.clone()); 55 | assert_eq!(header.header_len(), vlan.header_len()); 56 | } 57 | 58 | // macsec 59 | { 60 | let header = LinkExtHeader::Macsec(macsec.clone()); 61 | assert_eq!(header.header_len(), macsec.header_len()); 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /etherparse/src/link/linux_sll_payload_slice.rs: -------------------------------------------------------------------------------- 1 | use crate::{EtherPayloadSlice, EtherType, LenSource, LinuxSllProtocolType}; 2 | 3 | /// Payload of Linux Cooked Capture v1 (SLL) packet 4 | #[derive(Clone, Debug, Eq, PartialEq)] 5 | pub struct LinuxSllPayloadSlice<'a> { 6 | /// Identifying content of the payload. 7 | pub protocol_type: LinuxSllProtocolType, 8 | 9 | /// Payload 10 | pub payload: &'a [u8], 11 | } 12 | 13 | impl<'a> From> for LinuxSllPayloadSlice<'a> { 14 | fn from(value: EtherPayloadSlice<'a>) -> LinuxSllPayloadSlice<'a> { 15 | LinuxSllPayloadSlice { 16 | protocol_type: LinuxSllProtocolType::EtherType(value.ether_type), 17 | payload: value.payload, 18 | } 19 | } 20 | } 21 | 22 | impl<'a> TryFrom> for EtherPayloadSlice<'a> { 23 | type Error = (); 24 | 25 | fn try_from(value: LinuxSllPayloadSlice<'a>) -> Result, Self::Error> { 26 | match value.protocol_type { 27 | LinuxSllProtocolType::LinuxNonstandardEtherType(nonstandard_ether_type) => { 28 | Ok(EtherPayloadSlice { 29 | ether_type: EtherType(nonstandard_ether_type.into()), 30 | len_source: LenSource::Slice, 31 | payload: value.payload, 32 | }) 33 | } 34 | LinuxSllProtocolType::EtherType(ether_type) => Ok(EtherPayloadSlice { 35 | ether_type, 36 | len_source: LenSource::Slice, 37 | payload: value.payload, 38 | }), 39 | _ => Err(()), 40 | } 41 | } 42 | } 43 | 44 | #[cfg(test)] 45 | mod test { 46 | use super::*; 47 | use alloc::format; 48 | 49 | #[test] 50 | fn debug() { 51 | let s = LinuxSllPayloadSlice { 52 | protocol_type: LinuxSllProtocolType::EtherType(EtherType::IPV4), 53 | payload: &[], 54 | }; 55 | assert_eq!( 56 | format!( 57 | "LinuxSllPayloadSlice {{ protocol_type: {:?}, payload: {:?} }}", 58 | s.protocol_type, s.payload 59 | ), 60 | format!("{:?}", s) 61 | ); 62 | } 63 | 64 | #[test] 65 | fn clone_eq() { 66 | let s = LinuxSllPayloadSlice { 67 | protocol_type: LinuxSllProtocolType::EtherType(EtherType::IPV4), 68 | payload: &[], 69 | }; 70 | assert_eq!(s.clone(), s); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /etherparse/src/link/macsec_payload_slice.rs: -------------------------------------------------------------------------------- 1 | use super::EtherPayloadSlice; 2 | 3 | #[derive(Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)] 4 | pub enum MacsecPayloadSlice<'a> { 5 | /// Unencrypted unmodified ether payload. 6 | Unmodified(EtherPayloadSlice<'a>), 7 | 8 | /// Modified payload (either by encryption or other algorithm). 9 | Modified(&'a [u8]), 10 | } 11 | -------------------------------------------------------------------------------- /etherparse/src/link/macsec_ptype.rs: -------------------------------------------------------------------------------- 1 | use super::EtherType; 2 | 3 | /// Encryption & modification state of the payload 4 | /// of a mac sec packet including the next ether type if 5 | /// the payload is unencrypted & unmodified. 6 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] 7 | pub enum MacsecPType { 8 | /// Unencrypted & unmodified (`!tci.c && !tci.e`) containing 9 | /// the ether type of the after the mac sec. 10 | Unmodified(EtherType), 11 | 12 | /// Unencrypted but modified payload (`tci.c && !tci.e`). 13 | Modified, 14 | 15 | /// Encrypted and modified payload (`tci.c && tci.e`). 16 | Encrypted, 17 | 18 | /// Encrypted and unmodified payload (`tci.c && !tci.e`). 19 | /// This is not normal behavior. 20 | /// 21 | /// Normally if the "encryption" flag should always be set 22 | /// together with the modification flag. 23 | EncryptedUnmodified, 24 | } 25 | -------------------------------------------------------------------------------- /etherparse/src/link/mod.rs: -------------------------------------------------------------------------------- 1 | mod double_vlan_header; 2 | pub use double_vlan_header::*; 3 | 4 | mod double_vlan_slice; 5 | pub use double_vlan_slice::*; 6 | 7 | mod ether_payload_slice; 8 | pub use ether_payload_slice::*; 9 | 10 | mod ether_type_impl; 11 | pub use ether_type_impl::*; 12 | 13 | mod ethernet2_header; 14 | pub use ethernet2_header::*; 15 | 16 | mod ethernet2_header_slice; 17 | pub use ethernet2_header_slice::*; 18 | 19 | mod ethernet2_slice; 20 | pub use ethernet2_slice::*; 21 | 22 | mod lax_ether_payload_slice; 23 | pub use lax_ether_payload_slice::*; 24 | 25 | mod lax_link_ext_slice; 26 | pub use lax_link_ext_slice::*; 27 | 28 | mod lax_macsec_payload_slice; 29 | pub use lax_macsec_payload_slice::*; 30 | 31 | mod lax_macsec_slice; 32 | pub use lax_macsec_slice::*; 33 | 34 | mod link_ext_header; 35 | pub use link_ext_header::*; 36 | 37 | mod link_ext_slice; 38 | pub use link_ext_slice::*; 39 | 40 | mod link_header; 41 | pub use link_header::*; 42 | 43 | mod link_slice; 44 | pub use link_slice::*; 45 | 46 | mod linux_nonstandard_ether_type; 47 | pub use linux_nonstandard_ether_type::*; 48 | 49 | mod linux_sll_header; 50 | pub use linux_sll_header::*; 51 | 52 | mod linux_sll_header_slice; 53 | pub use linux_sll_header_slice::*; 54 | 55 | mod linux_sll_packet_type; 56 | pub use linux_sll_packet_type::*; 57 | 58 | mod linux_sll_payload_slice; 59 | pub use linux_sll_payload_slice::*; 60 | 61 | mod linux_sll_protocol_type; 62 | pub use linux_sll_protocol_type::*; 63 | 64 | mod linux_sll_slice; 65 | pub use linux_sll_slice::*; 66 | 67 | mod macsec_an; 68 | pub use macsec_an::*; 69 | 70 | mod macsec_header_slice; 71 | pub use macsec_header_slice::*; 72 | 73 | mod macsec_header; 74 | pub use macsec_header::*; 75 | 76 | mod macsec_payload_slice; 77 | pub use macsec_payload_slice::*; 78 | 79 | mod macsec_short_len; 80 | pub use macsec_short_len::*; 81 | 82 | mod macsec_slice; 83 | pub use macsec_slice::*; 84 | 85 | mod macsec_ptype; 86 | pub use macsec_ptype::*; 87 | 88 | mod single_vlan_header; 89 | pub use single_vlan_header::*; 90 | 91 | mod single_vlan_header_slice; 92 | pub use single_vlan_header_slice::*; 93 | 94 | mod single_vlan_slice; 95 | pub use single_vlan_slice::*; 96 | 97 | mod vlan_header; 98 | pub use vlan_header::*; 99 | 100 | mod vlan_id; 101 | pub use vlan_id::*; 102 | 103 | mod vlan_pcp; 104 | pub use vlan_pcp::*; 105 | 106 | mod vlan_slice; 107 | pub use vlan_slice::*; 108 | -------------------------------------------------------------------------------- /etherparse/src/link/vlan_header.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | 3 | /// IEEE 802.1Q VLAN Tagging Header (can be single or double tagged). 4 | #[derive(Clone, Debug, Eq, PartialEq)] 5 | pub enum VlanHeader { 6 | /// IEEE 802.1Q VLAN Tagging Header 7 | Single(SingleVlanHeader), 8 | /// IEEE 802.1Q double VLAN Tagging Header 9 | Double(DoubleVlanHeader), 10 | } 11 | 12 | impl VlanHeader { 13 | /// All ether types that identify a vlan header. 14 | pub const VLAN_ETHER_TYPES: [EtherType; 3] = [ 15 | ether_type::VLAN_TAGGED_FRAME, 16 | ether_type::PROVIDER_BRIDGING, 17 | ether_type::VLAN_DOUBLE_TAGGED_FRAME, 18 | ]; 19 | 20 | /// Returns the ether type of the next header after the vlan header(s). 21 | #[inline] 22 | pub fn next_header(&self) -> EtherType { 23 | match self { 24 | VlanHeader::Single(s) => s.ether_type, 25 | VlanHeader::Double(d) => d.inner.ether_type, 26 | } 27 | } 28 | } 29 | 30 | #[cfg(test)] 31 | mod test { 32 | use super::*; 33 | use crate::test_gens::*; 34 | use alloc::format; 35 | use proptest::prelude::*; 36 | 37 | #[test] 38 | fn constants() { 39 | use ether_type::*; 40 | use VlanHeader as V; 41 | 42 | assert_eq!(3, V::VLAN_ETHER_TYPES.len()); 43 | assert_eq!(VLAN_TAGGED_FRAME, V::VLAN_ETHER_TYPES[0]); 44 | assert_eq!(PROVIDER_BRIDGING, V::VLAN_ETHER_TYPES[1]); 45 | assert_eq!(VLAN_DOUBLE_TAGGED_FRAME, V::VLAN_ETHER_TYPES[2]); 46 | } 47 | 48 | proptest! { 49 | #[test] 50 | fn clone_eq( 51 | single in vlan_single_any(), 52 | double in vlan_double_any(), 53 | ) { 54 | // single eq 55 | { 56 | let value = VlanHeader::Single(single.clone()); 57 | assert_eq!(value, value.clone()); 58 | } 59 | // double 60 | { 61 | let value = VlanHeader::Double(double); 62 | assert_eq!(value, value.clone()); 63 | } 64 | } 65 | } 66 | 67 | proptest! { 68 | #[test] 69 | fn dbg( 70 | single in vlan_single_any(), 71 | double in vlan_double_any(), 72 | ) { 73 | // single 74 | { 75 | let value = VlanHeader::Single(single.clone()); 76 | assert_eq!( 77 | &format!( 78 | "Single({:?})", 79 | single 80 | ), 81 | &format!("{:?}", value) 82 | ); 83 | } 84 | // double 85 | { 86 | let value = VlanHeader::Double(double.clone()); 87 | assert_eq!( 88 | &format!( 89 | "Double({:?})", 90 | double 91 | ), 92 | &format!("{:?}", value) 93 | ); 94 | } 95 | } 96 | } 97 | 98 | proptest! { 99 | #[test] 100 | fn next_header( 101 | single in vlan_single_any(), 102 | double in vlan_double_any(), 103 | ) { 104 | // single 105 | { 106 | let value = VlanHeader::Single(single.clone()); 107 | assert_eq!(value.next_header(), single.ether_type); 108 | } 109 | // double 110 | { 111 | let value = VlanHeader::Double(double.clone()); 112 | assert_eq!(value.next_header(), double.inner.ether_type); 113 | } 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /etherparse/src/net/arp_operation.rs: -------------------------------------------------------------------------------- 1 | /// Operation field value in an ARP packet. 2 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)] 3 | pub struct ArpOperation(pub u16); 4 | 5 | impl ArpOperation { 6 | pub const REQUEST: ArpOperation = ArpOperation(1); 7 | pub const REPLY: ArpOperation = ArpOperation(2); 8 | } 9 | 10 | impl From for ArpOperation { 11 | #[inline] 12 | fn from(raw: u16) -> Self { 13 | ArpOperation(raw) 14 | } 15 | } 16 | 17 | #[cfg(test)] 18 | mod tests { 19 | use crate::ArpOperation; 20 | 21 | #[test] 22 | pub fn from_u16() { 23 | assert_eq!(ArpOperation::from(12), ArpOperation(12)) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /etherparse/src/net/ip_payload_slice.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | 3 | /// Payload of an IP packet. 4 | #[derive(Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)] 5 | pub struct IpPayloadSlice<'a> { 6 | /// Identifying content of the payload. 7 | pub ip_number: IpNumber, 8 | 9 | /// True if the payload is not complete and has been fragmented. 10 | /// 11 | /// This can occur if the IPv4 indicates that the payload 12 | /// has been fragmented or if there is an IPv6 fragmentation 13 | /// header indicating that the payload has been fragmented. 14 | pub fragmented: bool, 15 | 16 | /// Length field that was used to determine the length 17 | /// of the payload (e.g. IPv6 "payload_length" field). 18 | pub len_source: LenSource, 19 | 20 | /// Payload 21 | pub payload: &'a [u8], 22 | } 23 | 24 | #[cfg(test)] 25 | mod test { 26 | use super::*; 27 | use alloc::format; 28 | 29 | #[test] 30 | fn debug() { 31 | let s = IpPayloadSlice { 32 | ip_number: IpNumber::UDP, 33 | fragmented: true, 34 | len_source: LenSource::Slice, 35 | payload: &[], 36 | }; 37 | assert_eq!( 38 | format!( 39 | "IpPayloadSlice {{ ip_number: {:?}, fragmented: {:?}, len_source: {:?}, payload: {:?} }}", 40 | s.ip_number, 41 | s.fragmented, 42 | s.len_source, 43 | s.payload 44 | ), 45 | format!("{:?}", s) 46 | ); 47 | } 48 | 49 | #[test] 50 | fn clone_eq_hash_ord() { 51 | let s = IpPayloadSlice { 52 | ip_number: IpNumber::UDP, 53 | fragmented: true, 54 | len_source: LenSource::Slice, 55 | payload: &[], 56 | }; 57 | assert_eq!(s.clone(), s); 58 | 59 | use std::collections::hash_map::DefaultHasher; 60 | use std::hash::{Hash, Hasher}; 61 | 62 | let a_hash = { 63 | let mut hasher = DefaultHasher::new(); 64 | s.hash(&mut hasher); 65 | hasher.finish() 66 | }; 67 | let b_hash = { 68 | let mut hasher = DefaultHasher::new(); 69 | s.clone().hash(&mut hasher); 70 | hasher.finish() 71 | }; 72 | assert_eq!(a_hash, b_hash); 73 | 74 | use std::cmp::Ordering; 75 | assert_eq!(s.clone().cmp(&s), Ordering::Equal); 76 | assert_eq!(s.clone().partial_cmp(&s), Some(Ordering::Equal)); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /etherparse/src/net/ipv6_routing_exts.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | 3 | /// In case a route header is present it is also possible 4 | /// to attach a "final destination" header. 5 | #[derive(Clone, Debug, Eq, PartialEq)] 6 | pub struct Ipv6RoutingExtensions { 7 | pub routing: Ipv6RawExtHeader, 8 | pub final_destination_options: Option, 9 | } 10 | 11 | impl Ipv6RoutingExtensions { 12 | /// Minimum length required for routing extension headers in bytes/octets. 13 | pub const MIN_LEN: usize = Ipv6RawExtHeader::MAX_LEN; 14 | 15 | /// Maximum summed up length of all extension headers in bytes/octets. 16 | pub const MAX_LEN: usize = Ipv6RawExtHeader::MAX_LEN * 2; 17 | 18 | /// Return the length of the headers in bytes. 19 | pub fn header_len(&self) -> usize { 20 | self.routing.header_len() 21 | + self 22 | .final_destination_options 23 | .as_ref() 24 | .map(|h| h.header_len()) 25 | .unwrap_or(0) 26 | } 27 | } 28 | 29 | #[cfg(test)] 30 | mod tests { 31 | use super::*; 32 | use crate::test_gens::ipv6_raw_ext_any; 33 | use proptest::prelude::*; 34 | 35 | #[test] 36 | fn debug() { 37 | use alloc::format; 38 | 39 | let a: Ipv6RoutingExtensions = Ipv6RoutingExtensions { 40 | routing: Ipv6RawExtHeader::new_raw(0.into(), &[0; 6]).unwrap(), 41 | final_destination_options: None, 42 | }; 43 | assert_eq!( 44 | &format!( 45 | "Ipv6RoutingExtensions {{ routing: {:?}, final_destination_options: {:?} }}", 46 | a.routing, a.final_destination_options, 47 | ), 48 | &format!("{:?}", a) 49 | ); 50 | } 51 | 52 | #[test] 53 | fn clone_eq() { 54 | let a: Ipv6RoutingExtensions = Ipv6RoutingExtensions { 55 | routing: Ipv6RawExtHeader::new_raw(0.into(), &[0; 6]).unwrap(), 56 | final_destination_options: None, 57 | }; 58 | assert_eq!(a, a.clone()); 59 | } 60 | 61 | proptest! { 62 | #[test] 63 | fn header_len( 64 | routing in ipv6_raw_ext_any(), 65 | final_destination_options in ipv6_raw_ext_any() 66 | ) { 67 | // without final dest options 68 | assert_eq!( 69 | Ipv6RoutingExtensions{ 70 | routing: routing.clone(), 71 | final_destination_options: None, 72 | }.header_len(), 73 | routing.header_len() 74 | ); 75 | 76 | // with final dest options 77 | assert_eq!( 78 | Ipv6RoutingExtensions{ 79 | routing: routing.clone(), 80 | final_destination_options: Some(final_destination_options.clone()), 81 | }.header_len(), 82 | routing.header_len() + final_destination_options.header_len() 83 | ); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /etherparse/src/net/lax_ip_payload_slice.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | 3 | /// Laxly identified payload of an IP packet (potentially incomplete). 4 | /// 5 | /// To check if the payload is complete check the `incomplete` field. 6 | #[derive(Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)] 7 | pub struct LaxIpPayloadSlice<'a> { 8 | /// True if the length field in the IP header indicates more data 9 | /// should be present but it was not (aka the packet data is cut off). 10 | /// 11 | /// Note that this different from fragmentation. If a packet is 12 | /// fragmented the length field in the individual IP headers is 13 | /// still correctly set. 14 | pub incomplete: bool, 15 | 16 | /// Identifying content of the payload. 17 | pub ip_number: IpNumber, 18 | 19 | /// True if the payload is not complete and has been fragmented. 20 | /// 21 | /// This can occur if the IPv4 incdicates that the payload 22 | /// has been fragmented or if there is an IPv6 fragmentation 23 | /// header indicating that the payload has been fragmented. 24 | pub fragmented: bool, 25 | 26 | /// Length field that was used to determine the length 27 | /// of the payload (e.g. IPv6 "payload_length" field). 28 | pub len_source: LenSource, 29 | 30 | /// Payload 31 | pub payload: &'a [u8], 32 | } 33 | 34 | #[cfg(test)] 35 | mod test { 36 | use super::*; 37 | use alloc::format; 38 | 39 | #[test] 40 | fn debug() { 41 | let s = LaxIpPayloadSlice { 42 | incomplete: false, 43 | ip_number: IpNumber::UDP, 44 | fragmented: true, 45 | len_source: LenSource::Slice, 46 | payload: &[], 47 | }; 48 | assert_eq!( 49 | format!( 50 | "LaxIpPayloadSlice {{ incomplete: {:?}, ip_number: {:?}, fragmented: {:?}, len_source: {:?}, payload: {:?} }}", 51 | s.incomplete, 52 | s.ip_number, 53 | s.fragmented, 54 | s.len_source, 55 | s.payload 56 | ), 57 | format!("{:?}", s) 58 | ); 59 | } 60 | 61 | #[test] 62 | fn clone_eq_hash_ord() { 63 | let s = LaxIpPayloadSlice { 64 | incomplete: false, 65 | ip_number: IpNumber::UDP, 66 | fragmented: true, 67 | len_source: LenSource::Slice, 68 | payload: &[], 69 | }; 70 | assert_eq!(s.clone(), s); 71 | 72 | use std::collections::hash_map::DefaultHasher; 73 | use std::hash::{Hash, Hasher}; 74 | 75 | let a_hash = { 76 | let mut hasher = DefaultHasher::new(); 77 | s.hash(&mut hasher); 78 | hasher.finish() 79 | }; 80 | let b_hash = { 81 | let mut hasher = DefaultHasher::new(); 82 | s.clone().hash(&mut hasher); 83 | hasher.finish() 84 | }; 85 | assert_eq!(a_hash, b_hash); 86 | 87 | use std::cmp::Ordering; 88 | assert_eq!(s.clone().cmp(&s), Ordering::Equal); 89 | assert_eq!(s.clone().partial_cmp(&s), Some(Ordering::Equal)); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /etherparse/src/net/mod.rs: -------------------------------------------------------------------------------- 1 | mod arp_eth_ipv4_packet; 2 | pub use arp_eth_ipv4_packet::*; 3 | 4 | mod arp_hardware_id; 5 | pub use arp_hardware_id::*; 6 | 7 | mod arp_packet; 8 | pub use arp_packet::*; 9 | 10 | mod arp_operation; 11 | pub use arp_operation::*; 12 | 13 | mod ip_auth_header; 14 | pub use ip_auth_header::*; 15 | 16 | mod ip_auth_header_slice; 17 | pub use ip_auth_header_slice::*; 18 | 19 | mod ip_dscp; 20 | pub use ip_dscp::*; 21 | 22 | mod ip_dscp_known; 23 | pub use ip_dscp_known::*; 24 | 25 | mod ip_ecn; 26 | pub use ip_ecn::*; 27 | 28 | mod ip_frag_offset; 29 | pub use ip_frag_offset::*; 30 | 31 | mod ip_headers; 32 | pub use ip_headers::*; 33 | 34 | mod ip_number_impl; 35 | pub use ip_number_impl::*; 36 | 37 | mod ip_payload_slice; 38 | pub use ip_payload_slice::*; 39 | 40 | mod ip_slice; 41 | pub use ip_slice::*; 42 | 43 | mod ipv4_exts; 44 | pub use ipv4_exts::*; 45 | 46 | mod ipv4_exts_slice; 47 | pub use ipv4_exts_slice::*; 48 | 49 | mod ipv4_header; 50 | pub use ipv4_header::*; 51 | 52 | mod ipv4_header_slice; 53 | pub use ipv4_header_slice::*; 54 | 55 | mod ipv4_options; 56 | pub use ipv4_options::*; 57 | 58 | mod ipv4_slice; 59 | pub use ipv4_slice::*; 60 | 61 | mod ipv6_ext_slice; 62 | pub use ipv6_ext_slice::*; 63 | 64 | mod ipv6_ext_slice_iter; 65 | pub use ipv6_ext_slice_iter::*; 66 | 67 | mod ipv6_exts; 68 | pub use ipv6_exts::*; 69 | 70 | mod ipv6_exts_slice; 71 | pub use ipv6_exts_slice::*; 72 | 73 | mod ipv6_flow_label; 74 | pub use ipv6_flow_label::*; 75 | 76 | mod ipv6_fragment_header; 77 | pub use ipv6_fragment_header::*; 78 | 79 | mod ipv6_fragment_header_slice; 80 | pub use ipv6_fragment_header_slice::*; 81 | 82 | mod ipv6_header; 83 | pub use ipv6_header::*; 84 | 85 | mod ipv6_header_slice; 86 | pub use ipv6_header_slice::*; 87 | 88 | mod ipv6_raw_ext_header; 89 | pub use ipv6_raw_ext_header::*; 90 | 91 | mod ipv6_raw_ext_header_slice; 92 | pub use ipv6_raw_ext_header_slice::*; 93 | 94 | mod ipv6_routing_exts; 95 | pub use ipv6_routing_exts::*; 96 | 97 | mod ipv6_slice; 98 | pub use ipv6_slice::*; 99 | 100 | mod lax_ip_payload_slice; 101 | pub use lax_ip_payload_slice::*; 102 | 103 | mod lax_ip_slice; 104 | pub use lax_ip_slice::*; 105 | 106 | mod lax_ipv4_slice; 107 | pub use lax_ipv4_slice::*; 108 | 109 | mod lax_ipv6_slice; 110 | pub use lax_ipv6_slice::*; 111 | 112 | mod lax_net_slice; 113 | pub use lax_net_slice::*; 114 | 115 | mod net_headers; 116 | pub use net_headers::*; 117 | 118 | mod net_slice; 119 | pub use net_slice::*; 120 | 121 | mod arp_packet_slice; 122 | pub use arp_packet_slice::*; 123 | -------------------------------------------------------------------------------- /etherparse/src/transport/icmp_echo_header.rs: -------------------------------------------------------------------------------- 1 | /// Echo Request & Response common parts between ICMPv4 and ICMPv6. 2 | /// 3 | /// # RFC 4443 Description (ICMPv6) 4 | /// 5 | /// Every node MUST implement an ICMPv6 Echo responder function that 6 | /// receives Echo Requests and originates corresponding Echo Replies. A 7 | /// node SHOULD also implement an application-layer interface for 8 | /// originating Echo Requests and receiving Echo Replies, for diagnostic 9 | /// purposes. 10 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] 11 | pub struct IcmpEchoHeader { 12 | /// An identifier to aid in matching Echo Replies to Echo Requests. May be zero. 13 | pub id: u16, 14 | /// A sequence number to aid in matching Echo Replies to Echo Requests. May be zero. 15 | pub seq: u16, 16 | } 17 | 18 | impl IcmpEchoHeader { 19 | /// Serialized size of an IcmpEchoHeader header in bytes/octets. 20 | pub const LEN: usize = 4; 21 | 22 | /// Return the seq + id encoded to the on the wire format. 23 | #[inline] 24 | pub fn to_bytes(&self) -> [u8; 4] { 25 | let id_be = self.id.to_be_bytes(); 26 | let seq_be = self.seq.to_be_bytes(); 27 | [id_be[0], id_be[1], seq_be[0], seq_be[1]] 28 | } 29 | 30 | /// Decodes the seq + id from the on the wire format. 31 | #[inline] 32 | pub fn from_bytes(bytes5to8: [u8; 4]) -> IcmpEchoHeader { 33 | IcmpEchoHeader { 34 | id: u16::from_be_bytes([bytes5to8[0], bytes5to8[1]]), 35 | seq: u16::from_be_bytes([bytes5to8[2], bytes5to8[3]]), 36 | } 37 | } 38 | } 39 | 40 | #[cfg(test)] 41 | mod test { 42 | use crate::*; 43 | use alloc::format; 44 | use proptest::prelude::*; 45 | 46 | proptest! { 47 | #[test] 48 | fn to_bytes( 49 | id in any::(), 50 | seq in any::() 51 | ) { 52 | let id_bytes = id.to_be_bytes(); 53 | let seq_bytes = seq.to_be_bytes(); 54 | assert_eq!( 55 | IcmpEchoHeader{ id, seq }.to_bytes(), 56 | [ 57 | id_bytes[0], id_bytes[1], 58 | seq_bytes[0], seq_bytes[1] 59 | ] 60 | ); 61 | } 62 | 63 | #[test] 64 | fn from_bytes( 65 | bytes in any::<[u8;4]>() 66 | ) { 67 | assert_eq!( 68 | IcmpEchoHeader::from_bytes(bytes), 69 | IcmpEchoHeader { 70 | id: u16::from_be_bytes([bytes[0], bytes[1]]), 71 | seq: u16::from_be_bytes([bytes[2], bytes[3]]) 72 | } 73 | ); 74 | } 75 | 76 | #[test] 77 | fn clone_eq( 78 | id in any::(), 79 | seq in any::() 80 | ) { 81 | let value = IcmpEchoHeader{ id, seq }; 82 | assert_eq!(value.clone(), value); 83 | } 84 | 85 | #[test] 86 | fn debug( 87 | id in any::(), 88 | seq in any::() 89 | ) { 90 | assert_eq!( 91 | format!("{:?}", IcmpEchoHeader{ id, seq }), 92 | format!("IcmpEchoHeader {{ id: {:?}, seq: {:?} }}", id, seq) 93 | ); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /etherparse/src/transport/icmpv4/parameter_problem_header.rs: -------------------------------------------------------------------------------- 1 | /// The header of an ICMPv4 Parameter Problems (contents up to 2 | /// the offending ip header). 3 | #[derive(Clone, Debug, PartialEq, Eq)] 4 | pub enum ParameterProblemHeader { 5 | /// Identifies the octet where an error was detected. 6 | /// 7 | /// The value is the pointer pointing to the offending octet in 8 | /// the offending packet. 9 | PointerIndicatesError(u8), 10 | /// Missing a Required Option 11 | MissingRequiredOption, 12 | /// Bad Length 13 | BadLength, 14 | } 15 | 16 | impl ParameterProblemHeader { 17 | /// Tries to convert the code [`u8`] value and pointer to a [`ParameterProblemHeader`] value. 18 | /// 19 | /// Returns [`None`] in case the code value is not known as a parameter problem code. 20 | pub fn from_values(code_u8: u8, pointer: u8) -> Option { 21 | use super::{ParameterProblemHeader::*, *}; 22 | match code_u8 { 23 | CODE_PARAMETER_PROBLEM_POINTER_INDICATES_ERROR => Some(PointerIndicatesError(pointer)), 24 | CODE_PARAMETER_PROBLEM_MISSING_REQUIRED_OPTION => Some(MissingRequiredOption), 25 | CODE_PARAMETER_PROBLEM_BAD_LENGTH => Some(BadLength), 26 | _ => None, 27 | } 28 | } 29 | } 30 | 31 | #[cfg(test)] 32 | mod test { 33 | use crate::icmpv4::{ParameterProblemHeader::*, *}; 34 | use alloc::format; 35 | use proptest::prelude::*; 36 | 37 | proptest! { 38 | #[test] 39 | fn from_values(pointer in any::()) { 40 | { 41 | let tests = [ 42 | (CODE_PARAMETER_PROBLEM_POINTER_INDICATES_ERROR, PointerIndicatesError(pointer)), 43 | (CODE_PARAMETER_PROBLEM_MISSING_REQUIRED_OPTION, MissingRequiredOption), 44 | (CODE_PARAMETER_PROBLEM_BAD_LENGTH, BadLength), 45 | ]; 46 | for t in tests { 47 | assert_eq!(Some(t.1), ParameterProblemHeader::from_values(t.0, pointer)); 48 | } 49 | } 50 | for code_u8 in 3..=u8::MAX { 51 | assert_eq!(None, ParameterProblemHeader::from_values(code_u8, pointer)); 52 | } 53 | } 54 | } 55 | 56 | #[test] 57 | fn clone_eq() { 58 | let tests = [PointerIndicatesError(0), MissingRequiredOption, BadLength]; 59 | for t in tests { 60 | assert_eq!(t.clone(), t); 61 | } 62 | } 63 | 64 | #[test] 65 | fn debug() { 66 | let tests = [ 67 | ("PointerIndicatesError(0)", PointerIndicatesError(0)), 68 | ("MissingRequiredOption", MissingRequiredOption), 69 | ("BadLength", BadLength), 70 | ]; 71 | for t in tests { 72 | assert_eq!(t.0, format!("{:?}", t.1)); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /etherparse/src/transport/icmpv4/redirect_header.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[derive(Clone, Debug, PartialEq, Eq)] 4 | pub struct RedirectHeader { 5 | pub code: RedirectCode, 6 | pub gateway_internet_address: [u8; 4], 7 | } 8 | 9 | #[cfg(test)] 10 | mod test { 11 | use crate::icmpv4::{RedirectCode::*, *}; 12 | use alloc::format; 13 | 14 | #[test] 15 | fn clone_eq() { 16 | let v = RedirectHeader { 17 | code: RedirectForNetwork, 18 | gateway_internet_address: [0; 4], 19 | }; 20 | assert_eq!(v.clone(), v); 21 | } 22 | 23 | #[test] 24 | fn debug() { 25 | let v = RedirectHeader { 26 | code: RedirectForNetwork, 27 | gateway_internet_address: [0; 4], 28 | }; 29 | assert_eq!( 30 | format!("{:?}", v), 31 | format!( 32 | "RedirectHeader {{ code: {:?}, gateway_internet_address: {:?} }}", 33 | v.code, v.gateway_internet_address 34 | ) 35 | ); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /etherparse/src/transport/icmpv4/time_exceeded_code.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | /// Code values for ICMPv4 time exceeded message. 4 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] 5 | pub enum TimeExceededCode { 6 | /// Time-to-live exceeded in transit. 7 | TtlExceededInTransit = 0, 8 | /// Fragment reassembly time exceeded. 9 | FragmentReassemblyTimeExceeded = 1, 10 | } 11 | 12 | impl TimeExceededCode { 13 | /// Tries to convert a code [`u8`] value to a [`TimeExceededCode`] value. 14 | /// 15 | /// Returns [`None`] in case the code value is not known as a time exceeded code. 16 | #[inline] 17 | pub fn from_u8(code_u8: u8) -> Option { 18 | use TimeExceededCode::*; 19 | match code_u8 { 20 | CODE_TIME_EXCEEDED_TTL_EXCEEDED_IN_TRANSIT => Some(TtlExceededInTransit), 21 | CODE_TIME_EXCEEDED_FRAG_REASSEMBLY_TIME_EXCEEDED => { 22 | Some(FragmentReassemblyTimeExceeded) 23 | } 24 | _ => None, 25 | } 26 | } 27 | 28 | /// Returns the [`u8`] value of the code. 29 | #[inline] 30 | pub fn code_u8(&self) -> u8 { 31 | *self as u8 32 | } 33 | } 34 | 35 | #[cfg(test)] 36 | mod test { 37 | use crate::icmpv4::{TimeExceededCode::*, *}; 38 | use alloc::format; 39 | 40 | #[test] 41 | fn from_u8() { 42 | assert_eq!( 43 | TimeExceededCode::from_u8(CODE_TIME_EXCEEDED_TTL_EXCEEDED_IN_TRANSIT), 44 | Some(TtlExceededInTransit) 45 | ); 46 | assert_eq!( 47 | TimeExceededCode::from_u8(CODE_TIME_EXCEEDED_FRAG_REASSEMBLY_TIME_EXCEEDED), 48 | Some(FragmentReassemblyTimeExceeded) 49 | ); 50 | 51 | for code_u8 in 2..=u8::MAX { 52 | assert_eq!(None, TimeExceededCode::from_u8(code_u8)); 53 | } 54 | } 55 | 56 | #[test] 57 | fn code_u8() { 58 | assert_eq!( 59 | TtlExceededInTransit.code_u8(), 60 | CODE_TIME_EXCEEDED_TTL_EXCEEDED_IN_TRANSIT 61 | ); 62 | assert_eq!( 63 | FragmentReassemblyTimeExceeded.code_u8(), 64 | CODE_TIME_EXCEEDED_FRAG_REASSEMBLY_TIME_EXCEEDED 65 | ); 66 | } 67 | 68 | #[test] 69 | fn debug() { 70 | let values = [ 71 | ("TtlExceededInTransit", TtlExceededInTransit), 72 | ( 73 | "FragmentReassemblyTimeExceeded", 74 | FragmentReassemblyTimeExceeded, 75 | ), 76 | ]; 77 | for (expected, input) in values { 78 | assert_eq!(expected, format!("{:?}", input)); 79 | } 80 | } 81 | 82 | #[test] 83 | fn clone_eq() { 84 | let values = [TtlExceededInTransit, FragmentReassemblyTimeExceeded]; 85 | for value in values { 86 | assert_eq!(value.clone(), value); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /etherparse/src/transport/icmpv4/timestamp_message.rs: -------------------------------------------------------------------------------- 1 | /// A ICMPv4 timestamp or timestamp response message. 2 | #[derive(Clone, Debug, PartialEq, Eq)] 3 | pub struct TimestampMessage { 4 | pub id: u16, 5 | pub seq: u16, 6 | pub originate_timestamp: u32, 7 | pub receive_timestamp: u32, 8 | pub transmit_timestamp: u32, 9 | } 10 | 11 | impl TimestampMessage { 12 | /// Deprecated use [`TimestampMessage::LEN`] instead. 13 | #[deprecated(since = "0.14.0", note = "Use `TimestampMessage::LEN` instead")] 14 | pub const SERIALIZED_SIZE: usize = 20; 15 | 16 | /// The size in bytes/octets of a timestamp request or timestamp response message. 17 | pub const LEN: usize = 20; 18 | 19 | /// Decodes the timestamp message part of an ICMPv4 message. 20 | pub fn from_bytes(bytes: [u8; 16]) -> TimestampMessage { 21 | TimestampMessage { 22 | id: u16::from_be_bytes([bytes[0], bytes[1]]), 23 | seq: u16::from_be_bytes([bytes[2], bytes[3]]), 24 | originate_timestamp: u32::from_be_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]), 25 | receive_timestamp: u32::from_be_bytes([bytes[8], bytes[9], bytes[10], bytes[11]]), 26 | transmit_timestamp: u32::from_be_bytes([bytes[12], bytes[13], bytes[14], bytes[15]]), 27 | } 28 | } 29 | } 30 | 31 | #[cfg(test)] 32 | mod test { 33 | use crate::icmpv4::*; 34 | use alloc::format; 35 | use proptest::prelude::*; 36 | 37 | #[test] 38 | fn constants() { 39 | assert_eq!(20, TimestampMessage::LEN); 40 | } 41 | 42 | proptest! { 43 | #[test] 44 | fn from_bytes(bytes in any::<[u8;16]>()) { 45 | assert_eq!( 46 | TimestampMessage::from_bytes(bytes), 47 | TimestampMessage{ 48 | id: u16::from_be_bytes([bytes[0], bytes[1]]), 49 | seq: u16::from_be_bytes([bytes[2], bytes[3]]), 50 | originate_timestamp: u32::from_be_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]), 51 | receive_timestamp: u32::from_be_bytes([bytes[8], bytes[9], bytes[10], bytes[11]]), 52 | transmit_timestamp: u32::from_be_bytes([bytes[12], bytes[13], bytes[14], bytes[15]]), 53 | } 54 | ); 55 | } 56 | } 57 | 58 | #[test] 59 | fn clone_eq() { 60 | let v = TimestampMessage { 61 | id: 0, 62 | seq: 0, 63 | originate_timestamp: 0, 64 | receive_timestamp: 0, 65 | transmit_timestamp: 0, 66 | }; 67 | assert_eq!(v.clone(), v); 68 | } 69 | 70 | #[test] 71 | fn debug() { 72 | let v = TimestampMessage { 73 | id: 0, 74 | seq: 0, 75 | originate_timestamp: 0, 76 | receive_timestamp: 0, 77 | transmit_timestamp: 0, 78 | }; 79 | assert_eq!( 80 | format!("{:?}", v), 81 | format!( 82 | "TimestampMessage {{ id: {:?}, seq: {:?}, originate_timestamp: {:?}, receive_timestamp: {:?}, transmit_timestamp: {:?} }}", 83 | v.id, 84 | v.seq, 85 | v.originate_timestamp, 86 | v.receive_timestamp, 87 | v.transmit_timestamp, 88 | ) 89 | ); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /etherparse/src/transport/icmpv6/parameter_problem_header.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | /// ICMPv6 parameter problem header. 4 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] 5 | pub struct ParameterProblemHeader { 6 | /// The code can offer additional informations about what kind of parameter 7 | /// problem caused the error. 8 | pub code: ParameterProblemCode, 9 | /// Identifies the octet offset within the 10 | /// invoking packet where the error was detected. 11 | /// 12 | /// The pointer will point beyond the end of the ICMPv6 13 | /// packet if the field in error is beyond what can fit 14 | /// in the maximum size of an ICMPv6 error message. 15 | pub pointer: u32, 16 | } 17 | 18 | #[cfg(test)] 19 | mod test { 20 | use super::*; 21 | use alloc::format; 22 | 23 | #[test] 24 | fn clone_eq() { 25 | let value = ParameterProblemHeader { 26 | code: ParameterProblemCode::ErroneousHeaderField, 27 | pointer: 0, 28 | }; 29 | assert_eq!(value.clone(), value); 30 | } 31 | 32 | #[test] 33 | fn debug() { 34 | let value = ParameterProblemHeader { 35 | code: ParameterProblemCode::ErroneousHeaderField, 36 | pointer: 0, 37 | }; 38 | 39 | assert_eq!( 40 | format!("{:?}", value), 41 | format!( 42 | "ParameterProblemHeader {{ code: {:?}, pointer: {:?} }}", 43 | value.code, value.pointer 44 | ) 45 | ); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /etherparse/src/transport/icmpv6/time_exceeded_code.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | /// Code values for ICMPv6 time exceeded message. 4 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] 5 | pub enum TimeExceededCode { 6 | /// "hop limit exceeded in transit" 7 | HopLimitExceeded = 0, 8 | /// "fragment reassembly time exceeded" 9 | FragmentReassemblyTimeExceeded = 1, 10 | } 11 | 12 | impl TimeExceededCode { 13 | /// Tries to convert a code [`u8`] value to a [`TimeExceededCode`] value. 14 | /// 15 | /// Returns [`None`] in case the code value is not known as a time exceeded code. 16 | #[inline] 17 | pub fn from_u8(code_u8: u8) -> Option { 18 | use TimeExceededCode::*; 19 | match code_u8 { 20 | CODE_TIME_EXCEEDED_HOP_LIMIT_EXCEEDED => Some(HopLimitExceeded), 21 | CODE_TIME_EXCEEDED_FRAGMENT_REASSEMBLY_TIME_EXCEEDED => { 22 | Some(FragmentReassemblyTimeExceeded) 23 | } 24 | _ => None, 25 | } 26 | } 27 | 28 | /// Returns the [`u8`] value of the code. 29 | #[inline] 30 | pub fn code_u8(&self) -> u8 { 31 | *self as u8 32 | } 33 | } 34 | 35 | #[cfg(test)] 36 | pub(crate) mod time_exceeded_code_test_consts { 37 | use super::{TimeExceededCode::*, *}; 38 | 39 | pub const VALID_VALUES: [(TimeExceededCode, u8); 2] = [ 40 | (HopLimitExceeded, CODE_TIME_EXCEEDED_HOP_LIMIT_EXCEEDED), 41 | ( 42 | FragmentReassemblyTimeExceeded, 43 | CODE_TIME_EXCEEDED_FRAGMENT_REASSEMBLY_TIME_EXCEEDED, 44 | ), 45 | ]; 46 | } 47 | 48 | #[cfg(test)] 49 | mod test { 50 | use super::{time_exceeded_code_test_consts::*, TimeExceededCode::*, *}; 51 | use alloc::format; 52 | 53 | #[test] 54 | fn from_u8() { 55 | for (code, code_u8) in VALID_VALUES { 56 | assert_eq!(Some(code), TimeExceededCode::from_u8(code_u8)); 57 | } 58 | for code_u8 in 2..=u8::MAX { 59 | assert_eq!(None, TimeExceededCode::from_u8(code_u8)); 60 | } 61 | } 62 | 63 | #[test] 64 | fn from_enum() { 65 | for (code, code_u8) in VALID_VALUES { 66 | assert_eq!(code.code_u8(), code_u8); 67 | } 68 | } 69 | 70 | #[test] 71 | fn clone_eq() { 72 | for (code, _) in VALID_VALUES { 73 | assert_eq!(code.clone(), code); 74 | } 75 | } 76 | 77 | #[test] 78 | fn debug() { 79 | let tests = [ 80 | (HopLimitExceeded, "HopLimitExceeded"), 81 | ( 82 | FragmentReassemblyTimeExceeded, 83 | "FragmentReassemblyTimeExceeded", 84 | ), 85 | ]; 86 | for test in tests { 87 | assert_eq!(format!("{:?}", test.0), test.1); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /etherparse/src/transport/mod.rs: -------------------------------------------------------------------------------- 1 | /// Module containing ICMPv4 related types and constants. 2 | pub mod icmpv4; 3 | 4 | /// Module containing ICMPv6 related types and constants 5 | pub mod icmpv6; 6 | 7 | mod icmp_echo_header; 8 | pub use icmp_echo_header::*; 9 | 10 | mod icmpv4_header; 11 | pub use icmpv4_header::*; 12 | 13 | mod icmpv4_slice; 14 | pub use icmpv4_slice::*; 15 | 16 | mod icmpv4_type; 17 | pub use icmpv4_type::*; 18 | 19 | mod icmpv6_header; 20 | pub use icmpv6_header::*; 21 | 22 | mod icmpv6_slice; 23 | pub use icmpv6_slice::*; 24 | 25 | mod icmpv6_type; 26 | pub use icmpv6_type::*; 27 | 28 | mod tcp_header; 29 | pub use tcp_header::*; 30 | 31 | mod tcp_header_slice; 32 | pub use tcp_header_slice::*; 33 | 34 | mod tcp_option_element; 35 | pub use tcp_option_element::*; 36 | 37 | mod tcp_option_impl; 38 | pub use tcp_option_impl::*; 39 | 40 | mod tcp_option_read_error; 41 | pub use tcp_option_read_error::*; 42 | 43 | mod tcp_option_write_error; 44 | pub use tcp_option_write_error::*; 45 | 46 | mod tcp_options; 47 | pub use tcp_options::*; 48 | 49 | mod tcp_options_iterator; 50 | pub use tcp_options_iterator::*; 51 | 52 | mod tcp_slice; 53 | pub use tcp_slice::*; 54 | 55 | mod transport_header; 56 | pub use transport_header::*; 57 | 58 | mod transport_slice; 59 | pub use transport_slice::*; 60 | 61 | mod udp_header; 62 | pub use udp_header::*; 63 | 64 | mod udp_header_slice; 65 | pub use udp_header_slice::*; 66 | 67 | mod udp_slice; 68 | pub use udp_slice::*; 69 | -------------------------------------------------------------------------------- /etherparse/src/transport/tcp_option_element.rs: -------------------------------------------------------------------------------- 1 | /// Different kinds of options that can be present in the options part of a tcp header. 2 | #[derive(Clone, Debug, Eq, PartialEq)] 3 | pub enum TcpOptionElement { 4 | /// "No-Operation" option. 5 | /// 6 | /// Description from RFC 793: 7 | /// 8 | /// This option code may be used between options, for example, to 9 | /// align the beginning of a subsequent option on a word boundary. 10 | /// There is no guarantee that senders will use this option, so 11 | /// receivers must be prepared to process options even if they do 12 | /// not begin on a word boundary. 13 | Noop, 14 | /// "Maximum Segment Size" option. 15 | /// 16 | /// Description from RFC 793: 17 | /// 18 | /// If this option is present, then it communicates the maximum 19 | /// receive segment size at the TCP which sends this segment. 20 | /// This field must only be sent in the initial connection request 21 | /// (i.e., in segments with the SYN control bit set). If this 22 | //// option is not used, any segment size is allowed. 23 | MaximumSegmentSize(u16), 24 | WindowScale(u8), 25 | SelectiveAcknowledgementPermitted, 26 | SelectiveAcknowledgement((u32, u32), [Option<(u32, u32)>; 3]), 27 | ///Timestamp & echo (first number is the sender timestamp, the second the echo timestamp) 28 | Timestamp(u32, u32), 29 | } 30 | 31 | #[cfg(test)] 32 | mod test { 33 | use crate::*; 34 | use alloc::format; 35 | 36 | #[test] 37 | fn clone_eq() { 38 | use TcpOptionElement::*; 39 | let values = [ 40 | Noop, 41 | MaximumSegmentSize(123), 42 | WindowScale(123), 43 | SelectiveAcknowledgementPermitted, 44 | SelectiveAcknowledgement((1, 2), [Some((3, 4)), Some((5, 6)), None]), 45 | Timestamp(123, 456), 46 | ]; 47 | for value in values { 48 | assert_eq!(value.clone(), value); 49 | } 50 | } 51 | 52 | #[test] 53 | fn debug() { 54 | use TcpOptionElement::*; 55 | assert_eq!("Noop", format!("{:?}", Noop)); 56 | assert_eq!( 57 | "MaximumSegmentSize(123)", 58 | format!("{:?}", MaximumSegmentSize(123)) 59 | ); 60 | assert_eq!("WindowScale(123)", format!("{:?}", WindowScale(123))); 61 | assert_eq!( 62 | "SelectiveAcknowledgementPermitted", 63 | format!("{:?}", SelectiveAcknowledgementPermitted) 64 | ); 65 | assert_eq!( 66 | "SelectiveAcknowledgement((1, 2), [Some((3, 4)), Some((5, 6)), None])", 67 | format!( 68 | "{:?}", 69 | SelectiveAcknowledgement((1, 2), [Some((3, 4)), Some((5, 6)), None]) 70 | ) 71 | ); 72 | assert_eq!("Timestamp(123, 456)", format!("{:?}", Timestamp(123, 456))); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /etherparse/src/transport/tcp_option_impl.rs: -------------------------------------------------------------------------------- 1 | #[deprecated(since = "0.10.1", note = "Please use tcp_option::KIND_END instead")] 2 | /// Deprecated please use [tcp_option::KIND_END] instead. 3 | pub const TCP_OPTION_ID_END: u8 = 0; 4 | 5 | #[deprecated(since = "0.10.1", note = "Please use tcp_option::KIND_NOOP instead")] 6 | /// Deprecated please use [tcp_option::KIND_NOOP] instead. 7 | pub const TCP_OPTION_ID_NOP: u8 = 1; 8 | 9 | #[deprecated( 10 | since = "0.10.1", 11 | note = "Please use tcp_option::KIND_MAXIMUM_SEGMENT_SIZE instead" 12 | )] 13 | /// Deprecated please use [tcp_option::KIND_MAXIMUM_SEGMENT_SIZE] instead. 14 | pub const TCP_OPTION_ID_MAXIMUM_SEGMENT_SIZE: u8 = 2; 15 | 16 | #[deprecated( 17 | since = "0.10.1", 18 | note = "Please use tcp_option::KIND_WINDOW_SCALE instead" 19 | )] 20 | /// Deprecated please use [tcp_option::KIND_WINDOW_SCALE] instead. 21 | pub const TCP_OPTION_ID_WINDOW_SCALE: u8 = 3; 22 | 23 | #[deprecated( 24 | since = "0.10.1", 25 | note = "Please use tcp_option::KIND_SELECTIVE_ACK_PERMITTED instead" 26 | )] 27 | /// Deprecated please use [tcp_option::KIND_SELECTIVE_ACK_PERMITTED] instead. 28 | pub const TCP_OPTION_ID_SELECTIVE_ACK_PERMITTED: u8 = 4; 29 | 30 | #[deprecated( 31 | since = "0.10.1", 32 | note = "Please use tcp_option::KIND_SELECTIVE_ACK instead" 33 | )] 34 | /// Deprecated please use [tcp_option::KIND_SELECTIVE_ACK] instead. 35 | pub const TCP_OPTION_ID_SELECTIVE_ACK: u8 = 5; 36 | 37 | #[deprecated( 38 | since = "0.10.1", 39 | note = "Please use tcp_option::KIND_TIMESTAMP instead" 40 | )] 41 | /// Deprecated please use [tcp_option::KIND_TIMESTAMP] instead. 42 | pub const TCP_OPTION_ID_TIMESTAMP: u8 = 8; 43 | 44 | /// Module containing the constants for tcp options (id number & sizes). 45 | pub mod tcp_option { 46 | /// `u8` identifying the "end of options list" in the tcp option. 47 | pub const KIND_END: u8 = 0; 48 | /// `u8` identifying a "no operation" tcp option. 49 | pub const KIND_NOOP: u8 = 1; 50 | /// `u8` identifying a "maximum segment size" tcp option. 51 | pub const KIND_MAXIMUM_SEGMENT_SIZE: u8 = 2; 52 | /// `u8` identifying a "window scaling" tcp option. 53 | pub const KIND_WINDOW_SCALE: u8 = 3; 54 | /// `u8` identifying a "selective acknowledgement permitted" tcp option. 55 | pub const KIND_SELECTIVE_ACK_PERMITTED: u8 = 4; 56 | /// `u8` identifying a "selective acknowledgement" tcp option. 57 | pub const KIND_SELECTIVE_ACK: u8 = 5; 58 | /// `u8` identifying a "timestamp and echo of previous timestamp" tcp option. 59 | pub const KIND_TIMESTAMP: u8 = 8; 60 | /// Length in octets/bytes of the "end" tcp option (includes kind value). 61 | pub const LEN_END: u8 = 1; 62 | /// Length in octets/bytes of the "no operation" tcp option (includes kind value). 63 | pub const LEN_NOOP: u8 = 1; 64 | /// Length in octets/bytes of the "maximum segment size" tcp option (includes kind value). 65 | pub const LEN_MAXIMUM_SEGMENT_SIZE: u8 = 4; 66 | /// Length in octets/bytes of the "window scaling" tcp option (includes kind value). 67 | pub const LEN_WINDOW_SCALE: u8 = 3; 68 | /// Length in octets/bytes of the "selective acknowledgement permitted" tcp option (includes kind value). 69 | pub const LEN_SELECTIVE_ACK_PERMITTED: u8 = 2; 70 | /// Length in octets/bytes of the "timestamp and echo of previous timestamp" tcp option (includes kind value). 71 | pub const LEN_TIMESTAMP: u8 = 10; 72 | } 73 | -------------------------------------------------------------------------------- /etherparse/src/transport/tcp_option_write_error.rs: -------------------------------------------------------------------------------- 1 | /// Errors that can occour when setting the options of a tcp header. 2 | #[derive(Clone, Debug, Eq, PartialEq)] 3 | pub enum TcpOptionWriteError { 4 | /// There is not enough memory to store all options in the options section of the header (maximum 40 bytes). 5 | /// 6 | /// The options size is limited by the 4 bit data_offset field in the header which describes 7 | /// the total tcp header size in multiple of 4 bytes. This leads to a maximum size for the options 8 | /// part of the header of 4*(15 - 5) (minus 5 for the size of the tcp header itself). 9 | NotEnoughSpace(usize), 10 | } 11 | 12 | #[cfg(feature = "std")] 13 | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] 14 | impl std::error::Error for TcpOptionWriteError { 15 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 16 | None 17 | } 18 | } 19 | 20 | impl core::fmt::Display for TcpOptionWriteError { 21 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 22 | use TcpOptionWriteError::*; 23 | match self { 24 | NotEnoughSpace(size) => { 25 | write!(f, "TcpOptionWriteError: Not enough memory to store all options in the options section of a tcp header (maximum 40 bytes can be stored, the options would have needed {} bytes).", size) 26 | } 27 | } 28 | } 29 | } 30 | 31 | #[cfg(test)] 32 | mod test { 33 | use crate::*; 34 | use alloc::format; 35 | use proptest::prelude::*; 36 | 37 | #[test] 38 | fn debug() { 39 | use TcpOptionWriteError::*; 40 | assert_eq!("NotEnoughSpace(0)", format!("{:?}", NotEnoughSpace(0))); 41 | } 42 | 43 | #[test] 44 | fn clone_eq() { 45 | use TcpOptionWriteError::*; 46 | let value = NotEnoughSpace(123); 47 | assert_eq!(value, value.clone()); 48 | } 49 | 50 | #[cfg(feature = "std")] 51 | proptest! { 52 | #[test] 53 | fn source(arg_usize in any::()) { 54 | use std::error::Error; 55 | use crate::TcpOptionWriteError::*; 56 | 57 | assert!(NotEnoughSpace(arg_usize).source().is_none()); 58 | } 59 | } 60 | 61 | proptest! { 62 | #[test] 63 | fn fmt(arg_usize in any::()) { 64 | use crate::TcpOptionWriteError::*; 65 | 66 | assert_eq!( 67 | &format!("TcpOptionWriteError: Not enough memory to store all options in the options section of a tcp header (maximum 40 bytes can be stored, the options would have needed {} bytes).", arg_usize), 68 | &format!("{}", NotEnoughSpace(arg_usize)) 69 | ); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /etherparse/src/transport/transport_slice.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | 3 | /// Slice containing UDP, TCP, ICMP or ICMPv4 header & payload. 4 | #[derive(Clone, Debug, Eq, PartialEq)] 5 | pub enum TransportSlice<'a> { 6 | /// A slice containing an Icmp4 header & payload. 7 | Icmpv4(Icmpv4Slice<'a>), 8 | 9 | /// A slice containing an Icmp6 header & payload. 10 | Icmpv6(Icmpv6Slice<'a>), 11 | 12 | /// A slice containing an UDP header & payload. 13 | Udp(UdpSlice<'a>), 14 | 15 | /// A slice containing a TCP header & payload. 16 | Tcp(TcpSlice<'a>), 17 | } 18 | 19 | #[cfg(test)] 20 | mod test { 21 | use super::*; 22 | use alloc::{format, vec::Vec}; 23 | 24 | #[test] 25 | fn debug_clone_eq() { 26 | // udp 27 | { 28 | let header: UdpHeader = Default::default(); 29 | let raw = header.to_bytes(); 30 | let u = UdpSlice::from_slice(&raw).unwrap(); 31 | let slice = TransportSlice::Udp(u.clone()); 32 | 33 | // clone & eq 34 | assert_eq!(slice.clone(), slice); 35 | 36 | // debug 37 | assert_eq!(format!("{:?}", slice), format!("Udp({:?})", u)); 38 | } 39 | // tcp 40 | { 41 | let header: TcpHeader = Default::default(); 42 | let buffer = { 43 | let mut buffer = Vec::with_capacity(header.header_len() as usize); 44 | header.write(&mut buffer).unwrap(); 45 | buffer 46 | }; 47 | let t = TcpSlice::from_slice(&buffer).unwrap(); 48 | let slice = TransportSlice::Tcp(t.clone()); 49 | 50 | // clone & eq 51 | assert_eq!(slice.clone(), slice); 52 | 53 | // debug 54 | assert_eq!(format!("{:?}", slice), format!("Tcp({:?})", t)); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /etherparse/tests/transport/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod icmpv4; 2 | pub mod icmpv6; 3 | -------------------------------------------------------------------------------- /etherparse/tests/unit-tests.rs: -------------------------------------------------------------------------------- 1 | use etherparse::*; 2 | mod transport; 3 | -------------------------------------------------------------------------------- /etherparse_proptest_generators/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "etherparse_proptest_generators" 3 | version = "0.18.0" 4 | authors = ["Julian Schmid "] 5 | edition = "2021" 6 | repository = "https://github.com/JulianSchmid/etherparse" 7 | description = "A library for parsing & writing a bunch of packet based protocols (EthernetII, IPv4, IPv6, UDP, TCP ...)." 8 | categories = ["network-programming", "parser-implementations"] 9 | keywords = ["ipv4", "ipv6", "vlan", "udp", "tcp"] 10 | license = "MIT OR Apache-2.0" 11 | readme = "README.md" 12 | exclude = [ 13 | ".gitignore", 14 | ".travis.yml", 15 | ".github/*", 16 | ".gitlab-ci.yml", 17 | ".travis/*", 18 | "appveyor.yml" 19 | ] 20 | rust-version = "1.83.0" 21 | 22 | [dependencies] 23 | etherparse = { path = "../etherparse" } 24 | proptest = "1.0.0" 25 | --------------------------------------------------------------------------------