Update etherparse to 0.17.0
Test: m rust
Change-Id: I7ebe6eb3f5fa516ddc6587a45acfeedb8b14cf4b
diff --git a/crates/etherparse/.android-checksum.json b/crates/etherparse/.android-checksum.json
index bb6dce5..ba115cb 100644
--- a/crates/etherparse/.android-checksum.json
+++ b/crates/etherparse/.android-checksum.json
@@ -1 +1 @@
-{"package":null,"files":{".cargo-checksum.json":"d523922e96bb91f38fa5f30c12283f20e1b137e939656bf413049fed0019b87e","Android.bp":"e3d51788b5b761d4b17c3dc3f907f7ce1bc0ea6f9a9ef254bc969f0f2cba0f07","Cargo.lock":"3a4ef1661ef22bc0aace5134ca69b46d24b02494769d4008637e86d67625f3a9","Cargo.toml":"fe313e1213e438a2ce44c9c1cb285b066b9b7b02f8b540dec0e51d5ee16edcf4","LICENSE":"fbaf014d4c710d74dfd291a6ac8ca8e564d4050dcb1eb3756e6c456abeb1de89","METADATA":"98cd1e6b6e9747641e07a282699c30c7f066ab03fd37722c322bc0d780abc709","MODULE_LICENSE_APACHE2":"0d6f8afa3940b7f06bebee651376d43bc8b0d5b437337be2696d30377451e93a","README.md":"3160b08ac64d87a2f45e543d92cd92a594e8f50433bb60d5239790b0b1cdbc9d","cargo_embargo.json":"762c744fbd4c3e924a9d034fd3c3e4e1399622b96d67058be0ca151ee0b63ba0","examples/ip_defrag.rs":"a748e2d3101caec0404bc011a76f041bbc3dbb41be37fe22e18e046433a9c36d","examples/read_by_slicing.rs":"f080d24eb824062533a056462127823d820258f97798c0ab5bd1d439f3cb53bc","examples/write_ipv4_udp.rs":"a9bc127e6dee230ec863ef8dd394d30bf82aae0038f865b778a79d058fd7daf9","examples/write_tcp.rs":"0354ff9ebc61aa2b80efe7ace7749e09129ff54ed926a3f0bcb29422fec4e306","examples/write_udp.rs":"c7483fa6698ab4477a7025a07ee86d6e2af7be86a9f80132124a10c12dff4396","patches/license.patch":"f1ecd16d788765e2876fe8c77fd98cfbd893ebcc0ca6ee56350a4924b58cbb4c","proptest-regressions/compositions_tests.txt":"657ffcf022cd012b2ad2108321647ebf10402b895618f5d08bd5813250314abf","proptest-regressions/internet/internet_slice.txt":"f28bf9cbf302409ce9c32456bb0268fa860014e3e21f9b4dc02f17cd02bc8494","proptest-regressions/internet/ip_auth_header.txt":"ec14f9811b5c951e0ab48284b0a6df54ca33385fd419527ddd70bf98ee89fd7d","proptest-regressions/internet/ip_auth_header_slice.txt":"cf07ba1c614744d6a39e10c83f8a4ee14adfe93246dc0af1378299a9e7f64d48","proptest-regressions/internet/ip_header.txt":"7aa825d4c10f28971a4680aaacd1ab9dc99f985513ea0134cfb97445820e98eb","proptest-regressions/internet/ip_slice.txt":"44763f60e2c6ca22a9db0a9223f96331a042b752537e729061de2f65eb6dceb4","proptest-regressions/internet/ipv4_dscp.txt":"a60060713d0a470cc0d8727eb662cbe52836bd2eb92392089bbe7d0b0bd73044","proptest-regressions/internet/ipv4_exts.txt":"fc4e9cda0c41357fd90c9b7cb3424a1cb50706b4ebad54c4e0b75b9f1af647ff","proptest-regressions/internet/ipv4_header.txt":"c1a217c80e1962d7c7d8203a27deeb76ce4d691133295a69e123c239071888e3","proptest-regressions/internet/ipv4_header_slice.txt":"0b0026858b9372e15c1da36931855cb0712b4ed870393614b451280207e47665","proptest-regressions/internet/ipv4_slice.txt":"3d7b66a49887cd90a9c8be2d273e338323ca9b1d14335056ce328a391c610058","proptest-regressions/internet/ipv6_exts.txt":"2019584269283fa58c4edd1da153007cb1d267612a4c45522f29d6cd811c1389","proptest-regressions/internet/ipv6_exts_slice.txt":"5fdabc3c7d82661a5c0e5cb74b2defdf5d9cc879ab4d9955c79f663c55f0817b","proptest-regressions/internet/ipv6_fragment_header.txt":"ce1198917716fdb582004979d0e7b3f23fb0bd24cc4d5a6bb1609942e520b195","proptest-regressions/internet/ipv6_header.txt":"b5f1b9acc5b5a485f8d608246cd047f5e85fd8416994ace5f10b67ddd0ab6b85","proptest-regressions/internet/ipv6_header_slice.txt":"189f88c6ef73383e4f058e4b9731fd70c2a2daf9a8f2ffc34e0887ba1364b94d","proptest-regressions/internet/ipv6_raw_ext_header.txt":"94f5a82ab1d85e198a1d8b6eca0b86b4bc6848d5cedb3859fcd45ed2c3dda642","proptest-regressions/internet/ipv6_slice.txt":"544a3a69312f4bea4e57c4543486ce35137ffa825a01fa94e95529f4f671af2d","proptest-regressions/internet/lax_ip_slice.txt":"085a62ae1a44aa0e2448af0f06762aa3b6b62df7054da6c4f499c986bff502f5","proptest-regressions/internet/lax_ipv4_slice.txt":"7f2d13cb52b93fa1c9650abc182fafd5f9d76fdfc3c06c1316a08de3910e24a7","proptest-regressions/internet/lax_ipv6_slice.txt":"3c3153b0cde13eaf5097733119c4ada982b425a8dfe8943555b9f0d82bb78495","proptest-regressions/link/double_vlan_slice.txt":"5aced4ec8d4d624cf24e61b6c1a159f93b4d51687f0fe12a56fa0a85cc206623","proptest-regressions/link/ethernet2_header.txt":"b5d91d0ac393ee5bf85a105f13f89aebdb5700f6ec07c98f726a1875fe2d12d7","proptest-regressions/link/ethernet2_slice.txt":"1f9047bfe526e0b6af9dee7ca108d4855418159801891dfff31ebb1d3059eaa3","proptest-regressions/link/single_vlan_header.txt":"eefed03214259ad8ec23ef26f98ea973cac1b80dad8d13f34bb2b99de007f894","proptest-regressions/link/single_vlan_slice.txt":"760bd91c71b9653bd4506869d57d4c38057b95da10bbbfbc2a57be429131c7c4","proptest-regressions/link/vlan_id.txt":"249807f03882e8d86aa68c460e0a5170fd2b040c158ff5bfcf6e8cc72ca9c89a","proptest-regressions/link/vlan_pcp.txt":"c935f15506be4836ecd04d535f884c590ef52ba3eafc8a65c3202e66c2195240","proptest-regressions/packet_filters.rs.txt":"b32112123b4ebcac3b1a2370c603f1a55b65a6a47abbcb71882886271a5bf041","proptest-regressions/sliced_packet.txt":"0f59adccb52aad6467cb562cc279288de262e64c570d4b08bba37e417e1259ae","proptest-regressions/transport/icmpv4_header.txt":"5cfe000c67124a90b839fd438ced654b69e417f769dfad10d10d5c948fece351","proptest-regressions/transport/icmpv6_header.txt":"a1dcb259f46d843c26b5708a727107644b228d88e358098a051e2474f80b8cac","proptest-regressions/transport/tcp_header.txt":"455bb8904eb89c77fb87c38632da93ade4e965ee7068d443898b3c3dada7615f","proptest-regressions/transport/tcp_header_slice.txt":"9e2b405c9bbde67d092dfd8aade7225e5ac99f99f8e4d85b5c619048fe9c14ff","proptest-regressions/transport/tcp_options.txt":"14c9787903b076e4f77212b4bdb34f0757e82daab993c5e836009de1e4204576","proptest-regressions/transport/tcp_slice.txt":"90b4c039e438af806b7054ad38d46934e92e8ea4393505e5ef47dbef41091e4a","proptest-regressions/transport/transport_header.txt":"54bc8b2e0052cd29caf7487b8f38a6121b5f3250b8bb6109d8572da4b0736963","proptest-regressions/transport/udp_header.txt":"1043f35c4643defde43bbe105e0e2c780603a35196e84de6201f489a27b640cf","proptest-regressions/transport/udp_slice.txt":"a909bd42229448498a77909169aebc44b37f286e9a7a42184453d79f20d43247","src/checksum.rs":"7388dad242209f4d6c001a0cd0fa5cef5047326fb010391dba034ef084d9fe20","src/compositions_tests.rs":"7d4bac4539745ca2a660fc8b3bd1f20026c9d66d905c629b8012aa6d273fa159","src/defrag/ip_defrag_buf.rs":"c493b38b492c940411a12041fff9034cb03dcf0ec79a1e3cfa80160f397f7d56","src/defrag/ip_defrag_error.rs":"72f25a2bd689e5c5b33ad2c97a5c77dd098a333221145c1de7616d72b889f243","src/defrag/ip_defrag_payload_vec.rs":"3e52e7d70b7d90344582a2deee4acf035f6fc92e7b54cd42d34c5b62f4268ae2","src/defrag/ip_defrag_pool.rs":"0adbbb8101cb4796a12d225ab5eb9398a3725c0c6be05f7e8c0601757e9fcc9a","src/defrag/ip_frag_id.rs":"11153393c6daff8cbe753ba38ca96578c2c1ef6a616f84f9c6cd9a2bf1a8f96a","src/defrag/ip_frag_range.rs":"4ea25928a52736db9a179ce40fc854b8158c0415ddc020eff2f868e31a6942ff","src/defrag/ip_frag_version_spec_id.rs":"82a3a87b27bcfd1c9c6622bf25e37e7de77d1146d6aac120e4943a672eeb53f0","src/defrag/mod.rs":"4c05ede1918af9e6df0bfa5245fb94c32ab8549d8b541a69c592af41bf5f631a","src/err/double_vlan/header_error.rs":"94b224334eb6182ececb530f59d14c270ca1996441995be84fa542d9d241ed2c","src/err/double_vlan/header_read_error.rs":"c7ce4eaff1c20c10e36b8cc689db909027fe5bdb317bf8fd59327fc7f34b6c11","src/err/double_vlan/header_slice_error.rs":"3c6857ae3ff38070ffefdaa1dc60573f2c2ca4245a7dc5d19a875175c5d7d524","src/err/double_vlan/mod.rs":"968abc73c13026c39932f349ac0cc44d4e65811624621b7bbfff39e477a968a9","src/err/from_slice_error.rs":"536cfe25b491dfe6e681918c0821b5454ae18466a8bd41609b8f056a8be88dfd","src/err/io/limited_read_error.rs":"5a38dc71e00e4e8c6d676e60dfb379c20d49ce274b71349d252a317427958c08","src/err/io/mod.rs":"9b1c86158fc40b115e44d48af107c3e24d3bdc3ad07a7f24938d599bbb5c0b40","src/err/ip/header_error.rs":"449e2f2acd703a9c01a88f882b91e5952143ae3007e117402b29e3b74a7f60a6","src/err/ip/headers_error.rs":"0315889f76d125262169f18592b55fe070dc9cd1bf2019bdf7bdad6b6885eff4","src/err/ip/headers_read_error.rs":"de7dea1c2aa5c12ef205fbc0d300e5e62905017bd7be52bbec5219540648e740","src/err/ip/headers_slice_error.rs":"2279864b0225f1f3c52d252e3fbd648685e77c5f5620e12c9b58115bfa0b1a84","src/err/ip/headers_write_error.rs":"fcd21869d86e39af87e5508d223b3d0045f0c29b89e249a3edefec19934a708b","src/err/ip/lax_header_slice_error.rs":"57378dab273cc2597c2be9275b2a47f41f0bfee2aa0183987b8aa1ee1d37e7c0","src/err/ip/mod.rs":"8cf92db0272bc87cb1535735707024494bf22d26ae31bb8a16ec522c658fb2ab","src/err/ip/slice_error.rs":"6967467fb090d55e08f61fb9f3e141ae67765c09f0307a171e78495ca2a8158a","src/err/ip_auth/header_error.rs":"95c8daada91eb344fe604e750859b5e311ef8b43d2a446b1f6a082c382a2f679","src/err/ip_auth/header_limited_read_error.rs":"b834012f616673ba66b260dfd44b353f4bea553394ce11b8c4fe1efd0c9aaa27","src/err/ip_auth/header_read_error.rs":"e540027bd6db20c16029d770a045e4cbfcdda7c23ad9858c1cb97dd6c2006600","src/err/ip_auth/header_slice_error.rs":"3040b7ac84cd81dda5f51570789723bdce90238bb8c4ba0d38a49855d6cd5b3b","src/err/ip_auth/icv_len_error.rs":"1083b80d844e645b4bc0d95c5a0f393c60704907cbd29a62e5540e3e1386594c","src/err/ip_auth/mod.rs":"8d6c873698028773016d43f89c8f1f4207258ff24c1d82edfa12b880df76e956","src/err/ip_exts/exts_walk_error.rs":"fcf004213d739390d6ccdbd5ed97b5ed11813c0c020005881d0cb6f4b9629f7e","src/err/ip_exts/header_error.rs":"b74ae7a23a677836da7553662f140f5d4079c8de2938f4a339fd86329ff00cd8","src/err/ip_exts/headers_slice_error.rs":"5c803b2e659ee9f228d6a3c21dd6b4dc4ddf30ee93d2ffeba4f1f776bd655e24","src/err/ip_exts/mod.rs":"f5957b2253e52571fa2cc7e6d9e20bdc903f5ccfcdec6ad8c317b8a13560748d","src/err/ipv4/bad_options_len.rs":"ba7924a492736cadf23bb94fd4a2d03443d2581ba7ecc7bd6f159a5999e94c71","src/err/ipv4/header_error.rs":"08e881e7e3aa2c66d4b3aaf502e2fb44b57a8cd0e12680226921eeaf41641e01","src/err/ipv4/header_read_error.rs":"8c23bc0536b492100f5da785001be475d0aa3ffc96fcdd21a663ff6b5afd11e8","src/err/ipv4/header_slice_error.rs":"e132f20188ad07098fb2f4d99a64276083c37a246035ca0a388aa629c7e0a2fe","src/err/ipv4/mod.rs":"22be02f957eae93403a3b5e9892d8bc8c6e48636c7b46e4a3c48c647cad01ba6","src/err/ipv4/slice_error.rs":"4cf6f7ad034dbc39f2af27b1e10e69050883c3c386d0a81c14f25e27aeaffd59","src/err/ipv4_exts/exts_walk_error.rs":"a86116539f0e354267a982800f48a90bc6576bdc0d07594b336bff598eb63428","src/err/ipv4_exts/header_write_error.rs":"0b9a014265f84edf5595dca68f75e64b6d1c43c5b865824fedfeadb5436cfc4f","src/err/ipv4_exts/mod.rs":"3f15f230f0e89a41ac1e4d8799bc713a5c06197dee36e627f3c074dbaea16a9e","src/err/ipv6/header_error.rs":"77d0fc97d86111f2d0faa3616e69794add675715c64847098334872ae9f9086a","src/err/ipv6/header_read_error.rs":"13c1c949477a179398d79402ff476b5452988c64c97b23a69bc56697a99edbb9","src/err/ipv6/header_slice_error.rs":"ae3c39185449a98066938d77c8be1c8b5faf1333207aaad9e96de882f60fc6be","src/err/ipv6/mod.rs":"d62c636c86f5a60f21809a9dd6afd8920077380dc3f968a8bbdd13222603024e","src/err/ipv6/slice_error.rs":"c354e6af13c8ea670d2a9b8201d3c3e44bd257e881aa888decc6a5489e863f93","src/err/ipv6_exts/ext_payload_len_error.rs":"4f5061bca4f8b6c50b94c8c0ff7c191e7fb95c0a8c97e40eb340b5978b1ff9f5","src/err/ipv6_exts/exts_walk_error.rs":"f5731b01fb3d41efc690ab1bf6818ed7d3a01465f0f9832987712611124dcb87","src/err/ipv6_exts/header_error.rs":"8c0c84f50680f86ef8dc7ee54fa4cbb6760d49640f73f48d4b88ebc170b556e3","src/err/ipv6_exts/header_limited_read_error.rs":"5cc090823388b1daa24640fbd9be279b7a74c77236b38b4426e882d2586415ca","src/err/ipv6_exts/header_read_error.rs":"452d91d054deb790d5fe6867069faa6cc23f20ccd6f8728e61cfc2fc6fcafd08","src/err/ipv6_exts/header_slice_error.rs":"046413243923b4887fca1f88704cf64b36db27fb91a7a4f819d4ddf043891d9c","src/err/ipv6_exts/header_write_error.rs":"551f355334f5b8954200e8ddd12eca84486a6af4b782f7aacae3b53ffe3fce1e","src/err/ipv6_exts/mod.rs":"5e20a8c16ba544de38e463e0ab94a3dce700b3d5bccf5991392982ee7c726a15","src/err/layer.rs":"8de1e31b7332561926bbe7e7467277d6bd62ab9d270f1138d21e08fcd017d4c4","src/err/len_error.rs":"2275d8f3a2c5f9558e387af5deb8a278ee90e0e01841d087b5787d2474b494c4","src/err/linux_sll/header_error.rs":"921dbe18038aeb00913df189c2f58a7b5335eb07fc93a5d511d0fbd821588bfe","src/err/linux_sll/header_read_error.rs":"167400a38c4ef3f93c4ea435cab6bad4c8624aca3711e9277ad5aa90c6a95aaf","src/err/linux_sll/header_slice_error.rs":"d4ae8dc2b0904292d5a00517c7ec3a8d8d47ac874550c0085e4e3f2d5370e475","src/err/linux_sll/mod.rs":"968abc73c13026c39932f349ac0cc44d4e65811624621b7bbfff39e477a968a9","src/err/mod.rs":"9e6012012ab29ba52104192de40b9887d8bc55869061876312c5b652bbf75db8","src/err/packet/build_write_error.rs":"3014c30fc2b04385cb867758f689b4446c892b921d96a6234375828247de258f","src/err/packet/mod.rs":"05c2973ce964fd061f9cb53f17a4e88d880a4e70461546871d73e28cc90fb04f","src/err/packet/slice_error.rs":"ec82afb42c6b75c2d9e945d337463e89390e2736da6a73f56be11f489b75df74","src/err/packet/transport_checksum_error.rs":"db0503fe7f0c3e278a34480afa8a2f906538839bb2f913579fc6cae3d0d819fc","src/err/read_error.rs":"3bf7e6da93a2bbad3a635abce0d0dda10f96c9261b4955f4f448df1d81928fee","src/err/slice_write_space_error.rs":"dafd90ac1352a6924a16644733e2f3eac83bcba3a5535f31ae192ec0ecba2974","src/err/tcp/header_error.rs":"821c34df02a3d7f52f90e019c94f5d434b5d1687ed2537ca717417ef4c1fc2b4","src/err/tcp/header_read_error.rs":"c29758051be2beab762ff01e262adb90dab3812a9e0f279b06a0e90ce0ff9969","src/err/tcp/header_slice_error.rs":"e9743c1bff4dc6d286164df44e78a5764f497f33d10dc25bc1207f26d390f549","src/err/tcp/mod.rs":"968abc73c13026c39932f349ac0cc44d4e65811624621b7bbfff39e477a968a9","src/err/value_too_big_error.rs":"6f247333b36b504a41870688834c06ce53ae263af316ed418d1ce8804ed03a9b","src/err/value_type.rs":"a66a995d3452d261b40bf7323c6ea2e06236f726ad89826b73f128d93e8744ef","src/helpers.rs":"94b2d9469d376f39d38fef3d76dfd5a444425c414221ee48eee4b13b42e5a6fd","src/io/limited_reader.rs":"b8499bd2e3ffebb5b6d88713bc382cedf9a8d7033ce790e2c56f8932b25e9020","src/io/mod.rs":"bb81e1b6b01b26c3496675905dba6f9dc19b0a6333352e6eb904ed51bfa91007","src/lax_packet_headers.rs":"ffd7a7297ba06b27a3ed5f96dd1e2107878dca74719d3b072fbb90446a885eb5","src/lax_payload_slice.rs":"61620d457af9feb9b4ff6a39c207a46364d88dd3736c987ed78779ee8fc4d46b","src/lax_sliced_packet.rs":"1772cbdf1ef0a0543db9523ec22ac5c452727babba8061ad09edef0769acea79","src/lax_sliced_packet_cursor.rs":"6dd2274aa72eecfd8a25e3e5284f4411665edb0e70870c3e55f5bce385dbee16","src/len_source.rs":"ef19f4bb54903bdb02b8583de71da35670db2b60e48b25baedc2554949ac5df4","src/lib.rs":"21c5c2ae48af0d5b42646d7e4102cca70b75f7666b54f1fc2c449a550b898c1f","src/link/arp_hardware_id.rs":"820cf6c3a53c382dfefa89ef4bf0180b83dc5f030f26766d895776470781a87b","src/link/double_vlan_header.rs":"3c1abb259356f82c04f564edb8a01c11174ed4b46f7ea33f91ab063097d3490d","src/link/double_vlan_header_slice.rs":"02ed6e77124f73bea98577d725f63a93237f4b7f2b5c0dc6b82917ef91dd3156","src/link/double_vlan_slice.rs":"908443605865891a220f64abb0c1bddada2ea0c451ce896bb8ab50702654e496","src/link/ether_payload_slice.rs":"8282c6f2b7fa47176090fa0117dab1720568b05f93f703d6a1fda87b26b2b86b","src/link/ether_type_impl.rs":"99a87b820dc3ad0c193740d1e971ac0256ecf3568becaadae596a10b5543ae0b","src/link/ethernet2_header.rs":"b574e528989e989e4c38a5a31a93017578cd564efc0261b7ef1d33c1625300fc","src/link/ethernet2_header_slice.rs":"7c48ecb25a178b41027e8f5ce305d67bf0df883bc9e8ff2cc13b4aeb2e5bf987","src/link/ethernet2_slice.rs":"d9045388aa8d0577468d5680aaaf56afcfb788ada798b315e84f821789ac6ec2","src/link/link_header.rs":"819ebaa407501f1086f6bb409d47f81152eb1f63c118b6c3df6885becc8ebbc0","src/link/link_slice.rs":"bc72d4655c15fd842ff51b52ff5185ef8d20690587d3130b3aad2a7722b1cac3","src/link/linux_nonstandard_ether_type.rs":"6d31bf570c7f1ed78e4df0212589b02b54752f73f470e659dd43436ed2074b7b","src/link/linux_sll_header.rs":"6e2b97e6e9f210d638cc7ef08b333ce0037c6451e0bfe44040a1d88e53890898","src/link/linux_sll_header_slice.rs":"983f237dbf7dc15408c8e201c2e43ad71e4d97e3fde68647b26c78fd358bad1e","src/link/linux_sll_packet_type.rs":"8fd4214ae97f691db2069566eaf2ac07773d87dd78fb0d900c885591d89ea7c1","src/link/linux_sll_payload_slice.rs":"a83e19868863fabd1c3b6374be4259eddeafd8778bb469d27a9015ec3f112e87","src/link/linux_sll_protocol_type.rs":"87277262c2d44028847302a091a79bfb8c13640e4f3115b1edbfe51c344aae0c","src/link/linux_sll_slice.rs":"9d4c45042700a8b5b984618f35a48a8d94d50681ab92594f2363a307dd113b96","src/link/mod.rs":"fb402297a7bd0a848fdf966d65e404f67aa147ad2191d2965b7e70c9c55aa091","src/link/single_vlan_header.rs":"1e26b6eb1244b63296e87375f06e70cd207933268fcd390d993037deeca13232","src/link/single_vlan_header_slice.rs":"2cd0131e33a80aff3abf10c372a34744a4d976f10b3172a61deb1e77d3e09a92","src/link/single_vlan_slice.rs":"5666a78a1c922b988618daec2adbd7e9594135a041352a0ab4f70bdf6161f791","src/link/vlan_header.rs":"b403aff1ce9baf249b6dd3edbaf4c581bb82e764da0724f979ddf762ddbd22b9","src/link/vlan_id.rs":"fd00d92c100d380005c5f8aaa8587730562d9aa34b318229d08cc8a036b391b3","src/link/vlan_pcp.rs":"08eb38d5d2f1a4478dd068fcdc439869c841df7b46a7773279d68485984a92e3","src/link/vlan_slice.rs":"25f40947307db56362ccd802cd115585f54c0d6e85a245219f9c96bb4ff24222","src/net/ip_auth_header.rs":"22573d6e5dca187f69270c4482349a6c32021c34370e86418e330cc0dea2cbfa","src/net/ip_auth_header_slice.rs":"24af9e7ef37e5a68fa75ba1e60ff77bcc1c69c542c734ba8fe3edfd5c59e8fc4","src/net/ip_frag_offset.rs":"d80220902049a8cba3bb2d418aaa1ffbe92a1cd5ad86f1c06a87e5e398a22820","src/net/ip_headers.rs":"ea965ed2036ef572eafc833dc8a1a91eb0762985c92544e44738d73705f498be","src/net/ip_number_impl.rs":"0c8f8244e1e0e89c7b725665795a1ddb994780fda1d222dc5c122828c18ebf26","src/net/ip_payload_slice.rs":"fdb9c7e0c4a1b36b85e254d966a978c5eefadc460dfbc77c101aecc56e356874","src/net/ip_slice.rs":"557272d95be6e0cd194f5f275c582110b0ed82c5ac6e043ce287e413b039ba2c","src/net/ipv4_dscp.rs":"a58269019f9c8d8a75e96bc0ebef88ccf52bc124e413890b2708938945382a60","src/net/ipv4_ecn.rs":"058538db9b40fe5b38528d7132681992bfd40ab05e1424de37e26d6628ef6b28","src/net/ipv4_exts.rs":"e86c7ea1a253541f6033fb45b2280abcd8f00e8cbc6bceab91581db0128fa641","src/net/ipv4_exts_slice.rs":"8573d4c148e42769fc50ddfcace0fb21e0ce58fe3f07131a1e87d1370e88d721","src/net/ipv4_header.rs":"362411271d3255555a201b9b922a92fe1e1d445a10a4c70775b61c814b97f43a","src/net/ipv4_header_slice.rs":"9c054952ad845a9fc53d799beba064cebf574316f7896cb8669d99ce935a8bcc","src/net/ipv4_options.rs":"1c00583a8d71fc1a3fa2ff288b2b7332ab45723fd1cc5a3eaeaa8f3df56d98c1","src/net/ipv4_slice.rs":"d40d738911319e6af37e5bb0f72bd37a8608f8bc299ef9124d0d54c987625fa6","src/net/ipv6_ext_slice.rs":"ecfe7370fbf0199c8a28d7dd292ce4f94441d3c1abadb281229e141fe1d1a852","src/net/ipv6_ext_slice_iter.rs":"5683edd54d6fc81fed5e130634cbc0570cd6ba2c04123259012d8c241c3e2233","src/net/ipv6_exts.rs":"674d4a33e7fbbea422cb0f0ff0d0fa8f04a3c26c33113676c175b83da90367de","src/net/ipv6_exts_slice.rs":"9264956fcbead2ead446dc5976a223719d8a98fe8fa285c1da2793a25ee8366d","src/net/ipv6_flow_label.rs":"8e271b96e476641d64ab74d16f44980fc266477af7d567f6f5bc5e6b1e61da67","src/net/ipv6_fragment_header.rs":"ed6c9ebbfdb388e6dca0e1f89954ef744a94c5882a1ceb13fab1bddd1d530617","src/net/ipv6_fragment_header_slice.rs":"115429110c4501d786aec68b96b1d440e3c92c68786ad97dc1b12e8419fa8647","src/net/ipv6_header.rs":"beab70250d6b23a2c1fa92e949af67868f9abf421ba8361b5f75ae8a15b41716","src/net/ipv6_header_slice.rs":"2f13f5894031b592142d6ada1058910190c0cafdcc03cb5ff1e9ba84024d4026","src/net/ipv6_raw_ext_header.rs":"9a56a6aca63fc8a744dfc596d2e178f3611fdcdf9e381e7eb8a4d4ab31d17108","src/net/ipv6_raw_ext_header_slice.rs":"ca8bbe564bcffb6c811ed584a6976b156800999f20bace94be8299947a4434ed","src/net/ipv6_routing_exts.rs":"de9f55abbf535a89fa55d97877ed998ee3000acc6dd79ac084c4fe7414fa9cbe","src/net/ipv6_slice.rs":"757c6f9fd25b5a1f7280c3a87053725352aafbd37abc4fca22b3b31745275a85","src/net/lax_ip_payload_slice.rs":"6ea047579308125bf414304458d6c204fc9d93c6332a5a10d65b6be17688df1d","src/net/lax_ip_slice.rs":"bb2d4d7f4c4f19a964b0456f8de43907cff2ab5fc6650ffc350d417e39d0f547","src/net/lax_ipv4_slice.rs":"e16b4249bdab3dc863d87f80843eb72ce0bb7c4dc90b3f8cafe52b5ac8bd9b95","src/net/lax_ipv6_slice.rs":"2d09cad4725130ed59c57a8d944e6effa9a63749d512e796f7ca4b9700f516ec","src/net/lax_net_slice.rs":"0767180ff21a17ef5a2a8a907ff040f0747fa8d0dc2658fcc91e9830e37f957f","src/net/mod.rs":"56d11c919fe390547573692fe5067ed631055855d86e344978ef90c5ad44a2c1","src/net/net_headers.rs":"be5d336c3663521c92f0363bd1a58bbbd69eb1e81f76b2bd9fcc0754695eaf55","src/net/net_slice.rs":"954a0762cac6d4d07041faf8c5c08b278e3e4bcb4158039e6eb88fd43ea1c695","src/packet_builder.rs":"5579fb16f89f79f29550f5ecc433a76820bf43084a62bed06b8f8587931c5a6c","src/packet_headers.rs":"c895203c3989123c143ee23a16b9232c7ed3e7b42edcd46ee8949c1364a652a3","src/payload_slice.rs":"3af8aed34d3e283cc6e16b90e6dd513ab6c635cf1f932c6cb0aecff739261ee8","src/sliced_packet.rs":"8efd36ce204c6a265c910e821d4fbcae559c5b359b86a0d32d960ee7bb54815f","src/sliced_packet_cursor.rs":"ab1c314a6715fd2247d06a582fee10097cb3af9f952d2fc2720817697151f8d0","src/test_gens/mod.rs":"b1a17d5d1a1f13265c26b8f133e68f4d1be280a1d55f855f13306dd811e77906","src/test_packet.rs":"281159ad1b8c7bc3c2af9df093dbc7dfc982d740cb38a6d0f4c3576e1e72652e","src/transport/icmp_echo_header.rs":"b2ec597f411dabde553c66583d21339765e623cb7d4d96cab5252079a53f9abd","src/transport/icmpv4/dest_unreachable_header.rs":"1f619edf7538cb84f9924ce9c9e1461bd6bff6254f7c4e1879a054e37f71e9c4","src/transport/icmpv4/mod.rs":"445a123811fa05bd966e7c93543ab61f2edf317f553044696d92b62e232d97e8","src/transport/icmpv4/parameter_problem_header.rs":"ee95757391f3d2189ea4b8a05bae5faeea62dbc8282092ac99fe527d96392bce","src/transport/icmpv4/redirect_code.rs":"20f833e7b44a24edcdbacb4a42e1bd6709251711f56d9091a3667f5754d00a86","src/transport/icmpv4/redirect_header.rs":"9b93ecf873776b3d387b0eb2da369d6da87c647aa48fa7e12896b81e035bded9","src/transport/icmpv4/time_exceeded_code.rs":"ebc54359a02e6897a3b419274f01b73548ba5c8ac847f996e8f651893a53578c","src/transport/icmpv4/timestamp_message.rs":"42fae4577982a51da7c24f42b77e54b680d540784efe801f0541c023e6ebc78f","src/transport/icmpv4_header.rs":"47d1245f759880b1c36ce659ab572de437ec3e83038e2bae39abe6a4db6d0e8c","src/transport/icmpv4_slice.rs":"4db10d54fefa306f20170a6cff0572b861778613238816e9e95f1200de3cac56","src/transport/icmpv4_type.rs":"afec53948c2141eceeee6b5e825879427a7cf059d86ad4c97773ec3a7185b804","src/transport/icmpv6/dest_unreachable_code.rs":"dc513f7b9dbbe0f3ceb3eb0eaaaed15487d5038bf7dbc51e05f60eb269190111","src/transport/icmpv6/mod.rs":"251734f9a53f91f28468c580de64f0cd30f54f74e1e53852cfe25f71bc5ee9fe","src/transport/icmpv6/parameter_problem_code.rs":"0fd1f4f3abe254222add89bca8b3acfeca56c6d67882041de38e5c7a7a4fff46","src/transport/icmpv6/parameter_problem_header.rs":"66c54b02ad56e99b39ee68712d1634400a882ac3de2271807708bc0f0be10d72","src/transport/icmpv6/time_exceeded_code.rs":"e0464ec86abd7c6c61618a6a136d6ebfe6a7673ed08d53d4a3b67fb53c0abdb7","src/transport/icmpv6_header.rs":"612f7189f7626c02de13d2792965b74faebf27aa212329ae2b54f694d681f222","src/transport/icmpv6_slice.rs":"d63c435426e2bf357285d6a7ec7d956c7c4a66ce92bcf762f31a823358f70a8d","src/transport/icmpv6_type.rs":"81239361b78e2bd588098f04dfbbdf92163c04119bc19761f0e2cccd8bf61773","src/transport/mod.rs":"183ee758b9af872f75cf741c764f9ae8c4672c3b784c10a73d9eb2007f8089e8","src/transport/tcp_header.rs":"a6153039059dc6ff74bfa45ae567ea05a5d1d598c139a80ab47fc0d98b709429","src/transport/tcp_header_slice.rs":"de3766544a3ff9f40ea11ba3150a1e8175a48e1e1bcb05305fa00039ae87a690","src/transport/tcp_option_element.rs":"0133f6759caab0368634523699d77cb18e6c9a1b816e3ee9eae3867eb6ca7f04","src/transport/tcp_option_impl.rs":"a57d3b760358f448691b9094202291241d165616a226e6fe4590c6d3f62175e4","src/transport/tcp_option_read_error.rs":"678d6904cdb82d829d8bf8df8022a5823b20ab1b654127b479dc19b9f1a62536","src/transport/tcp_option_write_error.rs":"b078629cfa5255ae4bfaf21c4115683180d757a82bfd6760a91a3511293339a4","src/transport/tcp_options.rs":"0cae0fe51364a7c8e4129e4b401d3ecef9f28ebcd239e4c5b351b17f9c984266","src/transport/tcp_options_iterator.rs":"74c97eaa9e5da0f1c957a2ac8b49fd28ced139f1c47ae4574544f3620a9dc3bb","src/transport/tcp_slice.rs":"2f87ba7506dbf1ca3302e7cc1ddf969ba5b078603aa250c8710ab268f8f41455","src/transport/transport_header.rs":"80bc33b7ff4ecd59d2724a58c94bcd476298c9a160f3db10b4d8a3722d0d5737","src/transport/transport_slice.rs":"3ba479cb2d045fce1d6dd1b46be026c3abfa46ee41635a992a7ce2db250ecdb9","src/transport/udp_header.rs":"91adcd615bd37f6abe5210c12cff9771b0e99fab5782713fd8123cc1c8778da0","src/transport/udp_header_slice.rs":"c1bb4d00238bc3562df71716d2606106503b428c81a8ada129ab6d3917e8a2bb","src/transport/udp_slice.rs":"2b88b26a945eb13e2e2e956b802e9b035e695748391b89597ec2e7f9bda5dc9d","tests/transport/icmpv4.rs":"bfd1b7e295011011c79347f6bcb2d3fb20be8c57cfca6c79d6470ee7082b5fe6","tests/transport/icmpv6.rs":"fbeded3e512f03a9bd93868347d01c170db613057d65757a95e2d6cc49686141","tests/transport/mod.rs":"6c3fd5a92f8c736b1ac9a74bd9b784c70551205ac6e9be7efdcd3d3ac3907a4c","tests/unit-tests.rs":"dcd05eed939140e201d69c67f6db1cf526d8c641f7aabe4985e5dbf27a9ef2db"}}
\ No newline at end of file
+{"package":null,"files":{".cargo-checksum.json":"5ca075330924108e56bc42b7deb1858e23ab2eaf8ac364fce5cdc8266d228624","Android.bp":"9999162f140019820dbc9d045fb3e8a6cd951a45898976c07231877b37eda36e","Cargo.lock":"6d79b2025092ff63457023cc5bf527b6c98238cad427544f40b0ddd269c9f05d","Cargo.toml":"179b31da4533164412f00679bb22989b38b135ebf3a88091d9e354d0216b75ae","LICENSE":"fbaf014d4c710d74dfd291a6ac8ca8e564d4050dcb1eb3756e6c456abeb1de89","METADATA":"859fbe6597bb741dcde2be0c256bab7479aba0317cf6059f66c50963cba7f688","MODULE_LICENSE_APACHE2":"0d6f8afa3940b7f06bebee651376d43bc8b0d5b437337be2696d30377451e93a","README.md":"c33d47442c2b3c1c22373da7bed6a08892717ad667b1141abcc5c97ef390fcf3","cargo_embargo.json":"762c744fbd4c3e924a9d034fd3c3e4e1399622b96d67058be0ca151ee0b63ba0","examples/ip_defrag.rs":"a748e2d3101caec0404bc011a76f041bbc3dbb41be37fe22e18e046433a9c36d","examples/read_by_slicing.rs":"67b21139e527b19d0512828c1e62c885aa20ac29b8a88b24ff0e2c34ac2f0f1d","examples/write_ipv4_udp.rs":"a9bc127e6dee230ec863ef8dd394d30bf82aae0038f865b778a79d058fd7daf9","examples/write_tcp.rs":"0354ff9ebc61aa2b80efe7ace7749e09129ff54ed926a3f0bcb29422fec4e306","examples/write_udp.rs":"c7483fa6698ab4477a7025a07ee86d6e2af7be86a9f80132124a10c12dff4396","patches/license.patch":"f1ecd16d788765e2876fe8c77fd98cfbd893ebcc0ca6ee56350a4924b58cbb4c","proptest-regressions/compositions_tests.txt":"cda554b354a481c7d6cead4108681cd6b8c051a7bb73e697dce9936b82b16319","proptest-regressions/internet/internet_slice.txt":"f28bf9cbf302409ce9c32456bb0268fa860014e3e21f9b4dc02f17cd02bc8494","proptest-regressions/internet/ip_auth_header.txt":"ec14f9811b5c951e0ab48284b0a6df54ca33385fd419527ddd70bf98ee89fd7d","proptest-regressions/internet/ip_auth_header_slice.txt":"cf07ba1c614744d6a39e10c83f8a4ee14adfe93246dc0af1378299a9e7f64d48","proptest-regressions/internet/ip_header.txt":"7aa825d4c10f28971a4680aaacd1ab9dc99f985513ea0134cfb97445820e98eb","proptest-regressions/internet/ip_slice.txt":"44763f60e2c6ca22a9db0a9223f96331a042b752537e729061de2f65eb6dceb4","proptest-regressions/internet/ipv4_dscp.txt":"a60060713d0a470cc0d8727eb662cbe52836bd2eb92392089bbe7d0b0bd73044","proptest-regressions/internet/ipv4_exts.txt":"fc4e9cda0c41357fd90c9b7cb3424a1cb50706b4ebad54c4e0b75b9f1af647ff","proptest-regressions/internet/ipv4_header.txt":"c1a217c80e1962d7c7d8203a27deeb76ce4d691133295a69e123c239071888e3","proptest-regressions/internet/ipv4_header_slice.txt":"0b0026858b9372e15c1da36931855cb0712b4ed870393614b451280207e47665","proptest-regressions/internet/ipv4_slice.txt":"3d7b66a49887cd90a9c8be2d273e338323ca9b1d14335056ce328a391c610058","proptest-regressions/internet/ipv6_exts.txt":"2019584269283fa58c4edd1da153007cb1d267612a4c45522f29d6cd811c1389","proptest-regressions/internet/ipv6_exts_slice.txt":"5fdabc3c7d82661a5c0e5cb74b2defdf5d9cc879ab4d9955c79f663c55f0817b","proptest-regressions/internet/ipv6_fragment_header.txt":"ce1198917716fdb582004979d0e7b3f23fb0bd24cc4d5a6bb1609942e520b195","proptest-regressions/internet/ipv6_header.txt":"b5f1b9acc5b5a485f8d608246cd047f5e85fd8416994ace5f10b67ddd0ab6b85","proptest-regressions/internet/ipv6_header_slice.txt":"189f88c6ef73383e4f058e4b9731fd70c2a2daf9a8f2ffc34e0887ba1364b94d","proptest-regressions/internet/ipv6_raw_ext_header.txt":"94f5a82ab1d85e198a1d8b6eca0b86b4bc6848d5cedb3859fcd45ed2c3dda642","proptest-regressions/internet/ipv6_slice.txt":"544a3a69312f4bea4e57c4543486ce35137ffa825a01fa94e95529f4f671af2d","proptest-regressions/internet/lax_ip_slice.txt":"085a62ae1a44aa0e2448af0f06762aa3b6b62df7054da6c4f499c986bff502f5","proptest-regressions/internet/lax_ipv4_slice.txt":"7f2d13cb52b93fa1c9650abc182fafd5f9d76fdfc3c06c1316a08de3910e24a7","proptest-regressions/internet/lax_ipv6_slice.txt":"3c3153b0cde13eaf5097733119c4ada982b425a8dfe8943555b9f0d82bb78495","proptest-regressions/link/double_vlan_slice.txt":"5aced4ec8d4d624cf24e61b6c1a159f93b4d51687f0fe12a56fa0a85cc206623","proptest-regressions/link/ethernet2_header.txt":"b5d91d0ac393ee5bf85a105f13f89aebdb5700f6ec07c98f726a1875fe2d12d7","proptest-regressions/link/ethernet2_slice.txt":"1f9047bfe526e0b6af9dee7ca108d4855418159801891dfff31ebb1d3059eaa3","proptest-regressions/link/single_vlan_header.txt":"eefed03214259ad8ec23ef26f98ea973cac1b80dad8d13f34bb2b99de007f894","proptest-regressions/link/single_vlan_slice.txt":"760bd91c71b9653bd4506869d57d4c38057b95da10bbbfbc2a57be429131c7c4","proptest-regressions/link/vlan_id.txt":"249807f03882e8d86aa68c460e0a5170fd2b040c158ff5bfcf6e8cc72ca9c89a","proptest-regressions/link/vlan_pcp.txt":"c935f15506be4836ecd04d535f884c590ef52ba3eafc8a65c3202e66c2195240","proptest-regressions/net/arp_eth_ipv4_packet.txt":"92d487df120ccd798becdbc7f77d0349d9d7a9541aff95d649a77e0337854eb8","proptest-regressions/net/arp_packet.txt":"6a20485e3ce488f9da9a64f7b9fc76e15c39575e51c8b6a02b0d6c49dd690c0d","proptest-regressions/net/arp_packet_slice.txt":"2449177084f07e190f6bbc2c067813cb9cd380e983073f2543aa3f7050298fc1","proptest-regressions/packet_filters.rs.txt":"b32112123b4ebcac3b1a2370c603f1a55b65a6a47abbcb71882886271a5bf041","proptest-regressions/sliced_packet.txt":"0f59adccb52aad6467cb562cc279288de262e64c570d4b08bba37e417e1259ae","proptest-regressions/transport/icmpv4_header.txt":"5cfe000c67124a90b839fd438ced654b69e417f769dfad10d10d5c948fece351","proptest-regressions/transport/icmpv6_header.txt":"a1dcb259f46d843c26b5708a727107644b228d88e358098a051e2474f80b8cac","proptest-regressions/transport/tcp_header.txt":"455bb8904eb89c77fb87c38632da93ade4e965ee7068d443898b3c3dada7615f","proptest-regressions/transport/tcp_header_slice.txt":"9e2b405c9bbde67d092dfd8aade7225e5ac99f99f8e4d85b5c619048fe9c14ff","proptest-regressions/transport/tcp_options.txt":"14c9787903b076e4f77212b4bdb34f0757e82daab993c5e836009de1e4204576","proptest-regressions/transport/tcp_slice.txt":"90b4c039e438af806b7054ad38d46934e92e8ea4393505e5ef47dbef41091e4a","proptest-regressions/transport/transport_header.txt":"54bc8b2e0052cd29caf7487b8f38a6121b5f3250b8bb6109d8572da4b0736963","proptest-regressions/transport/udp_header.txt":"1043f35c4643defde43bbe105e0e2c780603a35196e84de6201f489a27b640cf","proptest-regressions/transport/udp_slice.txt":"a909bd42229448498a77909169aebc44b37f286e9a7a42184453d79f20d43247","src/checksum.rs":"7388dad242209f4d6c001a0cd0fa5cef5047326fb010391dba034ef084d9fe20","src/compositions_tests.rs":"6c91b99eb6d48247074b3d604f6157b60f45bbc5f416e832eadfb26a7ee21fbd","src/defrag/ip_defrag_buf.rs":"c493b38b492c940411a12041fff9034cb03dcf0ec79a1e3cfa80160f397f7d56","src/defrag/ip_defrag_error.rs":"72f25a2bd689e5c5b33ad2c97a5c77dd098a333221145c1de7616d72b889f243","src/defrag/ip_defrag_payload_vec.rs":"3e52e7d70b7d90344582a2deee4acf035f6fc92e7b54cd42d34c5b62f4268ae2","src/defrag/ip_defrag_pool.rs":"08d1d0f97f614dca6b1cf79a84af6721604bce106eb5983968e0b37baaabc70a","src/defrag/ip_frag_id.rs":"11153393c6daff8cbe753ba38ca96578c2c1ef6a616f84f9c6cd9a2bf1a8f96a","src/defrag/ip_frag_range.rs":"4ea25928a52736db9a179ce40fc854b8158c0415ddc020eff2f868e31a6942ff","src/defrag/ip_frag_version_spec_id.rs":"82a3a87b27bcfd1c9c6622bf25e37e7de77d1146d6aac120e4943a672eeb53f0","src/defrag/mod.rs":"4c05ede1918af9e6df0bfa5245fb94c32ab8549d8b541a69c592af41bf5f631a","src/err/arp/arp_eth_ipv4_from_error.rs":"7a977704e99cda33e4ce76f95d9e68f910049b05aff2a8927456374079fa8592","src/err/arp/arp_hw_addr_error.rs":"947e0c3e9ed80ec2d4c4e11bdd3bff393a0e9ce794271fa15f394deb7b3256c2","src/err/arp/arp_new_error.rs":"a65cb9317495017f9eabe911249ea9dd99385515d2ba1f42f656628103b291a0","src/err/arp/arp_proto_addr_error.rs":"270d2c1f0a27291a80ba04adf304642c448e3d3b6cd957f7ec0a02dbdd68107b","src/err/arp/mod.rs":"8e30244317ebaec12c123c4a2e6252a4d77bfe593d372001d99f251b8f30026f","src/err/double_vlan/header_error.rs":"94b224334eb6182ececb530f59d14c270ca1996441995be84fa542d9d241ed2c","src/err/double_vlan/header_read_error.rs":"c7ce4eaff1c20c10e36b8cc689db909027fe5bdb317bf8fd59327fc7f34b6c11","src/err/double_vlan/header_slice_error.rs":"3c6857ae3ff38070ffefdaa1dc60573f2c2ca4245a7dc5d19a875175c5d7d524","src/err/double_vlan/mod.rs":"968abc73c13026c39932f349ac0cc44d4e65811624621b7bbfff39e477a968a9","src/err/from_slice_error.rs":"dd58dd0a19b475b84e030d1da148255142e2c2e0434a66a72ea2d021444978fd","src/err/io/limited_read_error.rs":"5a38dc71e00e4e8c6d676e60dfb379c20d49ce274b71349d252a317427958c08","src/err/io/mod.rs":"9b1c86158fc40b115e44d48af107c3e24d3bdc3ad07a7f24938d599bbb5c0b40","src/err/ip/header_error.rs":"449e2f2acd703a9c01a88f882b91e5952143ae3007e117402b29e3b74a7f60a6","src/err/ip/headers_error.rs":"0315889f76d125262169f18592b55fe070dc9cd1bf2019bdf7bdad6b6885eff4","src/err/ip/headers_read_error.rs":"de7dea1c2aa5c12ef205fbc0d300e5e62905017bd7be52bbec5219540648e740","src/err/ip/headers_slice_error.rs":"2279864b0225f1f3c52d252e3fbd648685e77c5f5620e12c9b58115bfa0b1a84","src/err/ip/headers_write_error.rs":"fcd21869d86e39af87e5508d223b3d0045f0c29b89e249a3edefec19934a708b","src/err/ip/lax_header_slice_error.rs":"57378dab273cc2597c2be9275b2a47f41f0bfee2aa0183987b8aa1ee1d37e7c0","src/err/ip/mod.rs":"8cf92db0272bc87cb1535735707024494bf22d26ae31bb8a16ec522c658fb2ab","src/err/ip/slice_error.rs":"6967467fb090d55e08f61fb9f3e141ae67765c09f0307a171e78495ca2a8158a","src/err/ip_auth/header_error.rs":"95c8daada91eb344fe604e750859b5e311ef8b43d2a446b1f6a082c382a2f679","src/err/ip_auth/header_limited_read_error.rs":"b834012f616673ba66b260dfd44b353f4bea553394ce11b8c4fe1efd0c9aaa27","src/err/ip_auth/header_read_error.rs":"e540027bd6db20c16029d770a045e4cbfcdda7c23ad9858c1cb97dd6c2006600","src/err/ip_auth/header_slice_error.rs":"3040b7ac84cd81dda5f51570789723bdce90238bb8c4ba0d38a49855d6cd5b3b","src/err/ip_auth/icv_len_error.rs":"1083b80d844e645b4bc0d95c5a0f393c60704907cbd29a62e5540e3e1386594c","src/err/ip_auth/mod.rs":"8d6c873698028773016d43f89c8f1f4207258ff24c1d82edfa12b880df76e956","src/err/ip_exts/exts_walk_error.rs":"fcf004213d739390d6ccdbd5ed97b5ed11813c0c020005881d0cb6f4b9629f7e","src/err/ip_exts/header_error.rs":"b74ae7a23a677836da7553662f140f5d4079c8de2938f4a339fd86329ff00cd8","src/err/ip_exts/headers_slice_error.rs":"5c803b2e659ee9f228d6a3c21dd6b4dc4ddf30ee93d2ffeba4f1f776bd655e24","src/err/ip_exts/mod.rs":"f5957b2253e52571fa2cc7e6d9e20bdc903f5ccfcdec6ad8c317b8a13560748d","src/err/ipv4/bad_options_len.rs":"ba7924a492736cadf23bb94fd4a2d03443d2581ba7ecc7bd6f159a5999e94c71","src/err/ipv4/header_error.rs":"08e881e7e3aa2c66d4b3aaf502e2fb44b57a8cd0e12680226921eeaf41641e01","src/err/ipv4/header_read_error.rs":"8c23bc0536b492100f5da785001be475d0aa3ffc96fcdd21a663ff6b5afd11e8","src/err/ipv4/header_slice_error.rs":"e132f20188ad07098fb2f4d99a64276083c37a246035ca0a388aa629c7e0a2fe","src/err/ipv4/mod.rs":"22be02f957eae93403a3b5e9892d8bc8c6e48636c7b46e4a3c48c647cad01ba6","src/err/ipv4/slice_error.rs":"4cf6f7ad034dbc39f2af27b1e10e69050883c3c386d0a81c14f25e27aeaffd59","src/err/ipv4_exts/exts_walk_error.rs":"a86116539f0e354267a982800f48a90bc6576bdc0d07594b336bff598eb63428","src/err/ipv4_exts/header_write_error.rs":"0b9a014265f84edf5595dca68f75e64b6d1c43c5b865824fedfeadb5436cfc4f","src/err/ipv4_exts/mod.rs":"3f15f230f0e89a41ac1e4d8799bc713a5c06197dee36e627f3c074dbaea16a9e","src/err/ipv6/header_error.rs":"77d0fc97d86111f2d0faa3616e69794add675715c64847098334872ae9f9086a","src/err/ipv6/header_read_error.rs":"13c1c949477a179398d79402ff476b5452988c64c97b23a69bc56697a99edbb9","src/err/ipv6/header_slice_error.rs":"ae3c39185449a98066938d77c8be1c8b5faf1333207aaad9e96de882f60fc6be","src/err/ipv6/mod.rs":"d62c636c86f5a60f21809a9dd6afd8920077380dc3f968a8bbdd13222603024e","src/err/ipv6/slice_error.rs":"c354e6af13c8ea670d2a9b8201d3c3e44bd257e881aa888decc6a5489e863f93","src/err/ipv6_exts/ext_payload_len_error.rs":"4f5061bca4f8b6c50b94c8c0ff7c191e7fb95c0a8c97e40eb340b5978b1ff9f5","src/err/ipv6_exts/exts_walk_error.rs":"f5731b01fb3d41efc690ab1bf6818ed7d3a01465f0f9832987712611124dcb87","src/err/ipv6_exts/header_error.rs":"8c0c84f50680f86ef8dc7ee54fa4cbb6760d49640f73f48d4b88ebc170b556e3","src/err/ipv6_exts/header_limited_read_error.rs":"5cc090823388b1daa24640fbd9be279b7a74c77236b38b4426e882d2586415ca","src/err/ipv6_exts/header_read_error.rs":"452d91d054deb790d5fe6867069faa6cc23f20ccd6f8728e61cfc2fc6fcafd08","src/err/ipv6_exts/header_slice_error.rs":"046413243923b4887fca1f88704cf64b36db27fb91a7a4f819d4ddf043891d9c","src/err/ipv6_exts/header_write_error.rs":"551f355334f5b8954200e8ddd12eca84486a6af4b782f7aacae3b53ffe3fce1e","src/err/ipv6_exts/mod.rs":"5e20a8c16ba544de38e463e0ab94a3dce700b3d5bccf5991392982ee7c726a15","src/err/layer.rs":"eff5ae3b4d925e525a2bf374544d8c3effb78cb78ca9bf09e19f8adcfb12b90a","src/err/len_error.rs":"b72b38891edd0f2a6af5873b23d99d10ec5c224ce8defe7da77815b84e1d85c5","src/err/linux_sll/header_error.rs":"cb87d51a9d63945d4208c7b25a939a27b620b0350dfb9b43f367b7593a266111","src/err/linux_sll/header_read_error.rs":"167400a38c4ef3f93c4ea435cab6bad4c8624aca3711e9277ad5aa90c6a95aaf","src/err/linux_sll/header_slice_error.rs":"d4ae8dc2b0904292d5a00517c7ec3a8d8d47ac874550c0085e4e3f2d5370e475","src/err/linux_sll/mod.rs":"968abc73c13026c39932f349ac0cc44d4e65811624621b7bbfff39e477a968a9","src/err/mod.rs":"46ac424c27eceb541e0fe976ed8527f7a1879217416bd961c22959a6a735bb82","src/err/net/mod.rs":"b1024961c26c1e1d73eb1b01186c54b8914556022853d5f564134ddf2103b6c1","src/err/net/net_set_next_header_error.rs":"1bdf056b3a97078135b83906c9e2c2afe00989d850fc4ff469b70ff2ae52b42b","src/err/packet/build_write_error.rs":"e51320e0dcdec10ce69ddc19602c7a79aa548f39fe85fde33f6bae44df458685","src/err/packet/mod.rs":"05c2973ce964fd061f9cb53f17a4e88d880a4e70461546871d73e28cc90fb04f","src/err/packet/slice_error.rs":"9f05acdf5d949ed484c5c162de923fba2e261da2ead14057119061699e32bdb6","src/err/packet/transport_checksum_error.rs":"db0503fe7f0c3e278a34480afa8a2f906538839bb2f913579fc6cae3d0d819fc","src/err/read_error.rs":"47cf36c5b1b1fc19f37cae597bd26512565d0ffaca5ea9c2bcf1e77aabbbacfe","src/err/slice_write_space_error.rs":"dafd90ac1352a6924a16644733e2f3eac83bcba3a5535f31ae192ec0ecba2974","src/err/tcp/header_error.rs":"821c34df02a3d7f52f90e019c94f5d434b5d1687ed2537ca717417ef4c1fc2b4","src/err/tcp/header_read_error.rs":"c29758051be2beab762ff01e262adb90dab3812a9e0f279b06a0e90ce0ff9969","src/err/tcp/header_slice_error.rs":"e9743c1bff4dc6d286164df44e78a5764f497f33d10dc25bc1207f26d390f549","src/err/tcp/mod.rs":"968abc73c13026c39932f349ac0cc44d4e65811624621b7bbfff39e477a968a9","src/err/value_too_big_error.rs":"6f247333b36b504a41870688834c06ce53ae263af316ed418d1ce8804ed03a9b","src/err/value_type.rs":"a66a995d3452d261b40bf7323c6ea2e06236f726ad89826b73f128d93e8744ef","src/helpers.rs":"94b2d9469d376f39d38fef3d76dfd5a444425c414221ee48eee4b13b42e5a6fd","src/io/limited_reader.rs":"b8499bd2e3ffebb5b6d88713bc382cedf9a8d7033ce790e2c56f8932b25e9020","src/io/mod.rs":"bb81e1b6b01b26c3496675905dba6f9dc19b0a6333352e6eb904ed51bfa91007","src/lax_packet_headers.rs":"d9940c39c66bfb8f3bc016d4cc6ea3c0d793a5cc19fd836d0e14cf84500b1af5","src/lax_payload_slice.rs":"12b998d4e6592789181a9ae0d694fa3fcea4eed35327ecb1dced095c8b47f8bd","src/lax_sliced_packet.rs":"d080c8c6bb84b89d7cf92f40adc08f2c7583152ad46a2d043f9aa00967cd3732","src/lax_sliced_packet_cursor.rs":"88a631f41d899f1bee9c103cae1dc88d8d07cc5a3bd01971d2e4ed4a325d2242","src/len_source.rs":"0fafe650476732516e6196386d0cf1dcb456999f68ac541973c3e100d66e7dea","src/lib.rs":"93961bcbcf0ee78468ce34eacf708817b33d9897ca7cf70973e1416de74138c2","src/link/double_vlan_header.rs":"3c1abb259356f82c04f564edb8a01c11174ed4b46f7ea33f91ab063097d3490d","src/link/double_vlan_header_slice.rs":"02ed6e77124f73bea98577d725f63a93237f4b7f2b5c0dc6b82917ef91dd3156","src/link/double_vlan_slice.rs":"772c7747ebdf1f811a3c93dce485362462364c03fd2ee42f474f0c0e051bbcb3","src/link/ether_payload_slice.rs":"8282c6f2b7fa47176090fa0117dab1720568b05f93f703d6a1fda87b26b2b86b","src/link/ether_type_impl.rs":"99a87b820dc3ad0c193740d1e971ac0256ecf3568becaadae596a10b5543ae0b","src/link/ethernet2_header.rs":"b574e528989e989e4c38a5a31a93017578cd564efc0261b7ef1d33c1625300fc","src/link/ethernet2_header_slice.rs":"7c48ecb25a178b41027e8f5ce305d67bf0df883bc9e8ff2cc13b4aeb2e5bf987","src/link/ethernet2_slice.rs":"37ce79fbc4f97c5c0c76784c317591fdd99c2484cc6d7e70b6608fb5de0e79d7","src/link/link_header.rs":"819ebaa407501f1086f6bb409d47f81152eb1f63c118b6c3df6885becc8ebbc0","src/link/link_slice.rs":"68f71f79b4c990e29f3717ec73cae631d9248e677b4a8693c7ced2f230e6f2b4","src/link/linux_nonstandard_ether_type.rs":"6d31bf570c7f1ed78e4df0212589b02b54752f73f470e659dd43436ed2074b7b","src/link/linux_sll_header.rs":"6e2b97e6e9f210d638cc7ef08b333ce0037c6451e0bfe44040a1d88e53890898","src/link/linux_sll_header_slice.rs":"983f237dbf7dc15408c8e201c2e43ad71e4d97e3fde68647b26c78fd358bad1e","src/link/linux_sll_packet_type.rs":"8fd4214ae97f691db2069566eaf2ac07773d87dd78fb0d900c885591d89ea7c1","src/link/linux_sll_payload_slice.rs":"a83e19868863fabd1c3b6374be4259eddeafd8778bb469d27a9015ec3f112e87","src/link/linux_sll_protocol_type.rs":"d3a943ef12d5a7fd2c3f68dada9deacab76abf8e3867c932c03b6bd6bde29053","src/link/linux_sll_slice.rs":"1d2dbf93e8c47fddc824c97de3362cf77f863f918f320973708c820053a4bccf","src/link/mod.rs":"42b892be2e48f06f6f235dd5cd6f767428982971cb32ad9ccdbc1c0bbc391b11","src/link/single_vlan_header.rs":"1e26b6eb1244b63296e87375f06e70cd207933268fcd390d993037deeca13232","src/link/single_vlan_header_slice.rs":"2cd0131e33a80aff3abf10c372a34744a4d976f10b3172a61deb1e77d3e09a92","src/link/single_vlan_slice.rs":"cc9f690f79cb71cb269fb4d221db2aa67c0cda3278d8f7e3d5646ba44e05442a","src/link/vlan_header.rs":"b403aff1ce9baf249b6dd3edbaf4c581bb82e764da0724f979ddf762ddbd22b9","src/link/vlan_id.rs":"fd00d92c100d380005c5f8aaa8587730562d9aa34b318229d08cc8a036b391b3","src/link/vlan_pcp.rs":"08eb38d5d2f1a4478dd068fcdc439869c841df7b46a7773279d68485984a92e3","src/link/vlan_slice.rs":"25f40947307db56362ccd802cd115585f54c0d6e85a245219f9c96bb4ff24222","src/net/arp_eth_ipv4_packet.rs":"872df2a3be2a8b1abf0885ba4f25d93278a418897828912ae4ba718f7a199207","src/net/arp_hardware_id.rs":"492f83b9570962906500ada7b0e02a1bad4a974c4a0a8848553ad2a1dcef0dd6","src/net/arp_operation.rs":"105f1fe6e5d3b5fa9b9ef322429253462d9136582be2b2fe2b8425f6ed117192","src/net/arp_packet.rs":"8af35ac986858db6ecd5afc00df232ce68aa92a886679ce0f396a81b1225becc","src/net/arp_packet_slice.rs":"3212f9d5823db29693ab00784cbd3f178b00a7ed2eb66802f9277ed941bcc7a0","src/net/ip_auth_header.rs":"22573d6e5dca187f69270c4482349a6c32021c34370e86418e330cc0dea2cbfa","src/net/ip_auth_header_slice.rs":"24af9e7ef37e5a68fa75ba1e60ff77bcc1c69c542c734ba8fe3edfd5c59e8fc4","src/net/ip_frag_offset.rs":"d80220902049a8cba3bb2d418aaa1ffbe92a1cd5ad86f1c06a87e5e398a22820","src/net/ip_headers.rs":"0aff6c01aa4e88933f930972aee4af02a28c577873d8074beea0f47906c20104","src/net/ip_number_impl.rs":"0c8f8244e1e0e89c7b725665795a1ddb994780fda1d222dc5c122828c18ebf26","src/net/ip_payload_slice.rs":"fdb9c7e0c4a1b36b85e254d966a978c5eefadc460dfbc77c101aecc56e356874","src/net/ip_slice.rs":"557272d95be6e0cd194f5f275c582110b0ed82c5ac6e043ce287e413b039ba2c","src/net/ipv4_dscp.rs":"a58269019f9c8d8a75e96bc0ebef88ccf52bc124e413890b2708938945382a60","src/net/ipv4_ecn.rs":"058538db9b40fe5b38528d7132681992bfd40ab05e1424de37e26d6628ef6b28","src/net/ipv4_exts.rs":"e86c7ea1a253541f6033fb45b2280abcd8f00e8cbc6bceab91581db0128fa641","src/net/ipv4_exts_slice.rs":"8573d4c148e42769fc50ddfcace0fb21e0ce58fe3f07131a1e87d1370e88d721","src/net/ipv4_header.rs":"362411271d3255555a201b9b922a92fe1e1d445a10a4c70775b61c814b97f43a","src/net/ipv4_header_slice.rs":"9c054952ad845a9fc53d799beba064cebf574316f7896cb8669d99ce935a8bcc","src/net/ipv4_options.rs":"1c00583a8d71fc1a3fa2ff288b2b7332ab45723fd1cc5a3eaeaa8f3df56d98c1","src/net/ipv4_slice.rs":"d40d738911319e6af37e5bb0f72bd37a8608f8bc299ef9124d0d54c987625fa6","src/net/ipv6_ext_slice.rs":"ecfe7370fbf0199c8a28d7dd292ce4f94441d3c1abadb281229e141fe1d1a852","src/net/ipv6_ext_slice_iter.rs":"edc969e0d25724543a9530b9aa5dc3c6da6503f7135cc63de52bbaaa4418ccc1","src/net/ipv6_exts.rs":"674d4a33e7fbbea422cb0f0ff0d0fa8f04a3c26c33113676c175b83da90367de","src/net/ipv6_exts_slice.rs":"9264956fcbead2ead446dc5976a223719d8a98fe8fa285c1da2793a25ee8366d","src/net/ipv6_flow_label.rs":"8e271b96e476641d64ab74d16f44980fc266477af7d567f6f5bc5e6b1e61da67","src/net/ipv6_fragment_header.rs":"ed6c9ebbfdb388e6dca0e1f89954ef744a94c5882a1ceb13fab1bddd1d530617","src/net/ipv6_fragment_header_slice.rs":"115429110c4501d786aec68b96b1d440e3c92c68786ad97dc1b12e8419fa8647","src/net/ipv6_header.rs":"beab70250d6b23a2c1fa92e949af67868f9abf421ba8361b5f75ae8a15b41716","src/net/ipv6_header_slice.rs":"2f13f5894031b592142d6ada1058910190c0cafdcc03cb5ff1e9ba84024d4026","src/net/ipv6_raw_ext_header.rs":"9a56a6aca63fc8a744dfc596d2e178f3611fdcdf9e381e7eb8a4d4ab31d17108","src/net/ipv6_raw_ext_header_slice.rs":"ca8bbe564bcffb6c811ed584a6976b156800999f20bace94be8299947a4434ed","src/net/ipv6_routing_exts.rs":"de9f55abbf535a89fa55d97877ed998ee3000acc6dd79ac084c4fe7414fa9cbe","src/net/ipv6_slice.rs":"757c6f9fd25b5a1f7280c3a87053725352aafbd37abc4fca22b3b31745275a85","src/net/lax_ip_payload_slice.rs":"6ea047579308125bf414304458d6c204fc9d93c6332a5a10d65b6be17688df1d","src/net/lax_ip_slice.rs":"0e11a7c18f8893106a2f11ad1e237e27ce4132d6d1b3b9069514395775126fb2","src/net/lax_ipv4_slice.rs":"ebb1ffb78b600ff167516f68105335b03163e0faf8fd7ba35b5067544467f9fb","src/net/lax_ipv6_slice.rs":"2d09cad4725130ed59c57a8d944e6effa9a63749d512e796f7ca4b9700f516ec","src/net/lax_net_slice.rs":"1e6968208602ae285804d09b6c71113048d51b91d5d5ad28064c88df28d1b595","src/net/mod.rs":"5c30f09ac80e57bbb0bafa66511195ed6e2a561b62f91d11f887bd49c2660bb5","src/net/net_headers.rs":"19806ffca943aa7c9aee69ae71cf63f9d5df96fa41206b43bed068940cb33be8","src/net/net_slice.rs":"f4b066a394250de381648f4007bc89438a51e86dc10594f6dfabf628696b536f","src/packet_builder.rs":"3de47508e0b20ae6c89be2ca81f5ff03147a4a084e9601f38864ca7af5dcbc02","src/packet_headers.rs":"336195e131e4ec06f7a286c67f72b3e56a653197dda21f22b656711817d8ea04","src/payload_slice.rs":"67bad607216dbda28772fe7d884e225dd0b3edfcdc85be1068dbe809c29ec180","src/sliced_packet.rs":"64120ae039b98693a9963ae4e32b8ea35ccf563d9eb61610022348dc8df9148a","src/sliced_packet_cursor.rs":"3c7678fb802ba4454dbc711e37900ba8f0e2f95e1fa820094742aceb0071695f","src/test_gens/mod.rs":"82d6011c4b38ef626fcd4048e966efd935e1637662c074f1f25af4354f36e188","src/test_packet.rs":"a8cf05a372690e70a60e37a14b9215d6ad9f96b97b562bdd2f3432c6cd7403a4","src/transport/icmp_echo_header.rs":"b2ec597f411dabde553c66583d21339765e623cb7d4d96cab5252079a53f9abd","src/transport/icmpv4/dest_unreachable_header.rs":"1f619edf7538cb84f9924ce9c9e1461bd6bff6254f7c4e1879a054e37f71e9c4","src/transport/icmpv4/mod.rs":"445a123811fa05bd966e7c93543ab61f2edf317f553044696d92b62e232d97e8","src/transport/icmpv4/parameter_problem_header.rs":"ee95757391f3d2189ea4b8a05bae5faeea62dbc8282092ac99fe527d96392bce","src/transport/icmpv4/redirect_code.rs":"20f833e7b44a24edcdbacb4a42e1bd6709251711f56d9091a3667f5754d00a86","src/transport/icmpv4/redirect_header.rs":"9b93ecf873776b3d387b0eb2da369d6da87c647aa48fa7e12896b81e035bded9","src/transport/icmpv4/time_exceeded_code.rs":"ebc54359a02e6897a3b419274f01b73548ba5c8ac847f996e8f651893a53578c","src/transport/icmpv4/timestamp_message.rs":"42fae4577982a51da7c24f42b77e54b680d540784efe801f0541c023e6ebc78f","src/transport/icmpv4_header.rs":"47d1245f759880b1c36ce659ab572de437ec3e83038e2bae39abe6a4db6d0e8c","src/transport/icmpv4_slice.rs":"4db10d54fefa306f20170a6cff0572b861778613238816e9e95f1200de3cac56","src/transport/icmpv4_type.rs":"afec53948c2141eceeee6b5e825879427a7cf059d86ad4c97773ec3a7185b804","src/transport/icmpv6/dest_unreachable_code.rs":"dc513f7b9dbbe0f3ceb3eb0eaaaed15487d5038bf7dbc51e05f60eb269190111","src/transport/icmpv6/mod.rs":"251734f9a53f91f28468c580de64f0cd30f54f74e1e53852cfe25f71bc5ee9fe","src/transport/icmpv6/parameter_problem_code.rs":"0fd1f4f3abe254222add89bca8b3acfeca56c6d67882041de38e5c7a7a4fff46","src/transport/icmpv6/parameter_problem_header.rs":"66c54b02ad56e99b39ee68712d1634400a882ac3de2271807708bc0f0be10d72","src/transport/icmpv6/time_exceeded_code.rs":"e0464ec86abd7c6c61618a6a136d6ebfe6a7673ed08d53d4a3b67fb53c0abdb7","src/transport/icmpv6_header.rs":"612f7189f7626c02de13d2792965b74faebf27aa212329ae2b54f694d681f222","src/transport/icmpv6_slice.rs":"d63c435426e2bf357285d6a7ec7d956c7c4a66ce92bcf762f31a823358f70a8d","src/transport/icmpv6_type.rs":"81239361b78e2bd588098f04dfbbdf92163c04119bc19761f0e2cccd8bf61773","src/transport/mod.rs":"c647c794e7c46fc4098da76b1a23743d35c4b7d1ac9b0ea6282ce851ed977a9b","src/transport/tcp_header.rs":"a6153039059dc6ff74bfa45ae567ea05a5d1d598c139a80ab47fc0d98b709429","src/transport/tcp_header_slice.rs":"de3766544a3ff9f40ea11ba3150a1e8175a48e1e1bcb05305fa00039ae87a690","src/transport/tcp_option_element.rs":"0133f6759caab0368634523699d77cb18e6c9a1b816e3ee9eae3867eb6ca7f04","src/transport/tcp_option_impl.rs":"a57d3b760358f448691b9094202291241d165616a226e6fe4590c6d3f62175e4","src/transport/tcp_option_read_error.rs":"678d6904cdb82d829d8bf8df8022a5823b20ab1b654127b479dc19b9f1a62536","src/transport/tcp_option_write_error.rs":"b078629cfa5255ae4bfaf21c4115683180d757a82bfd6760a91a3511293339a4","src/transport/tcp_options.rs":"0cae0fe51364a7c8e4129e4b401d3ecef9f28ebcd239e4c5b351b17f9c984266","src/transport/tcp_options_iterator.rs":"606b27483d1e0a112c9c706c9fdca1b9673c15dd3f1f74611948cbbde8c2dc04","src/transport/tcp_slice.rs":"3e6479bbef88793bbdcfa1249858c33a96b105d6059a469c9ae9f0a3337dff13","src/transport/transport_header.rs":"80bc33b7ff4ecd59d2724a58c94bcd476298c9a160f3db10b4d8a3722d0d5737","src/transport/transport_slice.rs":"3ba479cb2d045fce1d6dd1b46be026c3abfa46ee41635a992a7ce2db250ecdb9","src/transport/udp_header.rs":"91adcd615bd37f6abe5210c12cff9771b0e99fab5782713fd8123cc1c8778da0","src/transport/udp_header_slice.rs":"c1bb4d00238bc3562df71716d2606106503b428c81a8ada129ab6d3917e8a2bb","src/transport/udp_slice.rs":"968ea622a6dceee3c864bb8523cd3ed2acacf726ea6deafe9c2af51c49faf3b7","tests/transport/icmpv4.rs":"bfd1b7e295011011c79347f6bcb2d3fb20be8c57cfca6c79d6470ee7082b5fe6","tests/transport/icmpv6.rs":"fbeded3e512f03a9bd93868347d01c170db613057d65757a95e2d6cc49686141","tests/transport/mod.rs":"6c3fd5a92f8c736b1ac9a74bd9b784c70551205ac6e9be7efdcd3d3ac3907a4c","tests/unit-tests.rs":"dcd05eed939140e201d69c67f6db1cf526d8c641f7aabe4985e5dbf27a9ef2db"}}
\ No newline at end of file
diff --git a/crates/etherparse/.cargo-checksum.json b/crates/etherparse/.cargo-checksum.json
index 9e7f1fa..aa9b744 100644
--- a/crates/etherparse/.cargo-checksum.json
+++ b/crates/etherparse/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.lock":"c6c8759d63866be883d313752bbbb59f3256db07ee66ecb87038508a04cd63a1","Cargo.toml":"ca1078ddda905f406031e572de334900b5610ce388bcdbfb65164957bbd08a77","README.md":"1a95ab84877b1da4e4be45f68a0fa49ee35d051e106c363d133f93883b2f2073","examples/ip_defrag.rs":"10bb2e8c3f9eb68dcd51ec16238e5add36f20b06b675b461c13761f7be31519f","examples/read_by_slicing.rs":"e4b69312db614635c438a19f28c6fb3b76ea50c0c5e9b37e8e475bdb606f194f","examples/write_ipv4_udp.rs":"11dbb0d0ee11fe82590bafb6d2b62c90c5665f62eda4b99c94ccba8b06e88582","examples/write_tcp.rs":"45f1442730369f5b69b0e6af0474feee5b725fc96bc4605ddf232bd57d4cb834","examples/write_udp.rs":"31c6b6b7ef388260ae34ac1f7a25f1ecb52d7af879dba2fdd861ef23132d0abf","proptest-regressions/compositions_tests.txt":"3219d12560d2a798bc6053ea7c6b598cd9df893d20611c350fb2ebac0c1a07cb","proptest-regressions/internet/internet_slice.txt":"3e6d037f650d2e01302802d1c311faefc174223ae0aead73f26e410c1b530a5d","proptest-regressions/internet/ip_auth_header.txt":"50def8f52412a867fb9055410d34ee295c86ce39d3ed3f86589e13cc88a6e946","proptest-regressions/internet/ip_auth_header_slice.txt":"b2f3a53904e815f9a9f2eecfc91da0306dd804efb0f022cea93d7b0a418eb392","proptest-regressions/internet/ip_header.txt":"daf1a8841fff4bb83b80bd4d78e9151d3fdca3dbf3ea3e01eca5b40c6413a568","proptest-regressions/internet/ip_slice.txt":"28ef712b2f188fb7330138d6ee356bdb15c08ed80fe09366fdb54f4c72cf616e","proptest-regressions/internet/ipv4_dscp.txt":"1d22c76326a8840478ce688721fa68610bacf40d57ec8121d24b0ab4cf5f00e9","proptest-regressions/internet/ipv4_exts.txt":"2988687b1b40b289b521b3ab45e2098eb0e689c35bd449dbe0d237e94740b9f1","proptest-regressions/internet/ipv4_header.txt":"ca7981b5b5254a936f0750f50f8ac1a277f6ec8e90a61cdf89fbf39159004851","proptest-regressions/internet/ipv4_header_slice.txt":"072f6280761243272c290d1588d08081f788584b3cddbd4de4d429c15fe88d52","proptest-regressions/internet/ipv4_slice.txt":"ccaec805c9d7e5ef3912e261924386920960dbb8d4d6857e34c97be5f963f63c","proptest-regressions/internet/ipv6_exts.txt":"ba2116cbde67db1235fa82818071313cd638370931d8ae63258e046bdde86f3e","proptest-regressions/internet/ipv6_exts_slice.txt":"406b131864c399d7d04963a092002cea02794313a9c1457b0a27c9147f8d0a29","proptest-regressions/internet/ipv6_fragment_header.txt":"860219218508f64d03748a13c16968ff858d62db27675f9086fa62a7f87c0029","proptest-regressions/internet/ipv6_header.txt":"550b1bffc1bd380f31092a98100ccbfdde8431dbf9bec5a1d3f918f39b92de9e","proptest-regressions/internet/ipv6_header_slice.txt":"e765b5ce6e0c84f38195dbe5ddf0812b2a634aec86b927d5ebd322517a3fd0b3","proptest-regressions/internet/ipv6_raw_ext_header.txt":"d87b0366ec9b7196099bec67d4d87f3a47de9c31c34a865c55f26200a916599b","proptest-regressions/internet/ipv6_slice.txt":"8a34d0394144f95166c7c5ec10255c96065d9973eb46c1e28daff949210dd87b","proptest-regressions/internet/lax_ip_slice.txt":"0bf5fd42357f94b7e3fa96e169daf1795dcb0819785f366759885cd8dbe9cb37","proptest-regressions/internet/lax_ipv4_slice.txt":"ad8377842c1cebafd9f484a5b41d0782918695514265fb74915cdf2b985c8426","proptest-regressions/internet/lax_ipv6_slice.txt":"749d41084ff5c956cf0c81adc21ec174560ca5a533515f2ff55c9941f5df0f7e","proptest-regressions/link/double_vlan_slice.txt":"a69268e277a86f9322f4d4ac078b51394cff82dfc57a6228e61c68a81fb3a8f6","proptest-regressions/link/ethernet2_header.txt":"ac42e6de59b38553abfce6da0aa730e727b6057bd141b5e3dde0f2cfb2d224f9","proptest-regressions/link/ethernet2_slice.txt":"bb1db1468629ba839a220c16fed9df4989f6cb47d76dc72d7c50d90858309af2","proptest-regressions/link/single_vlan_header.txt":"84375d8d2857b45c86e34efd7d1e0162b1c6a074afe7222dbb782769949338ab","proptest-regressions/link/single_vlan_slice.txt":"c30842de60e3705a9cee5e784e138666b36c41c4404d25c1b10aeebf91828ae1","proptest-regressions/link/vlan_id.txt":"4291d1f8635129adff85337ce636ffecccdd31fc7d65235d007769adc0758aa7","proptest-regressions/link/vlan_pcp.txt":"5c71c71a5968abaec8acf317cae3c98eaf2b748679706f57ef0a74aafecfea54","proptest-regressions/packet_filters.rs.txt":"8e4c6382eee4ab90a83dde3f5dc49b0bd314315c0697e131e7205a20cf810358","proptest-regressions/sliced_packet.txt":"7a6337669ee5fd8c4491964f5c2253b670da990b32290092b00b6481aaab106a","proptest-regressions/transport/icmpv4_header.txt":"8576df10a1af73820327e7f5bf9c61eac800b0d8b403b50f63087012861e8782","proptest-regressions/transport/icmpv6_header.txt":"c330100866d05828baa7c1e166872163509deba82adbf24a4ac4c3db6cb24b35","proptest-regressions/transport/tcp_header.txt":"fc661c2c82fe62a2fbd344133e56f05bca9019cf4de01711beb69450c8f28214","proptest-regressions/transport/tcp_header_slice.txt":"d9777d9454282cf18826c3a84a878b16a82a338965c4ae80ce0b3819c53cd6d6","proptest-regressions/transport/tcp_options.txt":"c9f8c46b2c43168022a0e89b58c50f1868d1ef92a45523ca8777aabde57665f5","proptest-regressions/transport/tcp_slice.txt":"abb4a9403f6e61953e2428986c8a53cabb5690148855bc14a9f80d20c28aff59","proptest-regressions/transport/transport_header.txt":"210d13c7568afb787354c964e94a524ba248dfbca8096b8624f0307a8d7af59e","proptest-regressions/transport/udp_header.txt":"b01f1d27645bea66631cebacc1d3194ad9df8ebb47ff749d6cce807c08a83b95","proptest-regressions/transport/udp_slice.txt":"9fe0840204b6828df208e6c2bf3f8a443c10355183d0f9865a660024f1737547","src/checksum.rs":"6f55a67ed111ae0e1cb0607ba3e4a8c8d90f13ac1ea51756070344d39ed5f776","src/compositions_tests.rs":"ecc6a2e77b5a7970bea4129dedd07e22d78cd9cc125f0339eb72433d552d7d45","src/defrag/ip_defrag_buf.rs":"1085d477f1169af7e28629933f9c1daea3a6e7f645d85d6ad80d7886f2298ea1","src/defrag/ip_defrag_error.rs":"eef705111716961072bc81c17b18a1da31cf9e81ac4c35d543d172a2aecc2056","src/defrag/ip_defrag_payload_vec.rs":"0b9b8f01c62a5732cfb27de02bb5c743acc23644ffde25b4e63700211ed25494","src/defrag/ip_defrag_pool.rs":"146a78d96483813990782a7ef7b97fba2d4ab745f46b82e10abd478dbeac2ab4","src/defrag/ip_frag_id.rs":"71765a4e0697091088e17a070542d822311a2c608dacd2815a3d380bc12bc2c4","src/defrag/ip_frag_range.rs":"ab3882c6e6e89a04dbb603c64483092336b19624422616d47937827a9e3c0935","src/defrag/ip_frag_version_spec_id.rs":"5b3808f4a4ba45ff236dcfb37d11edc4dbf409fcf23812c70be6473e2c83ae60","src/defrag/mod.rs":"b45da0a043f4659bd9de595d863c760574b766a159b5ce5050ba6ee84da31de8","src/err/double_vlan/header_error.rs":"ef097f502e89088deef9f106708e0f02c5fc92f7f6da8ba92b160d52ab3d67a0","src/err/double_vlan/header_read_error.rs":"cbaf6dbc5c67955801334823b607745e386482c36bc2452d917eb5fee971f006","src/err/double_vlan/header_slice_error.rs":"7331d4cbaa998b3517d8164710d5eca67129244836d834a8ae3262f0a61c389d","src/err/double_vlan/mod.rs":"53f7d8288023d6c5e408a15d376d9ecc3eab44b87bb014e8e9f2a71ce0165a2e","src/err/from_slice_error.rs":"ad0f2505e6fcd229d40a6af3acf34250d82ec824365fa7aea4543f0a7a44ac42","src/err/io/limited_read_error.rs":"e9ffdc05c7e0650927e8a644e4d0495995e382451df5281cb3610c693e2d89e5","src/err/io/mod.rs":"fc6eb32dca0207bbb3a9f8a33c171aa35594113cdfaa6abe9a73d80fca233720","src/err/ip/header_error.rs":"ece81ed3d73a29cf0a646830351423214fe0c560fe92568f026635238be28c3e","src/err/ip/headers_error.rs":"77757d9d2f3e47e4d9965db04a0c9e4a24f23ccda070e0323f239de4cc135aaf","src/err/ip/headers_read_error.rs":"03aa63d54d6ff65046afbd05a46bf87a70756a84429c28bc2f708dbdf2b01739","src/err/ip/headers_slice_error.rs":"8ed4ca0c2e6af2763ef7a69ce13bc891194f809a427139da21e687a2d1c43c8a","src/err/ip/headers_write_error.rs":"6a33b64db0fc0d6da08fe799c44e34261e3e2f0a5a52251100826663607aad4a","src/err/ip/lax_header_slice_error.rs":"47d070a1963e17481e0fc999de643cfa62a77c84ee5e09f03e28aa1d3d28fd65","src/err/ip/mod.rs":"057da7aea668eb146e3d1bfdfb71fa61ffb265d0f26a10b018609dfae4d91a79","src/err/ip/slice_error.rs":"504cec082cd17da5efde6bd396a12f93fbc12caa98c2459cd2ce862300944e78","src/err/ip_auth/header_error.rs":"4b57829951a8e7e9b39bfd42f0d910b8836933f6b8d10d785e5fa8c1f472adf9","src/err/ip_auth/header_limited_read_error.rs":"eecd056eba8c4c26cc277e1e12dbe9d321aa406a74df29688d4e25345607688d","src/err/ip_auth/header_read_error.rs":"319e2125c5086e425c7503ea5dc7169bf316ee7b78837a27e31b8d99de119d8b","src/err/ip_auth/header_slice_error.rs":"5a8f7db033c8cd6e34663b7c302a97a61740fa535a0a6f169ac21a0fcfce93f4","src/err/ip_auth/icv_len_error.rs":"fb2027f53a00409b6cfb531c384f0a92808a2e34b2e2ab5203129c2604c8246c","src/err/ip_auth/mod.rs":"0386ece85ef2733cbe12ff442c95d21c47e6ffb294197049be90f8c0c7ff394e","src/err/ip_exts/exts_walk_error.rs":"2b9038166052d15f8bdc0618f8b1c87aae1aa0823ccf626f4b48add1a448b3ed","src/err/ip_exts/header_error.rs":"5c7c06e6d4621bcd91ac6da67a87ea8633ea13ddd808297a82738d75ad3e23de","src/err/ip_exts/headers_slice_error.rs":"bef8bf9f26656f22634144e1a5b0802baf1a0489cbf41d71651a0ce6c7d2427e","src/err/ip_exts/mod.rs":"238ef5a2e3f85941636661081c5bab07aa8bf5164269a90f1bb353e3907d9199","src/err/ipv4/bad_options_len.rs":"330eafcee414d77dd15aa7e399874f69e9966e8b791814dd224249c23929d825","src/err/ipv4/header_error.rs":"bc239fbef6ce2a1c2e40e6e24a53b121bbc03aeff11d587b081a5311869eabb2","src/err/ipv4/header_read_error.rs":"da9d0b00729ca4332ec0df2f81c18a57aee710c2acfd9e491c1d9f8329cf7a8c","src/err/ipv4/header_slice_error.rs":"34a126fb3e9ba1622276e116ed10304741297f3a29d7f8bcb8d5c460a66baaba","src/err/ipv4/mod.rs":"a10d86a8b0760acd1214216959b53d14bce827a9d8d60732a852cea93df79144","src/err/ipv4/slice_error.rs":"79951b4f875df657aed82503a715a9c7b50593a1ca3b876abebe8e032905bbd1","src/err/ipv4_exts/exts_walk_error.rs":"be6ca20dfbf1da74130541c871e29629284edff69bfea0907548173cc40c1b59","src/err/ipv4_exts/header_write_error.rs":"6121fc1b06916cbb3b2db5d2db59330f730c22cfa6d5cc2c5d2f75e9721772b3","src/err/ipv4_exts/mod.rs":"7667e113c21c7f642aea212313d2d931e7377f1cd4610eb11097af885c201242","src/err/ipv6/header_error.rs":"35260f1b840d5225da534449e59005057ca505188d42667b891df6d6ef64e9d8","src/err/ipv6/header_read_error.rs":"afcbdb422fbb2c2cda70c39e617dfe561d66308ff32fc4dd0db2b46d3858b4f5","src/err/ipv6/header_slice_error.rs":"b4ab4ea3470e64bd0f9c5551bb68508384ce650859d9709b04f89b9c82879fd6","src/err/ipv6/mod.rs":"861569fe58827b67a0e00c8baafdf9e369e7354d331cd541ba6209880c7362f5","src/err/ipv6/slice_error.rs":"6b96e7d30b26eaf6645a3aab8148a8011453daa17a8597e6d7cf3bd7e5062d01","src/err/ipv6_exts/ext_payload_len_error.rs":"e9eba7b7cc372f9148c25103caa85b468b7192f9464d1b0c0615b3b3be678d07","src/err/ipv6_exts/exts_walk_error.rs":"c2580d09e1c253d55bb0209b9cc24095f002417129ad90878be09483302f281c","src/err/ipv6_exts/header_error.rs":"8c6ec561071f77421366616c0c7554536973e1eae88702691dcf6e2490304900","src/err/ipv6_exts/header_limited_read_error.rs":"eb06038e17bdb88337e0563e90c3af22694b8502ed2e8e8ce29f102cfd0220b1","src/err/ipv6_exts/header_read_error.rs":"7c16c83359817e68db50d55a3eaaab476f26ff9e38bdf43c2560a6c4d7df2ee6","src/err/ipv6_exts/header_slice_error.rs":"52e03033c67b24b8bc84bbda219c20d442139572b9ff01371f9791c589152163","src/err/ipv6_exts/header_write_error.rs":"acba426a080e4a487eccbbd0662450b79cb3cadb1f04269dbe586b04a3dfc0eb","src/err/ipv6_exts/mod.rs":"129078a0dac47dc6f73ef45558b8bc33cf8c42e1fce4a6801aef80090b501712","src/err/layer.rs":"9854f00174c029444fabe75cbc9af814c5ae736f1500466059c480a07e04f639","src/err/len_error.rs":"b13c86eeeead60ed068dc3bdf59eb4081c8f42b5dec1a4d01dd1ee0dbd098e2a","src/err/linux_sll/header_error.rs":"5126ea9324da5ed83c2eac450c90888dbfddf3d4792be45478280fb4216aa543","src/err/linux_sll/header_read_error.rs":"27abbe87ef13d3881eb84e175ddf5187263e552e91c0917dc6540c07b57a5ce4","src/err/linux_sll/header_slice_error.rs":"845a390e3860329c5478796e7e1f6dbc4532bf7cc5a13421af243e5af4acb40b","src/err/linux_sll/mod.rs":"53f7d8288023d6c5e408a15d376d9ecc3eab44b87bb014e8e9f2a71ce0165a2e","src/err/mod.rs":"19b8458679ae1a6513c4d4815b430beab908b1c74b132f50d31b153196213d83","src/err/packet/build_write_error.rs":"b45c45061f6e917d49ba4fa2626e51d3acaf37a0b29c3a4b8ad50dd0b80b418b","src/err/packet/mod.rs":"5c21d10215185879e66fb97f28697b37256d257caad4e3710d9103f25acb6de9","src/err/packet/slice_error.rs":"1c4b3283e06ef896b1318bf61782a69b317b5213131bce29b636fb4038146b0d","src/err/packet/transport_checksum_error.rs":"2187f9f0e8c41ba8d6842580cc9d103a1400723c1b44cb6867292736b52df0cc","src/err/read_error.rs":"91ec7b005eb97b05ca9b8f8f59c11623931d9a476d47078a64eef0332fd52672","src/err/slice_write_space_error.rs":"7eb2a68905e0f21edbf4c4c5fa61203bf17e70fb3ea134fe9c822717a406d9af","src/err/tcp/header_error.rs":"fa3daaae1ec3dec2ec9fd61c98e37bfd2d4892caa057b67a645ec24802a5dda5","src/err/tcp/header_read_error.rs":"301f9dbdf14bc6190cf8ef4b682048299fefd852e1a8ee2ea3b29454dccc0392","src/err/tcp/header_slice_error.rs":"7644fdc1179056661b143365273432018dff0fabcce4d2a6ceac92369d5b0baa","src/err/tcp/mod.rs":"53f7d8288023d6c5e408a15d376d9ecc3eab44b87bb014e8e9f2a71ce0165a2e","src/err/value_too_big_error.rs":"8d9c5643b3d4284c936f0d3236e01920d7d92abdccacfdf3da1a2b253f0340e6","src/err/value_type.rs":"ea66148ea02bfaee3603a67a9d3e2192af28fa4036f87b05697ef7723f64e595","src/helpers.rs":"62c8331f2ad285583e65641bd774dcd267f3ffc8c08b76b1b2c08d3401809e67","src/io/limited_reader.rs":"4983b692b8f78d9764f30249a82caf1288a469516fe7c67a34e531889a708686","src/io/mod.rs":"cff461989eac2488da2bf205d4cf023285a68f7290d16f4557a576c329a169e6","src/lax_packet_headers.rs":"7fe1cba5eb6eb8bd8e1aae4b9e33dca690e1489cab8e7c73f1fafa345fbce113","src/lax_payload_slice.rs":"50434cae0e2a5c775bb30163f5da8869b424d29f23ff8e9f58214bac717e9fa7","src/lax_sliced_packet.rs":"c3fc026de56142e68682f473550aabea6c148c1fa8d1364407234734abffff6b","src/lax_sliced_packet_cursor.rs":"64c6d26aaa7f3b184b27d2bf1091dc4f454d7c6b8dc6f43f2a4e3ede099feed9","src/len_source.rs":"9c39cf272ce1d88eae2c56228b712d36a02dea6795bfca3f0685c5330ef0eff0","src/lib.rs":"3a285db0894032da029060eba7d01fd7ea197edf92ddf23cc25d05ef502e1a80","src/link/arp_hardware_id.rs":"1205985b30ebf042001e8f2ea7d6341cc9b0bf62aa929f3454dfea5ebe6dda89","src/link/double_vlan_header.rs":"1e82218a3fc91d6b6472e14f6a867ab9c68d0e724ed15fc60495034b77a5a4e6","src/link/double_vlan_header_slice.rs":"d707fa926ada8cda35210ac7df60ac775eacaa75e97821b375fe1b220672948e","src/link/double_vlan_slice.rs":"782836081083bfa21919a39c81f52fe2c00f9e6cd134b2791f710274c119134e","src/link/ether_payload_slice.rs":"79f1330e6e7e164dd0e0b27dbf193dbc73e6042c7354612ad6bf72d2ac446739","src/link/ether_type_impl.rs":"1d7fe84589c388a733fbce6e40182b18d3b0bb4164cfc4a088833be46f0b4dd0","src/link/ethernet2_header.rs":"0d923e19d4be5ebb679f955ce690a7ccbd14f672ea00a182d4cfa5a63a9baa2b","src/link/ethernet2_header_slice.rs":"71ec03ea364fb8a0da73a570ca5e8f5b116d67933c89caa690e4da14baa820bc","src/link/ethernet2_slice.rs":"4e29f5dbac2d1fa90dbdb65f968319f8c7e670854cf640378232f1cbdb828d94","src/link/link_header.rs":"9599547d9dd183bb10b8c8f3e16919a2a03d475e625729e8d12422acef5f660a","src/link/link_slice.rs":"b51ceebdf91128d0dbf1d603d3c245541aecaf67d97cdecd1a1b2ecbb1d7c35f","src/link/linux_nonstandard_ether_type.rs":"4b77cb04641a14f44223fbb6e59c4206dd4c8dd825ba9e1132902471a8da8595","src/link/linux_sll_header.rs":"d9b0a6982431f5dc4dddd9efd369eba18f1715587d59c1ba08a57dcdba3f6e04","src/link/linux_sll_header_slice.rs":"fcf91b2cad98d35c205c1ed72dcf5bf433af85fb0d226e8652fdef5dea961b2e","src/link/linux_sll_packet_type.rs":"aa4afa71da955452303b67b4f226f62a853f35508b7c7f94fea5e9d1d729b5be","src/link/linux_sll_payload_slice.rs":"d3a458cfbfafe79e7bb538b578590b5eb7fc4043538342219c1b8454eaf68454","src/link/linux_sll_protocol_type.rs":"1f46945367f07f4e787f2870a7205c42e55985e615123e16a68822459b275acd","src/link/linux_sll_slice.rs":"948e3fe474f32d135856b16a78586fd93f0bc2db8fadc7e65217a1f8df0b111b","src/link/mod.rs":"dc001b7ab6b481a881217b7734e2d71eb3d3909b6a6cf7b9101d7808fd1fe695","src/link/single_vlan_header.rs":"0cfef6a362db54f2d4f1e0d6cbb1bb1592fa29ed0f0dd2bdd8c7499a4dbc15a0","src/link/single_vlan_header_slice.rs":"c3548694ca831f065e6b0eb05f3e904a89d2536069fce0822964a5b730cd8512","src/link/single_vlan_slice.rs":"ae2d1820a30d00747df7e2d39fd69b530832a0927dfb17e2bd5d4d56b9173e76","src/link/vlan_header.rs":"436b2891f58598967d90d79cc3c34ec2d6cdc87a11f8e3b3cdf28a0a7dafb11e","src/link/vlan_id.rs":"a6ef816b48be3857542119f7222c7643662266afbd80fd8da8a6c07d6bf64223","src/link/vlan_pcp.rs":"0a47d453b333683438edf2d99368432dd1aaf3f2d34f4eb7c6fecd186e7f5643","src/link/vlan_slice.rs":"762af050c66e6063bb142a71c2547d939fc1731d5555e0126e6e96ca6da4406a","src/net/ip_auth_header.rs":"f3beea53a98c820d20e6a42827cff4cb2f8dfd490f8d401a7cc99f6c17130bfe","src/net/ip_auth_header_slice.rs":"d5b5d14a4cf1447dfe666ccedb89ee646a63082a005e2db343afbda18700e5df","src/net/ip_frag_offset.rs":"50fd35819241e986b6ab2632f3897525a5791fab15470e33a7e6e76996350e15","src/net/ip_headers.rs":"76aab86958c48dfa16abf99e9f1bd20802bfa4d2ff71916f5b838f6de6830ba1","src/net/ip_number_impl.rs":"38a6ff41e68832ecb6a472abbfef54bf699433c9fca404fa01ac5e54b1d50d1c","src/net/ip_payload_slice.rs":"70f1a0243150d19aef9e58c73badb2628fb57797b426dd71f33df00d8721302b","src/net/ip_slice.rs":"8a0aa9b841075076d3ca1e515f1a649098238001d40130e882c7c4d1890b6c02","src/net/ipv4_dscp.rs":"8b23a1a455cf0e2058040e4b5181cb038f03beb902150c17ca31e659e681404e","src/net/ipv4_ecn.rs":"4e18ab07530a511da97c78feb833a2b8ca7fb4821a9bd919a1436321bae7f161","src/net/ipv4_exts.rs":"dc70b6b757479151c28ae9d21dafb4d1cc1f8b80c0ab1f86294b2970f321cd6a","src/net/ipv4_exts_slice.rs":"c53ab47b58552c36d22809eec33850ede6111b6bdbd0708c9bc8d0e8ceffbdb3","src/net/ipv4_header.rs":"47be9590da698fc3591e024ddc339d2a774e289aa89ee579d86891452970c475","src/net/ipv4_header_slice.rs":"1be6eb90875ae7a76fcf2efdbe9551bd79ef7d22de3c978c23d0d1b008b5c830","src/net/ipv4_options.rs":"88c8e62c422b7b3154806dacb682e4cf30a0e9d71ef94f82da0e11c9c2dfd168","src/net/ipv4_slice.rs":"c673ef5d86a12a389dde01453f3be5039ac09cf9769066202f769afa02b2fa51","src/net/ipv6_ext_slice.rs":"a6fb7c4680e254f6cb207be71c5349faebc9f5c3b7f426d6b2ac82109e045085","src/net/ipv6_ext_slice_iter.rs":"2ef14b2071341cbbe74a83fa1326e13b34da5bee5146d27cea971716c79c7235","src/net/ipv6_exts.rs":"05db12d353f4cb9bfcfa601963c8318c8ff918a087f33b73e9304506a91db496","src/net/ipv6_exts_slice.rs":"ba2bd160acb1e039ffa33d5ca62293431d41e4ddb927e7b771629d1835748ee1","src/net/ipv6_flow_label.rs":"86d3d5059e00afb298889d3ad354d8d075a82fef4817fdcb07646bd806cea501","src/net/ipv6_fragment_header.rs":"3619f904899f81b4dcf93c66a3666a850fa0e26f3a1e982532a60a1020c10542","src/net/ipv6_fragment_header_slice.rs":"ad05dc98112345ab8ca97d371feb85ca12e2d6b6f09f431809f808a59e3042d9","src/net/ipv6_header.rs":"2cfd2944e63f173843cd8885bc5cf0d6a38f200179bf2a2ede99ad2d3ce1eca0","src/net/ipv6_header_slice.rs":"91e61f471bc04addc886341740197ccd7a460372417aa7059cd756b66174e4ef","src/net/ipv6_raw_ext_header.rs":"7bdaa8a0a01b4ac450008ba90b5df933faa75d05427286a9b39e54e1456993f5","src/net/ipv6_raw_ext_header_slice.rs":"4163f37d26648c07601ec42bf7dfcfeee4fb6cf38e1fefd46deabfd8aa5d4d48","src/net/ipv6_routing_exts.rs":"50f701a869987f5a8521933a67f942843bdbe21889aff99b36c388a729f5ded3","src/net/ipv6_slice.rs":"92839473e7290b92f0613aa9e08c4ea408bb314433b371780a069f2e82e14210","src/net/lax_ip_payload_slice.rs":"2dd48f564b75db1c1ca33d2b7d8309f031ad635130cbe221e1bfa8da1c11fd1f","src/net/lax_ip_slice.rs":"2b93e97c97b9703675796f97193ec9999133262eb1aac9ec77b5a1c93e95da17","src/net/lax_ipv4_slice.rs":"93d0cddd396a0d232f34f5db34fa13a71042ad560cbf9804e4c76aee6f5c5b1c","src/net/lax_ipv6_slice.rs":"926e49cb171996dede78c38b34a533e8bc717a86a4f01a010e38c8d5bf200ec2","src/net/lax_net_slice.rs":"3b9ac3efdcf0222933960653e82fce5fd777ab2bac6904fd6ad233db6b07f49c","src/net/mod.rs":"77cc0a5f204baa66737dd9342c267ad2ad3f3a84e107d36ccd3a368cb6589816","src/net/net_headers.rs":"8e3270952efb6ffff02d8e6420de8ef5ce5354f20733a533f942e2d8a3e5fa39","src/net/net_slice.rs":"3b7b1c594c2b85005e9b05606b47551950cd1761036a371e25fe205b00dcd9b9","src/packet_builder.rs":"a6336701ba5a4ec21902b73eda733807b4a6353b4a09cf1f187fd243496b9bdc","src/packet_headers.rs":"bf91d0bb1858996a3491e795805f38cf5a1a3d230550798d155a5b70ec6c8380","src/payload_slice.rs":"d1e28be998dadca48e1899b27c0cf4950489e6f064c2d7b0d76281f1cd430cbe","src/sliced_packet.rs":"d1240eb0207fe4a360d955e4b530a4a959edb634242e89ea2bc0a1ae58375629","src/sliced_packet_cursor.rs":"97056bd2570be2e4129a48e73b804870b0c5a2317fce469d0a37bcc4bfc61ff8","src/test_gens/mod.rs":"fd35b71197de9a7b644b52ef5beb1701da11b2fd52e6523b8b2983628d2ec676","src/test_packet.rs":"1b20612284540ac12e862f433075e8253864a66a201d7ebd9f3788b944671ce7","src/transport/icmp_echo_header.rs":"5c454788b4781a50ea3371e39ad2bc9dc8c04bc5d322d82c6a5b8c47b45cfc5d","src/transport/icmpv4/dest_unreachable_header.rs":"4ec29a7b1c337e826690146930d478f8c546b54e9a3c6a08dca251a301910265","src/transport/icmpv4/mod.rs":"975c6fcbc7ff20dd4898f8531aec14cd8afddee4033c22191a9ac1ebea0a5bc7","src/transport/icmpv4/parameter_problem_header.rs":"ba0dd5f4e7befa18fe8d7177ee6cb393a0aebee44a52d2d27559d4bd9872bef6","src/transport/icmpv4/redirect_code.rs":"742b5f8b502904c7e8191bf224da32e4aa0bb2a7a0911a90034c182a0ef6d986","src/transport/icmpv4/redirect_header.rs":"8324a2ad86e2ef1b4533acf15737e4f3f1f87caa577dd479d48993081e536fde","src/transport/icmpv4/time_exceeded_code.rs":"c4cce23d1cb8726e58cb6561378acf5d59506dfdcd0bd30fae1a09a7938f071e","src/transport/icmpv4/timestamp_message.rs":"79e3cb2f9bb00690e0901708b3d1d0557cb4986c4057aa86c0906d5773c0fa4c","src/transport/icmpv4_header.rs":"6eb918629a4fa16f6d69161ba6dbc511e7d054c85e80fd123df68535e7ae387f","src/transport/icmpv4_slice.rs":"8eb2c572a5279b01a7f1f031b8394a31e8986527fb1f5894352a63d156c78741","src/transport/icmpv4_type.rs":"92a21fc2170a78929a91c95b7fa40979c55187ecfdc907614bdcd1b1f130bbe9","src/transport/icmpv6/dest_unreachable_code.rs":"2a86ff06affbd96bd365addc16ac0834c3ccc9f8d5d127edadf37cf89d8cc59b","src/transport/icmpv6/mod.rs":"8f02d1bc1fffe3eec831e911af8a9c1ac7ad5ab30c44cc7884e48ce9e3fec45a","src/transport/icmpv6/parameter_problem_code.rs":"39e8646e4ac65350e72f0df6573d09b11374444cd6debc69516997c4716def39","src/transport/icmpv6/parameter_problem_header.rs":"2c8f44daa17384612c6b94532274fc0469af906ac485b5ae90f98aefd728924b","src/transport/icmpv6/time_exceeded_code.rs":"d69c191b512f8b4b71825ca54e3fd15f1419b0ff7c54794073d25025aa30a37c","src/transport/icmpv6_header.rs":"55af2262a2548bd5bbae138ca53a9a13f31ef9829f7bc7980eac6c9eb3ad9c8d","src/transport/icmpv6_slice.rs":"636913244caa6d05ca49ba45cf8c7ee589f31cf465a74b6556d1fe6bb3fcab80","src/transport/icmpv6_type.rs":"648a595eddbd32b828fd1982c5dff59e52da819da70e7e8aa8e7d16997db982a","src/transport/mod.rs":"d75e34b2b6d335fa2d58d7636c9ae21732f1696e04e5695454afbbb64d2361ab","src/transport/tcp_header.rs":"913cf0808db43a9788db339ef843f28771faef8175e3575b645dfd3dbc9204ef","src/transport/tcp_header_slice.rs":"d0027715f72e2cecbebe6b7c90ddd9dfbd10b83b755e177743dc7f164f6a45c8","src/transport/tcp_option_element.rs":"689a383f13e82f1d0bf5187c6facc56d55178318efa0e336fe536c07a3499593","src/transport/tcp_option_impl.rs":"c95838d1383718806cea28c29118912dec1c757b53e6b41dd840d0ae5e4e2cd8","src/transport/tcp_option_read_error.rs":"2d0a978519639aac12e48d4cb6b27120b7722e4138092bc37c7ed67244a64a8a","src/transport/tcp_option_write_error.rs":"41391bfc6decf6a2cfb44317f4d0ca910448431efbcf8c61917fe224a79188e1","src/transport/tcp_options.rs":"b631a3494e2eb97ffdb9677b8f5d77ff3aef06ee8578b4e250fa054f71026cab","src/transport/tcp_options_iterator.rs":"8341f142b8775c8f595c801c91d133af1fe36c0f7a6a11c1d238d8c0d70297d6","src/transport/tcp_slice.rs":"488a38e117c2a63203e84d4517940bcc44c5525506def95272d100f737d00155","src/transport/transport_header.rs":"9d9493a6c340f35a0f39a9dfffa1d74de278a4a23e9c1424639924955716bfdb","src/transport/transport_slice.rs":"97d8549b68cee06377ca21ac1ac19c6b6eb57c17ada43e538f5e0a00f7ec73c9","src/transport/udp_header.rs":"4787f4d34e0244676a12b68572ee9db1038a8522828039f80d355c34a8e4144f","src/transport/udp_header_slice.rs":"47810d0bc895f8ec001a10d005b141f3943144b5a47380a27e1f19da36c95a55","src/transport/udp_slice.rs":"c6585ed98b9491186a4be982c757eb72f0d6d179ae1cff00aa072bb60e123a4e","tests/transport/icmpv4.rs":"92be7785e5d5db0c85fe0f93974b34254a7badb4f21b4506a8575a638383ee84","tests/transport/icmpv6.rs":"e2451a13e6a5e379159bdfbb1cdcdcc88d470083b1778e7ead79ce32912a71d6","tests/transport/mod.rs":"c24bd8d361b60578a47874fcac7d7ed17cc05b7a17d5c286479b19221eb2e2f4","tests/unit-tests.rs":"3a1caee977f1a25678e19dc63a4d47b301737743471e1da0c847ccfdbf4fe353"},"package":"b8d8a704b617484e9d867a0423cd45f7577f008c4068e2e33378f8d3860a6d73"}
\ No newline at end of file
+{"files":{"Cargo.lock":"71b6fec6429227b2355a53a9dea553848a393a270e40dbf031cb4931a1fb432f","Cargo.toml":"dd418dc799b465e26f1045e8ef5a6daf6557001f4c5e6c67478cb60f7177dd09","README.md":"e5662576478230bb9e8444d71be913f84507a3dd8b7536ecef1cfbc17fdc5a68","examples/ip_defrag.rs":"10bb2e8c3f9eb68dcd51ec16238e5add36f20b06b675b461c13761f7be31519f","examples/read_by_slicing.rs":"4a5b46cd8d61799187a632394df90df1b035a8bb8616ba82a984460f9c51139c","examples/write_ipv4_udp.rs":"11dbb0d0ee11fe82590bafb6d2b62c90c5665f62eda4b99c94ccba8b06e88582","examples/write_tcp.rs":"45f1442730369f5b69b0e6af0474feee5b725fc96bc4605ddf232bd57d4cb834","examples/write_udp.rs":"31c6b6b7ef388260ae34ac1f7a25f1ecb52d7af879dba2fdd861ef23132d0abf","proptest-regressions/compositions_tests.txt":"e8aabc0c1864dc2d1ee656e5de6a38c356e95c69ab643414c154e275257f476d","proptest-regressions/internet/internet_slice.txt":"3e6d037f650d2e01302802d1c311faefc174223ae0aead73f26e410c1b530a5d","proptest-regressions/internet/ip_auth_header.txt":"50def8f52412a867fb9055410d34ee295c86ce39d3ed3f86589e13cc88a6e946","proptest-regressions/internet/ip_auth_header_slice.txt":"b2f3a53904e815f9a9f2eecfc91da0306dd804efb0f022cea93d7b0a418eb392","proptest-regressions/internet/ip_header.txt":"daf1a8841fff4bb83b80bd4d78e9151d3fdca3dbf3ea3e01eca5b40c6413a568","proptest-regressions/internet/ip_slice.txt":"28ef712b2f188fb7330138d6ee356bdb15c08ed80fe09366fdb54f4c72cf616e","proptest-regressions/internet/ipv4_dscp.txt":"1d22c76326a8840478ce688721fa68610bacf40d57ec8121d24b0ab4cf5f00e9","proptest-regressions/internet/ipv4_exts.txt":"2988687b1b40b289b521b3ab45e2098eb0e689c35bd449dbe0d237e94740b9f1","proptest-regressions/internet/ipv4_header.txt":"ca7981b5b5254a936f0750f50f8ac1a277f6ec8e90a61cdf89fbf39159004851","proptest-regressions/internet/ipv4_header_slice.txt":"072f6280761243272c290d1588d08081f788584b3cddbd4de4d429c15fe88d52","proptest-regressions/internet/ipv4_slice.txt":"ccaec805c9d7e5ef3912e261924386920960dbb8d4d6857e34c97be5f963f63c","proptest-regressions/internet/ipv6_exts.txt":"ba2116cbde67db1235fa82818071313cd638370931d8ae63258e046bdde86f3e","proptest-regressions/internet/ipv6_exts_slice.txt":"406b131864c399d7d04963a092002cea02794313a9c1457b0a27c9147f8d0a29","proptest-regressions/internet/ipv6_fragment_header.txt":"860219218508f64d03748a13c16968ff858d62db27675f9086fa62a7f87c0029","proptest-regressions/internet/ipv6_header.txt":"550b1bffc1bd380f31092a98100ccbfdde8431dbf9bec5a1d3f918f39b92de9e","proptest-regressions/internet/ipv6_header_slice.txt":"e765b5ce6e0c84f38195dbe5ddf0812b2a634aec86b927d5ebd322517a3fd0b3","proptest-regressions/internet/ipv6_raw_ext_header.txt":"d87b0366ec9b7196099bec67d4d87f3a47de9c31c34a865c55f26200a916599b","proptest-regressions/internet/ipv6_slice.txt":"8a34d0394144f95166c7c5ec10255c96065d9973eb46c1e28daff949210dd87b","proptest-regressions/internet/lax_ip_slice.txt":"0bf5fd42357f94b7e3fa96e169daf1795dcb0819785f366759885cd8dbe9cb37","proptest-regressions/internet/lax_ipv4_slice.txt":"ad8377842c1cebafd9f484a5b41d0782918695514265fb74915cdf2b985c8426","proptest-regressions/internet/lax_ipv6_slice.txt":"749d41084ff5c956cf0c81adc21ec174560ca5a533515f2ff55c9941f5df0f7e","proptest-regressions/link/double_vlan_slice.txt":"a69268e277a86f9322f4d4ac078b51394cff82dfc57a6228e61c68a81fb3a8f6","proptest-regressions/link/ethernet2_header.txt":"ac42e6de59b38553abfce6da0aa730e727b6057bd141b5e3dde0f2cfb2d224f9","proptest-regressions/link/ethernet2_slice.txt":"bb1db1468629ba839a220c16fed9df4989f6cb47d76dc72d7c50d90858309af2","proptest-regressions/link/single_vlan_header.txt":"84375d8d2857b45c86e34efd7d1e0162b1c6a074afe7222dbb782769949338ab","proptest-regressions/link/single_vlan_slice.txt":"c30842de60e3705a9cee5e784e138666b36c41c4404d25c1b10aeebf91828ae1","proptest-regressions/link/vlan_id.txt":"4291d1f8635129adff85337ce636ffecccdd31fc7d65235d007769adc0758aa7","proptest-regressions/link/vlan_pcp.txt":"5c71c71a5968abaec8acf317cae3c98eaf2b748679706f57ef0a74aafecfea54","proptest-regressions/net/arp_eth_ipv4_packet.txt":"a731324726356864708174dec6dc1cbdfccb64d1daf434b5482d5c543f95008d","proptest-regressions/net/arp_packet.txt":"7fb81ce390099aabe9fbd759c1206975a4841d06fa9a008a390b451e2bf767f8","proptest-regressions/net/arp_packet_slice.txt":"46b54193372e2cbcf79a80dda3be83d4afbe91895935891ff718517504aaf130","proptest-regressions/packet_filters.rs.txt":"8e4c6382eee4ab90a83dde3f5dc49b0bd314315c0697e131e7205a20cf810358","proptest-regressions/sliced_packet.txt":"7a6337669ee5fd8c4491964f5c2253b670da990b32290092b00b6481aaab106a","proptest-regressions/transport/icmpv4_header.txt":"8576df10a1af73820327e7f5bf9c61eac800b0d8b403b50f63087012861e8782","proptest-regressions/transport/icmpv6_header.txt":"c330100866d05828baa7c1e166872163509deba82adbf24a4ac4c3db6cb24b35","proptest-regressions/transport/tcp_header.txt":"fc661c2c82fe62a2fbd344133e56f05bca9019cf4de01711beb69450c8f28214","proptest-regressions/transport/tcp_header_slice.txt":"d9777d9454282cf18826c3a84a878b16a82a338965c4ae80ce0b3819c53cd6d6","proptest-regressions/transport/tcp_options.txt":"c9f8c46b2c43168022a0e89b58c50f1868d1ef92a45523ca8777aabde57665f5","proptest-regressions/transport/tcp_slice.txt":"abb4a9403f6e61953e2428986c8a53cabb5690148855bc14a9f80d20c28aff59","proptest-regressions/transport/transport_header.txt":"210d13c7568afb787354c964e94a524ba248dfbca8096b8624f0307a8d7af59e","proptest-regressions/transport/udp_header.txt":"b01f1d27645bea66631cebacc1d3194ad9df8ebb47ff749d6cce807c08a83b95","proptest-regressions/transport/udp_slice.txt":"9fe0840204b6828df208e6c2bf3f8a443c10355183d0f9865a660024f1737547","src/checksum.rs":"6f55a67ed111ae0e1cb0607ba3e4a8c8d90f13ac1ea51756070344d39ed5f776","src/compositions_tests.rs":"e55a3f6f0aad4c6cf52870193f291141cf6885fad038257f0138b8335e8ccb1b","src/defrag/ip_defrag_buf.rs":"1085d477f1169af7e28629933f9c1daea3a6e7f645d85d6ad80d7886f2298ea1","src/defrag/ip_defrag_error.rs":"eef705111716961072bc81c17b18a1da31cf9e81ac4c35d543d172a2aecc2056","src/defrag/ip_defrag_payload_vec.rs":"0b9b8f01c62a5732cfb27de02bb5c743acc23644ffde25b4e63700211ed25494","src/defrag/ip_defrag_pool.rs":"ef1e3f50eabbfedd11fffe1b2bfc187cea803e465494bbfa27153f564947eb68","src/defrag/ip_frag_id.rs":"71765a4e0697091088e17a070542d822311a2c608dacd2815a3d380bc12bc2c4","src/defrag/ip_frag_range.rs":"ab3882c6e6e89a04dbb603c64483092336b19624422616d47937827a9e3c0935","src/defrag/ip_frag_version_spec_id.rs":"5b3808f4a4ba45ff236dcfb37d11edc4dbf409fcf23812c70be6473e2c83ae60","src/defrag/mod.rs":"b45da0a043f4659bd9de595d863c760574b766a159b5ce5050ba6ee84da31de8","src/err/arp/arp_eth_ipv4_from_error.rs":"b183cb042d32202df2cadaee7ab303c7a16f493fac6e4d3b53a7d87da4edd278","src/err/arp/arp_hw_addr_error.rs":"c8ce595639973bd7c17cb3cade61374e899b118ca2f15c7dbc5e4875ed76932e","src/err/arp/arp_new_error.rs":"334b29e1895d4472fc38b2abbb01e5edd5fc687cdca68988b5cf035bd2db9210","src/err/arp/arp_proto_addr_error.rs":"c7902e70c9589580249990a149af93297d4b32809b6be8ba137fd5e3ae2f3b6b","src/err/arp/mod.rs":"0679cc4036d6aa0a06ebb111ae96fd9095432236143397fac95e8f37f4465ee1","src/err/double_vlan/header_error.rs":"ef097f502e89088deef9f106708e0f02c5fc92f7f6da8ba92b160d52ab3d67a0","src/err/double_vlan/header_read_error.rs":"cbaf6dbc5c67955801334823b607745e386482c36bc2452d917eb5fee971f006","src/err/double_vlan/header_slice_error.rs":"7331d4cbaa998b3517d8164710d5eca67129244836d834a8ae3262f0a61c389d","src/err/double_vlan/mod.rs":"53f7d8288023d6c5e408a15d376d9ecc3eab44b87bb014e8e9f2a71ce0165a2e","src/err/from_slice_error.rs":"19f6fc99f002d560c973776cc6caf2c340e7477c8b1b1de621171ad563b53af7","src/err/io/limited_read_error.rs":"e9ffdc05c7e0650927e8a644e4d0495995e382451df5281cb3610c693e2d89e5","src/err/io/mod.rs":"fc6eb32dca0207bbb3a9f8a33c171aa35594113cdfaa6abe9a73d80fca233720","src/err/ip/header_error.rs":"ece81ed3d73a29cf0a646830351423214fe0c560fe92568f026635238be28c3e","src/err/ip/headers_error.rs":"77757d9d2f3e47e4d9965db04a0c9e4a24f23ccda070e0323f239de4cc135aaf","src/err/ip/headers_read_error.rs":"03aa63d54d6ff65046afbd05a46bf87a70756a84429c28bc2f708dbdf2b01739","src/err/ip/headers_slice_error.rs":"8ed4ca0c2e6af2763ef7a69ce13bc891194f809a427139da21e687a2d1c43c8a","src/err/ip/headers_write_error.rs":"6a33b64db0fc0d6da08fe799c44e34261e3e2f0a5a52251100826663607aad4a","src/err/ip/lax_header_slice_error.rs":"47d070a1963e17481e0fc999de643cfa62a77c84ee5e09f03e28aa1d3d28fd65","src/err/ip/mod.rs":"057da7aea668eb146e3d1bfdfb71fa61ffb265d0f26a10b018609dfae4d91a79","src/err/ip/slice_error.rs":"504cec082cd17da5efde6bd396a12f93fbc12caa98c2459cd2ce862300944e78","src/err/ip_auth/header_error.rs":"4b57829951a8e7e9b39bfd42f0d910b8836933f6b8d10d785e5fa8c1f472adf9","src/err/ip_auth/header_limited_read_error.rs":"eecd056eba8c4c26cc277e1e12dbe9d321aa406a74df29688d4e25345607688d","src/err/ip_auth/header_read_error.rs":"319e2125c5086e425c7503ea5dc7169bf316ee7b78837a27e31b8d99de119d8b","src/err/ip_auth/header_slice_error.rs":"5a8f7db033c8cd6e34663b7c302a97a61740fa535a0a6f169ac21a0fcfce93f4","src/err/ip_auth/icv_len_error.rs":"fb2027f53a00409b6cfb531c384f0a92808a2e34b2e2ab5203129c2604c8246c","src/err/ip_auth/mod.rs":"0386ece85ef2733cbe12ff442c95d21c47e6ffb294197049be90f8c0c7ff394e","src/err/ip_exts/exts_walk_error.rs":"2b9038166052d15f8bdc0618f8b1c87aae1aa0823ccf626f4b48add1a448b3ed","src/err/ip_exts/header_error.rs":"5c7c06e6d4621bcd91ac6da67a87ea8633ea13ddd808297a82738d75ad3e23de","src/err/ip_exts/headers_slice_error.rs":"bef8bf9f26656f22634144e1a5b0802baf1a0489cbf41d71651a0ce6c7d2427e","src/err/ip_exts/mod.rs":"238ef5a2e3f85941636661081c5bab07aa8bf5164269a90f1bb353e3907d9199","src/err/ipv4/bad_options_len.rs":"330eafcee414d77dd15aa7e399874f69e9966e8b791814dd224249c23929d825","src/err/ipv4/header_error.rs":"bc239fbef6ce2a1c2e40e6e24a53b121bbc03aeff11d587b081a5311869eabb2","src/err/ipv4/header_read_error.rs":"da9d0b00729ca4332ec0df2f81c18a57aee710c2acfd9e491c1d9f8329cf7a8c","src/err/ipv4/header_slice_error.rs":"34a126fb3e9ba1622276e116ed10304741297f3a29d7f8bcb8d5c460a66baaba","src/err/ipv4/mod.rs":"a10d86a8b0760acd1214216959b53d14bce827a9d8d60732a852cea93df79144","src/err/ipv4/slice_error.rs":"79951b4f875df657aed82503a715a9c7b50593a1ca3b876abebe8e032905bbd1","src/err/ipv4_exts/exts_walk_error.rs":"be6ca20dfbf1da74130541c871e29629284edff69bfea0907548173cc40c1b59","src/err/ipv4_exts/header_write_error.rs":"6121fc1b06916cbb3b2db5d2db59330f730c22cfa6d5cc2c5d2f75e9721772b3","src/err/ipv4_exts/mod.rs":"7667e113c21c7f642aea212313d2d931e7377f1cd4610eb11097af885c201242","src/err/ipv6/header_error.rs":"35260f1b840d5225da534449e59005057ca505188d42667b891df6d6ef64e9d8","src/err/ipv6/header_read_error.rs":"afcbdb422fbb2c2cda70c39e617dfe561d66308ff32fc4dd0db2b46d3858b4f5","src/err/ipv6/header_slice_error.rs":"b4ab4ea3470e64bd0f9c5551bb68508384ce650859d9709b04f89b9c82879fd6","src/err/ipv6/mod.rs":"861569fe58827b67a0e00c8baafdf9e369e7354d331cd541ba6209880c7362f5","src/err/ipv6/slice_error.rs":"6b96e7d30b26eaf6645a3aab8148a8011453daa17a8597e6d7cf3bd7e5062d01","src/err/ipv6_exts/ext_payload_len_error.rs":"e9eba7b7cc372f9148c25103caa85b468b7192f9464d1b0c0615b3b3be678d07","src/err/ipv6_exts/exts_walk_error.rs":"c2580d09e1c253d55bb0209b9cc24095f002417129ad90878be09483302f281c","src/err/ipv6_exts/header_error.rs":"8c6ec561071f77421366616c0c7554536973e1eae88702691dcf6e2490304900","src/err/ipv6_exts/header_limited_read_error.rs":"eb06038e17bdb88337e0563e90c3af22694b8502ed2e8e8ce29f102cfd0220b1","src/err/ipv6_exts/header_read_error.rs":"7c16c83359817e68db50d55a3eaaab476f26ff9e38bdf43c2560a6c4d7df2ee6","src/err/ipv6_exts/header_slice_error.rs":"52e03033c67b24b8bc84bbda219c20d442139572b9ff01371f9791c589152163","src/err/ipv6_exts/header_write_error.rs":"acba426a080e4a487eccbbd0662450b79cb3cadb1f04269dbe586b04a3dfc0eb","src/err/ipv6_exts/mod.rs":"129078a0dac47dc6f73ef45558b8bc33cf8c42e1fce4a6801aef80090b501712","src/err/layer.rs":"1144989d3fd3f9df9950b254fa77a29d8e2b0b04330ae8f4491f4f2c8918ca7d","src/err/len_error.rs":"42fb2b9eef141b708563c8711b321350f50fb53013c35f1287b4e6c4de767a74","src/err/linux_sll/header_error.rs":"278ee0d79099aa52022f2eae7091e52da406f7faed771574b3b9c2201fdc27ba","src/err/linux_sll/header_read_error.rs":"27abbe87ef13d3881eb84e175ddf5187263e552e91c0917dc6540c07b57a5ce4","src/err/linux_sll/header_slice_error.rs":"845a390e3860329c5478796e7e1f6dbc4532bf7cc5a13421af243e5af4acb40b","src/err/linux_sll/mod.rs":"53f7d8288023d6c5e408a15d376d9ecc3eab44b87bb014e8e9f2a71ce0165a2e","src/err/mod.rs":"f174a20b8f0e35f254360d6e7fa2e7a14243711ca9beb2b6d3775d1fd1053572","src/err/net/mod.rs":"102a859211f2c725125761fb84ee93d0aaec16c627ecf7fc788d18a86d7c7d11","src/err/net/net_set_next_header_error.rs":"bfd38e0774683c62246220fee0f1ce4689e1f76955443116a852916801fd1dde","src/err/packet/build_write_error.rs":"068941fbb30cdb83fb0f5271bffb3ed47e1e7f60e84ba2c3baf7523ad35e20e8","src/err/packet/mod.rs":"5c21d10215185879e66fb97f28697b37256d257caad4e3710d9103f25acb6de9","src/err/packet/slice_error.rs":"b304a572d5f56f30c727bee2760fbcaa88b23182cfc2a4893b4f68637b218017","src/err/packet/transport_checksum_error.rs":"2187f9f0e8c41ba8d6842580cc9d103a1400723c1b44cb6867292736b52df0cc","src/err/read_error.rs":"cd5ad4d920995b5512b2539c8d643b463e078dae812962cf02d1cf62a853ed8a","src/err/slice_write_space_error.rs":"7eb2a68905e0f21edbf4c4c5fa61203bf17e70fb3ea134fe9c822717a406d9af","src/err/tcp/header_error.rs":"fa3daaae1ec3dec2ec9fd61c98e37bfd2d4892caa057b67a645ec24802a5dda5","src/err/tcp/header_read_error.rs":"301f9dbdf14bc6190cf8ef4b682048299fefd852e1a8ee2ea3b29454dccc0392","src/err/tcp/header_slice_error.rs":"7644fdc1179056661b143365273432018dff0fabcce4d2a6ceac92369d5b0baa","src/err/tcp/mod.rs":"53f7d8288023d6c5e408a15d376d9ecc3eab44b87bb014e8e9f2a71ce0165a2e","src/err/value_too_big_error.rs":"8d9c5643b3d4284c936f0d3236e01920d7d92abdccacfdf3da1a2b253f0340e6","src/err/value_type.rs":"ea66148ea02bfaee3603a67a9d3e2192af28fa4036f87b05697ef7723f64e595","src/helpers.rs":"62c8331f2ad285583e65641bd774dcd267f3ffc8c08b76b1b2c08d3401809e67","src/io/limited_reader.rs":"4983b692b8f78d9764f30249a82caf1288a469516fe7c67a34e531889a708686","src/io/mod.rs":"cff461989eac2488da2bf205d4cf023285a68f7290d16f4557a576c329a169e6","src/lax_packet_headers.rs":"151f7def2c251262672c58fd5b8dae5a7e7b0bee00f7c20d207a320c3f66976a","src/lax_payload_slice.rs":"173150ea93c1eab69155065f8f691f850cd84317e97f9b1ecc8c388cdbabe6ae","src/lax_sliced_packet.rs":"d44daab0d16c98cb3ce8b00a593712fc2089997b5b9cec2b44891a01bbde94e9","src/lax_sliced_packet_cursor.rs":"f05821476868dffe5a25df2751441046c6f65c44cc6ea2199b485ea024eb42cb","src/len_source.rs":"d02e8ce779318ee937ff1b530a10addb228dc1c48c1212251569196cb568d6a5","src/lib.rs":"09138d84b782d47916e3988000aeab968cf122c0448076f7bae925b060abacf7","src/link/double_vlan_header.rs":"1e82218a3fc91d6b6472e14f6a867ab9c68d0e724ed15fc60495034b77a5a4e6","src/link/double_vlan_header_slice.rs":"d707fa926ada8cda35210ac7df60ac775eacaa75e97821b375fe1b220672948e","src/link/double_vlan_slice.rs":"c50c00b7b2b0542ff08c39f6aa3a29bbd724407b033208a473e3bf0219426e2e","src/link/ether_payload_slice.rs":"79f1330e6e7e164dd0e0b27dbf193dbc73e6042c7354612ad6bf72d2ac446739","src/link/ether_type_impl.rs":"1d7fe84589c388a733fbce6e40182b18d3b0bb4164cfc4a088833be46f0b4dd0","src/link/ethernet2_header.rs":"0d923e19d4be5ebb679f955ce690a7ccbd14f672ea00a182d4cfa5a63a9baa2b","src/link/ethernet2_header_slice.rs":"71ec03ea364fb8a0da73a570ca5e8f5b116d67933c89caa690e4da14baa820bc","src/link/ethernet2_slice.rs":"56e2eefa1471ee52420c8ff7937c9e32b4be50a498f85e0180c1dd891bbb8243","src/link/link_header.rs":"9599547d9dd183bb10b8c8f3e16919a2a03d475e625729e8d12422acef5f660a","src/link/link_slice.rs":"4930cb53454794ed07d6643ce5f8088aba4b556750c29e23c59d082b049e59b7","src/link/linux_nonstandard_ether_type.rs":"4b77cb04641a14f44223fbb6e59c4206dd4c8dd825ba9e1132902471a8da8595","src/link/linux_sll_header.rs":"d9b0a6982431f5dc4dddd9efd369eba18f1715587d59c1ba08a57dcdba3f6e04","src/link/linux_sll_header_slice.rs":"fcf91b2cad98d35c205c1ed72dcf5bf433af85fb0d226e8652fdef5dea961b2e","src/link/linux_sll_packet_type.rs":"aa4afa71da955452303b67b4f226f62a853f35508b7c7f94fea5e9d1d729b5be","src/link/linux_sll_payload_slice.rs":"d3a458cfbfafe79e7bb538b578590b5eb7fc4043538342219c1b8454eaf68454","src/link/linux_sll_protocol_type.rs":"5193d895ba8860252489031f012953c6a0bd642f1d427951b9f20256be2c4d55","src/link/linux_sll_slice.rs":"b86193e4c0c9d5db8426b27d8e49a4e5eebc1d3171dff343a90876e2c490a1e1","src/link/mod.rs":"3229cad4cef7d7b34aa3d90b5064567ad178552e4f0ff94c80b3f1870c3c0b7c","src/link/single_vlan_header.rs":"0cfef6a362db54f2d4f1e0d6cbb1bb1592fa29ed0f0dd2bdd8c7499a4dbc15a0","src/link/single_vlan_header_slice.rs":"c3548694ca831f065e6b0eb05f3e904a89d2536069fce0822964a5b730cd8512","src/link/single_vlan_slice.rs":"acb66d750387dbae8684ce3f1c3da1b300e49383975cc110c4a679035eafc37d","src/link/vlan_header.rs":"436b2891f58598967d90d79cc3c34ec2d6cdc87a11f8e3b3cdf28a0a7dafb11e","src/link/vlan_id.rs":"a6ef816b48be3857542119f7222c7643662266afbd80fd8da8a6c07d6bf64223","src/link/vlan_pcp.rs":"0a47d453b333683438edf2d99368432dd1aaf3f2d34f4eb7c6fecd186e7f5643","src/link/vlan_slice.rs":"762af050c66e6063bb142a71c2547d939fc1731d5555e0126e6e96ca6da4406a","src/net/arp_eth_ipv4_packet.rs":"07649526aa3ebe73f9014dfffb0c0b33f6ecf44c75e1f5c476e3821c308f00ea","src/net/arp_hardware_id.rs":"ac12adbbb8a6003bd70b03bb270aaba1db5552a58d4ae9087a7251a7839b1821","src/net/arp_operation.rs":"e6ce14900f564ca8ce1488bdf8bb154057afbc9c4d628fc4791d0116d3a24c23","src/net/arp_packet.rs":"cf63170c357f40bd38b0f88f129e602670efed9caf9a3a3af81a961652cdee51","src/net/arp_packet_slice.rs":"b5dc8ee52120302d7e8fe806fe8831ff4d3bcec419453ffee6e27398ce3605f2","src/net/ip_auth_header.rs":"f3beea53a98c820d20e6a42827cff4cb2f8dfd490f8d401a7cc99f6c17130bfe","src/net/ip_auth_header_slice.rs":"d5b5d14a4cf1447dfe666ccedb89ee646a63082a005e2db343afbda18700e5df","src/net/ip_frag_offset.rs":"50fd35819241e986b6ab2632f3897525a5791fab15470e33a7e6e76996350e15","src/net/ip_headers.rs":"e46f0f8cffe90ec27813dcecb05ca574c8624f7c23810f2a521a3297ed45b798","src/net/ip_number_impl.rs":"38a6ff41e68832ecb6a472abbfef54bf699433c9fca404fa01ac5e54b1d50d1c","src/net/ip_payload_slice.rs":"70f1a0243150d19aef9e58c73badb2628fb57797b426dd71f33df00d8721302b","src/net/ip_slice.rs":"8a0aa9b841075076d3ca1e515f1a649098238001d40130e882c7c4d1890b6c02","src/net/ipv4_dscp.rs":"8b23a1a455cf0e2058040e4b5181cb038f03beb902150c17ca31e659e681404e","src/net/ipv4_ecn.rs":"4e18ab07530a511da97c78feb833a2b8ca7fb4821a9bd919a1436321bae7f161","src/net/ipv4_exts.rs":"dc70b6b757479151c28ae9d21dafb4d1cc1f8b80c0ab1f86294b2970f321cd6a","src/net/ipv4_exts_slice.rs":"c53ab47b58552c36d22809eec33850ede6111b6bdbd0708c9bc8d0e8ceffbdb3","src/net/ipv4_header.rs":"47be9590da698fc3591e024ddc339d2a774e289aa89ee579d86891452970c475","src/net/ipv4_header_slice.rs":"1be6eb90875ae7a76fcf2efdbe9551bd79ef7d22de3c978c23d0d1b008b5c830","src/net/ipv4_options.rs":"88c8e62c422b7b3154806dacb682e4cf30a0e9d71ef94f82da0e11c9c2dfd168","src/net/ipv4_slice.rs":"c673ef5d86a12a389dde01453f3be5039ac09cf9769066202f769afa02b2fa51","src/net/ipv6_ext_slice.rs":"a6fb7c4680e254f6cb207be71c5349faebc9f5c3b7f426d6b2ac82109e045085","src/net/ipv6_ext_slice_iter.rs":"99a369069280b6d637e0a54227aa0af23c47f4c41233282eb4a193a16c6cee2c","src/net/ipv6_exts.rs":"05db12d353f4cb9bfcfa601963c8318c8ff918a087f33b73e9304506a91db496","src/net/ipv6_exts_slice.rs":"ba2bd160acb1e039ffa33d5ca62293431d41e4ddb927e7b771629d1835748ee1","src/net/ipv6_flow_label.rs":"86d3d5059e00afb298889d3ad354d8d075a82fef4817fdcb07646bd806cea501","src/net/ipv6_fragment_header.rs":"3619f904899f81b4dcf93c66a3666a850fa0e26f3a1e982532a60a1020c10542","src/net/ipv6_fragment_header_slice.rs":"ad05dc98112345ab8ca97d371feb85ca12e2d6b6f09f431809f808a59e3042d9","src/net/ipv6_header.rs":"2cfd2944e63f173843cd8885bc5cf0d6a38f200179bf2a2ede99ad2d3ce1eca0","src/net/ipv6_header_slice.rs":"91e61f471bc04addc886341740197ccd7a460372417aa7059cd756b66174e4ef","src/net/ipv6_raw_ext_header.rs":"7bdaa8a0a01b4ac450008ba90b5df933faa75d05427286a9b39e54e1456993f5","src/net/ipv6_raw_ext_header_slice.rs":"4163f37d26648c07601ec42bf7dfcfeee4fb6cf38e1fefd46deabfd8aa5d4d48","src/net/ipv6_routing_exts.rs":"50f701a869987f5a8521933a67f942843bdbe21889aff99b36c388a729f5ded3","src/net/ipv6_slice.rs":"92839473e7290b92f0613aa9e08c4ea408bb314433b371780a069f2e82e14210","src/net/lax_ip_payload_slice.rs":"2dd48f564b75db1c1ca33d2b7d8309f031ad635130cbe221e1bfa8da1c11fd1f","src/net/lax_ip_slice.rs":"5d0e164f6ce040bf1a01e1655661847a8ffdbbcdc37f1ea565a119f680aea1ee","src/net/lax_ipv4_slice.rs":"855d3aa9989441044496b8a59f30f0113ff6201b35320b2f079436c985235d12","src/net/lax_ipv6_slice.rs":"926e49cb171996dede78c38b34a533e8bc717a86a4f01a010e38c8d5bf200ec2","src/net/lax_net_slice.rs":"da786d39f5329425413e2f931dacb17e40f35d272ecaf0d9c6b8d009d933eefb","src/net/mod.rs":"6aa9048f1d0a426821c44f83927611fe3c22b42f800ccc702636c0ed076efd82","src/net/net_headers.rs":"e7f5f498282c5aa617696a8ea53f339fac4c2f71e8d61aa13f058eb05ea4c6cd","src/net/net_slice.rs":"1dbd321f3a0d9367e32a89a0c0a520733204ee707f84d33b6ec237cd114db022","src/packet_builder.rs":"f480764e029be855cd0694fb258040b68359b2b107a923e3ba0660759512187b","src/packet_headers.rs":"5488e1aa1ceeb470562c39da58abc805b6ce4a984f245f1ef71f80b3aa3b196b","src/payload_slice.rs":"27d202b66385de0288bcd2213a3e7fd63f924a6aaa680d94e88e95297e386cae","src/sliced_packet.rs":"ae81864d688a534ba71288e90f317a94c6c9e48cd6cce81395a267dd86759539","src/sliced_packet_cursor.rs":"4b28bf70e3aaca7efb004dcbce0afac1af130d164a54e9f3be7ba57a978bd35f","src/test_gens/mod.rs":"e117e243a54811739fc7a503633fd6a439f2990d15f72f96d0a441320c1c58bc","src/test_packet.rs":"28b35492fd9a592214e8c395122ac8d17c3910173612b9a9ae5032f357eacdfa","src/transport/icmp_echo_header.rs":"5c454788b4781a50ea3371e39ad2bc9dc8c04bc5d322d82c6a5b8c47b45cfc5d","src/transport/icmpv4/dest_unreachable_header.rs":"4ec29a7b1c337e826690146930d478f8c546b54e9a3c6a08dca251a301910265","src/transport/icmpv4/mod.rs":"975c6fcbc7ff20dd4898f8531aec14cd8afddee4033c22191a9ac1ebea0a5bc7","src/transport/icmpv4/parameter_problem_header.rs":"ba0dd5f4e7befa18fe8d7177ee6cb393a0aebee44a52d2d27559d4bd9872bef6","src/transport/icmpv4/redirect_code.rs":"742b5f8b502904c7e8191bf224da32e4aa0bb2a7a0911a90034c182a0ef6d986","src/transport/icmpv4/redirect_header.rs":"8324a2ad86e2ef1b4533acf15737e4f3f1f87caa577dd479d48993081e536fde","src/transport/icmpv4/time_exceeded_code.rs":"c4cce23d1cb8726e58cb6561378acf5d59506dfdcd0bd30fae1a09a7938f071e","src/transport/icmpv4/timestamp_message.rs":"79e3cb2f9bb00690e0901708b3d1d0557cb4986c4057aa86c0906d5773c0fa4c","src/transport/icmpv4_header.rs":"6eb918629a4fa16f6d69161ba6dbc511e7d054c85e80fd123df68535e7ae387f","src/transport/icmpv4_slice.rs":"8eb2c572a5279b01a7f1f031b8394a31e8986527fb1f5894352a63d156c78741","src/transport/icmpv4_type.rs":"92a21fc2170a78929a91c95b7fa40979c55187ecfdc907614bdcd1b1f130bbe9","src/transport/icmpv6/dest_unreachable_code.rs":"2a86ff06affbd96bd365addc16ac0834c3ccc9f8d5d127edadf37cf89d8cc59b","src/transport/icmpv6/mod.rs":"8f02d1bc1fffe3eec831e911af8a9c1ac7ad5ab30c44cc7884e48ce9e3fec45a","src/transport/icmpv6/parameter_problem_code.rs":"39e8646e4ac65350e72f0df6573d09b11374444cd6debc69516997c4716def39","src/transport/icmpv6/parameter_problem_header.rs":"2c8f44daa17384612c6b94532274fc0469af906ac485b5ae90f98aefd728924b","src/transport/icmpv6/time_exceeded_code.rs":"d69c191b512f8b4b71825ca54e3fd15f1419b0ff7c54794073d25025aa30a37c","src/transport/icmpv6_header.rs":"55af2262a2548bd5bbae138ca53a9a13f31ef9829f7bc7980eac6c9eb3ad9c8d","src/transport/icmpv6_slice.rs":"636913244caa6d05ca49ba45cf8c7ee589f31cf465a74b6556d1fe6bb3fcab80","src/transport/icmpv6_type.rs":"648a595eddbd32b828fd1982c5dff59e52da819da70e7e8aa8e7d16997db982a","src/transport/mod.rs":"8990f71e8e13cd617afc8f49d060707675009e4b83ae2b2f49dbaae69e1079a8","src/transport/tcp_header.rs":"913cf0808db43a9788db339ef843f28771faef8175e3575b645dfd3dbc9204ef","src/transport/tcp_header_slice.rs":"d0027715f72e2cecbebe6b7c90ddd9dfbd10b83b755e177743dc7f164f6a45c8","src/transport/tcp_option_element.rs":"689a383f13e82f1d0bf5187c6facc56d55178318efa0e336fe536c07a3499593","src/transport/tcp_option_impl.rs":"c95838d1383718806cea28c29118912dec1c757b53e6b41dd840d0ae5e4e2cd8","src/transport/tcp_option_read_error.rs":"2d0a978519639aac12e48d4cb6b27120b7722e4138092bc37c7ed67244a64a8a","src/transport/tcp_option_write_error.rs":"41391bfc6decf6a2cfb44317f4d0ca910448431efbcf8c61917fe224a79188e1","src/transport/tcp_options.rs":"b631a3494e2eb97ffdb9677b8f5d77ff3aef06ee8578b4e250fa054f71026cab","src/transport/tcp_options_iterator.rs":"c7ad5ca46681797db5483aaae34dd6ebcc33f80299db1c566a4748f471ff29b9","src/transport/tcp_slice.rs":"80599f8266888271d46c92b75d8e8615bf0ce9b9796491219216b1132c06bfc3","src/transport/transport_header.rs":"9d9493a6c340f35a0f39a9dfffa1d74de278a4a23e9c1424639924955716bfdb","src/transport/transport_slice.rs":"97d8549b68cee06377ca21ac1ac19c6b6eb57c17ada43e538f5e0a00f7ec73c9","src/transport/udp_header.rs":"4787f4d34e0244676a12b68572ee9db1038a8522828039f80d355c34a8e4144f","src/transport/udp_header_slice.rs":"47810d0bc895f8ec001a10d005b141f3943144b5a47380a27e1f19da36c95a55","src/transport/udp_slice.rs":"51167999b2aa28eed4cf667745b3e08f9267c8e987b4d74d838523ee06766683","tests/transport/icmpv4.rs":"92be7785e5d5db0c85fe0f93974b34254a7badb4f21b4506a8575a638383ee84","tests/transport/icmpv6.rs":"e2451a13e6a5e379159bdfbb1cdcdcc88d470083b1778e7ead79ce32912a71d6","tests/transport/mod.rs":"c24bd8d361b60578a47874fcac7d7ed17cc05b7a17d5c286479b19221eb2e2f4","tests/unit-tests.rs":"3a1caee977f1a25678e19dc63a4d47b301737743471e1da0c847ccfdbf4fe353"},"package":"b14e4ac78394e3ea04edbbc412099cf54f2f52ded51efb79c466a282729399d2"}
\ No newline at end of file
diff --git a/crates/etherparse/Android.bp b/crates/etherparse/Android.bp
index 5b014f2..b13f720 100644
--- a/crates/etherparse/Android.bp
+++ b/crates/etherparse/Android.bp
@@ -18,7 +18,7 @@
host_supported: true,
crate_name: "etherparse",
cargo_env_compat: true,
- cargo_pkg_version: "0.16.0",
+ cargo_pkg_version: "0.17.0",
crate_root: "src/lib.rs",
edition: "2021",
features: [
diff --git a/crates/etherparse/Cargo.lock b/crates/etherparse/Cargo.lock
index 1af4d08..d4a621b 100644
--- a/crates/etherparse/Cargo.lock
+++ b/crates/etherparse/Cargo.lock
@@ -1,6 +1,6 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
-version = 3
+version = 4
[[package]]
name = "arrayvec"
@@ -59,7 +59,7 @@
[[package]]
name = "etherparse"
-version = "0.16.0"
+version = "0.17.0"
dependencies = [
"arrayvec",
"proptest",
diff --git a/crates/etherparse/Cargo.toml b/crates/etherparse/Cargo.toml
index 97719a6..15febcf 100644
--- a/crates/etherparse/Cargo.toml
+++ b/crates/etherparse/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2021"
name = "etherparse"
-version = "0.16.0"
+version = "0.17.0"
authors = ["Julian Schmid <info@julianschmid.name>"]
build = false
exclude = [
@@ -23,6 +23,7 @@
".travis/*",
"appveyor.yml",
]
+autolib = false
autobins = false
autoexamples = false
autotests = false
@@ -52,6 +53,10 @@
"docsrs",
]
+[features]
+default = ["std"]
+std = ["arrayvec/std"]
+
[lib]
name = "etherparse"
path = "src/lib.rs"
@@ -86,7 +91,3 @@
[dev-dependencies.proptest]
version = "1.4.0"
-
-[features]
-default = ["std"]
-std = ["arrayvec/std"]
diff --git a/crates/etherparse/METADATA b/crates/etherparse/METADATA
index 21d9f42..81ca5f0 100644
--- a/crates/etherparse/METADATA
+++ b/crates/etherparse/METADATA
@@ -1,17 +1,17 @@
name: "etherparse"
description: "A library for parsing & writing a bunch of packet based protocols (EthernetII, IPv4, IPv6, UDP, TCP ...)."
third_party {
- version: "0.16.0"
+ version: "0.17.0"
license_type: NOTICE
last_upgrade_date {
- year: 2024
- month: 9
- day: 30
+ year: 2025
+ month: 2
+ day: 20
}
homepage: "https://crates.io/crates/etherparse"
identifier {
type: "Archive"
- value: "https://static.crates.io/crates/etherparse/etherparse-0.16.0.crate"
- version: "0.16.0"
+ value: "https://static.crates.io/crates/etherparse/etherparse-0.17.0.crate"
+ version: "0.17.0"
}
-}
\ No newline at end of file
+}
diff --git a/crates/etherparse/README.md b/crates/etherparse/README.md
index 19a2505..7385cf9 100644
--- a/crates/etherparse/README.md
+++ b/crates/etherparse/README.md
@@ -11,6 +11,7 @@
Currently supported are:
* Ethernet II
* IEEE 802.1Q VLAN Tagging Header
+* ARP
* IPv4
* IPv6 (supporting the most common extension headers, but not all)
* UDP
@@ -25,7 +26,7 @@
```toml
[dependencies]
-etherparse = "0.16"
+etherparse = "0.17"
```
## What is etherparse?
@@ -49,7 +50,7 @@
Ok(value) => {
println!("link: {:?}", value.link);
println!("vlan: {:?}", value.vlan);
- println!("net: {:?}", value.net); // contains ip
+ println!("net: {:?}", value.net); // contains ip & arp
println!("transport: {:?}", value.transport);
}
}
@@ -77,7 +78,7 @@
Ok(value) => {
println!("link: {:?}", value.link);
println!("vlan: {:?}", value.vlan);
- println!("net: {:?}", value.net); // contains ip
+ println!("net: {:?}", value.net); // contains ip & arp
println!("transport: {:?}", value.transport);
}
}
@@ -103,6 +104,7 @@
* [`Ethernet2Slice::from_slice_without_fcs`](https://docs.rs/etherparse/~0/etherparse/struct.Ethernet2Slice.html#method.from_slice_without_fcs) & [`Ethernet2Slice::from_slice_with_crc32_fcs`](https://docs.rs/etherparse/~0/etherparse/struct.Ethernet2Slice.html#method.from_slice_with_crc32_fcs)
* [`LinuxSllSlice::from_slice`](https://docs.rs/etherparse/~0/etherparse/struct.LinuxSllSlice.html#method.from_slice)
* [`SingleVlanSlice::from_slice`](https://docs.rs/etherparse/~0/etherparse/struct.SingleVlanSlice.html#method.from_slice) & [`DoubleVlanSlice::from_slice`](https://docs.rs/etherparse/~0/etherparse/struct.DoubleVlanSlice.html#method.from_slice)
+* [`ArpPacketSlice::from_slice`](https://docs.rs/etherparse/~0/etherparse/struct.ArpPacketSlice.html#method.from_slice)
* [`IpSlice::from_slice`](https://docs.rs/etherparse/~0/etherparse/enum.IpSlice.html#method.from_slice) & [`LaxIpSlice::from_slice`](https://docs.rs/etherparse/~0/etherparse/enum.LaxIpSlice.html#method.from_slice)
* [`Ipv4Slice::from_slice`](https://docs.rs/etherparse/~0/etherparse/struct.Ipv4Slice.html#method.from_slice) & [`LaxIpv4Slice::from_slice`](https://docs.rs/etherparse/~0/etherparse/struct.LaxIpv4Slice.html#method.from_slice)
* [`Ipv6Slice::from_slice`](https://docs.rs/etherparse/~0/etherparse/struct.Ipv6Slice.html#method.from_slice) & [`LaxIpv6Slice::from_slice`](https://docs.rs/etherparse/~0/etherparse/struct.LaxIpv6Slice.html#method.from_slice)
@@ -141,6 +143,7 @@
* [`LinuxSllHeader::read`](https://docs.rs/etherparse/~0/etherparse/struct.LinuxSllHeader.html#method.read) & [`LinuxSllHeader::from_slice`](https://docs.rs/etherparse/~0/etherparse/struct.LinuxSllHeader.html#method.from_slice)
* [`SingleVlanHeader::read`](https://docs.rs/etherparse/~0/etherparse/struct.SingleVlanHeader.html#method.read) & [`SingleVlanHeader::from_slice`](https://docs.rs/etherparse/~0/etherparse/struct.SingleVlanHeader.html#method.from_slice)
* [`DoubleVlanHeader::read`](https://docs.rs/etherparse/~0/etherparse/struct.DoubleVlanHeader.html#method.read) & [`DoubleVlanHeader::from_slice`](https://docs.rs/etherparse/~0/etherparse/struct.DoubleVlanHeader.html#method.from_slice)
+* [`ArpPacket::read`](https://docs.rs/etherparse/~0/etherparse/struct.ArpPacket.html#method.read) & [`ArpPacket::from_slice`](https://docs.rs/etherparse/~0/etherparse/struct.ArpPacket.html#method.from_slice)
* [`IpHeaders::read`](https://docs.rs/etherparse/~0/etherparse/enum.IpHeaders.html#method.read) & [`IpHeaders::from_slice`](https://docs.rs/etherparse/~0/etherparse/enum.IpHeaders.html#method.from_slice)
* [`Ipv4Header::read`](https://docs.rs/etherparse/~0/etherparse/struct.Ipv4Header.html#method.read) & [`Ipv4Header::from_slice`](https://docs.rs/etherparse/~0/etherparse/struct.Ipv4Header.html#method.from_slice)
* [`Ipv4Extensions::read`](https://docs.rs/etherparse/~0/etherparse/struct.Ipv4Extensions.html#method.read) & [`Ipv4Extensions::from_slice`](https://docs.rs/etherparse/~0/etherparse/struct.Ipv4Extensions.html#method.from_slice)
@@ -198,6 +201,8 @@
* [`LinuxSllHeader::to_bytes`](https://docs.rs/etherparse/~0/etherparse/struct.LinuxSllHeader.html#method.to_bytes) & [`LinuxSllHeader::write`](https://docs.rs/etherparse/~0/etherparse/struct.LinuxSllHeader.html#method.write)
* [`SingleVlanHeader::to_bytes`](https://docs.rs/etherparse/~0/etherparse/struct.SingleVlanHeader.html#method.to_bytes) & [`SingleVlanHeader::write`](https://docs.rs/etherparse/~0/etherparse/struct.SingleVlanHeader.html#method.write)
* [`DoubleVlanHeader::to_bytes`](https://docs.rs/etherparse/~0/etherparse/struct.DoubleVlanHeader.html#method.to_bytes) & [`DoubleVlanHeader::write`](https://docs.rs/etherparse/~0/etherparse/struct.DoubleVlanHeader.html#method.write)
+* [`ArpPacket::to_bytes`](https://docs.rs/etherparse/~0/etherparse/struct.ArpPacket.html#method.to_bytes) & [`ArpPacket::write`](https://docs.rs/etherparse/~0/etherparse/struct.ArpPacket.html#method.write)
+* [`ArpEthIpv4Packet::to_bytes`](https://docs.rs/etherparse/~0/etherparse/struct.ArpEthIpv4Packet.html#method.to_bytes)
* [`Ipv4Header::to_bytes`](https://docs.rs/etherparse/~0/etherparse/struct.Ipv4Header.html#method.to_bytes) & [`Ipv4Header::write`](https://docs.rs/etherparse/~0/etherparse/struct.Ipv4Header.html#method.write) & [`Ipv4Header::write_raw`](https://docs.rs/etherparse/~0/etherparse/struct.Ipv4Header.html#method.write_raw)
* [`Ipv4Extensions::write`](https://docs.rs/etherparse/~0/etherparse/struct.Ipv4Extensions.html#method.write)
* [`Ipv6Header::to_bytes`](https://docs.rs/etherparse/~0/etherparse/struct.Ipv6Header.html#method.to_bytes) & [`Ipv6Header::write`](https://docs.rs/etherparse/~0/etherparse/struct.Ipv6Header.html#method.write)
diff --git a/crates/etherparse/examples/read_by_slicing.rs b/crates/etherparse/examples/read_by_slicing.rs
index f9299da..2186f94 100644
--- a/crates/etherparse/examples/read_by_slicing.rs
+++ b/crates/etherparse/examples/read_by_slicing.rs
@@ -92,6 +92,7 @@
println!(" {:?}", ipv6.extensions());
}
}
+ Some(Arp(value)) => println!(" Arp {:?}", value),
None => {}
}
diff --git a/crates/etherparse/proptest-regressions/compositions_tests.txt b/crates/etherparse/proptest-regressions/compositions_tests.txt
index 6bd98db..edd40da 100644
--- a/crates/etherparse/proptest-regressions/compositions_tests.txt
+++ b/crates/etherparse/proptest-regressions/compositions_tests.txt
@@ -6,3 +6,4 @@
# everyone who runs the test benefits from these saved cases.
cc 93464c2fb682bf96a32f9800d3932df8611a278bf6c993dc3ad6301d17795715 # shrinks to ref eth = Ethernet2Header { source: [0, 0, 0, 0, 0, 0], destination: [0, 0, 0, 0, 0, 0], ether_type: 0 }, ref vlan_outer = SingleVlanHeader { priority_code_point: 0, drop_eligible_indicator: false, vlan_identifier: 0, ether_type: 0 }, ref vlan_inner = SingleVlanHeader { priority_code_point: 0, drop_eligible_indicator: false, vlan_identifier: 0, ether_type: 0 }, ref ipv4 = 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: 4, header_checksum: 0, source: [0, 0, 0, 0], destination: [0, 0, 0, 0], options: [0, 0, 0, 0, 0, 0, 0, 0] }, ref ipv4_exts = Ipv4Extensions { auth: None }, ref ipv6 = Ipv6Header { traffic_class: 213, flow_label: 798389, payload_length: 24896, next_header: 187, hop_limit: 229, source: [14, 32, 160, 168, 37, 154, 115, 40, 38, 87, 212, 112, 188, 142, 254, 197], destination: [6, 159, 253, 179, 126, 197, 144, 208, 190, 191, 89, 166, 208, 140, 54, 50] }, ref ipv6_exts = Ipv6Extensions { hop_by_hop_options: None, destination_options: None, routing: None, fragment: Some(Ipv6FragmentHeader { next_header: 156, fragment_offset: 2564, more_fragments: false, identification: 3123850911 }), auth: None }, ref udp = UdpHeader { source_port: 45157, destination_port: 34201, length: 57104, checksum: 21037 }, ref tcp = TcpHeader { source_port: 51159, destination_port: 19610, sequence_number: 3703908533, acknowledgment_number: 8047906, data_offset: 13, ns: true, fin: false, syn: false, rst: false, psh: false, ack: false, urg: true, ece: false, cwr: true, window_size: 3326, checksum: 50866, urgent_pointer: 1068, options: [Err(UnknownId(34))] }, ref icmpv4 = Icmpv4Header { icmp_type: TimestampReply(TimestampMessage { id: 54195, seq: 33654, originate_timestamp: 2593543617, receive_timestamp: 534962444, transmit_timestamp: 141913819 }), checksum: 50019 }, ref icmpv6 = Icmpv6Header { icmp_type: Unknown { type_u8: 228, code_u8: 213, bytes5to8: [17, 44, 158, 162] }, checksum: 51305 }, ref payload = [176, 206, 197, 85, 12, 15, 112, 1, 92, 102, 232, 123, 66, 67, 0, 129, 111, 164, 134, 24, 82, 206, 103, 137, 239, 130, 78, 149, 131, 220, 160, 114, 222, 169, 165, 141, 202, 80, 8, 234, 94, 151, 21, 242, 120, 93, 230, 85, 162, 209, 105, 154, 72, 203, 198, 235, 64, 239, 33, 102, 54, 45, 201, 245, 26, 192, 182, 10, 232, 131, 82, 9, 32, 183, 65, 225, 132, 208, 61, 251, 109, 66, 234, 46, 65, 240, 148, 46, 146, 56, 17, 205, 103, 253, 158, 32, 21, 148, 243, 191, 23, 135, 145, 188, 136, 139, 125, 99, 144, 34, 142, 229, 128, 46, 226, 88, 205, 126, 2, 39, 87, 16, 74, 20, 184, 165, 75, 34, 0, 206, 61, 220, 196, 39, 190, 113, 217, 4, 238, 26, 232, 52, 18, 123, 48, 196, 238, 75, 120, 241, 41, 229, 114, 161, 65, 143, 237, 251, 87, 156, 155, 210, 178, 43, 166, 184, 11, 9, 250, 221, 22, 72, 65, 160, 116, 60, 242, 239, 97, 249, 39, 207, 214, 47, 6, 120, 51, 165, 69, 122, 156, 142, 159, 27, 224, 171, 233, 105, 79, 49, 32, 118, 141, 227, 174, 207, 109, 135, 5, 13, 248, 235, 33, 113, 233, 53, 131, 52, 188, 52, 203, 12, 88, 54, 84, 21, 132, 41, 211, 30, 215, 46, 108, 126, 141, 13, 113, 21, 233, 111, 115, 109, 107, 246, 214, 65, 211, 186, 60, 224, 211, 214, 191, 65, 62, 169, 122, 246, 237, 107, 183, 160, 179, 144, 106, 63, 10, 0, 87, 75, 175, 228, 178, 219, 35, 227, 161, 214, 134, 106, 156, 244, 126, 186, 201, 199, 202, 30, 220, 163, 146, 208, 192, 179, 241, 219, 6, 43, 39, 21, 231, 16, 213, 192, 194, 82, 33, 121, 188, 56, 108, 79, 219, 183, 20, 18, 192, 42, 7, 109, 217, 25, 42, 170, 154, 206, 35, 131, 193, 187, 217, 185, 178, 196, 130, 25, 85, 228, 103, 112, 163, 53, 154, 65, 68, 219, 219, 163, 208, 44, 33, 90, 118, 133, 114, 43, 242, 58, 196, 246, 55, 223, 181, 14, 249, 35, 73, 179, 242, 211, 188, 156, 4, 213, 54, 205, 50, 83, 116, 13, 128, 133, 239, 122, 106, 98, 140, 171, 202, 8, 11, 51, 219, 68, 19, 114, 8, 229, 177, 199, 9, 228, 130, 194, 211, 59, 16, 145, 23, 163, 228, 186, 187, 24, 194, 93, 75, 44, 23, 192, 96, 226, 164, 242, 75, 135, 48, 118, 108, 49, 62, 63, 228, 71, 153, 134, 15, 192, 249, 103, 44, 211]
cc 19938c0e61de8fbe9f8df17d1325091a1825e2b209a4adb8b21dcd28a0e0f558 # shrinks to ref eth = Ethernet2Header { source: [0, 0, 0, 0, 0, 0], destination: [0, 0, 0, 0, 0, 0], ether_type: 0 }, ref vlan_outer = SingleVlanHeader { priority_code_point: 0, drop_eligible_indicator: false, vlan_identifier: 0, ether_type: 0 }, ref vlan_inner = SingleVlanHeader { priority_code_point: 0, drop_eligible_indicator: false, vlan_identifier: 0, ether_type: 0 }, ref ipv4 = Ipv4Header { ihl: 8, differentiated_services_code_point: 0, explicit_congestion_notification: 0, payload_len: 34240, identification: 0, dont_fragment: false, more_fragments: false, fragments_offset: 0, time_to_live: 0, protocol: 95, header_checksum: 2458, source: [0, 0, 0, 0], destination: [0, 0, 0, 0], options: [80, 229, 92, 224, 82, 126, 48, 60, 105, 201, 96, 77] }, ref ipv4_exts = Ipv4Extensions { auth: None }, ref ipv6 = Ipv6Header { traffic_class: 129, flow_label: 787898, payload_length: 54827, next_header: 33, hop_limit: 254, source: [109, 7, 4, 79, 149, 61, 253, 73, 214, 117, 64, 10, 168, 230, 137, 73], destination: [44, 199, 106, 47, 71, 14, 18, 94, 107, 95, 41, 238, 83, 187, 218, 132] }, ref ipv6_exts = Ipv6Extensions { hop_by_hop_options: Some(Ipv6RawExtensionHeader { next_header: 60, payload: [112, 231, 1, 88, 255, 168, 119, 95, 144, 149, 61, 29, 235, 11, 182, 192, 83, 15, 201, 180, 189, 232, 85, 231, 220, 116, 192, 132, 43, 162, 23, 161, 129, 246, 28, 236, 164, 174, 67, 235, 121, 212, 9, 73, 30, 98, 190, 173, 122, 133, 58, 154, 142, 6, 24, 203, 3, 230, 232, 50, 77, 203, 83, 151, 3, 157, 193, 242, 25, 246, 224, 4, 178, 173, 156, 5, 210, 3, 97, 27, 171, 152, 187, 16, 98, 73, 57, 176, 35, 25, 246, 71, 154, 32, 132, 227, 164, 29, 92, 159, 74, 247, 144, 68, 39, 254, 227, 156, 63, 140, 246, 246, 199, 111, 101, 173, 179, 116, 79, 114, 249, 162, 71, 113, 121, 224, 229, 237, 67, 3, 4, 162, 152, 120, 58, 132, 244, 196, 136, 196, 206, 160, 45, 83, 167, 218, 32, 206, 52, 246, 144, 220, 133, 150, 36, 91, 193, 118, 28, 33, 236, 64, 255, 72, 190, 70, 160, 38, 139, 134, 80, 153, 236, 93, 198, 211, 21, 19, 251, 131, 119, 219, 161, 19, 144, 96, 6, 188, 115, 43, 91, 216, 5, 135, 101, 166, 99, 11, 174, 169, 255, 248, 101, 23, 62, 55, 169, 40, 6, 186, 195, 235, 76, 41] }), destination_options: Some(Ipv6RawExtensionHeader { next_header: 43, payload: [238, 203, 236, 202, 32, 25, 193, 164, 167, 189, 30, 208, 207, 108, 114, 10, 12, 226, 180, 59, 207, 44, 143, 244, 221, 200, 232, 154, 140, 180, 167, 70, 197, 72, 31, 249, 141, 75, 7, 255, 201, 53, 76, 234, 201, 187, 214, 141, 249, 216, 232, 12, 45, 196, 208, 110, 78, 14, 60, 251, 17, 239, 13, 141, 216, 29, 230, 120, 102, 88, 104, 237, 17, 252, 108, 126, 203, 75] }), routing: Some(Ipv6RoutingExtensions { routing: Ipv6RawExtensionHeader { next_header: 44, payload: [254, 77, 166, 70, 182, 207, 149, 153, 212, 40, 122, 249, 15, 84, 41, 126, 254, 103, 2, 162, 52, 216, 226, 175, 148, 253, 5, 153, 50, 16, 32, 44, 139, 24, 73, 245, 17, 9, 50, 18, 176, 70, 177, 29, 220, 255, 253, 255, 94, 39, 69, 225, 93, 176, 139, 48, 98, 210, 151, 80, 3, 105, 114, 59, 232, 171, 163, 235, 40, 56, 9, 85, 180, 225, 71, 230, 216, 128, 194, 109, 150, 198, 175, 68, 186, 112, 223, 48, 61, 245, 191, 34, 3, 207, 250, 27, 110, 21, 229, 221, 166, 76, 220, 214, 215, 104, 137, 46, 134, 94, 106, 89, 129, 218, 113, 234, 119, 79, 84, 147, 98, 202, 148, 239, 67, 99, 223, 222, 139, 13, 237, 170, 164, 89, 15, 185, 202, 252, 2, 156, 33, 28, 194, 52, 180, 232, 239, 202, 23, 123, 215, 81, 236, 65, 80, 192, 136, 184, 237, 135, 205, 183, 104, 66, 253, 128, 176, 245, 213, 65, 120, 202, 15, 130, 202, 55, 28, 94, 189, 8, 11, 59, 112, 96, 196, 186, 15, 96, 32, 60, 193, 8, 95, 44, 110, 224, 32, 71, 96, 140, 69, 124, 69, 241, 153, 87, 65, 15, 171, 113, 248, 239, 156, 78, 174, 47, 99, 190, 159, 163, 29, 197, 75, 161, 4, 209, 213, 236, 86, 120, 74, 15, 147, 85, 135, 147, 242, 220, 144, 55, 202, 170, 71, 90, 107, 103, 170, 8, 231, 169, 231, 170, 153, 184, 158, 99, 127, 228, 243, 191, 139, 69, 75, 133, 185, 212, 104, 214, 233, 171, 0, 135, 73, 14, 31, 2, 90, 187, 82, 205, 161, 69, 251, 143, 243, 15, 56, 250, 98, 175, 82, 196, 216, 95, 249, 127, 84, 181, 211, 50, 81, 36, 26, 247, 224, 3, 92, 61, 120, 67, 163, 170, 185, 61, 254, 91, 248, 20, 150, 19, 49, 71, 52, 102, 152, 209, 105, 219, 65, 151, 19, 101, 102, 133, 216, 94, 237, 221, 232, 168, 51, 28, 214, 231, 179, 180, 235, 17, 36, 19, 33, 54, 232, 131, 150, 95, 96, 84, 13, 6, 20, 28, 160, 92, 193, 206, 231, 10, 238, 240, 6, 77, 44, 78, 6, 253, 142, 54, 72, 135, 39, 144, 95, 132, 194, 5, 25, 225, 46, 143, 153, 93, 213, 32, 114, 214, 230, 61, 21, 189, 86, 34, 12, 85, 75, 242, 112, 3, 251, 4, 129, 141, 153, 47, 228, 157, 65, 13, 82, 38, 80, 34, 7, 52, 172, 210, 141, 83, 27, 39, 100, 16, 0, 216, 114, 134, 195, 220, 156, 79, 174, 220, 88, 252, 193, 210, 93, 190, 229, 6, 16, 63, 190, 46, 5, 126, 28, 10, 51, 102, 19, 8, 153, 157, 142, 125, 6, 40, 100, 68, 139, 231, 69, 159, 46, 98, 36, 25, 200, 140, 107, 101, 15, 70, 25, 89, 211, 3, 17, 253, 9, 50, 39, 60, 47, 185, 135, 17, 218, 116, 65, 107, 110, 122, 227, 202, 155, 71, 164, 119, 189, 84, 128, 8, 180, 93, 177, 45, 15, 198, 16, 79, 179, 46, 103, 85, 91, 229, 254, 12, 152, 129, 160, 104, 16, 217, 157, 157, 61, 137, 189, 194, 132, 234, 243, 123, 91, 70, 132, 5, 222, 200, 134, 26, 129, 182, 254, 254, 151, 165, 184, 13, 85, 106, 44, 20, 79, 183, 130, 223, 209, 88, 35, 174, 160, 91, 199, 118, 168, 40, 189, 181, 59, 38, 74, 43, 24, 80, 25, 224, 73, 119, 241, 101, 41, 109, 115, 24, 35, 204, 181, 100, 33, 78, 109, 253, 192, 21, 137, 4, 203, 143, 243, 152, 96, 237, 209, 26, 217, 68, 239, 59, 1, 200, 219, 177, 22, 196, 180, 1, 102, 202, 126, 216, 32, 221, 143, 99, 223, 7, 129, 183, 252, 35, 59, 15, 204, 56, 18, 118, 229, 215, 81, 147, 172, 69, 116, 46, 51, 169, 157, 22, 69, 178, 97, 224, 190, 198, 11, 216, 188, 108, 161, 120, 196, 181, 172, 21, 41, 124, 197, 106, 58, 193, 102, 16, 67, 127, 109, 45, 135, 60, 110, 30, 155, 88, 173, 34, 14, 78, 117, 93, 158, 51, 117, 168, 226, 43, 44, 173, 185, 20, 111, 151, 32, 95, 226, 103, 101, 76, 229, 117, 14, 56, 187, 185, 131, 185, 50, 68, 20, 173, 69, 94, 131, 252, 114, 133, 98, 55, 143, 45, 12, 25, 226, 189, 170, 73, 70, 163, 98, 27, 195, 211, 38, 108, 243, 46, 5, 140, 56, 85, 136, 98, 154, 22, 112, 91, 192, 81, 51, 252, 190, 222, 16, 151, 178, 51, 209, 208, 15, 72, 17, 127, 219, 117, 10, 93, 193, 133, 55, 125, 98, 95, 35, 63, 115, 88, 44, 80, 120, 10, 224, 207, 98, 243, 227, 236, 149, 9, 163, 166, 250, 134, 32, 144, 182, 144, 212, 237, 231, 157, 18, 39, 46, 116, 226, 106, 195, 193, 129, 171, 121, 5, 135, 72, 160, 170, 139, 83, 138, 70, 124, 115, 12, 219, 197, 250, 209, 205, 250, 55, 107, 37, 26, 107, 141, 164, 107, 93, 45, 26, 7, 240, 168, 25, 169, 241, 21, 22, 142, 216, 164, 17, 50, 214, 204, 32, 31, 184, 179, 11, 134, 255, 229, 160, 130, 167, 149, 190, 141, 191, 64, 247, 35, 182, 183, 9, 119, 116, 199, 43, 91, 48, 101, 117, 52, 145, 248, 62, 25, 82, 129, 253, 53, 206, 51, 195, 80, 45, 83, 239, 194, 4, 108, 177, 156, 196, 42, 215, 45, 2, 2, 251, 9, 122, 230, 239, 39, 83, 129, 88, 192, 181, 57, 235, 22, 25, 122, 54, 9, 242, 32, 96, 178, 29, 2, 9, 212, 157, 250, 227, 114, 138, 238, 202, 121, 90, 101, 42, 137, 159, 27, 112, 225, 206, 201, 104, 201, 177, 177, 26, 103, 227, 100, 190, 231, 117, 136, 230, 180, 121, 54, 60, 113, 26, 49, 140, 66, 76, 150, 183, 116, 193, 170, 130, 166, 214, 204, 212, 125, 75, 19, 17, 79, 245, 198, 176, 15, 17, 43, 92, 169, 227, 25, 11, 194, 245, 93, 126, 247, 254, 74, 148, 187, 231, 153, 196, 193, 177, 125, 67, 183, 79, 219, 77, 89, 233, 42, 45, 38, 232, 164, 146, 228, 179, 204, 107, 191, 254, 232, 61, 172, 148, 144, 56, 60, 178, 90, 211, 72, 255, 93, 3, 25, 220, 180, 82, 70, 85, 209, 97, 92, 7, 232, 204, 201, 202, 235, 31, 75, 60, 157, 149, 147, 168, 175, 138, 116, 118, 127, 123, 98, 115, 205, 37, 81, 74, 136, 150, 89, 83, 204, 201, 105, 154, 27, 1, 104, 193, 102, 17, 247, 204, 236, 134, 110, 165, 141, 123, 21, 229, 56, 215, 184, 3, 251, 7, 181, 246, 50, 133, 74, 50, 36, 224, 12, 171, 200, 245, 193, 110, 42, 93, 115, 215, 182, 128, 107, 175, 64, 170, 131, 206, 74, 124, 194, 150, 191, 102, 85, 139, 127, 117, 35, 239, 137, 225, 68, 108, 118, 250, 127, 250, 128, 167, 149, 240, 21, 238, 117, 98, 181, 186, 162, 83, 152, 255, 80, 111, 235, 55, 133, 209, 43, 118, 151, 148, 140, 253, 249, 178, 148, 174, 254, 236, 250, 172, 27, 220, 189, 20, 26, 201, 253, 187, 109, 55, 51, 26, 243, 44, 65, 59, 131, 116, 15, 52, 222, 174, 63, 49, 150, 113, 71, 98, 228, 48, 27, 236, 183, 240, 184, 87, 21, 146, 248, 224, 54, 46, 81, 109, 129, 243, 104, 48, 239, 36, 8, 232, 9, 229, 82, 164, 3, 186, 86, 202, 128, 224, 218, 19, 161, 92, 187, 55, 41, 203, 143, 139, 54, 50, 120, 253, 62, 26, 232, 113, 97, 136, 6, 53, 89, 90, 200, 202, 246, 102, 193, 14, 244, 179, 226, 253, 205, 189, 236, 98, 51, 154, 217, 83, 254, 238, 229, 32, 197, 124, 71, 165, 235, 224, 67, 190, 207, 23, 232, 240, 34, 203, 137, 64, 93, 65, 240, 205, 71, 61, 36, 104, 99, 125, 94, 9, 255, 131, 204, 210, 17, 210, 205, 112, 188, 146, 246, 237, 76, 128, 24, 198, 43, 184, 72, 22, 77, 196, 8, 77, 138, 105, 155, 165, 215, 253, 162, 248, 172, 95, 79, 102, 199, 90, 251, 122, 74, 24, 69, 65, 112, 172, 227, 140, 202, 104, 235, 119, 220, 80, 78, 234, 21, 129, 138, 250, 188, 87, 131, 20, 185, 76, 24, 103, 231, 145, 48, 207, 167, 230, 18, 30, 80, 190, 139, 36, 22, 165, 21, 176, 240, 227, 82, 246, 112, 184, 21, 226, 116, 175, 147, 250, 109, 236, 83, 52, 112, 156, 180, 111, 220, 43, 77, 112, 98, 193, 125, 145, 31, 38, 115, 213, 67, 95, 62, 81, 208, 123, 8, 158, 157, 171, 133, 246, 210, 56, 169, 221, 27, 153, 121, 210, 134, 24, 202, 90, 183, 78, 229, 99, 153, 245, 135, 122, 55, 158, 129, 216, 147, 80, 150, 203, 182, 220, 9, 95, 65, 222, 120, 144, 133, 148, 45, 134, 7, 113, 74, 219, 238, 229, 1, 112, 173, 189, 232, 176, 219, 14, 143, 14, 134, 108, 209, 218, 59, 252, 192, 185, 255, 142, 96, 87, 1, 77, 243, 219, 46, 78, 253, 128, 249, 182, 149, 144, 174, 176, 198, 64, 3, 200, 129, 217, 102, 131, 119, 102, 74, 10, 212, 86, 143, 165, 108, 235, 36, 100, 18, 3, 241, 8, 113, 92, 201, 114, 216, 97, 120, 199, 196, 172, 29, 179, 205, 252, 163, 199, 187, 139, 42, 103, 99, 51, 51, 8, 205, 180, 149, 177, 245, 77, 111, 26, 246, 112, 174, 236, 221, 168, 72, 137, 38, 59, 10, 89, 6, 68, 66, 158, 17, 246, 149, 239, 165, 221, 28, 144, 252, 247, 102, 194, 215, 90, 15, 206, 93, 133, 197, 15, 81, 155, 143, 200, 201, 112, 105, 60, 84, 52, 179, 179, 18, 67, 178, 126, 113, 15, 45, 26, 159, 223, 161, 249, 141, 31, 179, 43, 94, 8, 125, 194, 219, 26, 65, 57, 166, 236, 185, 24, 63, 206, 215, 22, 85, 117, 41, 197, 182, 147, 46, 202, 167, 206, 154, 89, 200, 95, 238, 93, 125, 4, 101, 195, 253, 179, 29, 13, 234, 225, 171, 72, 82, 224, 60, 191, 74, 113, 217, 161, 10, 13, 202, 196, 144, 104, 46, 71, 49, 212, 22, 181, 250, 28, 27, 95, 151, 158, 25, 84, 226, 200] }, final_destination_options: None }), fragment: Some(Ipv6FragmentHeader { next_header: 109, fragment_offset: 2113, more_fragments: true, identification: 5944605 }), auth: None }, ref udp = UdpHeader { source_port: 27523, destination_port: 52161, length: 45869, checksum: 14910 }, ref tcp = TcpHeader { source_port: 17245, destination_port: 46697, sequence_number: 160328470, acknowledgment_number: 2631620014, data_offset: 10, ns: false, fin: false, syn: false, rst: true, psh: false, ack: true, urg: false, ece: true, cwr: false, window_size: 24158, checksum: 53442, urgent_pointer: 8968, options: [Err(UnknownId(173))] }, ref icmpv4 = Icmpv4Header { icmp_type: Unknown { type_u8: 234, code_u8: 221, bytes5to8: [200, 89, 56, 131] }, checksum: 16430 }, ref icmpv6 = Icmpv6Header { icmp_type: Unknown { type_u8: 30, code_u8: 106, bytes5to8: [52, 110, 228, 155] }, checksum: 38251 }, ref payload = [111, 188, 151, 183, 149, 185, 18, 245, 219, 34, 101, 100, 224, 105, 138, 24, 34, 92, 6, 75, 219, 201, 60, 187, 214, 136, 150, 248, 6, 50, 64, 136, 89, 13, 42, 46, 93, 80, 5, 22, 114, 77, 34, 58, 115, 121, 159, 158, 151, 132, 171, 188, 57, 49, 52, 166, 160, 191, 60, 116, 6, 117, 215, 53, 99, 85, 33, 16, 109, 90, 48, 192, 31, 77, 71, 43, 229, 66, 22, 199, 176, 216, 156, 180, 197, 105, 72, 60, 198, 61, 119, 201, 118, 240, 131, 5, 102, 75, 200, 84, 254, 216, 228, 209, 150, 251, 234, 232, 20, 243, 127, 121, 97, 68, 16, 43, 140, 15, 235, 75, 178, 41, 209, 114, 244, 16, 163, 224, 223, 132, 128, 56, 142, 160, 184, 140, 89, 35, 167, 84, 217, 209, 200, 3, 120, 124, 220, 113, 169, 39, 64, 82, 255, 81, 239, 172, 199, 48, 179, 102, 109, 53, 167, 253, 203, 114, 225, 103, 233, 1, 72, 29, 178, 90, 44, 246, 248, 43, 137, 46, 5, 250, 25, 94, 155, 183, 46, 229, 121, 120, 16, 105, 40, 15, 168, 29, 93, 71, 42, 36, 179, 253, 67, 132, 81, 196, 190, 165, 130, 54, 57, 212, 240, 76, 252, 175, 147, 200, 18, 179, 196, 82, 9, 135, 197, 217, 12, 60, 130, 144, 129, 206, 133, 122, 183, 87, 194, 149, 79, 206, 67, 178, 51, 38, 60, 143, 132, 9, 221, 193, 27, 31, 145, 245, 137, 134, 248, 231, 68, 211, 125, 22, 234, 78, 231, 119, 27, 241, 143, 43, 173, 231, 117, 180, 255, 230, 138, 68, 233, 225, 184, 16, 132, 168, 65, 84, 177, 210, 183, 55, 188, 216, 82, 7, 137, 1, 81, 69, 14, 104, 82, 239, 73, 218, 70, 196, 163, 59, 183, 151, 95, 197, 81, 49, 97, 162, 96, 9, 95, 254, 137, 252, 100, 190, 218, 124, 130, 82, 32, 154, 253, 44, 253, 58, 149, 116, 45, 82, 104, 103, 119, 42, 175, 208, 203, 25, 65, 154, 218, 222, 22, 148, 94, 5, 226, 217, 158, 148, 30, 84, 36, 142, 214, 166, 176, 62, 198, 178, 94, 205, 220, 155, 5, 86, 48, 167, 114, 108, 210, 127, 105, 247, 106, 30, 77, 100, 149, 109, 139, 60, 174, 121, 24, 203, 35, 163, 15, 212, 151, 206, 94, 134, 28, 253, 192, 66, 12, 167, 45, 146, 101]
+cc 8a9b0a970a9a2fe38d925b7ce0f4ff73ba262d7258e2d20e1ff7c9251885a396 # shrinks to ref eth = Ethernet2Header { source: [0, 0, 0, 0, 0, 0], destination: [0, 0, 0, 0, 0, 0], ether_type: 0x0000 }, 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: 0x0806 (Address Resolution Protocol (ARP)) }, ref ipv4 = Ipv4Header { dscp: Ipv4Dscp(0), ecn: Ipv4Ecn(0), total_len: 20, identification: 0, dont_fragment: false, more_fragments: false, fragment_offset: IpFragOffset(0), time_to_live: 0, protocol: 29 (ISO-TP4 - ISO Transport Protocol Class 4), header_checksum: 0, source: [0, 0, 0, 0], destination: [0, 0, 0, 0], options: [] }, ref ipv4_exts = Ipv4Extensions { auth: Some(IpAuthHeader { next_header: 24 (TRUNK-2 - Trunk-2), spi: 2509063036, sequence_number: 3755394165, raw_icv: [92, 181, 195, 73, 130, 142, 140, 140, 223, 45, 197, 36, 9, 69, 55, 43, 149, 231, 9, 4, 120, 102, 160, 165, 107, 87, 64, 204, 231, 179, 197, 165, 115, 145, 144, 125, 94, 30, 168, 176, 19, 63, 236, 79, 115, 199, 15, 92, 162, 106, 139, 90, 248, 240, 127, 37, 144, 179, 147, 224, 57, 41, 152, 198, 117, 161, 199, 197, 98, 23, 220, 31, 79, 25, 99, 100, 171, 127, 4, 248, 29, 2, 189, 178, 206, 124, 247, 24, 51, 75, 240, 246, 123, 220, 42, 147, 91, 187, 218, 92, 90, 171, 47, 1, 54, 19, 58, 73, 82, 207, 143, 83, 100, 150, 44, 228, 214, 246, 111, 239, 107, 35, 187, 109, 244, 118, 33, 58, 192, 37, 195, 191, 74, 82, 149, 2, 25, 245, 127, 172, 34, 72, 200, 6, 37, 121, 147, 136, 76, 40, 209, 25, 202, 208, 118, 230, 122, 151, 38, 140, 238, 68, 101, 149, 46, 233, 83, 180, 105, 169, 213, 123, 189, 109, 9, 214, 192, 238, 95, 177, 223, 71, 103, 7, 243, 54, 156, 100, 138, 195, 151, 91, 193, 151, 177, 82, 165, 16, 106, 253, 90, 76, 0, 204, 20, 190, 229, 54, 147, 227, 190, 57, 233, 143, 98, 114, 82, 106, 157, 134, 187, 18, 66, 21, 220, 135, 175, 76, 33, 91, 242, 181, 47, 74, 206, 252, 84, 28, 248, 36, 94, 8, 124, 219, 150, 145, 213, 192, 233, 11, 56, 72, 201, 140, 48, 93, 198, 77, 26, 31, 208, 179, 191, 185, 195, 83, 39, 3, 110, 92, 146, 229, 222, 36, 53, 176, 178, 49, 44, 110, 75, 8, 104, 135, 52, 26, 50, 4, 183, 70, 84, 67, 8, 76, 25, 45, 106, 225, 33, 107, 142, 35, 90, 100, 141, 25, 202, 82, 41, 43, 49, 103, 33, 202, 244, 125, 123, 69, 118, 118, 118, 72, 244, 53, 71, 161, 133, 88, 131, 144, 109, 3, 60, 40, 166, 109, 206, 115, 18, 97, 172, 157, 50, 144, 179, 3, 7, 154, 121, 56, 138, 174, 242, 151, 95, 245, 204, 195, 241, 62, 200, 106, 28, 205, 27, 201, 190, 66, 12, 127, 70, 30, 227, 173, 225, 6, 142, 228, 215, 244, 138, 130, 171, 59, 180, 180, 127, 145, 1, 228, 40, 222, 36, 43, 141, 74, 226, 229, 46, 9, 101, 229, 99, 111, 102, 188, 153, 86, 118, 111, 1, 235, 176, 218, 83, 130, 14, 60, 142, 42, 26, 99, 245, 73, 213, 247, 185, 176, 118, 29, 139, 236, 218, 167, 13, 129, 124, 105, 194, 63, 95, 95, 197, 97, 65, 41, 221, 32, 122, 48, 218, 198, 95, 95, 124, 6, 2, 84, 160, 96, 128, 125, 172, 240, 53, 131, 49, 10, 254, 166, 16, 127, 66, 232, 206, 172, 31, 24, 115, 213, 172, 29, 96, 116, 88, 163, 135, 121, 233, 223, 63, 65, 45, 18, 119, 145, 192, 246, 94, 235, 25, 83, 174, 244, 215, 135, 229, 230, 216, 101, 146, 157, 118, 91, 43, 16, 196, 2, 167, 72, 139, 20, 105, 112, 167, 191, 83, 233, 43, 43, 254, 199, 49, 68, 69, 91, 192, 153, 244, 15, 59, 119, 80, 51, 129, 220, 154, 172, 193, 147, 59, 241, 215, 70, 224, 110, 21, 33, 34, 216, 177, 174, 227, 84, 38, 181, 249, 95, 87, 152, 165, 132, 95, 134, 37, 228] }) }, ref ipv6 = Ipv6Header { traffic_class: 15, flow_label: Ipv6FlowLabel(377208), payload_length: 39375, next_header: 11 (NVP-II - Network Voice Protocol), hop_limit: 164, source: [130, 247, 84, 229, 201, 228, 210, 155, 39, 71, 113, 56, 54, 232, 243, 221], destination: [42, 1, 131, 202, 153, 22, 76, 246, 14, 164, 20, 54, 68, 234, 189, 145] }, ref ipv6_exts = Ipv6Extensions { hop_by_hop_options: Some(Ipv6RawExtHeader { next_header: 60 (IPv6-Opts - Destination Options for IPv6), payload: [62, 47, 61, 126, 20, 254, 36, 110, 35, 19, 117, 163, 115, 86, 52, 46, 27, 154, 128, 33, 173, 71, 49, 222, 253, 62, 14, 57, 125, 78, 228, 70, 248, 103, 253, 195, 35, 6, 89, 220, 194, 161, 100, 221, 94, 202, 232, 176, 37, 104, 84, 204, 136, 200, 112, 93, 234, 1, 245, 194, 81, 94, 114, 17, 71, 224, 146, 87, 167, 234, 170, 48, 69, 136, 130, 154, 143, 122, 81, 104, 95, 50, 213, 82, 77, 182, 60, 31, 192, 201, 244, 231, 252, 125, 130, 59, 128, 141, 185, 41, 125, 190, 138, 143, 72, 81, 15, 3, 56, 216, 52, 209, 87, 197, 249, 92, 165, 226, 237, 205, 210, 3, 182, 13, 89, 244, 39, 149, 201, 75, 104, 25, 209, 124, 87, 125, 44, 51, 84, 70, 144, 225, 60, 8, 220, 2, 47, 131, 62, 183, 243, 165, 43, 20, 222, 245, 223, 171, 74, 184, 83, 63, 66, 200, 185, 58, 27, 172, 193, 98, 113, 56, 199, 151, 136, 20, 241, 232, 212, 165, 82, 187, 209, 172, 128, 153, 175, 140, 151, 178, 207, 210, 232, 57, 124, 187, 90, 140, 2, 203, 59, 81, 175, 81, 242, 125, 217, 19, 67, 109, 148, 37, 253, 127, 22, 118, 105, 86, 190, 137, 172, 53, 96, 87, 166, 105, 151, 59, 192, 91, 76, 58, 186, 14, 61, 133, 213, 36, 178, 48, 71, 226, 35, 225, 153, 252, 43, 154, 118, 6, 58, 243, 47, 180, 225, 73, 137, 234, 81, 56, 91, 175, 90, 151, 177, 210, 6, 73, 250, 9, 158, 217, 181, 141, 37, 184, 233, 148, 143, 13, 110, 161, 112, 191, 234, 14, 69, 54, 88, 227, 6, 43, 248, 36, 191, 157, 200, 209, 170, 189, 46, 203, 128, 37, 247, 62, 31, 116, 145, 11, 91, 150, 186, 252, 188, 28, 195, 202, 242, 240, 5, 204, 27, 102, 36, 94, 55, 244, 238, 9, 199, 126, 145, 192, 77, 88, 154, 197, 74, 186, 94, 81, 172, 19, 213, 130, 78, 98, 160, 53, 199, 70, 150, 17, 167, 36, 138, 239, 164, 89, 252, 210, 188, 230, 252, 180, 138, 105, 82, 71, 221, 160, 48, 40, 54, 168, 39, 153, 124, 210, 125, 202, 57, 145, 202, 186, 49, 218, 153, 18, 230, 234, 222, 250, 125, 160, 11, 228, 185, 111, 15, 183, 24, 54, 112, 220, 188, 185, 132, 199, 20, 9, 81, 53, 195, 100, 208, 40, 167, 241, 8, 215, 70, 112, 245, 242, 210, 225, 54, 113, 80, 45, 123, 44, 8, 54, 64, 21, 176, 55, 26, 47, 197, 145, 107, 144, 28, 110, 182, 27, 0, 1, 47, 166, 244, 61, 0, 10, 116, 36, 106, 85, 214, 49, 37, 215, 25, 113, 22, 34, 49, 194, 206, 54, 75, 250, 86, 72, 15, 180, 147, 202, 211, 42, 192, 83, 95, 133, 78, 13, 26, 51, 176, 183, 149, 132, 51, 13, 173, 190, 205, 236, 235, 28, 244, 110, 185, 136, 10, 52, 244, 24, 23, 202, 51, 101, 139, 150, 79, 118, 138, 55, 60, 90, 146, 20, 136, 15, 253, 103, 24, 159, 155, 229, 119, 121, 21, 60, 168, 62, 95, 95, 46, 230, 165, 224, 255, 68, 80, 233, 89, 185, 215, 238, 33, 186, 174, 233, 170, 65, 205, 66, 127, 30, 85, 119, 248, 136, 163, 213, 15, 159, 132, 160, 58, 4, 155, 47, 52, 166, 16, 195, 116, 156, 167, 25, 125, 160, 101, 29, 96, 11, 191, 192, 20, 96, 166, 203, 40, 233, 187, 197, 199, 27, 21, 152, 63, 26, 61, 148, 11, 101, 175, 137, 233, 155, 41, 178, 106, 177, 178, 138, 80, 93, 114, 47, 24, 166, 30, 109, 48, 54, 243, 44, 214, 250, 146, 62, 145, 212, 244, 227, 10, 68, 35, 137, 172, 242, 219, 175, 173, 66, 92, 87, 110, 244, 41, 10, 67, 161, 217, 164, 140, 199, 197, 195, 20, 165, 89, 133, 9, 128, 171, 67, 127, 142, 207, 60, 0, 69, 127, 52, 26, 222, 36, 254, 236, 223, 172, 209, 155, 199, 13, 241, 158, 249, 196, 185, 173, 37, 195, 94, 15, 183, 129, 51, 81, 28, 244, 179, 196, 200, 248, 33, 72, 202, 238, 176, 25, 197, 83, 42, 224, 214, 41, 11, 187, 211, 100, 57, 245, 80, 135, 213, 174, 58, 16, 1, 98, 13, 162, 178, 13, 61, 55, 165, 150, 209, 62, 115, 88, 178, 168, 2, 245, 21, 231, 221, 84, 131, 243, 0, 99, 193, 157, 227, 244, 41, 47, 127, 151, 23, 30, 83, 189, 104, 239, 97, 111, 79, 213, 165, 19, 75, 237, 148, 161, 132, 81, 29, 197, 193, 199, 119, 189, 102, 227, 122, 38, 110, 186, 178, 234, 41, 116, 127, 123, 65, 110, 128, 171, 65, 10, 156, 131, 186, 49, 112, 22, 189, 222, 27, 95, 65, 233, 51, 151, 52, 43, 185, 171, 194, 108, 200, 196, 8, 77, 238, 81, 37, 195, 19, 220, 248, 177, 227, 141, 76, 1, 150, 158, 187, 133, 49, 147, 64, 151, 48, 212, 97, 241, 153, 118, 8, 253, 119, 125, 8, 136, 228, 54, 174, 147, 63, 68, 219, 79, 5, 56, 43, 16, 144, 47, 79, 171, 180, 66, 142, 186, 132, 44, 50, 172, 44, 118, 96, 150, 161, 174, 218, 68, 217, 94, 113, 33, 49, 116, 13, 161, 46, 48, 206, 28, 53, 200, 208, 243, 104, 97, 204, 186, 126, 153, 70, 141, 149, 28, 189, 206, 100, 101, 179, 183, 106, 15, 243, 49, 90, 119, 183, 222, 49, 244, 50, 218, 16, 186, 19, 153, 141, 2, 210, 227, 45, 191, 60, 50, 226, 254, 160, 109, 3, 24, 189, 138, 220, 230, 73, 51, 61, 238, 228, 242, 183, 71, 166, 59, 183, 32, 223, 40, 233, 218, 48, 2, 215, 103, 222, 229, 8, 134, 145, 136, 143, 66, 139, 95, 212, 59, 173, 225, 105, 138, 189, 234, 113, 174, 7, 232, 207, 226, 74, 50, 247, 212, 76, 237, 177, 103, 145, 92, 3, 41, 13, 139, 149, 187, 128, 43, 202, 130, 94, 25, 82, 250, 220, 192, 164, 148, 221, 98, 94, 105, 178, 60, 20, 142, 231, 23, 76, 136, 12, 85, 180, 85, 75, 134, 195, 147, 194, 211, 59, 183, 85, 127, 123, 195, 153, 201, 197, 37, 212, 160, 39, 68, 229, 244, 71, 79, 248, 77, 84, 130, 71, 155, 4, 141, 158, 211, 173, 62, 87, 146, 15, 3, 122, 154, 175, 34, 158, 255, 137, 84, 218, 30, 59, 182, 59, 193, 92, 13, 174, 243, 178, 227, 194, 228, 41, 12, 121, 71, 170, 15, 201, 10, 155, 108, 48, 122, 69, 246, 158, 192, 155, 67, 100, 254, 16, 151, 85, 69, 24, 6, 254, 13, 94, 134, 144, 16, 5, 112, 80, 235, 159, 73, 15, 87, 114, 216, 36, 8, 168, 11, 215, 188, 210, 243, 85, 78, 96, 27, 242, 83, 32, 207, 27, 191, 176, 75, 76, 50, 200, 104, 154, 228, 203, 31, 232, 105, 79, 78, 89, 63, 146, 52, 108, 114, 8, 186, 201, 229, 162, 179, 214, 46, 177, 173, 146, 84, 73, 21, 79, 22, 137, 187, 240, 72, 47, 88, 165, 195, 244, 133, 27, 252, 218, 149, 50, 231, 92, 253, 198, 255, 51, 214, 53, 147, 189, 100, 71, 174, 39, 17, 247, 177, 185, 8, 181, 160, 139, 211, 223, 172, 33, 73, 116, 108, 182, 248, 82, 39, 215, 136, 26, 141, 159, 226, 129, 99, 232, 155, 174, 28, 115, 117, 119, 231, 30, 173, 235, 156, 13, 161, 1, 52, 174] }), destination_options: Some(Ipv6RawExtHeader { next_header: 44 (IPv6-Frag - Fragment Header for IPv6), payload: [32, 35, 195, 46, 88, 189, 22, 199, 230, 162, 123, 89, 66, 218, 24, 103, 194, 32, 107, 137, 196, 98, 188, 82, 148, 190, 188, 13, 7, 214, 106, 129, 158, 134, 232, 135, 109, 7, 40, 241, 74, 227, 139, 81, 143, 182, 224, 235, 137, 14, 81, 157, 200, 186, 195, 164, 166, 184, 143, 252, 54, 118, 10, 11, 253, 83, 239, 71, 139, 127, 25, 28, 91, 186, 238, 170, 141, 38, 47, 164, 229, 109, 243, 71, 182, 25, 136, 223, 183, 40, 91, 105, 9, 169, 64, 149, 69, 103, 60, 81, 192, 20, 161, 114, 111, 222, 211, 64, 255, 79, 20, 28, 205, 59, 6, 58, 243, 42, 228, 120, 180, 47, 106, 177, 89, 25, 53, 159, 172, 159, 96, 119, 139, 68, 27, 234, 249, 37, 174, 0, 78, 138, 48, 181, 7, 58, 62, 134, 209, 152, 63, 7, 167, 33, 48, 0, 204, 240, 31, 135, 59, 245, 179, 144, 36, 71, 18, 25, 132, 86, 133, 135, 186, 30, 198, 189, 95, 143, 189, 141, 108, 134, 202, 110, 171, 178, 92, 230, 238, 255, 155, 7, 233, 217, 134, 190, 33, 127, 176, 90, 11, 146, 61, 11, 79, 196, 173, 41, 88, 125, 15, 124, 8, 68, 88, 145, 171, 125, 177, 115, 162, 157, 127, 171, 41, 209, 86, 179, 79, 69, 28, 197, 177, 11, 211, 170, 162, 45, 123, 46, 59, 112, 11, 132, 84, 167, 203, 152, 42, 204, 198, 204, 248, 88, 61, 195, 248, 241, 145, 19, 231, 207, 226, 95, 130, 216, 147, 124, 19, 2, 55, 69, 223, 30, 178, 166, 99, 76, 122, 6, 136, 36, 19, 123, 147, 144, 105, 205, 243, 85, 216, 117, 77, 151, 122, 1, 161, 20, 133, 47, 0, 23, 127, 205, 49, 146, 136, 12, 98, 52, 141, 4, 237, 120, 230, 103, 248, 181, 37, 105, 127, 1, 174, 183, 137, 187, 134, 119, 102, 124, 195, 229, 3, 111, 49, 203, 33, 22, 18, 110, 11, 163, 202, 92, 158, 15, 187, 172, 222, 135, 79, 72, 178, 135, 131, 248, 213, 21, 243, 106, 98, 144, 114, 194, 103, 175, 69, 182, 57, 15, 93, 146, 221, 86, 173, 19, 112, 155, 52, 74, 82, 104, 174, 125, 47, 203, 64, 77, 230, 90, 110, 37, 36, 254, 210, 96, 29, 161, 124, 195, 83, 164, 43, 200, 101, 65] }), routing: None, fragment: Some(Ipv6FragmentHeader { next_header: 51 (AH - Authentication Header), fragment_offset: IpFragOffset(40), more_fragments: false, identification: 936320599 }), auth: Some(IpAuthHeader { next_header: 50 (ESP - Encap Security Payload), spi: 1791434917, sequence_number: 265966117, raw_icv: [226, 4, 122, 88, 130, 221, 201, 80, 210, 94, 96, 230, 244, 224, 150, 80, 90, 103, 75, 80, 142, 100, 22, 49, 19, 18, 103, 246, 4, 136, 202, 81, 234, 216, 135, 16, 59, 70, 188, 72, 16, 69, 103, 133, 58, 104, 118, 132, 203, 4, 197, 196, 209, 61, 43, 216, 193, 158, 252, 235, 62, 176, 46, 22, 85, 121, 196, 55, 203, 99, 107, 202, 139, 163, 4, 43, 215, 57, 61, 135, 76, 79, 100, 179, 207, 129, 248, 136, 109, 67, 122, 133, 83, 221, 197, 195, 207, 30, 196, 26, 122, 186, 45, 90, 27, 145, 130, 62, 159, 10, 18, 250, 179, 135, 90, 159, 56, 160, 141, 78, 234, 181, 54, 177, 30, 122, 102, 236, 57, 143, 72, 148, 169, 129, 165, 114, 216, 73, 88, 62, 207, 82, 87, 241, 130, 203, 224, 142, 244, 149, 108, 61, 147, 60, 45, 129, 140, 184, 248, 87, 128, 163, 202, 235, 5, 215, 128, 67, 251, 220, 80, 196, 27, 25, 114, 119, 216, 197, 29, 212, 42, 18, 143, 89, 7, 247, 195, 83, 206, 210, 81, 214, 42, 59, 42, 130, 98, 192, 168, 195, 208, 68, 155, 172, 68, 69, 214, 85, 223, 245, 217, 63, 159, 119, 114, 250, 162, 118, 227, 52, 135, 81, 254, 127, 79, 91, 236, 233, 41, 194, 143, 216, 26, 116, 33, 163, 141, 4, 218, 81, 169, 168, 223, 212, 84, 75, 241, 47, 148, 84, 170, 192, 125, 251, 4, 131, 113, 185, 170, 168, 243, 250, 238, 179, 55, 77, 112, 231, 69, 109, 232, 134, 1, 33, 46, 205, 222, 34, 75, 161, 47, 132, 19, 253, 16, 76, 213, 108, 218, 211, 25, 136, 167, 246, 153, 246, 40, 30, 238, 57, 153, 123, 156, 86, 131, 132, 40, 220, 143, 242, 217, 198, 197, 236, 155, 15, 142, 157, 24, 204, 2, 222, 185, 172, 224, 226, 91, 159, 15, 16, 197, 136, 229, 78, 78, 198, 54, 7, 255, 197, 179, 160, 176, 177, 50, 55, 28, 32, 203, 232, 251, 177, 129, 92, 29, 185, 90, 69, 125, 146, 205, 109, 51, 35, 75, 233, 189, 10, 133, 177, 73, 14, 65, 151, 56, 152, 214, 74, 139, 135, 139, 17, 108, 66, 201, 87, 117, 52, 37, 76, 247, 158, 129, 84, 28, 248, 46, 32, 115, 4, 94, 0, 244, 14, 245, 68, 38, 142, 6, 47, 6, 224, 158, 18, 95, 142, 250, 64, 229, 178, 176, 251, 50, 182, 245, 206, 90, 184, 111, 198, 240, 81, 177, 44, 78, 169, 175, 170, 135, 207, 192, 171, 199, 228, 164, 111, 18, 53, 253, 123, 38, 44, 175, 190, 78, 113, 65, 146, 97, 180, 141, 90, 160, 227, 222, 46, 156, 64, 42, 104, 216, 208, 114, 2, 181, 123, 194, 176, 188, 122, 235, 223, 224, 74, 157, 182, 84, 172, 150, 234, 99, 166, 39, 103, 242, 247, 219, 75, 223, 92, 154, 54, 80, 238, 226, 18, 17, 81, 108, 162, 87, 51, 128, 239, 96, 174, 56, 51, 122, 130, 143, 178, 140, 188, 153, 141, 120, 4, 183, 54, 42, 87, 158, 20, 182, 136, 248, 40, 154, 108, 116, 143, 167, 140, 77, 136, 212, 23, 29, 218, 246, 248, 129, 103, 33, 99, 195, 33, 13, 56, 64, 230, 120, 141, 99, 102, 102, 37, 236, 166, 214, 165, 235, 52, 104, 22, 229, 182, 167, 107, 251, 158, 192, 184, 7, 13, 245, 144, 39, 201, 228, 99, 92, 49, 182, 183, 195, 101, 35, 221, 59, 253, 174, 138, 130, 87, 167, 231, 233, 117, 244, 39, 187, 98, 254, 13, 210, 71, 236, 231, 166, 108, 172, 157, 216, 176, 180, 210, 181, 195, 86, 135, 86, 73, 56, 249, 192, 135, 242, 237, 216, 74, 173, 153, 12, 204, 187, 143, 83, 118, 243, 110, 115, 190, 151, 193, 229, 2, 88, 190, 87, 81, 35, 14, 161, 112, 126, 69, 134, 55, 18, 201, 217, 9, 189, 223, 205, 149, 231, 44, 132, 24, 78, 1, 191, 34, 43, 122, 200, 83, 124, 98, 99, 21, 118, 217, 215, 181, 129, 38, 177, 231, 251, 206, 149, 119, 177, 246, 198, 95, 50, 131, 253, 147, 97, 75, 132, 96, 64, 88, 182, 56, 193, 142, 147, 198, 62, 190, 157, 230, 229, 35, 193, 150, 46, 88, 250, 176, 190, 152, 239, 129, 162, 208, 38, 204, 42, 11, 118, 69, 82, 159, 60, 192, 82, 69, 57, 81, 45, 63, 106, 129, 200, 70, 234, 232, 252, 230, 87, 122, 17, 83, 147, 7, 255, 195, 30, 22, 246, 238, 139, 155, 59, 219, 75, 176, 174, 135, 176, 86, 12, 6, 161, 96, 112, 119, 226, 90, 144, 38, 248, 39, 170, 9, 183, 76, 227, 22, 162, 241, 140, 31, 62, 134, 157, 28, 72, 154, 128, 47, 30, 93, 184, 234, 163, 117, 10, 47, 30, 174, 53, 247, 20, 142, 66, 87, 22, 152, 208, 79, 240, 92, 45, 156, 43, 175, 81, 122, 48, 155, 190, 155, 25, 188, 231, 135, 192, 234, 227, 237, 240, 41, 125, 28, 209, 125, 74, 76, 241, 81, 212, 255, 255, 20, 68, 137, 24, 100, 128, 25, 50, 180, 168, 154, 114, 205, 45, 3, 174, 21, 4, 220, 135, 233, 62, 215, 141, 123, 223, 19, 125, 9, 143, 19, 60, 98, 183, 219, 95, 45, 234, 188, 253, 112, 172, 187, 240, 193, 124, 201, 174, 21, 55, 220, 35, 113, 245, 76, 160, 174, 56, 255, 2, 242, 69, 206, 165, 79, 245, 98, 66, 100, 92, 20, 140, 133, 37, 152, 221, 124, 43, 242, 116, 153, 82, 21, 120, 145, 106, 218, 47, 131, 244, 98, 18, 177, 186, 102, 221, 164, 13, 220, 210, 251, 199, 183, 204, 93, 203, 122] }) }, ref udp = UdpHeader { source_port: 37417, destination_port: 9108, length: 55031, checksum: 30539 }, ref tcp = TcpHeader { source_port: 890, destination_port: 63900, sequence_number: 1007304455, acknowledgment_number: 4179598739, ns: false, fin: false, syn: false, rst: true, psh: true, ack: true, urg: true, ece: false, cwr: false, window_size: 26948, checksum: 44775, urgent_pointer: 49253, options: [Err(UnknownId(91))] }, ref icmpv4 = Icmpv4Header { icmp_type: Unknown { type_u8: 115, code_u8: 63, bytes5to8: [197, 108, 248, 120] }, checksum: 2225 }, ref icmpv6 = Icmpv6Header { icmp_type: Unknown { type_u8: 78, code_u8: 128, bytes5to8: [71, 156, 20, 196] }, checksum: 11773 }, ref payload = [167, 22, 235, 99, 149, 6, 145, 225, 240, 172, 90, 57, 224, 202, 18, 160, 59, 126, 6, 142, 246, 221, 178, 142, 119, 149, 118, 24, 85, 202, 49, 206, 46, 138, 89, 120, 205, 44, 146, 68, 109, 183, 62, 194, 214, 224, 242, 51, 244, 121, 41, 30, 100, 88, 113, 252, 247, 30, 5, 51, 65, 174, 180, 40, 186, 204, 107, 12, 94, 171, 77, 238, 219, 1, 48, 192, 233, 160, 118, 122, 231, 175, 205, 222, 71, 3, 152, 89, 179, 124, 235, 147, 214, 240, 151, 170, 249, 41, 219, 41, 174, 39, 72, 81, 93, 33, 92, 38, 81, 230, 203, 184, 62, 40, 164, 56, 17, 246, 208, 119, 53, 119, 56, 57, 208, 123, 242, 126, 113, 173, 155, 254, 34, 97, 224, 150, 30, 183, 26, 88, 233, 142, 107, 189, 73, 181, 188, 88, 191, 151, 196, 115, 94, 128, 216, 121, 206, 65, 184, 150, 7, 85, 157, 169, 48, 0, 91, 59, 140, 20, 61, 231, 19, 43, 25, 8, 45, 153, 139, 171, 203, 72, 129, 96, 125, 200, 107, 24, 66, 116, 196, 166, 70, 84, 100, 252, 148, 198, 140, 190, 179, 227, 171, 217, 73, 201, 196, 252, 103, 198, 139, 22, 44, 141, 44, 49, 115, 210, 114, 152, 85, 78, 192, 14, 153, 14, 216, 154, 194, 198, 148, 217, 216, 28, 163, 245, 132, 125, 198, 159, 156, 92, 241, 20, 198, 42, 79, 230, 130, 38, 126, 161, 11, 92, 79, 203, 0, 104, 164, 106, 146, 111, 205, 110, 59, 18, 211, 10, 1, 215, 152, 28, 161, 31, 213, 126, 52, 199, 37, 225, 26, 181, 172, 222, 157, 154, 89, 215, 89, 91, 22, 86, 209, 30, 49, 149, 245, 117, 42, 128, 12, 38, 228, 11, 123, 4, 20, 233, 167, 243, 162, 158, 85, 20, 26, 13, 56, 54, 140, 115, 124, 233, 205, 48, 216, 209, 24, 245, 201, 81, 124, 205, 226, 125, 168, 248, 160, 149, 105, 214, 105, 200, 88, 229, 231, 148, 61, 84, 108, 111, 227, 248, 41, 155, 141, 56, 50, 10, 62, 239, 227, 153, 54, 253, 167, 244, 2, 96, 251, 214, 151, 51, 26, 240, 151, 251, 49, 68, 199, 115, 158, 72, 220, 201, 221, 238, 235, 163, 62, 221, 143, 228, 206, 176, 232, 134, 88, 55, 239, 9, 16, 20, 170, 132, 185, 192, 183, 227, 25, 192, 190, 109, 197, 130, 244, 221, 246, 129, 185, 45, 83, 250, 230, 19, 17, 167, 53, 2, 58, 206, 250, 223, 172, 35, 161, 236, 241, 62, 48, 120, 252, 211, 64, 57, 197, 163, 207, 224, 97, 67, 98, 225, 232, 193, 3, 173, 63, 83, 208, 180, 85, 133, 217, 177, 127, 4, 83, 113, 190, 79, 44, 36, 135, 204, 213, 181, 92, 154, 81, 8, 96, 191, 91, 5, 156, 218, 86, 145, 145, 223, 3, 111, 113, 118, 201, 40, 188, 31, 173, 75, 75, 239, 52, 253, 125, 88, 33, 169, 110, 187, 46, 103, 172, 70, 65, 160, 214, 149, 119, 36, 247, 215, 247, 91, 174, 111, 33, 180, 116, 196, 18, 142, 170, 40, 254, 155, 252, 96, 233, 59, 227, 218, 60, 219, 50, 183, 191, 19, 217, 175, 91, 226, 201, 246, 119, 151, 30, 179, 161, 243, 140, 221, 241, 144, 7, 80, 218, 64, 130, 44, 149, 253, 30, 64, 102, 58, 7, 184, 195, 16, 22, 127, 220, 129, 169, 45, 227, 162, 222, 144, 129, 10, 214, 191, 198, 12, 226, 227, 96, 96, 206, 101, 42, 110, 187, 140, 235, 160, 180, 201, 233, 146, 73, 67, 88, 81, 159, 116, 121, 73, 152, 161, 155, 241, 104, 71, 192, 252, 199, 162, 135, 203, 243, 38, 156, 198, 220, 13, 77, 57, 78, 40, 30, 127, 227, 104, 95, 81, 58, 156, 141, 193, 142, 36, 243, 57, 42, 43, 255, 72, 3, 101, 2, 124, 126, 77, 225, 190, 211, 134, 82, 180, 50, 0, 160, 155, 232, 219, 242, 36, 57, 46, 165, 60, 68, 123, 196, 144, 153, 209, 191, 62, 224, 188, 250, 211, 179, 157, 71, 164, 218, 132, 202, 63, 21, 83, 68, 132, 213, 204, 189, 169, 126, 242, 176, 93, 211, 209, 164, 134, 153, 161, 22, 134, 197, 184, 105, 191, 186, 152, 145, 133, 119, 183, 65, 55, 248, 204, 31, 28, 172, 85, 228, 86, 235, 47, 63, 235, 254, 93, 132, 86, 70, 233, 216, 2, 63, 26, 82, 45, 10, 182, 171, 13, 142, 142, 154, 50, 15, 133, 65, 137, 197, 3, 209, 20, 126, 93, 195, 249, 135, 44, 114, 55, 115, 33, 231, 195, 252, 42, 143, 181, 34, 52, 2, 183, 132, 124, 255, 83, 13, 19, 99, 236, 138, 64, 54, 176, 106, 29, 46, 222, 141, 142, 26, 167, 207, 104, 82, 178, 150, 26, 2, 59, 105, 37, 10, 229, 93, 30, 46, 204, 55, 56, 4, 29, 8, 212, 178, 77, 221, 53, 222, 191, 172, 85, 127, 159, 44, 73, 37, 251, 153, 173, 134, 13, 224, 164, 23, 35, 153, 190, 22, 22, 52, 28, 6, 28, 112, 117, 123, 216, 141, 98, 47, 140, 113, 1, 84, 236, 144, 94, 7, 71, 16, 196, 144, 96, 129, 29, 209, 66, 237, 67, 224, 10, 16, 160, 244, 217, 145, 241, 58, 83, 30, 77, 179, 140, 124, 243, 97, 121, 10, 54, 1, 30, 11, 116, 127, 188, 15, 122, 29, 133, 100, 178, 110, 201, 188, 63, 216, 168, 30, 6, 55, 127, 57, 255, 158, 222, 190, 110, 23, 36, 64, 230, 20, 155, 114, 16, 4, 60, 7, 71, 18, 44, 110, 66, 47, 217, 153, 202, 72, 66, 158, 204, 97, 44, 107, 172]
diff --git a/crates/etherparse/proptest-regressions/net/arp_eth_ipv4_packet.txt b/crates/etherparse/proptest-regressions/net/arp_eth_ipv4_packet.txt
new file mode 100644
index 0000000..3642797
--- /dev/null
+++ b/crates/etherparse/proptest-regressions/net/arp_eth_ipv4_packet.txt
@@ -0,0 +1,7 @@
+# Seeds for failure cases proptest has generated in the past. It is
+# automatically read and these particular cases re-run before any
+# novel cases are generated.
+#
+# It is recommended to check this file in to source control so that
+# everyone who runs the test benefits from these saved cases.
+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] }
diff --git a/crates/etherparse/proptest-regressions/net/arp_packet.txt b/crates/etherparse/proptest-regressions/net/arp_packet.txt
new file mode 100644
index 0000000..e7850cf
--- /dev/null
+++ b/crates/etherparse/proptest-regressions/net/arp_packet.txt
@@ -0,0 +1,7 @@
+# Seeds for failure cases proptest has generated in the past. It is
+# automatically read and these particular cases re-run before any
+# novel cases are generated.
+#
+# It is recommended to check this file in to source control so that
+# everyone who runs the test benefits from these saved cases.
+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] }
diff --git a/crates/etherparse/proptest-regressions/net/arp_packet_slice.txt b/crates/etherparse/proptest-regressions/net/arp_packet_slice.txt
new file mode 100644
index 0000000..b74c5a8
--- /dev/null
+++ b/crates/etherparse/proptest-regressions/net/arp_packet_slice.txt
@@ -0,0 +1,7 @@
+# Seeds for failure cases proptest has generated in the past. It is
+# automatically read and these particular cases re-run before any
+# novel cases are generated.
+#
+# It is recommended to check this file in to source control so that
+# everyone who runs the test benefits from these saved cases.
+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] }
diff --git a/crates/etherparse/src/compositions_tests.rs b/crates/etherparse/src/compositions_tests.rs
index fd04b69..ba3dd8e 100644
--- a/crates/etherparse/src/compositions_tests.rs
+++ b/crates/etherparse/src/compositions_tests.rs
@@ -8,7 +8,7 @@
struct ComponentTest {
link: Option<LinkHeader>,
vlan: Option<VlanHeader>,
- ip: Option<IpHeaders>,
+ net: Option<NetHeaders>,
transport: Option<TransportHeader>,
payload: Vec<u8>,
}
@@ -28,7 +28,7 @@
} + match &self.vlan {
Some(header) => header.header_len(),
None => 0,
- } + match &self.ip {
+ } + match &self.net {
Some(headers) => headers.header_len(),
None => 0,
} + match &self.transport {
@@ -48,15 +48,18 @@
Some(Double(header)) => header.write(&mut buffer).unwrap(),
None => {}
}
- match &self.ip {
- Some(IpHeaders::Ipv4(header, exts)) => {
+ match &self.net {
+ Some(NetHeaders::Ipv4(header, exts)) => {
header.write_raw(&mut buffer).unwrap();
exts.write(&mut buffer, header.protocol).unwrap();
}
- Some(IpHeaders::Ipv6(header, exts)) => {
+ Some(NetHeaders::Ipv6(header, exts)) => {
header.write(&mut buffer).unwrap();
exts.write(&mut buffer, header.next_header).unwrap();
}
+ Some(NetHeaders::Arp(arp)) => {
+ arp.write(&mut buffer).unwrap();
+ }
None => {}
}
match &self.transport {
@@ -84,9 +87,9 @@
let mut test = self.clone();
// set the payload length
- if let Some(ip) = test.ip.as_mut() {
- match ip {
- IpHeaders::Ipv4(ipv4, exts) => {
+ if let Some(net) = test.net.as_mut() {
+ match net {
+ NetHeaders::Ipv4(ipv4, exts) => {
ipv4.set_payload_len(
exts.header_len()
+ self.transport.as_ref().map_or(0, |t| t.header_len())
@@ -94,7 +97,7 @@
)
.unwrap();
}
- IpHeaders::Ipv6(ipv6, exts) => {
+ NetHeaders::Ipv6(ipv6, exts) => {
ipv6.set_payload_length(
exts.header_len()
+ self.transport.as_ref().map_or(0, |t| t.header_len())
@@ -102,6 +105,7 @@
)
.unwrap();
}
+ NetHeaders::Arp(_) => {}
}
}
if let Some(TransportHeader::Udp(udp)) = test.transport.as_mut() {
@@ -176,7 +180,7 @@
}
// packet from the internet layer down (without ethernet2 & vlan headers)
- if test.ip.is_some() {
+ if test.net.as_ref().map(|v| v.is_ip()).unwrap_or(false) {
// serialize from the ip layer downwards
let ip_down = {
let mut ip_down = test.clone();
@@ -240,9 +244,9 @@
}
}
}
- if let Some(ip) = self.ip.as_ref() {
- use IpHeaders::*;
- match ip {
+ if let Some(net) = self.net.as_ref() {
+ use NetHeaders::*;
+ match net {
Ipv4(header, exts) => {
builder.add(header.header_len());
if let Some(auth) = exts.auth.as_ref() {
@@ -270,6 +274,9 @@
builder.add(e.header_len());
}
}
+ Arp(arp) => {
+ builder.add(arp.packet_len());
+ }
}
}
if let Some(transport) = self.transport.as_ref() {
@@ -282,7 +289,7 @@
fn assert_headers(&self, actual: PacketHeaders) {
assert_eq!(self.link, actual.link);
assert_eq!(self.vlan, actual.vlan);
- assert_eq!(self.ip, self.ip);
+ assert_eq!(self.net, self.net);
assert_eq!(self.transport, actual.transport);
assert_eq!(self.payload[..], actual.payload.slice()[..]);
}
@@ -307,16 +314,16 @@
assert_eq!(self.vlan, result.vlan.as_ref().map(|ref x| x.to_header()));
//ip
- assert_eq!(self.ip, {
+ assert_eq!(self.net, {
use crate::NetSlice::*;
match result.net.as_ref() {
- Some(Ipv4(actual)) => Some(IpHeaders::Ipv4(
+ Some(Ipv4(actual)) => Some(NetHeaders::Ipv4(
actual.header().to_header(),
Ipv4Extensions {
auth: actual.extensions().auth.map(|ref x| x.to_header()),
},
)),
- Some(Ipv6(actual)) => Some(IpHeaders::Ipv6(
+ Some(Ipv6(actual)) => Some(NetHeaders::Ipv6(
actual.header().to_header(),
Ipv6Extensions::from_slice(
actual.header().next_header(),
@@ -325,6 +332,7 @@
.unwrap()
.0,
)),
+ Some(Arp(arp)) => Some(NetHeaders::Arp(arp.to_packet())),
None => None,
}
});
@@ -372,6 +380,7 @@
match ip {
NetSlice::Ipv4(s) => s.payload.payload,
NetSlice::Ipv6(s) => s.payload.payload,
+ NetSlice::Arp(_) => &[],
}
);
} else {
@@ -391,6 +400,7 @@
&self,
outer_vlan: &SingleVlanHeader,
inner_vlan: &SingleVlanHeader,
+ arp: &ArpPacket,
ipv4: &Ipv4Header,
ipv4_ext: &Ipv4Extensions,
ipv6: &Ipv6Header,
@@ -429,12 +439,14 @@
//single
setup_single(inner_vlan.ether_type).run();
+ setup_single(ether_type::ARP).run_arp(arp);
setup_single(ether_type::IPV4).run_ipv4(ipv4, ipv4_ext, udp, tcp, icmpv4, icmpv6);
setup_single(ether_type::IPV6).run_ipv6(ipv6, ipv6_ext, udp, tcp, icmpv4, icmpv6);
//double
for ether_type in VLAN_ETHER_TYPES {
setup_double(*ether_type, inner_vlan.ether_type).run();
+ setup_double(*ether_type, ether_type::ARP).run_arp(arp);
setup_double(*ether_type, ether_type::IPV4)
.run_ipv4(ipv4, ipv4_ext, udp, tcp, icmpv4, icmpv6);
setup_double(*ether_type, ether_type::IPV6)
@@ -442,6 +454,13 @@
}
}
+ fn run_arp(&self, arp: &ArpPacket) {
+ let mut test = self.clone();
+ test.net = Some(NetHeaders::Arp(arp.clone()));
+ test.payload.clear();
+ test.run();
+ }
+
fn run_ipv4(
&self,
ip: &Ipv4Header,
@@ -454,14 +473,14 @@
// fragmenting
{
let mut test = self.clone();
- test.ip = Some({
+ test.net = Some({
let mut frag = ip.clone();
if false == frag.is_fragmenting_payload() {
frag.more_fragments = true;
}
- let mut header = IpHeaders::Ipv4(frag, ip_exts.clone());
- header.set_next_headers(ip.protocol);
- header
+ let mut ip_exts = ip_exts.clone();
+ frag.protocol = ip_exts.set_next_headers(ip.protocol);
+ NetHeaders::Ipv4(frag, ip_exts.clone())
});
// run without transport header
@@ -471,13 +490,13 @@
// non fragmenting
{
let mut test = self.clone();
- test.ip = Some({
+ test.net = Some({
let mut non_frag = ip.clone();
non_frag.more_fragments = false;
non_frag.fragment_offset = 0.try_into().unwrap();
- let mut header = IpHeaders::Ipv4(non_frag, ip_exts.clone());
- header.set_next_headers(ip.protocol);
- header
+ let mut ip_exts = ip_exts.clone();
+ non_frag.protocol = ip_exts.set_next_headers(ip.protocol);
+ NetHeaders::Ipv4(non_frag, ip_exts)
});
test.run_transport(udp, tcp, icmpv4, icmpv6);
}
@@ -495,7 +514,7 @@
// fragmenting
{
let mut test = self.clone();
- test.ip = Some({
+ test.net = Some({
let mut frag = ip_exts.clone();
if let Some(frag) = frag.fragment.as_mut() {
if false == frag.is_fragmenting_payload() {
@@ -509,9 +528,9 @@
0,
));
}
- let mut header = IpHeaders::Ipv6(ip.clone(), frag);
- header.set_next_headers(ip.next_header);
- header
+ let mut ip = ip.clone();
+ ip.next_header = frag.set_next_headers(ip.next_header);
+ NetHeaders::Ipv6(ip, frag)
});
test.run();
}
@@ -519,12 +538,12 @@
// non fragmenting
{
let mut test = self.clone();
- test.ip = Some({
+ test.net = Some({
let mut non_frag = ip_exts.clone();
non_frag.fragment = None;
- let mut header = IpHeaders::Ipv6(ip.clone(), non_frag);
- header.set_next_headers(ip.next_header);
- header
+ let mut ip = ip.clone();
+ ip.next_header = non_frag.set_next_headers(ip.next_header);
+ NetHeaders::Ipv6(ip, non_frag)
});
test.run_transport(udp, tcp, icmpv4, icmpv6);
}
@@ -543,7 +562,11 @@
// udp
{
let mut test = self.clone();
- test.ip.as_mut().unwrap().set_next_headers(ip_number::UDP);
+ test.net
+ .as_mut()
+ .unwrap()
+ .try_set_next_headers(ip_number::UDP)
+ .unwrap();
test.transport = Some(TransportHeader::Udp(udp.clone()));
test.run()
}
@@ -551,7 +574,11 @@
// tcp
{
let mut test = self.clone();
- test.ip.as_mut().unwrap().set_next_headers(ip_number::TCP);
+ test.net
+ .as_mut()
+ .unwrap()
+ .try_set_next_headers(ip_number::TCP)
+ .unwrap();
test.transport = Some(TransportHeader::Tcp(tcp.clone()));
test.run()
}
@@ -559,14 +586,22 @@
// icmpv4
if let Some(payload_size) = icmpv4.fixed_payload_size() {
let mut test = self.clone();
- test.ip.as_mut().unwrap().set_next_headers(ip_number::ICMP);
+ test.net
+ .as_mut()
+ .unwrap()
+ .try_set_next_headers(ip_number::ICMP)
+ .unwrap();
test.transport = Some(TransportHeader::Icmpv4(icmpv4.clone()));
// resize the payload in case it does not have to be as big
test.payload.resize(payload_size, 0);
test.run()
} else {
let mut test = self.clone();
- test.ip.as_mut().unwrap().set_next_headers(ip_number::ICMP);
+ test.net
+ .as_mut()
+ .unwrap()
+ .try_set_next_headers(ip_number::ICMP)
+ .unwrap();
test.transport = Some(TransportHeader::Icmpv4(icmpv4.clone()));
test.run()
}
@@ -574,20 +609,22 @@
// icmpv6
if let Some(payload_size) = icmpv6.fixed_payload_size() {
let mut test = self.clone();
- test.ip
+ test.net
.as_mut()
.unwrap()
- .set_next_headers(ip_number::IPV6_ICMP);
+ .try_set_next_headers(ip_number::IPV6_ICMP)
+ .unwrap();
test.transport = Some(TransportHeader::Icmpv6(icmpv6.clone()));
// resize the payload in case it does not have to be as big
test.payload.resize(payload_size, 0);
test.run()
} else {
let mut test = self.clone();
- test.ip
+ test.net
.as_mut()
.unwrap()
- .set_next_headers(ip_number::IPV6_ICMP);
+ .try_set_next_headers(ip_number::IPV6_ICMP)
+ .unwrap();
test.transport = Some(TransportHeader::Icmpv6(icmpv6.clone()));
test.run()
}
@@ -605,6 +642,7 @@
ref ipv4_exts in ipv4_extensions_unknown(),
ref ipv6 in ipv6_unknown(),
ref ipv6_exts in ipv6_extensions_unknown(),
+ ref arp in arp_packet_any(),
ref udp in udp_any(),
ref tcp in tcp_any(),
ref icmpv4 in icmpv4_header_any(),
@@ -620,19 +658,20 @@
LinkHeader::Ethernet2(result)
}),
vlan: None,
- ip: None,
+ net: None,
transport: None
}
};
//ethernet 2: standalone, ipv4, ipv6
setup_eth(eth.ether_type).run();
+ setup_eth(ether_type::ARP).run_arp(arp);
setup_eth(ether_type::IPV4).run_ipv4(ipv4, ipv4_exts, udp, tcp, icmpv4, icmpv6);
setup_eth(ether_type::IPV6).run_ipv6(ipv6, ipv6_exts, udp, tcp, icmpv4, icmpv6);
//vlans
for ether_type in VLAN_ETHER_TYPES {
- setup_eth(*ether_type).run_vlan(vlan_outer, vlan_inner, ipv4, ipv4_exts, ipv6, ipv6_exts, udp, tcp, icmpv4, icmpv6);
+ setup_eth(*ether_type).run_vlan(vlan_outer, vlan_inner, arp, ipv4, ipv4_exts, ipv6, ipv6_exts, udp, tcp, icmpv4, icmpv6);
}
}
}
@@ -654,7 +693,7 @@
ether_type: 0.into(),
})),
vlan: None,
- ip: None,
+ net: None,
transport: None,
payload: vec![],
}
diff --git a/crates/etherparse/src/defrag/ip_defrag_pool.rs b/crates/etherparse/src/defrag/ip_defrag_pool.rs
index d7c2f19..c5d342d 100644
--- a/crates/etherparse/src/defrag/ip_defrag_pool.rs
+++ b/crates/etherparse/src/defrag/ip_defrag_pool.rs
@@ -12,7 +12,7 @@
///
/// # This implementation is NOT safe against "Out of Memory" attacks
///
-/// If you use the [`DefragPool`] in an untrusted environment an attacker could
+/// If you use the [`IpDefragPool`] in an untrusted environment an attacker could
/// cause an "out of memory error" by opening up multiple parallel TP streams,
/// never ending them and filling them up with as much data as possible.
///
@@ -143,7 +143,7 @@
false,
)
}
- None => {
+ Some(NetSlice::Arp(_)) | None => {
// nothing to defragment here, skip packet
return Ok(None);
}
@@ -385,7 +385,7 @@
&Ipv6Header {
traffic_class: 0,
flow_label: Default::default(),
- payload_length: (payload.len() + Ipv6FragmentHeader::LEN) as u16,
+ payload_length: (payload.len() + Ipv6FragmentHeader::LEN + 8) as u16,
next_header: IpNumber::IPV6_FRAGMENTATION_HEADER,
hop_limit: 2,
source,
@@ -395,13 +395,21 @@
);
buf.extend_from_slice(
&Ipv6FragmentHeader {
- next_header: id.payload_ip_number,
+ next_header: IpNumber::IPV6_ROUTE_HEADER,
fragment_offset: IpFragOffset::try_new(offset).unwrap(),
more_fragments: more,
identification,
}
.to_bytes(),
);
+ buf.extend_from_slice(
+ &{
+ let mut h: Ipv6RawExtHeader = Default::default();
+ h.next_header = id.payload_ip_number;
+ h
+ }
+ .to_bytes(),
+ );
}
}
buf.extend_from_slice(payload);
@@ -410,6 +418,22 @@
#[test]
fn process_sliced_packet() {
+ // non ip packet
+ {
+ let mut pool = IpDefragPool::<(), ()>::new();
+ let pslice = SlicedPacket {
+ link: None,
+ vlan: None,
+ net: None,
+ transport: None,
+ };
+ let v = pool.process_sliced_packet(&pslice, (), ());
+ assert_eq!(Ok(None), v);
+ assert_eq!(pool.active.len(), 0);
+ assert_eq!(pool.finished_data_bufs.len(), 0);
+ assert_eq!(pool.finished_section_bufs.len(), 0);
+ }
+
// v4 non fragmented
{
let mut pool = IpDefragPool::<(), ()>::new();
@@ -572,7 +596,25 @@
}
{
- let pdata = build_packet(frag_id.clone(), 1, false, &[9, 10]);
+ let pdata = build_packet(
+ frag_id.clone(),
+ 1,
+ true,
+ &[
+ 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ ],
+ );
+ let pslice = SlicedPacket::from_ethernet(&pdata).unwrap();
+ let v = pool.process_sliced_packet(&pslice, (), ());
+ assert_eq!(Ok(None), v);
+
+ // check the frag id was correctly calculated
+ assert_eq!(1, pool.active.len());
+ assert_eq!(pool.active.iter().next().unwrap().0, &frag_id);
+ }
+
+ {
+ let pdata = build_packet(frag_id.clone(), 3, false, &[25, 26]);
let pslice = SlicedPacket::from_ethernet(&pdata).unwrap();
let v = pool
.process_sliced_packet(&pslice, (), ())
@@ -594,7 +636,13 @@
LenSource::Ipv6HeaderPayloadLen
}
);
- assert_eq!(v.payload, &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
+ assert_eq!(
+ v.payload,
+ &[
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26
+ ]
+ );
// there should be nothing left
assert_eq!(pool.active.len(), 0);
@@ -610,6 +658,164 @@
}
}
}
+
+ // ipv6 no frag header
+ {
+ // build packet without ipv6
+ let pdata = {
+ let mut v = Vec::with_capacity(Ipv6Header::LEN + UdpHeader::LEN + 16);
+ v.extend_from_slice(
+ &Ipv6Header {
+ traffic_class: 0,
+ flow_label: Ipv6FlowLabel::try_new(0).unwrap(),
+ payload_length: UdpHeader::LEN_U16 + 16,
+ next_header: IpNumber::UDP,
+ hop_limit: 2,
+ source: [0; 16],
+ destination: [0; 16],
+ }
+ .to_bytes(),
+ );
+ v.extend_from_slice(
+ &UdpHeader {
+ source_port: 1234,
+ destination_port: 2345,
+ length: UdpHeader::LEN_U16 + 10,
+ checksum: 0,
+ }
+ .to_bytes(),
+ );
+ v.extend_from_slice(&[0; 16]);
+ v
+ };
+ let slice = SlicedPacket::from_ip(&pdata).unwrap();
+
+ let mut pool = IpDefragPool::<(), ()>::new();
+ assert_eq!(Ok(None), pool.process_sliced_packet(&slice, (), ()));
+ assert_eq!(pool.active.len(), 0);
+ assert_eq!(pool.finished_data_bufs.len(), 0);
+ assert_eq!(pool.finished_section_bufs.len(), 0);
+ }
+
+ // error in initial packet
+ {
+ let frag_ids = [
+ // v4
+ IpFragId {
+ outer_vlan_id: None,
+ inner_vlan_id: None,
+ ip: IpFragVersionSpecId::Ipv4 {
+ source: [1, 2, 3, 4],
+ destination: [5, 6, 7, 8],
+ identification: 9,
+ },
+ payload_ip_number: IpNumber::UDP,
+ channel_id: (),
+ },
+ // v6
+ IpFragId {
+ outer_vlan_id: None,
+ inner_vlan_id: None,
+ ip: IpFragVersionSpecId::Ipv6 {
+ source: [0; 16],
+ destination: [0; 16],
+ identification: 0,
+ },
+ payload_ip_number: IpNumber::UDP,
+ channel_id: (),
+ },
+ ];
+ let mut pool = IpDefragPool::<(), ()>::new();
+
+ for frag_id in frag_ids {
+ let pdata = build_packet(frag_id.clone(), 0, true, &[0; 7]);
+ let pslice = SlicedPacket::from_ethernet(&pdata).unwrap();
+ let v = pool.process_sliced_packet(&pslice, (), ());
+ assert_eq!(
+ Err(IpDefragError::UnalignedFragmentPayloadLen {
+ offset: IpFragOffset::try_new(0).unwrap(),
+ payload_len: 7
+ }),
+ v
+ );
+ assert_eq!(0, pool.active.len());
+ }
+ }
+
+ // error in followup packet
+ {
+ let frag_ids = [
+ // v4
+ IpFragId {
+ outer_vlan_id: None,
+ inner_vlan_id: None,
+ ip: IpFragVersionSpecId::Ipv4 {
+ source: [1, 2, 3, 4],
+ destination: [5, 6, 7, 8],
+ identification: 9,
+ },
+ payload_ip_number: IpNumber::UDP,
+ channel_id: (),
+ },
+ // v6
+ IpFragId {
+ outer_vlan_id: None,
+ inner_vlan_id: None,
+ ip: IpFragVersionSpecId::Ipv6 {
+ source: [0; 16],
+ destination: [0; 16],
+ identification: 0,
+ },
+ payload_ip_number: IpNumber::UDP,
+ channel_id: (),
+ },
+ ];
+
+ for frag_id in frag_ids {
+ let mut pool = IpDefragPool::<(), ()>::new();
+
+ // initial packet
+ {
+ let pdata = build_packet(frag_id.clone(), 0, true, &[1, 2, 3, 4, 5, 6, 7, 8]);
+ let pslice = SlicedPacket::from_ethernet(&pdata).unwrap();
+ let v = pool.process_sliced_packet(&pslice, (), ());
+ assert_eq!(Ok(None), v);
+
+ // check the frag id was correctly calculated
+ assert_eq!(1, pool.active.len());
+ assert_eq!(pool.active.iter().next().unwrap().0, &frag_id);
+ }
+
+ // follow up packet error
+ {
+ let pdata = build_packet(
+ frag_id.clone(),
+ 1,
+ true,
+ &[9, 10, 11, 12, 13, 14, 15, 16, 17],
+ );
+ let pslice = SlicedPacket::from_ethernet(&pdata).unwrap();
+ let v = pool.process_sliced_packet(&pslice, (), ());
+ assert_eq!(
+ Err(IpDefragError::UnalignedFragmentPayloadLen {
+ offset: IpFragOffset::try_new(1).unwrap(),
+ payload_len: 9
+ }),
+ v
+ );
+
+ // check the frag id was correctly calculated
+ assert_eq!(1, pool.active.len());
+ {
+ let p = pool.active.iter().next().unwrap();
+ assert_eq!(p.0, &frag_id);
+ assert_eq!(p.1 .0.data(), &[1, 2, 3, 4, 5, 6, 7, 8]);
+ assert_eq!(p.1 .0.sections()[0].start, 0);
+ assert_eq!(p.1 .0.sections()[0].end, 8);
+ }
+ }
+ }
+ }
}
#[test]
diff --git a/crates/etherparse/src/err/arp/arp_eth_ipv4_from_error.rs b/crates/etherparse/src/err/arp/arp_eth_ipv4_from_error.rs
new file mode 100644
index 0000000..b27fb21
--- /dev/null
+++ b/crates/etherparse/src/err/arp/arp_eth_ipv4_from_error.rs
@@ -0,0 +1,95 @@
+use crate::*;
+
+/// Error while converting an [`crate::ArpPacket`] to an [`crate::ArpEthIpv4Packet`].
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
+pub enum ArpEthIpv4FromError {
+ /// Error if `hw_addr_type` is not [`crate::ArpHardwareId::ETHERNET`].
+ NonMatchingHwType(ArpHardwareId),
+
+ /// Error if `proto_addr_type` is not [`crate::EtherType::IPV4`].
+ NonMatchingProtocolType(EtherType),
+
+ /// Error if `hw_addr_size` is not `6`
+ NonMatchingHwAddrSize(u8),
+
+ /// Error if `hw_addr_size` is not `6`
+ NonMatchingProtoAddrSize(u8),
+}
+
+impl core::fmt::Display for ArpEthIpv4FromError {
+ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ match self {
+ ArpEthIpv4FromError::NonMatchingHwType(t) =>
+ write!(f, "Hardware address type is expected to have the type '1 (Ethernet)' but is '{t:?}'"),
+ ArpEthIpv4FromError::NonMatchingProtocolType(t) =>
+ write!(f, "Protocol address type is expected to have the type '0x0800 (Internet Protocol version 4 (IPv4))' but is '{t:?}'"),
+ ArpEthIpv4FromError::NonMatchingHwAddrSize(len) =>
+ write!(f, "Hardware address size is expected to be 6 but is {len}"),
+ ArpEthIpv4FromError::NonMatchingProtoAddrSize(len) =>
+ write!(f, "Protocol address size is expected to be 4 but is {len}"),
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
+impl std::error::Error for ArpEthIpv4FromError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
+ None
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::{ArpEthIpv4FromError::*, ArpHardwareId, EtherType};
+ use alloc::format;
+ use std::{
+ collections::hash_map::DefaultHasher,
+ error::Error,
+ hash::{Hash, Hasher},
+ };
+
+ #[test]
+ fn debug() {
+ assert_eq!(
+ "NonMatchingProtoAddrSize(3)",
+ format!("{:?}", NonMatchingProtoAddrSize(3))
+ );
+ }
+
+ #[test]
+ fn clone_eq_hash() {
+ let err = NonMatchingProtoAddrSize(3);
+ assert_eq!(err, err.clone());
+ let hash_a = {
+ let mut hasher = DefaultHasher::new();
+ err.hash(&mut hasher);
+ hasher.finish()
+ };
+ let hash_b = {
+ let mut hasher = DefaultHasher::new();
+ err.clone().hash(&mut hasher);
+ hasher.finish()
+ };
+ assert_eq!(hash_a, hash_b);
+ }
+
+ #[test]
+ fn fmt() {
+ let tests = [
+ (NonMatchingHwType(ArpHardwareId::CHAOS), "Hardware address type is expected to have the type '1 (Ethernet)' but is '5 (Chaosnet)'"),
+ (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))'"),
+ (NonMatchingHwAddrSize(21), "Hardware address size is expected to be 6 but is 21"),
+ (NonMatchingProtoAddrSize(22), "Protocol address size is expected to be 4 but is 22")
+ ];
+ for test in tests {
+ assert_eq!(format!("{}", test.0), test.1);
+ }
+ }
+
+ #[cfg(feature = "std")]
+ #[test]
+ fn source() {
+ assert!(NonMatchingProtoAddrSize(3).source().is_none());
+ }
+}
diff --git a/crates/etherparse/src/err/arp/arp_hw_addr_error.rs b/crates/etherparse/src/err/arp/arp_hw_addr_error.rs
new file mode 100644
index 0000000..47135be
--- /dev/null
+++ b/crates/etherparse/src/err/arp/arp_hw_addr_error.rs
@@ -0,0 +1,80 @@
+/// Error in the hardware addresses when creating an [`crate::ArpPacket`] or
+/// changing the hardware addresses in an [`crate::ArpPacket`].
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
+pub enum ArpHwAddrError {
+ /// Error if the given hardware address is longer than
+ /// the maximum of 255 bytes/octets.
+ LenTooBig(usize),
+
+ /// Hardware address lengths of sender and target differ.
+ LenNonMatching(usize, usize),
+}
+
+impl core::fmt::Display for ArpHwAddrError {
+ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ match self {
+ ArpHwAddrError::LenTooBig(len) =>
+ write!(f, "ARP Hardware Address Error: Given hardware address has a length of {len} which is greater then the maximum of 255."),
+ ArpHwAddrError::LenNonMatching(len_sender, len_target) =>
+ write!(f, "ARP Hardware Address Error: Given sender & target hardware addresses have differing lengths of {len_sender} & {len_target} (must be matching)."),
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
+impl std::error::Error for ArpHwAddrError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
+ None
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::ArpHwAddrError::*;
+ use alloc::format;
+ use std::{
+ collections::hash_map::DefaultHasher,
+ error::Error,
+ hash::{Hash, Hasher},
+ };
+
+ #[test]
+ fn debug() {
+ assert_eq!("LenTooBig(300)", format!("{:?}", LenTooBig(300)));
+ }
+
+ #[test]
+ fn clone_eq_hash() {
+ let err = LenTooBig(300);
+ assert_eq!(err, err.clone());
+ let hash_a = {
+ let mut hasher = DefaultHasher::new();
+ err.hash(&mut hasher);
+ hasher.finish()
+ };
+ let hash_b = {
+ let mut hasher = DefaultHasher::new();
+ err.clone().hash(&mut hasher);
+ hasher.finish()
+ };
+ assert_eq!(hash_a, hash_b);
+ }
+
+ #[test]
+ fn fmt() {
+ let tests = [
+ (LenTooBig(300), "ARP Hardware Address Error: Given hardware address has a length of 300 which is greater then the maximum of 255."),
+ (LenNonMatching(21, 22), "ARP Hardware Address Error: Given sender & target hardware addresses have differing lengths of 21 & 22 (must be matching)."),
+ ];
+ for test in tests {
+ assert_eq!(format!("{}", test.0), test.1);
+ }
+ }
+
+ #[cfg(feature = "std")]
+ #[test]
+ fn source() {
+ assert!(LenTooBig(300).source().is_none());
+ }
+}
diff --git a/crates/etherparse/src/err/arp/arp_new_error.rs b/crates/etherparse/src/err/arp/arp_new_error.rs
new file mode 100644
index 0000000..11e2675
--- /dev/null
+++ b/crates/etherparse/src/err/arp/arp_new_error.rs
@@ -0,0 +1,85 @@
+use super::{ArpHwAddrError, ArpProtoAddrError};
+
+/// Error while creating a new [`crate::ArpPacket`].
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
+pub enum ArpNewError {
+ /// Error in the given hardware addresses.
+ HwAddr(ArpHwAddrError),
+
+ /// Error in the given protocol addresses.
+ ProtoAddr(ArpProtoAddrError),
+}
+
+impl core::fmt::Display for ArpNewError {
+ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ match self {
+ ArpNewError::HwAddr(err) => err.fmt(f),
+ ArpNewError::ProtoAddr(err) => err.fmt(f),
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
+impl std::error::Error for ArpNewError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
+ None
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::err::arp::{ArpHwAddrError, ArpProtoAddrError};
+
+ use super::ArpNewError::*;
+ use alloc::format;
+ use std::{
+ collections::hash_map::DefaultHasher,
+ error::Error,
+ hash::{Hash, Hasher},
+ };
+
+ #[test]
+ fn debug() {
+ assert_eq!(
+ "HwAddr(LenTooBig(300))",
+ format!("{:?}", HwAddr(ArpHwAddrError::LenTooBig(300)))
+ );
+ }
+
+ #[test]
+ fn clone_eq_hash() {
+ let err = HwAddr(ArpHwAddrError::LenTooBig(300));
+ assert_eq!(err, err.clone());
+ let hash_a = {
+ let mut hasher = DefaultHasher::new();
+ err.hash(&mut hasher);
+ hasher.finish()
+ };
+ let hash_b = {
+ let mut hasher = DefaultHasher::new();
+ err.clone().hash(&mut hasher);
+ hasher.finish()
+ };
+ assert_eq!(hash_a, hash_b);
+ }
+
+ #[test]
+ fn fmt() {
+ let tests = [
+ (HwAddr(ArpHwAddrError::LenTooBig(300)), "ARP Hardware Address Error: Given hardware address has a length of 300 which is greater then the maximum of 255."),
+ (ProtoAddr(ArpProtoAddrError::LenTooBig(301)), "ARP Protocol Address Error: Given protocol address has a length of 301 which is greater then the maximum of 255."),
+ (HwAddr(ArpHwAddrError::LenNonMatching(21, 22)), "ARP Hardware Address Error: Given sender & target hardware addresses have differing lengths of 21 & 22 (must be matching)."),
+ (ProtoAddr(ArpProtoAddrError::LenNonMatching(23, 24)), "ARP Protocol Address Error: Given sender & target protocol addresses have differing lengths of 23 & 24 (must be matching).")
+ ];
+ for test in tests {
+ assert_eq!(format!("{}", test.0), test.1);
+ }
+ }
+
+ #[cfg(feature = "std")]
+ #[test]
+ fn source() {
+ assert!(HwAddr(ArpHwAddrError::LenTooBig(300)).source().is_none());
+ }
+}
diff --git a/crates/etherparse/src/err/arp/arp_proto_addr_error.rs b/crates/etherparse/src/err/arp/arp_proto_addr_error.rs
new file mode 100644
index 0000000..5203d37
--- /dev/null
+++ b/crates/etherparse/src/err/arp/arp_proto_addr_error.rs
@@ -0,0 +1,80 @@
+/// Error in the protocol addresses when creating an [`crate::ArpPacket`] or
+/// changing the protocol addresses in an [`crate::ArpPacket`].
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
+pub enum ArpProtoAddrError {
+ /// Error if the given protocol address is longer than
+ /// the maximum of 255 bytes/octets.
+ LenTooBig(usize),
+
+ /// Protocol address lengths of sender and target differ.
+ LenNonMatching(usize, usize),
+}
+
+impl core::fmt::Display for ArpProtoAddrError {
+ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ match self {
+ ArpProtoAddrError::LenTooBig(len) =>
+ write!(f, "ARP Protocol Address Error: Given protocol address has a length of {len} which is greater then the maximum of 255."),
+ ArpProtoAddrError::LenNonMatching(len_sender, len_target) =>
+ write!(f, "ARP Protocol Address Error: Given sender & target protocol addresses have differing lengths of {len_sender} & {len_target} (must be matching)."),
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
+impl std::error::Error for ArpProtoAddrError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
+ None
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::ArpProtoAddrError::*;
+ use alloc::format;
+ use std::{
+ collections::hash_map::DefaultHasher,
+ error::Error,
+ hash::{Hash, Hasher},
+ };
+
+ #[test]
+ fn debug() {
+ assert_eq!("LenTooBig(300)", format!("{:?}", LenTooBig(300)));
+ }
+
+ #[test]
+ fn clone_eq_hash() {
+ let err = LenTooBig(300);
+ assert_eq!(err, err.clone());
+ let hash_a = {
+ let mut hasher = DefaultHasher::new();
+ err.hash(&mut hasher);
+ hasher.finish()
+ };
+ let hash_b = {
+ let mut hasher = DefaultHasher::new();
+ err.clone().hash(&mut hasher);
+ hasher.finish()
+ };
+ assert_eq!(hash_a, hash_b);
+ }
+
+ #[test]
+ fn fmt() {
+ let tests = [
+ (LenTooBig(301), "ARP Protocol Address Error: Given protocol address has a length of 301 which is greater then the maximum of 255."),
+ (LenNonMatching(23, 24), "ARP Protocol Address Error: Given sender & target protocol addresses have differing lengths of 23 & 24 (must be matching).")
+ ];
+ for test in tests {
+ assert_eq!(format!("{}", test.0), test.1);
+ }
+ }
+
+ #[cfg(feature = "std")]
+ #[test]
+ fn source() {
+ assert!(LenTooBig(300).source().is_none());
+ }
+}
diff --git a/crates/etherparse/src/err/arp/mod.rs b/crates/etherparse/src/err/arp/mod.rs
new file mode 100644
index 0000000..fca131b
--- /dev/null
+++ b/crates/etherparse/src/err/arp/mod.rs
@@ -0,0 +1,11 @@
+mod arp_eth_ipv4_from_error;
+pub use arp_eth_ipv4_from_error::*;
+
+mod arp_hw_addr_error;
+pub use arp_hw_addr_error::*;
+
+mod arp_new_error;
+pub use arp_new_error::*;
+
+mod arp_proto_addr_error;
+pub use arp_proto_addr_error::*;
diff --git a/crates/etherparse/src/err/from_slice_error.rs b/crates/etherparse/src/err/from_slice_error.rs
index e879edf..fae1383 100644
--- a/crates/etherparse/src/err/from_slice_error.rs
+++ b/crates/etherparse/src/err/from_slice_error.rs
@@ -438,7 +438,7 @@
layer_start_offset: 0,
}),
LinuxSll(linux_sll::HeaderError::UnsupportedArpHardwareId {
- arp_hardware_type: ArpHardwareId::ETHER,
+ arp_hardware_type: ArpHardwareId::ETHERNET,
}),
DoubleVlan(double_vlan::HeaderError::NonVlanEtherType {
unexpected_ether_type: EtherType(123),
@@ -469,7 +469,7 @@
layer_start_offset: 0,
};
let linux_sll_error = || linux_sll::HeaderError::UnsupportedArpHardwareId {
- arp_hardware_type: ArpHardwareId::ETHER,
+ arp_hardware_type: ArpHardwareId::ETHERNET,
};
let double_vlan_error = || double_vlan::HeaderError::NonVlanEtherType {
unexpected_ether_type: EtherType(1),
@@ -548,7 +548,7 @@
// linux sll
{
let header_error = || linux_sll::HeaderError::UnsupportedArpHardwareId {
- arp_hardware_type: ArpHardwareId::ETHER,
+ arp_hardware_type: ArpHardwareId::ETHERNET,
};
assert_eq!(
&header_error(),
diff --git a/crates/etherparse/src/err/layer.rs b/crates/etherparse/src/err/layer.rs
index 16e2ce2..a6b3c79 100644
--- a/crates/etherparse/src/err/layer.rs
+++ b/crates/etherparse/src/err/layer.rs
@@ -45,6 +45,8 @@
Icmpv4TimestampReply,
/// Error occurred while parsing an ICMPv6 packet.
Icmpv6,
+ /// Error occurred while parsing an Address Resolution Protocol packet.
+ Arp,
}
impl Layer {
@@ -74,6 +76,7 @@
Icmpv4Timestamp => "ICMP Timestamp Error",
Icmpv4TimestampReply => "ICMP Timestamp Reply Error",
Icmpv6 => "ICMPv6 Packet Error",
+ Arp => "Address Resolution Protocol Packet Error",
}
}
}
@@ -104,6 +107,7 @@
Icmpv4Timestamp => write!(f, "ICMP timestamp message"),
Icmpv4TimestampReply => write!(f, "ICMP timestamp reply message"),
Icmpv6 => write!(f, "ICMPv6 packet"),
+ Arp => write!(f, "Address Resolution Protocol packet"),
}
}
}
@@ -145,7 +149,9 @@
#[test]
fn error_title() {
let tests = [
+ (LinuxSllHeader, "Linux Cooked Capture v1 Error"),
(Ethernet2Header, "Ethernet 2 Header Error"),
+ (EtherPayload, "Payload with Ether Type Error"),
(VlanHeader, "VLAN Header Error"),
(IpHeader, "IP Header Error"),
(Ipv4Header, "IPv4 Header Error"),
@@ -177,7 +183,9 @@
#[test]
fn fmt() {
let tests = [
+ (LinuxSllHeader, "Linux Cooked Capture v1 header"),
(Ethernet2Header, "Ethernet 2 header"),
+ (EtherPayload, "Ether type payload"),
(VlanHeader, "VLAN header"),
(IpHeader, "IP header"),
(Ipv4Header, "IPv4 header"),
diff --git a/crates/etherparse/src/err/len_error.rs b/crates/etherparse/src/err/len_error.rs
index bf60e15..0ff1ff8 100644
--- a/crates/etherparse/src/err/len_error.rs
+++ b/crates/etherparse/src/err/len_error.rs
@@ -84,6 +84,9 @@
}
UdpHeaderLen => "length calculated from the UDP header 'length' field",
TcpHeaderLen => "length calculated from the TCP header 'length' field",
+ ArpAddrLengths => {
+ "length calculated from the ARP 'hw_addr_size' & 'proto_addr_size' fields"
+ }
}
};
diff --git a/crates/etherparse/src/err/linux_sll/header_error.rs b/crates/etherparse/src/err/linux_sll/header_error.rs
index 2fb504d..e745566 100644
--- a/crates/etherparse/src/err/linux_sll/header_error.rs
+++ b/crates/etherparse/src/err/linux_sll/header_error.rs
@@ -17,7 +17,7 @@
use HeaderError::*;
match self {
UnsupportedPacketTypeField { packet_type } => write!(f, "Linux cooked capture v1 (SLL) Header Error: Encountered '{}' as the packet type, but its not supported.", packet_type),
- 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),
+ 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),
}
}
}
@@ -78,8 +78,8 @@
format!("{}", UnsupportedPacketTypeField{ packet_type: 6 })
);
assert_eq!(
- "Linux cooked capture v1 (SLL) Header Error: Encountered '1 (Ethernet 10Mbps)' as the ARP harware type, but its not supported.",
- format!("{}", UnsupportedArpHardwareId{ arp_hardware_type: ArpHardwareId::ETHER })
+ "Linux cooked capture v1 (SLL) Header Error: Encountered '1 (Ethernet)' as the ARP harware type, but its not supported.",
+ format!("{}", UnsupportedArpHardwareId{ arp_hardware_type: ArpHardwareId::ETHERNET })
);
}
@@ -89,7 +89,7 @@
let values = [
UnsupportedPacketTypeField { packet_type: 6 },
UnsupportedArpHardwareId {
- arp_hardware_type: ArpHardwareId::ETHER,
+ arp_hardware_type: ArpHardwareId::ETHERNET,
},
];
for v in values {
diff --git a/crates/etherparse/src/err/mod.rs b/crates/etherparse/src/err/mod.rs
index 27d97d1..4d0b1d1 100644
--- a/crates/etherparse/src/err/mod.rs
+++ b/crates/etherparse/src/err/mod.rs
@@ -1,3 +1,4 @@
+pub mod arp;
pub mod double_vlan;
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
@@ -10,6 +11,7 @@
pub mod ipv6;
pub mod ipv6_exts;
pub mod linux_sll;
+pub mod net;
pub mod packet;
pub mod tcp;
diff --git a/crates/etherparse/src/err/net/mod.rs b/crates/etherparse/src/err/net/mod.rs
new file mode 100644
index 0000000..8a53c5d
--- /dev/null
+++ b/crates/etherparse/src/err/net/mod.rs
@@ -0,0 +1,2 @@
+mod net_set_next_header_error;
+pub use net_set_next_header_error::*;
diff --git a/crates/etherparse/src/err/net/net_set_next_header_error.rs b/crates/etherparse/src/err/net/net_set_next_header_error.rs
new file mode 100644
index 0000000..fc2c95a
--- /dev/null
+++ b/crates/etherparse/src/err/net/net_set_next_header_error.rs
@@ -0,0 +1,79 @@
+/// Errors when setting the next header IP number.
+#[derive(Clone, Debug, Eq, PartialEq, Hash)]
+pub enum NetSetNextHeaderError {
+ /// It is possible to set the ip_number in an ARP header.
+ ArpHeader,
+}
+
+impl core::fmt::Display for NetSetNextHeaderError {
+ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ use NetSetNextHeaderError::*;
+ match self {
+ ArpHeader => write!(
+ f,
+ "It is not possible to set the payload 'IP number' for an ARP header."
+ ),
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
+impl std::error::Error for NetSetNextHeaderError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
+ None
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use alloc::format;
+ use std::{
+ collections::hash_map::DefaultHasher,
+ error::Error,
+ hash::{Hash, Hasher},
+ };
+
+ #[test]
+ fn debug() {
+ assert_eq!(
+ "ArpHeader",
+ format!("{:?}", NetSetNextHeaderError::ArpHeader)
+ );
+ }
+
+ #[test]
+ fn clone_eq_hash() {
+ let err = NetSetNextHeaderError::ArpHeader;
+ assert_eq!(err, err.clone());
+ let hash_a = {
+ let mut hasher = DefaultHasher::new();
+ err.hash(&mut hasher);
+ hasher.finish()
+ };
+ let hash_b = {
+ let mut hasher = DefaultHasher::new();
+ err.clone().hash(&mut hasher);
+ hasher.finish()
+ };
+ assert_eq!(hash_a, hash_b);
+ }
+
+ #[test]
+ fn fmt() {
+ assert_eq!(
+ "It is not possible to set the payload 'IP number' for an ARP header.",
+ format!("{}", NetSetNextHeaderError::ArpHeader)
+ );
+ }
+
+ #[cfg(feature = "std")]
+ #[test]
+ fn source() {
+ let values = [NetSetNextHeaderError::ArpHeader];
+ for v in values {
+ assert!(v.source().is_none());
+ }
+ }
+}
diff --git a/crates/etherparse/src/err/packet/build_write_error.rs b/crates/etherparse/src/err/packet/build_write_error.rs
index 67251c5..e81a052 100644
--- a/crates/etherparse/src/err/packet/build_write_error.rs
+++ b/crates/etherparse/src/err/packet/build_write_error.rs
@@ -25,6 +25,9 @@
/// Error if ICMPv6 is packaged in an IPv4 packet (it is undefined
/// how to calculate the checksum).
Icmpv6InIpv4,
+
+ /// address size defined in the ARP header does not match the actual size
+ ArpHeaderNotMatch,
}
#[cfg(feature = "std")]
@@ -82,6 +85,7 @@
PayloadLen(err) => err.fmt(f),
Ipv4Exts(err) => err.fmt(f),
Ipv6Exts(err) => err.fmt(f),
+ ArpHeaderNotMatch => write!(f, "address size defined in the ARP header does not match the actual size"),
Icmpv6InIpv4 => write!(f, "Error: ICMPv6 can not be combined with an IPv4 headers (checksum can not be calculated)."),
}
}
@@ -98,6 +102,7 @@
Ipv4Exts(err) => Some(err),
Ipv6Exts(err) => Some(err),
Icmpv6InIpv4 => None,
+ ArpHeaderNotMatch => None,
}
}
}
diff --git a/crates/etherparse/src/err/packet/slice_error.rs b/crates/etherparse/src/err/packet/slice_error.rs
index 1326156..5123c03 100644
--- a/crates/etherparse/src/err/packet/slice_error.rs
+++ b/crates/etherparse/src/err/packet/slice_error.rs
@@ -177,7 +177,7 @@
// IpHeaders
{
let err = err::linux_sll::HeaderError::UnsupportedArpHardwareId {
- arp_hardware_type: ArpHardwareId::ETHER,
+ arp_hardware_type: ArpHardwareId::ETHERNET,
};
assert!(LinuxSll(err).source().is_some());
}
diff --git a/crates/etherparse/src/err/read_error.rs b/crates/etherparse/src/err/read_error.rs
index 8fab928..f0fb68a 100644
--- a/crates/etherparse/src/err/read_error.rs
+++ b/crates/etherparse/src/err/read_error.rs
@@ -490,7 +490,7 @@
(
"LinuxSll",
LinuxSll(linux_sll::HeaderError::UnsupportedArpHardwareId {
- arp_hardware_type: ArpHardwareId::ETHER,
+ arp_hardware_type: ArpHardwareId::ETHERNET,
}),
),
(
@@ -555,7 +555,7 @@
layer_start_offset: 0,
}),
LinuxSll(linux_sll::HeaderError::UnsupportedArpHardwareId {
- arp_hardware_type: ArpHardwareId::ETHER,
+ arp_hardware_type: ArpHardwareId::ETHERNET,
}),
DoubleVlan(double_vlan::HeaderError::NonVlanEtherType {
unexpected_ether_type: EtherType(123),
@@ -683,7 +683,7 @@
// linux sll
{
let header_error = || linux_sll::HeaderError::UnsupportedArpHardwareId {
- arp_hardware_type: ArpHardwareId::ETHER,
+ arp_hardware_type: ArpHardwareId::ETHERNET,
};
assert_eq!(
&header_error(),
diff --git a/crates/etherparse/src/lax_packet_headers.rs b/crates/etherparse/src/lax_packet_headers.rs
index 42f4df6..b8a255f 100644
--- a/crates/etherparse/src/lax_packet_headers.rs
+++ b/crates/etherparse/src/lax_packet_headers.rs
@@ -83,6 +83,9 @@
/// // net (ip) & transport (udp or tcp)
/// println!("net: {:?}", value.net);
/// match value.payload {
+ /// LaxPayloadSlice::Empty => {
+ /// // in case of ARP packet the payload is empty
+ /// }
/// LaxPayloadSlice::Ether(e) => {
/// println!("ether payload (ether type {:?}): {:?}", e.ether_type, e.payload);
/// }
@@ -194,6 +197,9 @@
/// // net (ip) & transport (udp or tcp)
/// println!("net: {:?}", value.net);
/// match value.payload {
+ /// LaxPayloadSlice::Empty => {
+ /// // Some packets don't have seperate payloads. For example ARP packets.
+ /// }
/// LaxPayloadSlice::Ether(e) => {
/// println!("ether payload (ether type {:?}): {:?}", e.ether_type, e.payload);
/// }
@@ -305,7 +311,7 @@
_ => None,
};
- // parse ip
+ // parse ip or arp
match ether_type {
IPV4 | IPV6 => match result.add_ip(offset, rest) {
Ok(_) => {}
@@ -321,6 +327,18 @@
return result;
}
},
+ ARP => {
+ let arp = match ArpPacket::from_slice(rest) {
+ Ok(value) => value,
+ Err(mut err) => {
+ err.layer_start_offset += offset;
+ result.stop_err = Some((Len(err), Layer::Arp));
+ return result;
+ }
+ };
+ result.net = Some(NetHeaders::Arp(arp));
+ return result;
+ }
_ => {}
};
@@ -392,8 +410,9 @@
/// // net (ip) & transport (udp or tcp)
/// println!("net: {:?}", value.net);
/// match value.payload {
- /// // if you parse from IP down there will be no ether payload
- /// LaxPayloadSlice::Ether(e) => unreachable!(),
+ /// // if you parse from IP down there will be no ether payload and the
+ /// // empty payload does not appear (only present in ARP packets).
+ /// LaxPayloadSlice::Ether(_) | LaxPayloadSlice::Empty => unreachable!(),
/// LaxPayloadSlice::Ip(ip) => {
/// println!("IP payload (IP number {:?}): {:?}", ip.ip_number, ip.payload);
/// if ip.incomplete {
@@ -674,7 +693,7 @@
fn from_x_slice_vlan_variants(base: &TestPacket) {
// none
- from_x_slice_ip_variants(base);
+ from_x_slice_net_variants(base);
// single vlan header
{
@@ -691,7 +710,7 @@
test.vlan = Some(VlanHeader::Single(single.clone()));
// ok vlan header
- from_x_slice_ip_variants(&test);
+ from_x_slice_net_variants(&test);
// len error
{
@@ -740,7 +759,7 @@
test.vlan = Some(VlanHeader::Double(double.clone()));
// ok double vlan header
- from_x_slice_ip_variants(&test);
+ from_x_slice_net_variants(&test);
// len error
{
@@ -768,10 +787,57 @@
}
}
- fn from_x_slice_ip_variants(base: &TestPacket) {
+ fn from_x_slice_net_variants(base: &TestPacket) {
// none
from_x_slice_transport_variants(base);
+ // arp
+ {
+ let arp = ArpPacket::new(
+ ArpHardwareId::ETHERNET,
+ EtherType::IPV4,
+ ArpOperation::REQUEST,
+ &[1, 2, 3, 4, 5, 6],
+ &[7, 8, 9, 10],
+ &[11, 12, 13, 14, 15, 16],
+ &[17, 18, 19, 20],
+ )
+ .unwrap();
+
+ let mut test = base.clone();
+ test.set_ether_type(ether_type::ARP);
+ test.net = Some(NetHeaders::Arp(arp.clone()));
+ from_x_slice_assert_ok(&test);
+
+ // arp len error
+ {
+ let data = test.to_vec(&[]);
+ for len in 0..arp.packet_len() {
+ let base_len = test.len(&[]) - arp.packet_len();
+
+ let err = LenError {
+ required_len: if len < 8 { 8 } else { arp.packet_len() },
+ len,
+ len_source: if len < 8 {
+ LenSource::Slice
+ } else {
+ LenSource::ArpAddrLengths
+ },
+ layer: Layer::Arp,
+ layer_start_offset: base_len,
+ };
+
+ assert_test_result(
+ &test,
+ &[],
+ &data[..base_len + len],
+ Some(err::ip::LaxHeaderSliceError::Len(err.clone())),
+ Some((SliceError::Len(err.clone()), Layer::Arp)),
+ );
+ }
+ }
+ }
+
// ipv4
for fragmented in [false, true] {
let ipv4 = {
@@ -1140,6 +1206,7 @@
let mut ip = match ip {
NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
+ NetHeaders::Arp(_) => unreachable!(),
};
ip.set_next_headers(ip_number::UDP);
ip.into()
@@ -1169,6 +1236,7 @@
len_source: match test.net.as_ref().unwrap() {
NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
+ NetHeaders::Arp(_) => unreachable!(),
},
layer: Layer::UdpHeader,
layer_start_offset: base_len,
@@ -1192,6 +1260,7 @@
let mut ip = match ip {
NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
+ NetHeaders::Arp(_) => unreachable!(),
};
ip.set_next_headers(ip_number::TCP);
ip.into()
@@ -1220,6 +1289,7 @@
len_source: match test.net.as_ref().unwrap() {
NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
+ NetHeaders::Arp(_) => unreachable!(),
},
layer: Layer::TcpHeader,
layer_start_offset: base_len,
@@ -1263,6 +1333,7 @@
let mut ip = match ip {
NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
+ NetHeaders::Arp(_) => unreachable!(),
};
ip.set_next_headers(ip_number::ICMP);
ip.into()
@@ -1289,6 +1360,7 @@
len_source: match test.net.as_ref().unwrap() {
NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
+ NetHeaders::Arp(_) => unreachable!(),
},
layer: Layer::Icmpv4,
layer_start_offset: base_len,
@@ -1313,6 +1385,7 @@
let mut ip = match ip {
NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
+ NetHeaders::Arp(_) => unreachable!(),
};
ip.set_next_headers(ip_number::IPV6_ICMP);
ip.into()
@@ -1339,6 +1412,7 @@
len_source: match test.net.as_ref().unwrap() {
NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
+ NetHeaders::Arp(_) => unreachable!(),
},
layer: Layer::Icmpv6,
layer_start_offset: base_len,
@@ -1410,18 +1484,20 @@
}
}
- fn compare_ip_header_only(test: &TestPacket, actual: &LaxPacketHeaders) {
+ fn compare_net_only(test: &TestPacket, actual: &LaxPacketHeaders) {
assert_eq!(
test.net.as_ref().map(|s| -> NetHeaders {
match s {
NetHeaders::Ipv4(h, _) => NetHeaders::Ipv4(h.clone(), Default::default()),
NetHeaders::Ipv6(h, _) => NetHeaders::Ipv6(h.clone(), Default::default()),
+ NetHeaders::Arp(h) => NetHeaders::Arp(h.clone()),
}
}),
actual.net.as_ref().map(|s| -> NetHeaders {
match s {
NetHeaders::Ipv4(h, _) => NetHeaders::Ipv4(h.clone(), Default::default()),
NetHeaders::Ipv6(h, _) => NetHeaders::Ipv6(h.clone(), Default::default()),
+ NetHeaders::Arp(h) => NetHeaders::Arp(h.clone()),
}
})
);
@@ -1520,7 +1596,10 @@
assert_eq!(None, actual.transport);
assert!(matches!(actual.payload, LaxPayloadSlice::Ether(_)));
}
- Some(Layer::Ipv6Header) | Some(Layer::Ipv4Header) | Some(Layer::IpHeader) => {
+ Some(Layer::Ipv6Header)
+ | Some(Layer::Ipv4Header)
+ | Some(Layer::IpHeader)
+ | Some(Layer::Arp) => {
assert_eq!(test.link, actual.link);
compare_vlan(test, data, &actual);
assert_eq!(None, actual.net);
@@ -1535,7 +1614,7 @@
| Some(Layer::Ipv6FragHeader) => {
assert_eq!(test.link, actual.link);
compare_vlan(test, data, &actual);
- compare_ip_header_only(test, &actual);
+ compare_net_only(test, &actual);
assert_eq!(None, actual.transport);
assert!(matches!(actual.payload, LaxPayloadSlice::Ip(_)));
}
@@ -1549,7 +1628,7 @@
assert_eq!(None, actual.transport);
assert!(matches!(actual.payload, LaxPayloadSlice::Ip(_)));
}
- _ => unreachable!("error in an unexpected layer"),
+ layer => unreachable!("error in an unexpected layer {layer:?}"),
}
}
}
@@ -1574,7 +1653,10 @@
assert_eq!(None, actual.transport);
assert!(matches!(actual.payload, LaxPayloadSlice::Ether(_)));
}
- Some(Layer::Ipv6Header) | Some(Layer::Ipv4Header) | Some(Layer::IpHeader) => {
+ Some(Layer::Ipv6Header)
+ | Some(Layer::Ipv4Header)
+ | Some(Layer::IpHeader)
+ | Some(Layer::Arp) => {
assert_eq!(None, actual.net);
assert_eq!(None, actual.transport);
assert!(matches!(actual.payload, LaxPayloadSlice::Ether(_)));
@@ -1585,7 +1667,7 @@
| Some(Layer::Ipv6DestOptionsHeader)
| Some(Layer::Ipv6RouteHeader)
| Some(Layer::Ipv6FragHeader) => {
- compare_ip_header_only(test, &actual);
+ compare_net_only(test, &actual);
assert_eq!(None, actual.transport);
assert!(matches!(actual.payload, LaxPayloadSlice::Ip(_)));
}
@@ -1601,17 +1683,18 @@
}
}
}
- // from_ether_type (ip at start)
+ // from_ether_type (ip or arp at start)
if test.link.is_none() && test.vlan.is_none() {
- if let Some(ip) = &test.net {
- let ether_type = match ip {
+ if let Some(net) = &test.net {
+ let ether_type = match net {
NetHeaders::Ipv4(_, _) => ether_type::IPV4,
NetHeaders::Ipv6(_, _) => ether_type::IPV6,
+ NetHeaders::Arp(_) => ether_type::ARP,
};
let actual = LaxPacketHeaders::from_ether_type(ether_type, &data);
assert_eq!(actual.stop_err, expected_stop_err);
assert_eq!(None, actual.link);
- assert_eq!(test.vlan, None);
+ assert_eq!(None, test.vlan);
match expected_stop_err.as_ref().map(|v| v.1) {
None => {
assert_eq!(test.net, actual.net);
@@ -1622,7 +1705,10 @@
&actual,
);
}
- Some(Layer::Ipv6Header) | Some(Layer::Ipv4Header) | Some(Layer::IpHeader) => {
+ Some(Layer::Ipv6Header)
+ | Some(Layer::Ipv4Header)
+ | Some(Layer::IpHeader)
+ | Some(Layer::Arp) => {
assert_eq!(None, actual.net);
assert_eq!(None, actual.transport);
assert_eq!(
@@ -1639,7 +1725,7 @@
| Some(Layer::Ipv6DestOptionsHeader)
| Some(Layer::Ipv6RouteHeader)
| Some(Layer::Ipv6FragHeader) => {
- compare_ip_header_only(test, &actual);
+ compare_net_only(test, &actual);
assert_eq!(None, actual.transport);
assert!(matches!(actual.payload, LaxPayloadSlice::Ip(_)));
}
@@ -1656,7 +1742,11 @@
}
}
// from_ip_slice
- if test.link.is_none() && test.vlan.is_none() && test.net.is_some() {
+ if test.link.is_none()
+ && test.vlan.is_none()
+ && test.net.is_some()
+ && !matches!(test.net, Some(NetHeaders::Arp(_)))
+ {
if let Some(err) = expected_ip_err {
assert_eq!(err, LaxPacketHeaders::from_ip(&data).unwrap_err());
} else {
@@ -1680,7 +1770,7 @@
| Some(Layer::Ipv6DestOptionsHeader)
| Some(Layer::Ipv6RouteHeader)
| Some(Layer::Ipv6FragHeader) => {
- compare_ip_header_only(test, &actual);
+ compare_net_only(test, &actual);
assert_eq!(None, actual.transport);
assert!(matches!(actual.payload, LaxPayloadSlice::Ip(_)));
}
diff --git a/crates/etherparse/src/lax_payload_slice.rs b/crates/etherparse/src/lax_payload_slice.rs
index 704531b..e1934bd 100644
--- a/crates/etherparse/src/lax_payload_slice.rs
+++ b/crates/etherparse/src/lax_payload_slice.rs
@@ -4,6 +4,8 @@
/// information if the payload is incomplete.
#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
pub enum LaxPayloadSlice<'a> {
+ /// No specific payload (e.g. ARP packet).
+ Empty,
/// Payload with it's type identified by an ether type number
/// (e.g. after an ethernet II or vlan header).
Ether(EtherPayloadSlice<'a>),
@@ -37,6 +39,7 @@
impl<'a> LaxPayloadSlice<'a> {
pub fn slice(&self) -> &'a [u8] {
match self {
+ LaxPayloadSlice::Empty => &[],
LaxPayloadSlice::Ether(e) => e.payload,
LaxPayloadSlice::Ip(i) => i.payload,
LaxPayloadSlice::Udp {
diff --git a/crates/etherparse/src/lax_sliced_packet.rs b/crates/etherparse/src/lax_sliced_packet.rs
index 3c6364c..d790529 100644
--- a/crates/etherparse/src/lax_sliced_packet.rs
+++ b/crates/etherparse/src/lax_sliced_packet.rs
@@ -264,6 +264,7 @@
match net {
Ipv4(v) => Some(v.payload()),
Ipv6(v) => Some(v.payload()),
+ Arp(_) => None,
}
} else {
None
@@ -1034,6 +1035,7 @@
let mut ip = match ip {
NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
+ NetHeaders::Arp(_) => unreachable!(),
};
ip.set_next_headers(ip_number::UDP);
ip.into()
@@ -1063,6 +1065,7 @@
len_source: match test.net.as_ref().unwrap() {
NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
+ NetHeaders::Arp(_) => unreachable!(),
},
layer: Layer::UdpHeader,
layer_start_offset: base_len,
@@ -1086,6 +1089,7 @@
let mut ip = match ip {
NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
+ NetHeaders::Arp(_) => unreachable!(),
};
ip.set_next_headers(ip_number::TCP);
ip.into()
@@ -1114,6 +1118,7 @@
len_source: match test.net.as_ref().unwrap() {
NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
+ NetHeaders::Arp(_) => unreachable!(),
},
layer: Layer::TcpHeader,
layer_start_offset: base_len,
@@ -1157,6 +1162,7 @@
let mut ip = match ip {
NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
+ NetHeaders::Arp(_) => unreachable!(),
};
ip.set_next_headers(ip_number::ICMP);
ip.into()
@@ -1183,6 +1189,7 @@
len_source: match test.net.as_ref().unwrap() {
NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
+ NetHeaders::Arp(_) => unreachable!(),
},
layer: Layer::Icmpv4,
layer_start_offset: base_len,
@@ -1207,6 +1214,7 @@
let mut ip = match ip {
NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
+ NetHeaders::Arp(_) => unreachable!(),
};
ip.set_next_headers(ip_number::IPV6_ICMP);
ip.into()
@@ -1233,6 +1241,7 @@
len_source: match test.net.as_ref().unwrap() {
NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
+ NetHeaders::Arp(_) => unreachable!(),
},
layer: Layer::Icmpv6,
layer_start_offset: base_len,
@@ -1328,6 +1337,7 @@
.unwrap()
.0,
),
+ LaxNetSlice::Arp(arp) => NetHeaders::Arp(arp.to_packet()),
}
})
);
@@ -1339,6 +1349,7 @@
match s {
NetHeaders::Ipv4(h, _) => NetHeaders::Ipv4(h.clone(), Default::default()),
NetHeaders::Ipv6(h, _) => NetHeaders::Ipv6(h.clone(), Default::default()),
+ NetHeaders::Arp(_) => unreachable!(),
}
}),
actual.net.as_ref().map(|s| -> NetHeaders {
@@ -1349,6 +1360,7 @@
LaxNetSlice::Ipv6(ipv6) => {
NetHeaders::Ipv6(ipv6.header().to_header(), Default::default())
}
+ LaxNetSlice::Arp(arp) => NetHeaders::Arp(arp.to_packet()),
}
})
);
@@ -1523,6 +1535,7 @@
let ether_type = match ip {
NetHeaders::Ipv4(_, _) => ether_type::IPV4,
NetHeaders::Ipv6(_, _) => ether_type::IPV6,
+ NetHeaders::Arp(_) => unreachable!(),
};
let actual = LaxSlicedPacket::from_ether_type(ether_type, &data);
assert_eq!(actual.stop_err, expected_stop_err);
diff --git a/crates/etherparse/src/lax_sliced_packet_cursor.rs b/crates/etherparse/src/lax_sliced_packet_cursor.rs
index 5464c16..9aff1eb 100644
--- a/crates/etherparse/src/lax_sliced_packet_cursor.rs
+++ b/crates/etherparse/src/lax_sliced_packet_cursor.rs
@@ -61,11 +61,11 @@
};
use ether_type::*;
match ether_type {
- IPV4 => cursor.slice_ip(slice),
- IPV6 => cursor.slice_ip(slice),
+ IPV4 | IPV6 => cursor.slice_ip(slice),
VLAN_TAGGED_FRAME | PROVIDER_BRIDGING | VLAN_DOUBLE_TAGGED_FRAME => {
cursor.slice_vlan(slice)
}
+ ARP => cursor.slice_arp(slice),
_ => cursor.result,
}
}
@@ -168,6 +168,19 @@
}
}
+ pub fn slice_arp(mut self, slice: &'a [u8]) -> LaxSlicedPacket<'a> {
+ let arp = match ArpPacketSlice::from_slice(slice) {
+ Ok(arp) => arp,
+ Err(mut e) => {
+ e.layer_start_offset += self.offset;
+ self.result.stop_err = Some((err::packet::SliceError::Len(e), Layer::Arp));
+ return self.result;
+ }
+ };
+ self.result.net = Some(LaxNetSlice::Arp(arp));
+ self.result
+ }
+
pub fn slice_ip(mut self, slice: &'a [u8]) -> LaxSlicedPacket<'a> {
// ip slice
let ip = match LaxIpSlice::from_slice(slice) {
diff --git a/crates/etherparse/src/len_source.rs b/crates/etherparse/src/len_source.rs
index 45d0039..16ff5c7 100644
--- a/crates/etherparse/src/len_source.rs
+++ b/crates/etherparse/src/len_source.rs
@@ -12,6 +12,8 @@
UdpHeaderLen,
/// Error occurred while decoding a TCP header.
TcpHeaderLen,
+ /// Error occurred while decoding a ARP packet.
+ ArpAddrLengths,
}
#[cfg(test)]
diff --git a/crates/etherparse/src/lib.rs b/crates/etherparse/src/lib.rs
index 2da16e7..59fad73 100644
--- a/crates/etherparse/src/lib.rs
+++ b/crates/etherparse/src/lib.rs
@@ -3,6 +3,7 @@
//! Currently supported are:
//! * Ethernet II
//! * IEEE 802.1Q VLAN Tagging Header
+//! * ARP
//! * IPv4
//! * IPv6 (supporting the most common extension headers, but not all)
//! * UDP
@@ -17,7 +18,7 @@
//!
//! ```toml
//! [dependencies]
-//! etherparse = "0.16"
+//! etherparse = "0.17"
//! ```
//!
//! # What is etherparse?
@@ -57,7 +58,7 @@
//! Ok(value) => {
//! println!("link: {:?}", value.link);
//! println!("vlan: {:?}", value.vlan);
-//! println!("net: {:?}", value.net); // contains ip
+//! println!("net: {:?}", value.net); // contains ip & arp
//! println!("transport: {:?}", value.transport);
//! }
//! }
@@ -101,7 +102,7 @@
//! Ok(value) => {
//! println!("link: {:?}", value.link);
//! println!("vlan: {:?}", value.vlan);
-//! println!("net: {:?}", value.net); // contains ip
+//! println!("net: {:?}", value.net); // contains ip & arp
//! println!("transport: {:?}", value.transport);
//! }
//! }
@@ -149,6 +150,7 @@
//! * [`LinuxSllHeaderSlice::from_slice`]
//! * [`SingleVlanHeaderSlice::from_slice`]
//! * [`DoubleVlanHeaderSlice::from_slice`]
+//! * [`ArpPacketSlice::from_slice`]
//! * [`Ipv4HeaderSlice::from_slice`]
//! * [`Ipv4ExtensionsSlice::from_slice`]
//! * [`Ipv6HeaderSlice::from_slice`]
@@ -165,6 +167,7 @@
//! * [`LinuxSllHeader::read`] & [`LinuxSllHeader::from_slice`]
//! * [`SingleVlanHeader::read`] & [`SingleVlanHeader::from_slice`]
//! * [`DoubleVlanHeader::read`] & [`DoubleVlanHeader::from_slice`]
+//! * [`ArpPacket::read`] & [`ArpPacket::from_slice`]
//! * [`IpHeaders::read`] & [`IpHeaders::from_slice`]
//! * [`Ipv4Header::read`] & [`Ipv4Header::from_slice`]
//! * [`Ipv4Extensions::read`] & [`Ipv4Extensions::from_slice`]
@@ -229,6 +232,8 @@
//! * [`LinuxSllHeader::to_bytes`] & [`LinuxSllHeader::write`]
//! * [`SingleVlanHeader::to_bytes`] & [`SingleVlanHeader::write`]
//! * [`DoubleVlanHeader::to_bytes`] & [`DoubleVlanHeader::write`]
+//! * [`ArpPacket::to_bytes`] & [`ArpPacket::write`]
+//! * [`ArpEthIpv4Packet::to_bytes`]
//! * [`Ipv4Header::to_bytes`] & [`Ipv4Header::write`] & [`Ipv4Header::write_raw`]
//! * [`Ipv4Extensions::write`]
//! * [`Ipv6Header::to_bytes`] & [`Ipv6Header::write`]
@@ -310,31 +315,7 @@
pub mod defrag;
mod link;
-pub use crate::link::arp_hardware_id::*;
-pub use crate::link::double_vlan_header::*;
-pub use crate::link::double_vlan_header_slice::*;
-pub use crate::link::double_vlan_slice::*;
-pub use crate::link::ether_payload_slice::*;
-pub use crate::link::ether_type_impl::*;
-pub use crate::link::ethernet2_header::*;
-pub use crate::link::ethernet2_header_slice::*;
-pub use crate::link::ethernet2_slice::*;
-pub use crate::link::link_header::*;
-pub use crate::link::link_slice::*;
-pub use crate::link::linux_nonstandard_ether_type::*;
-pub use crate::link::linux_sll_header::*;
-pub use crate::link::linux_sll_header_slice::*;
-pub use crate::link::linux_sll_packet_type::*;
-pub use crate::link::linux_sll_payload_slice::*;
-pub use crate::link::linux_sll_protocol_type::*;
-pub use crate::link::linux_sll_slice::*;
-pub use crate::link::single_vlan_header::*;
-pub use crate::link::single_vlan_header_slice::*;
-pub use crate::link::single_vlan_slice::*;
-pub use crate::link::vlan_header::*;
-pub use crate::link::vlan_id::*;
-pub use crate::link::vlan_pcp::*;
-pub use crate::link::vlan_slice::*;
+pub use link::*;
#[cfg(test)]
pub(crate) mod test_gens;
@@ -347,29 +328,7 @@
pub mod io;
mod transport;
-pub use crate::transport::icmp_echo_header::*;
-pub use crate::transport::icmpv4;
-pub use crate::transport::icmpv4_header::*;
-pub use crate::transport::icmpv4_slice::*;
-pub use crate::transport::icmpv4_type::*;
-pub use crate::transport::icmpv6;
-pub use crate::transport::icmpv6_header::*;
-pub use crate::transport::icmpv6_slice::*;
-pub use crate::transport::icmpv6_type::*;
-pub use crate::transport::tcp_header::*;
-pub use crate::transport::tcp_header_slice::*;
-pub use crate::transport::tcp_option_element::*;
-pub use crate::transport::tcp_option_impl::*;
-pub use crate::transport::tcp_option_read_error::*;
-pub use crate::transport::tcp_option_write_error::*;
-pub use crate::transport::tcp_options::*;
-pub use crate::transport::tcp_options_iterator::*;
-pub use crate::transport::tcp_slice::*;
-pub use crate::transport::transport_header::*;
-pub use crate::transport::transport_slice::*;
-pub use crate::transport::udp_header::*;
-pub use crate::transport::udp_header_slice::*;
-pub use crate::transport::udp_slice::*;
+pub use transport::*;
/// Helpers for calculating checksums.
pub mod checksum;
diff --git a/crates/etherparse/src/link/double_vlan_slice.rs b/crates/etherparse/src/link/double_vlan_slice.rs
index ead1c36..7b2de5f 100644
--- a/crates/etherparse/src/link/double_vlan_slice.rs
+++ b/crates/etherparse/src/link/double_vlan_slice.rs
@@ -106,7 +106,7 @@
}
}
-impl<'a> core::fmt::Debug for DoubleVlanSlice<'a> {
+impl core::fmt::Debug for DoubleVlanSlice<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("DoubleVlanSlice")
.field("outer", &self.outer().to_header())
diff --git a/crates/etherparse/src/link/ethernet2_slice.rs b/crates/etherparse/src/link/ethernet2_slice.rs
index 5460632..b309707 100644
--- a/crates/etherparse/src/link/ethernet2_slice.rs
+++ b/crates/etherparse/src/link/ethernet2_slice.rs
@@ -155,7 +155,7 @@
}
}
-impl<'a> core::fmt::Debug for Ethernet2Slice<'a> {
+impl core::fmt::Debug for Ethernet2Slice<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Ethernet2Slice")
.field("header", &self.to_header())
diff --git a/crates/etherparse/src/link/link_slice.rs b/crates/etherparse/src/link/link_slice.rs
index 3257e6c..fb1bd03 100644
--- a/crates/etherparse/src/link/link_slice.rs
+++ b/crates/etherparse/src/link/link_slice.rs
@@ -187,4 +187,70 @@
}
}
}
+
+ proptest! {
+ #[test]
+ fn sll_payload(
+ ref eth in ethernet_2_unknown(),
+ ref linux_sll in linux_sll_any()
+ ) {
+ let p = [1,2,3,4];
+ {
+ let mut bytes = Vec::with_capacity(Ethernet2Header::LEN + p.len());
+ bytes.extend_from_slice(ð.to_bytes());
+ bytes.extend_from_slice(&p);
+ let slice = LinkSlice::Ethernet2(
+ Ethernet2Slice::from_slice_without_fcs(&bytes).unwrap()
+ );
+ assert_eq!(
+ slice.sll_payload(),
+ LinuxSllPayloadSlice{
+ protocol_type: LinuxSllProtocolType::EtherType(eth.ether_type),
+ payload: &p
+ }
+ );
+ }
+ {
+ let slice = LinkSlice::EtherPayload(EtherPayloadSlice {
+ ether_type: eth.ether_type,
+ payload: &p
+ });
+ assert_eq!(
+ slice.sll_payload(),
+ LinuxSllPayloadSlice{
+ protocol_type: LinuxSllProtocolType::EtherType(eth.ether_type),
+ payload: &p
+ }
+ );
+ }
+ {
+ let mut bytes = Vec::with_capacity(LinuxSllHeader::LEN + p.len());
+ bytes.extend_from_slice(&linux_sll.to_bytes());
+ bytes.extend_from_slice(&p);
+ let slice = LinkSlice::LinuxSll(
+ LinuxSllSlice::from_slice(&bytes).unwrap()
+ );
+ assert_eq!(
+ slice.sll_payload(),
+ LinuxSllPayloadSlice{
+ protocol_type: linux_sll.protocol_type,
+ payload: &p
+ }
+ );
+ }
+ {
+ let slice = LinkSlice::LinuxSllPayload(LinuxSllPayloadSlice {
+ protocol_type: linux_sll.protocol_type,
+ payload: &p
+ });
+ assert_eq!(
+ slice.sll_payload(),
+ LinuxSllPayloadSlice{
+ protocol_type: linux_sll.protocol_type,
+ payload: &p
+ }
+ );
+ }
+ }
+ }
}
diff --git a/crates/etherparse/src/link/linux_sll_protocol_type.rs b/crates/etherparse/src/link/linux_sll_protocol_type.rs
index da259b6..7ee53c2 100644
--- a/crates/etherparse/src/link/linux_sll_protocol_type.rs
+++ b/crates/etherparse/src/link/linux_sll_protocol_type.rs
@@ -39,7 +39,7 @@
ArpHardwareId::IPGRE,
ArpHardwareId::IEEE80211_RADIOTAP,
ArpHardwareId::FRAD,
- ArpHardwareId::ETHER,
+ ArpHardwareId::ETHERNET,
];
pub fn change_value(&mut self, value: u16) {
@@ -75,7 +75,7 @@
}
ArpHardwareId::IEEE80211_RADIOTAP => Ok(LinuxSllProtocolType::Ignored(protocol_type)),
ArpHardwareId::FRAD => Ok(LinuxSllProtocolType::Ignored(protocol_type)),
- ArpHardwareId::ETHER => match LinuxNonstandardEtherType::try_from(protocol_type) {
+ ArpHardwareId::ETHERNET => match LinuxNonstandardEtherType::try_from(protocol_type) {
Ok(v) => Ok(LinuxSllProtocolType::LinuxNonstandardEtherType(v)),
Err(_) => Ok(LinuxSllProtocolType::EtherType(EtherType(protocol_type))),
},
@@ -122,7 +122,7 @@
);
assert_eq!(
LinuxSllProtocolType::try_from((
- ArpHardwareId::ETHER,
+ ArpHardwareId::ETHERNET,
u16::from(LinuxNonstandardEtherType::N802_3)
)),
Ok(LinuxSllProtocolType::LinuxNonstandardEtherType(
@@ -130,7 +130,7 @@
))
);
assert_eq!(
- LinuxSllProtocolType::try_from((ArpHardwareId::ETHER, u16::from(EtherType::IPV4))),
+ LinuxSllProtocolType::try_from((ArpHardwareId::ETHERNET, u16::from(EtherType::IPV4))),
Ok(LinuxSllProtocolType::EtherType(EtherType::IPV4))
);
}
diff --git a/crates/etherparse/src/link/linux_sll_slice.rs b/crates/etherparse/src/link/linux_sll_slice.rs
index 9c2f219..3adb34e 100644
--- a/crates/etherparse/src/link/linux_sll_slice.rs
+++ b/crates/etherparse/src/link/linux_sll_slice.rs
@@ -132,7 +132,7 @@
}
}
-impl<'a> core::fmt::Debug for LinuxSllSlice<'a> {
+impl core::fmt::Debug for LinuxSllSlice<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("LinuxSllSlice")
.field("header", &self.to_header())
diff --git a/crates/etherparse/src/link/mod.rs b/crates/etherparse/src/link/mod.rs
index fab5b80..5f94511 100644
--- a/crates/etherparse/src/link/mod.rs
+++ b/crates/etherparse/src/link/mod.rs
@@ -1,25 +1,71 @@
-pub mod arp_hardware_id;
-pub mod double_vlan_header;
-pub mod double_vlan_header_slice;
-pub mod double_vlan_slice;
-pub mod ether_payload_slice;
-pub mod ether_type_impl;
-pub mod ethernet2_header;
-pub mod ethernet2_header_slice;
-pub mod ethernet2_slice;
-pub mod link_header;
-pub mod link_slice;
-pub mod linux_nonstandard_ether_type;
-pub mod linux_sll_header;
-pub mod linux_sll_header_slice;
-pub mod linux_sll_packet_type;
-pub mod linux_sll_payload_slice;
-pub mod linux_sll_protocol_type;
-pub mod linux_sll_slice;
-pub mod single_vlan_header;
-pub mod single_vlan_header_slice;
-pub mod single_vlan_slice;
-pub mod vlan_header;
-pub mod vlan_id;
-pub mod vlan_pcp;
-pub mod vlan_slice;
+mod double_vlan_header;
+pub use double_vlan_header::*;
+
+mod double_vlan_header_slice;
+pub use double_vlan_header_slice::*;
+
+mod double_vlan_slice;
+pub use double_vlan_slice::*;
+
+mod ether_payload_slice;
+pub use ether_payload_slice::*;
+
+mod ether_type_impl;
+pub use ether_type_impl::*;
+
+mod ethernet2_header;
+pub use ethernet2_header::*;
+
+mod ethernet2_header_slice;
+pub use ethernet2_header_slice::*;
+
+mod ethernet2_slice;
+pub use ethernet2_slice::*;
+
+mod link_header;
+pub use link_header::*;
+
+mod link_slice;
+pub use link_slice::*;
+
+mod linux_nonstandard_ether_type;
+pub use linux_nonstandard_ether_type::*;
+
+mod linux_sll_header;
+pub use linux_sll_header::*;
+
+mod linux_sll_header_slice;
+pub use linux_sll_header_slice::*;
+
+mod linux_sll_packet_type;
+pub use linux_sll_packet_type::*;
+
+mod linux_sll_payload_slice;
+pub use linux_sll_payload_slice::*;
+
+mod linux_sll_protocol_type;
+pub use linux_sll_protocol_type::*;
+
+mod linux_sll_slice;
+pub use linux_sll_slice::*;
+
+mod single_vlan_header;
+pub use single_vlan_header::*;
+
+mod single_vlan_header_slice;
+pub use single_vlan_header_slice::*;
+
+mod single_vlan_slice;
+pub use single_vlan_slice::*;
+
+mod vlan_header;
+pub use vlan_header::*;
+
+mod vlan_id;
+pub use vlan_id::*;
+
+mod vlan_pcp;
+pub use vlan_pcp::*;
+
+mod vlan_slice;
+pub use vlan_slice::*;
diff --git a/crates/etherparse/src/link/single_vlan_slice.rs b/crates/etherparse/src/link/single_vlan_slice.rs
index ca3ce29..77a060e 100644
--- a/crates/etherparse/src/link/single_vlan_slice.rs
+++ b/crates/etherparse/src/link/single_vlan_slice.rs
@@ -133,7 +133,7 @@
}
}
-impl<'a> core::fmt::Debug for SingleVlanSlice<'a> {
+impl core::fmt::Debug for SingleVlanSlice<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("SingleVlanSlice")
.field("header", &self.to_header())
diff --git a/crates/etherparse/src/net/arp_eth_ipv4_packet.rs b/crates/etherparse/src/net/arp_eth_ipv4_packet.rs
new file mode 100644
index 0000000..0bf5546
--- /dev/null
+++ b/crates/etherparse/src/net/arp_eth_ipv4_packet.rs
@@ -0,0 +1,212 @@
+use core::net::Ipv4Addr;
+
+use crate::{ArpHardwareId, EtherType};
+
+use super::{ArpOperation, ArpPacket};
+
+/// An ethernet & IPv4 "Address Resolution Protocol" Packet (a specific
+/// version of [`crate::ArpPacket`]).
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub struct ArpEthIpv4Packet {
+ /// Specifies the operation that the sender is performing.
+ pub operation: ArpOperation,
+
+ /// Sender MAC address.
+ pub sender_mac: [u8; 6],
+
+ /// Sender IPv4 address.
+ pub sender_ipv4: [u8; 4],
+
+ /// Sender MAC address.
+ pub target_mac: [u8; 6],
+
+ /// Target IPv4 address.
+ pub target_ipv4: [u8; 4],
+}
+
+impl ArpEthIpv4Packet {
+ /// Number of octets/bytes of the serialized packet.
+ pub const LEN: usize = 8 + 6 * 2 + 4 * 2;
+
+ /// Sender IPv4 address as [`core::net::Ipv4Addr`].
+ #[inline]
+ pub const fn sender_ipv4_addr(&self) -> Ipv4Addr {
+ Ipv4Addr::new(
+ self.sender_ipv4[0],
+ self.sender_ipv4[1],
+ self.sender_ipv4[2],
+ self.sender_ipv4[3],
+ )
+ }
+
+ /// Target IPv4 address as [`core::net::Ipv4Addr`].
+ #[inline]
+ pub const fn target_ipv4_addr(&self) -> Ipv4Addr {
+ Ipv4Addr::new(
+ self.target_ipv4[0],
+ self.target_ipv4[1],
+ self.target_ipv4[2],
+ self.target_ipv4[3],
+ )
+ }
+
+ /// Returns the serialized header.
+ pub const fn to_bytes(&self) -> [u8; Self::LEN] {
+ const ETH_HW_TYPE: [u8; 2] = ArpHardwareId::ETHERNET.0.to_be_bytes();
+ const IPV4_ETH_TYPE: [u8; 2] = EtherType::IPV4.0.to_be_bytes();
+ let op = self.operation.0.to_be_bytes();
+ [
+ ETH_HW_TYPE[0],
+ ETH_HW_TYPE[1],
+ IPV4_ETH_TYPE[0],
+ IPV4_ETH_TYPE[1],
+ 6,
+ 4,
+ op[0],
+ op[1],
+ self.sender_mac[0],
+ self.sender_mac[1],
+ self.sender_mac[2],
+ self.sender_mac[3],
+ self.sender_mac[4],
+ self.sender_mac[5],
+ self.sender_ipv4[0],
+ self.sender_ipv4[1],
+ self.sender_ipv4[2],
+ self.sender_ipv4[3],
+ self.target_mac[0],
+ self.target_mac[1],
+ self.target_mac[2],
+ self.target_mac[3],
+ self.target_mac[4],
+ self.target_mac[5],
+ self.target_ipv4[0],
+ self.target_ipv4[1],
+ self.target_ipv4[2],
+ self.target_ipv4[3],
+ ]
+ }
+
+ /// Converts the packet to generic arp packet.
+ #[inline]
+ pub const fn to_arp_packet(&self) -> ArpPacket {
+ // SAFETY: This is safe as
+ // * Both the hardware addresses have matching length 6 which is bellow the max of 255.
+ // * Both the protocol addresses have matching length 6 which is bellow the max of 255.
+ unsafe {
+ ArpPacket::new_unchecked(
+ ArpHardwareId::ETHERNET,
+ EtherType::IPV4,
+ self.operation,
+ &self.sender_mac,
+ &self.sender_ipv4,
+ &self.target_mac,
+ &self.target_ipv4,
+ )
+ }
+ }
+}
+
+impl From<ArpEthIpv4Packet> for ArpPacket {
+ fn from(value: ArpEthIpv4Packet) -> Self {
+ value.to_arp_packet()
+ }
+}
+
+impl TryFrom<ArpPacket> for ArpEthIpv4Packet {
+ type Error = crate::err::arp::ArpEthIpv4FromError;
+
+ fn try_from(value: ArpPacket) -> Result<Self, Self::Error> {
+ value.try_eth_ipv4()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::test_gens::*;
+ use proptest::prelude::*;
+
+ proptest! {
+ #[test]
+ fn sender_ipv4_addr(
+ arp in arp_eth_ipv4_packet_any()
+ ) {
+ assert_eq!(
+ arp.sender_ipv4_addr(),
+ Ipv4Addr::new(
+ arp.sender_ipv4[0],
+ arp.sender_ipv4[1],
+ arp.sender_ipv4[2],
+ arp.sender_ipv4[3]
+ )
+ )
+ }
+ }
+
+ proptest! {
+ #[test]
+ fn target_ipv4_addr(
+ arp in arp_eth_ipv4_packet_any()
+ ) {
+ assert_eq!(
+ arp.target_ipv4_addr(),
+ Ipv4Addr::new(
+ arp.target_ipv4[0],
+ arp.target_ipv4[1],
+ arp.target_ipv4[2],
+ arp.target_ipv4[3]
+ )
+ )
+ }
+ }
+
+ proptest! {
+ #[test]
+ fn to_bytes(
+ arp in arp_eth_ipv4_packet_any()
+ ) {
+ assert_eq!(
+ &arp.to_bytes()[..],
+ &arp.to_arp_packet().to_bytes()[..]
+ );
+ }
+ }
+
+ proptest! {
+ #[test]
+ fn to_arp_packet(
+ arp in arp_eth_ipv4_packet_any()
+ ) {
+ let actual = arp.to_arp_packet();
+ assert_eq!(ArpHardwareId::ETHERNET, actual.hw_addr_type);
+ assert_eq!(EtherType::IPV4, actual.proto_addr_type);
+ assert_eq!(6, actual.hw_addr_size());
+ assert_eq!(4, actual.protocol_addr_size());
+ assert_eq!(&arp.target_mac[..], actual.target_hw_addr());
+ assert_eq!(&arp.target_ipv4[..], actual.target_protocol_addr());
+ assert_eq!(&arp.sender_mac[..], actual.sender_hw_addr());
+ assert_eq!(&arp.sender_ipv4[..], actual.sender_protocol_addr());
+ }
+ }
+
+ proptest! {
+ #[test]
+ fn into_arp_packet(
+ arp in arp_eth_ipv4_packet_any()
+ ) {
+ let actual = ArpPacket::from(arp.clone());
+ assert_eq!(actual, arp.to_arp_packet());
+ }
+ }
+
+ proptest! {
+ #[test]
+ fn try_from_arp_packet(
+ arp in arp_packet_any()
+ ) {
+ let actual = ArpEthIpv4Packet::try_from(arp.clone());
+ assert_eq!(actual, arp.clone().try_eth_ipv4());
+ }
+ }
+}
diff --git a/crates/etherparse/src/link/arp_hardware_id.rs b/crates/etherparse/src/net/arp_hardware_id.rs
similarity index 76%
rename from crates/etherparse/src/link/arp_hardware_id.rs
rename to crates/etherparse/src/net/arp_hardware_id.rs
index 2f89ce4..351a843 100644
--- a/crates/etherparse/src/link/arp_hardware_id.rs
+++ b/crates/etherparse/src/net/arp_hardware_id.rs
@@ -6,40 +6,153 @@
/// ```
/// use etherparse::ArpHardwareId;
///
-/// assert_eq!(ArpHardwareId::ETHER.0, 0x0001);
-/// assert_eq!(ArpHardwareId::ETHER, ArpHardwareId(0x0001));
+/// assert_eq!(ArpHardwareId::ETHERNET.0, 0x0001);
+/// assert_eq!(ArpHardwareId::ETHERNET, ArpHardwareId(0x0001));
///
/// // convert to ArpHardwareId using the from & into trait
/// let arp_hrd_id: ArpHardwareId = 0x0001.into();
-/// assert_eq!(ArpHardwareId::ETHER, arp_hrd_id);
+/// assert_eq!(ArpHardwareId::ETHERNET, arp_hrd_id);
///
/// // convert to u16 using the from & into trait
-/// let num: u16 = ArpHardwareId::ETHER.into();
+/// let num: u16 = ArpHardwareId::ETHERNET.into();
/// assert_eq!(0x0001, num);
/// ```
///
-
-#[derive(Clone, Copy, Eq, PartialEq, Default, Hash)]
+#[derive(Clone, Copy, Eq, PartialEq, Default, Ord, PartialOrd, Hash)]
pub struct ArpHardwareId(pub u16);
impl ArpHardwareId {
- // Numbers sourced from https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/include/uapi/linux/if_arp.h?id=e33c4963bf536900f917fb65a687724d5539bc21
+ // Numbers sourced from
+ // * https://www.iana.org/assignments/arp-parameters/arp-parameters.xhtml
+ // * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/include/uapi/linux/if_arp.h?id=e33c4963bf536900f917fb65a687724d5539bc21
+ /// Reserved
pub const NETROM: ArpHardwareId = Self(0);
+
+ /// Ethernet (10Mb)
+ pub const ETHERNET: ArpHardwareId = Self(1);
+
+ /// Deprecated use [`ArpHardwareId::ETHERNET`] instead
+ #[deprecated(since = "0.17.0", note = "Use `ArpHardwareId::ETHERNET` instead")]
pub const ETHER: ArpHardwareId = Self(1);
+
+ /// Experimental Ethernet (3Mb)
pub const EETHER: ArpHardwareId = Self(2);
+
+ /// Amateur Radio AX.25
pub const AX25: ArpHardwareId = Self(3);
+
+ /// Proteon ProNET Token Ring
pub const PRONET: ArpHardwareId = Self(4);
+
+ /// Chaos
pub const CHAOS: ArpHardwareId = Self(5);
+
+ /// IEEE 802 Networks
pub const IEEE802: ArpHardwareId = Self(6);
+
+ /// ARCNET
pub const ARCNET: ArpHardwareId = Self(7);
+
+ /// Hyperchannel
+ pub const HYPERCHANNEL: ArpHardwareId = Self(8);
+
+ /// APPLEtalk
pub const APPLETLK: ArpHardwareId = Self(8);
+
+ /// Lanstar
+ pub const LANSTAR: ArpHardwareId = Self(9);
+
+ /// Autonet Short Address
+ pub const AUTONET_SHORT_ADDRESS: ArpHardwareId = Self(10);
+
+ /// LocalTalk
+ pub const LOCAL_TALK: ArpHardwareId = Self(11);
+
+ /// LocalNet (IBM PCNet or SYTEK LocalNET)
+ pub const LOCAL_NET: ArpHardwareId = Self(12);
+
+ /// Ultra link
+ pub const ULTRA_LINK: ArpHardwareId = Self(13);
+
+ /// SMDS
+ pub const SMDS: ArpHardwareId = Self(14);
+
+ /// DLCI (alias for [`ArpHardwareId::FRAME_RELAY`])
pub const DLCI: ArpHardwareId = Self(15);
+
+ /// Frame Relay (alias for [`ArpHardwareId::DLCI`])
+ pub const FRAME_RELAY: ArpHardwareId = Self(15);
+
+ /// Asynchronous Transmission Mode (ATM) \[JXB2\]
+ pub const ATM_JXB2: ArpHardwareId = Self(16);
+
+ /// HDLC
+ pub const HDLC: ArpHardwareId = Self(17);
+
+ /// Fibre Channel
+ pub const FIBRE_CHANNEL: ArpHardwareId = Self(18);
+
+ /// Asynchronous Transmission Mode (ATM) \[RFC2225\]
pub const ATM: ArpHardwareId = Self(19);
+
+ /// Serial Line
+ pub const SERIAL_LINE: ArpHardwareId = Self(20);
+
+ /// Asynchronous Transmission Mode (ATM) \[Mike_Burrows\]
+ pub const ATM_21: ArpHardwareId = Self(21);
+
+ /// MIL-STD-188-220
+ pub const MIL_STD_188_220: ArpHardwareId = Self(22);
+
+ /// Metricom
pub const METRICOM: ArpHardwareId = Self(23);
+
+ /// IEEE 1394.1995
pub const IEEE1394: ArpHardwareId = Self(24);
+
+ /// MAPOS
+ pub const MAPOS: ArpHardwareId = Self(25);
+
+ /// Twinaxial
+ pub const TWINAXIAL: ArpHardwareId = Self(26);
+
+ /// EUI-64
pub const EUI64: ArpHardwareId = Self(27);
+
+ /// HIPARP
+ pub const HIPARP: ArpHardwareId = Self(28);
+
+ /// IP and ARP over ISO 7816-3
+ pub const IP_AND_ARP_OVER_ISO_7816_3: ArpHardwareId = Self(29);
+
+ /// ARPSec
+ pub const ARPSEC: ArpHardwareId = Self(30);
+
+ /// IPsec tunnel
+ pub const IPSEC_TUNNEL: ArpHardwareId = Self(31);
+
+ /// InfiniBand
pub const INFINIBAND: ArpHardwareId = Self(32);
+
+ /// TIA-102 Project 25 Common Air Interface (CAI)
+ pub const CAI: ArpHardwareId = Self(33);
+
+ /// Wiegand Interface
+ pub const WIEGAND_INTERFACE: ArpHardwareId = Self(34);
+
+ /// Pure IP
+ pub const PURE_IP: ArpHardwareId = Self(35);
+
+ /// HW_EXP1
+ pub const HW_EXP1: ArpHardwareId = Self(36);
+
+ /// HFI
+ pub const HFI: ArpHardwareId = Self(37);
+
+ /// Unified Bus (UB)
+ pub const UNIFIED_BUS: ArpHardwareId = Self(38);
+
pub const SLIP: ArpHardwareId = Self(256);
pub const CSLIP: ArpHardwareId = Self(257);
pub const SLIP6: ArpHardwareId = Self(258);
@@ -107,26 +220,54 @@
}
}
-impl core::fmt::Display for ArpHardwareId {
- // Names sourced from https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/include/uapi/linux/if_arp.h?id=e33c4963bf536900f917fb65a687724d5539bc21
-
+impl core::fmt::Debug for ArpHardwareId {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match *self {
Self::NETROM => write!(f, "{} (from KA9Q: NET/ROM pseudo)", self.0),
- Self::ETHER => write!(f, "{} (Ethernet 10Mbps)", self.0),
+ Self::ETHERNET => write!(f, "{} (Ethernet)", self.0),
Self::EETHER => write!(f, "{} (Experimental Ethernet)", self.0),
Self::AX25 => write!(f, "{} (AX.25 Level 2)", self.0),
Self::PRONET => write!(f, "{} (PROnet token ring)", self.0),
Self::CHAOS => write!(f, "{} (Chaosnet)", self.0),
Self::IEEE802 => write!(f, "{} (IEEE 802.2 Ethernet/TR/TB)", self.0),
Self::ARCNET => write!(f, "{} (ARCnet)", self.0),
- Self::APPLETLK => write!(f, "{} (APPLEtalk)", self.0),
+ Self::APPLETLK => write!(f, "{} (APPLEtalk or Hyperchannel)", self.0),
+ Self::LANSTAR => write!(f, "{} (Lanstar)", self.0),
+ Self::AUTONET_SHORT_ADDRESS => write!(f, "{} (Autonet Short Address)", self.0),
+ Self::LOCAL_TALK => write!(f, "{} (LocalTalk)", self.0),
+ Self::LOCAL_NET => write!(f, "{} (LocalNet)", self.0),
+ Self::ULTRA_LINK => write!(f, "{} (Ultra link)", self.0),
+ Self::SMDS => write!(f, "{} (SMDS)", self.0),
Self::DLCI => write!(f, "{} (Frame Relay DLCI)", self.0),
+ Self::ATM_JXB2 => write!(f, "{} (Asynchronous Transmission Mode (ATM) JXB2)", self.0),
+ Self::HDLC => write!(f, "{} (HDLC)", self.0),
+ Self::FIBRE_CHANNEL => write!(f, "{} (Fibre Channel)", self.0),
Self::ATM => write!(f, "{} (ATM)", self.0),
+ Self::SERIAL_LINE => write!(f, "{} (Serial Line)", self.0),
+ Self::ATM_21 => write!(f, "{} (Asynchronous Transmission Mode (ATM))", self.0),
+ Self::MIL_STD_188_220 => write!(f, "{} (MIL-STD-188-220)", self.0),
Self::METRICOM => write!(f, "{} (Metricom STRIP (new IANA id))", self.0),
Self::IEEE1394 => write!(f, "{} (IEEE 1394 IPv4 - RFC 2734)", self.0),
+ Self::MAPOS => write!(f, "{} (MAPOS)", self.0),
+ Self::TWINAXIAL => write!(f, "{} (Twinaxial)", self.0),
Self::EUI64 => write!(f, "{} (EUI-64)", self.0),
+ Self::HIPARP => write!(f, "{} (HIPARP)", self.0),
+ Self::IP_AND_ARP_OVER_ISO_7816_3 => {
+ write!(f, "{} (IP and ARP over ISO 7816-3)", self.0)
+ }
+ Self::ARPSEC => write!(f, "{} (ARPSec)", self.0),
+ Self::IPSEC_TUNNEL => write!(f, "{} (IPsec tunnel)", self.0),
Self::INFINIBAND => write!(f, "{} (InfiniBand)", self.0),
+ Self::CAI => write!(
+ f,
+ "{} (TIA-102 Project 25 Common Air Interface (CAI))",
+ self.0
+ ),
+ Self::WIEGAND_INTERFACE => write!(f, "{} (Wiegand Interface)", self.0),
+ Self::PURE_IP => write!(f, "{} (Pure IP)", self.0),
+ Self::HW_EXP1 => write!(f, "{} (HW_EXP1)", self.0),
+ Self::HFI => write!(f, "{} (HFI)", self.0),
+ Self::UNIFIED_BUS => write!(f, "{} (Unified Bus (UB))", self.0),
Self::SLIP => write!(f, "{} (SLIP)", self.0),
Self::CSLIP => write!(f, "{} (CSLIP)", self.0),
Self::SLIP6 => write!(f, "{} (SLIP6)", self.0),
@@ -183,12 +324,6 @@
}
}
-impl core::fmt::Debug for ArpHardwareId {
- fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
- core::fmt::Display::fmt(&self, f)
- }
-}
-
#[cfg(test)]
mod test {
use super::*;
@@ -197,7 +332,7 @@
#[test]
fn to_u16() {
assert_eq!(0, u16::from(ArpHardwareId::NETROM));
- assert_eq!(1, u16::from(ArpHardwareId::ETHER));
+ assert_eq!(1, u16::from(ArpHardwareId::ETHERNET));
assert_eq!(2, u16::from(ArpHardwareId::EETHER));
assert_eq!(3, u16::from(ArpHardwareId::AX25));
assert_eq!(4, u16::from(ArpHardwareId::PRONET));
@@ -273,7 +408,7 @@
#[test]
fn from_u16() {
assert_eq!(ArpHardwareId::from(0), ArpHardwareId::NETROM);
- assert_eq!(ArpHardwareId::from(1), ArpHardwareId::ETHER);
+ assert_eq!(ArpHardwareId::from(1), ArpHardwareId::ETHERNET);
assert_eq!(ArpHardwareId::from(2), ArpHardwareId::EETHER);
assert_eq!(ArpHardwareId::from(3), ArpHardwareId::AX25);
assert_eq!(ArpHardwareId::from(4), ArpHardwareId::PRONET);
@@ -350,20 +485,59 @@
fn display_dbg() {
let pairs = &[
(ArpHardwareId::NETROM, "0 (from KA9Q: NET/ROM pseudo)"),
- (ArpHardwareId::ETHER, "1 (Ethernet 10Mbps)"),
+ (ArpHardwareId::ETHERNET, "1 (Ethernet)"),
(ArpHardwareId::EETHER, "2 (Experimental Ethernet)"),
(ArpHardwareId::AX25, "3 (AX.25 Level 2)"),
(ArpHardwareId::PRONET, "4 (PROnet token ring)"),
(ArpHardwareId::CHAOS, "5 (Chaosnet)"),
(ArpHardwareId::IEEE802, "6 (IEEE 802.2 Ethernet/TR/TB)"),
(ArpHardwareId::ARCNET, "7 (ARCnet)"),
- (ArpHardwareId::APPLETLK, "8 (APPLEtalk)"),
+ (ArpHardwareId::APPLETLK, "8 (APPLEtalk or Hyperchannel)"),
+ (ArpHardwareId::LANSTAR, "9 (Lanstar)"),
+ (
+ ArpHardwareId::AUTONET_SHORT_ADDRESS,
+ "10 (Autonet Short Address)",
+ ),
+ (ArpHardwareId::LOCAL_TALK, "11 (LocalTalk)"),
+ (ArpHardwareId::LOCAL_NET, "12 (LocalNet)"),
+ (ArpHardwareId::ULTRA_LINK, "13 (Ultra link)"),
+ (ArpHardwareId::SMDS, "14 (SMDS)"),
(ArpHardwareId::DLCI, "15 (Frame Relay DLCI)"),
+ (
+ ArpHardwareId::ATM_JXB2,
+ "16 (Asynchronous Transmission Mode (ATM) JXB2)",
+ ),
+ (ArpHardwareId::HDLC, "17 (HDLC)"),
+ (ArpHardwareId::FIBRE_CHANNEL, "18 (Fibre Channel)"),
(ArpHardwareId::ATM, "19 (ATM)"),
+ (ArpHardwareId::SERIAL_LINE, "20 (Serial Line)"),
+ (
+ ArpHardwareId::ATM_21,
+ "21 (Asynchronous Transmission Mode (ATM))",
+ ),
+ (ArpHardwareId::MIL_STD_188_220, "22 (MIL-STD-188-220)"),
(ArpHardwareId::METRICOM, "23 (Metricom STRIP (new IANA id))"),
(ArpHardwareId::IEEE1394, "24 (IEEE 1394 IPv4 - RFC 2734)"),
+ (ArpHardwareId::MAPOS, "25 (MAPOS)"),
+ (ArpHardwareId::TWINAXIAL, "26 (Twinaxial)"),
(ArpHardwareId::EUI64, "27 (EUI-64)"),
+ (ArpHardwareId::HIPARP, "28 (HIPARP)"),
+ (
+ ArpHardwareId::IP_AND_ARP_OVER_ISO_7816_3,
+ "29 (IP and ARP over ISO 7816-3)",
+ ),
+ (ArpHardwareId::ARPSEC, "30 (ARPSec)"),
+ (ArpHardwareId::IPSEC_TUNNEL, "31 (IPsec tunnel)"),
(ArpHardwareId::INFINIBAND, "32 (InfiniBand)"),
+ (
+ ArpHardwareId::CAI,
+ "33 (TIA-102 Project 25 Common Air Interface (CAI))",
+ ),
+ (ArpHardwareId::WIEGAND_INTERFACE, "34 (Wiegand Interface)"),
+ (ArpHardwareId::PURE_IP, "35 (Pure IP)"),
+ (ArpHardwareId::HW_EXP1, "36 (HW_EXP1)"),
+ (ArpHardwareId::HFI, "37 (HFI)"),
+ (ArpHardwareId::UNIFIED_BUS, "38 (Unified Bus (UB))"),
(ArpHardwareId::SLIP, "256 (SLIP)"),
(ArpHardwareId::CSLIP, "257 (CSLIP)"),
(ArpHardwareId::SLIP6, "258 (SLIP6)"),
@@ -433,9 +607,8 @@
(ArpHardwareId::from(0x1234), "0x1234"),
];
- for (ether_type, str_value) in pairs {
- assert_eq!(str_value, &format!("{}", ether_type));
- assert_eq!(str_value, &format!("{:?}", ether_type));
+ for (arp_hw_id, str_value) in pairs {
+ assert_eq!(str_value, &format!("{:?}", arp_hw_id));
}
}
@@ -449,7 +622,7 @@
fn clone_eq() {
let values = &[
ArpHardwareId::NETROM,
- ArpHardwareId::ETHER,
+ ArpHardwareId::ETHERNET,
ArpHardwareId::EETHER,
ArpHardwareId::AX25,
ArpHardwareId::PRONET,
diff --git a/crates/etherparse/src/net/arp_operation.rs b/crates/etherparse/src/net/arp_operation.rs
new file mode 100644
index 0000000..a8c9f73
--- /dev/null
+++ b/crates/etherparse/src/net/arp_operation.rs
@@ -0,0 +1,25 @@
+/// Operation field value in an ARP packet.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
+pub struct ArpOperation(pub u16);
+
+impl ArpOperation {
+ pub const REQUEST: ArpOperation = ArpOperation(1);
+ pub const REPLY: ArpOperation = ArpOperation(2);
+}
+
+impl From<u16> for ArpOperation {
+ #[inline]
+ fn from(raw: u16) -> Self {
+ ArpOperation(raw)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::ArpOperation;
+
+ #[test]
+ pub fn from_u16() {
+ assert_eq!(ArpOperation::from(12), ArpOperation(12))
+ }
+}
diff --git a/crates/etherparse/src/net/arp_packet.rs b/crates/etherparse/src/net/arp_packet.rs
new file mode 100644
index 0000000..efbc0be
--- /dev/null
+++ b/crates/etherparse/src/net/arp_packet.rs
@@ -0,0 +1,1100 @@
+use arrayvec::ArrayVec;
+use err::arp::{ArpHwAddrError, ArpNewError, ArpProtoAddrError};
+
+use crate::*;
+use core::mem::MaybeUninit;
+
+/// "Address Resolution Protocol" Packet.
+#[derive(Clone)]
+pub struct ArpPacket {
+ /// Network link protocol type (e.g. `ArpHardwareId::ETHERNET`).
+ pub hw_addr_type: ArpHardwareId,
+
+ /// Protocol for which the ARP request is intended (e.g. `EtherType::IPV4`).
+ pub proto_addr_type: EtherType,
+
+ /// Length (in octets) of a hardware address (e.g. 6 for Ethernet).
+ hw_addr_size: u8,
+
+ /// Length (in octets) of internetwork addresses (e.g. 4 for IPv4 or 16 for IPv6).
+ proto_addr_size: u8,
+
+ /// Specifies the operation that the sender is performing
+ pub operation: ArpOperation,
+
+ /// Buffer containing the sender hardware address (e.g. MAC address).
+ sender_hw_addr_buf: [MaybeUninit<u8>; 0xff],
+
+ /// Buffer containing the sender protocol address (e.g. IPv4 address).
+ sender_protocol_addr_buf: [MaybeUninit<u8>; 0xff],
+
+ /// Buffer containing the target hardware address (e.g. MAC address).
+ target_hw_addr_buf: [MaybeUninit<u8>; 0xff],
+
+ /// Buffer containing the target protocol address (e.g. IPv4 address)..
+ target_protocol_addr_buf: [MaybeUninit<u8>; 0xff],
+}
+
+impl ArpPacket {
+ /// Maximum length of an ARP packet in bytes/octets.
+ ///
+ /// This number is calculated by taking the maximum values
+ /// that `hw_addr_size`(255/u8::MAX) & `proto_addr_size` (255/u8::MAX)
+ /// can take and calculate the maximum packet size from that.
+ pub const MAX_LEN: usize = 8 + 2 * 255 + 2 * 255;
+
+ /// Create a new ARP packet with the given values.
+ pub const fn new(
+ hw_addr_type: ArpHardwareId,
+ proto_addr_type: EtherType,
+ operation: ArpOperation,
+ sender_hw_addr: &[u8],
+ sender_protocol_addr: &[u8],
+ target_hw_addr: &[u8],
+ target_protocol_addr: &[u8],
+ ) -> Result<ArpPacket, ArpNewError> {
+ if sender_hw_addr.len() != target_hw_addr.len() {
+ return Err(ArpNewError::HwAddr(ArpHwAddrError::LenNonMatching(
+ sender_hw_addr.len(),
+ target_hw_addr.len(),
+ )));
+ }
+ if sender_protocol_addr.len() != target_protocol_addr.len() {
+ return Err(ArpNewError::ProtoAddr(ArpProtoAddrError::LenNonMatching(
+ sender_protocol_addr.len(),
+ target_protocol_addr.len(),
+ )));
+ }
+ if sender_hw_addr.len() > 255 {
+ return Err(ArpNewError::HwAddr(ArpHwAddrError::LenTooBig(
+ sender_hw_addr.len(),
+ )));
+ }
+ if sender_protocol_addr.len() > 255 {
+ return Err(ArpNewError::ProtoAddr(ArpProtoAddrError::LenTooBig(
+ sender_protocol_addr.len(),
+ )));
+ }
+ Ok(ArpPacket {
+ hw_addr_type,
+ proto_addr_type,
+ // cast ok as we verfied the len to be less equal then 255.
+ hw_addr_size: sender_hw_addr.len() as u8,
+ // cast ok as we verfied the len to be less equal then 255.
+ proto_addr_size: sender_protocol_addr.len() as u8,
+ operation,
+ sender_hw_addr_buf: {
+ let mut buf: [MaybeUninit<u8>; 255] = [const { MaybeUninit::uninit() }; 255];
+ // SAFETY: Safe as
+ // * sender_hw_addr.len() is guranteed to be <= 255 (checked in if above)
+ // * memory areas guranteed to be non overlapping (buf created in this function).
+ unsafe {
+ core::ptr::copy_nonoverlapping(
+ sender_hw_addr.as_ptr(),
+ buf.as_mut_ptr() as *mut u8,
+ sender_hw_addr.len(),
+ );
+ }
+ buf
+ },
+ sender_protocol_addr_buf: {
+ let mut buf: [MaybeUninit<u8>; 255] = [const { MaybeUninit::uninit() }; 255];
+ // SAFETY: Safe as
+ // * sender_protocol_addr.len() is guranteed to be <= 255 (checked in if above)
+ // * memory areas guranteed to be non overlapping (buf created in this function).
+ unsafe {
+ core::ptr::copy_nonoverlapping(
+ sender_protocol_addr.as_ptr(),
+ buf.as_mut_ptr() as *mut u8,
+ sender_protocol_addr.len(),
+ );
+ }
+ buf
+ },
+ target_hw_addr_buf: {
+ let mut buf: [MaybeUninit<u8>; 255] = [const { MaybeUninit::uninit() }; 255];
+ // SAFETY: Safe as
+ // * target_hw_addr.len() is guranteed to be <= 255 (checked in if above)
+ // * memory areas guranteed to be non overlapping (buf created in this function).
+ unsafe {
+ core::ptr::copy_nonoverlapping(
+ target_hw_addr.as_ptr(),
+ buf.as_mut_ptr() as *mut u8,
+ target_hw_addr.len(),
+ );
+ }
+ buf
+ },
+ target_protocol_addr_buf: {
+ let mut buf: [MaybeUninit<u8>; 255] = [const { MaybeUninit::uninit() }; 255];
+ // SAFETY: Safe as
+ // * target_protocol_addr.len() is guranteed to be <= 255 (checked in if above)
+ // * memory areas guranteed to be non overlapping (buf created in this function).
+ unsafe {
+ core::ptr::copy_nonoverlapping(
+ target_protocol_addr.as_ptr(),
+ buf.as_mut_ptr() as *mut u8,
+ target_protocol_addr.len(),
+ );
+ }
+ buf
+ },
+ })
+ }
+
+ /// Create a new ARP packet with the given values without checking
+ /// hardware & protocol address sizes.
+ ///
+ /// # Safety
+ ///
+ /// The caller must gurantee that
+ ///
+ /// * `sender_hw_addr` & `target_hw_addr` have the same length and the length must be smaller or equal than 255.
+ /// * `sender_protocol_addr` & `target_protocol_addr` have the same length and the length must be smaller or equal than 255.
+ ///
+ /// The gurantees the caller must fullfill are equal to the following
+ /// preconditions:
+ ///
+ /// * `sender_hw_addr.len() == target_hw_addr.len()`
+ /// * `sender_hw_addr.len() <= 255`
+ /// * `target_hw_addr.len() <= 255`
+ /// * `sender_protocol_addr.len() == target_protocol_addr.len()`
+ /// * `sender_protocol_addr.len() <= 255`
+ /// * `target_protocol_addr.len() <= 255`
+ pub const unsafe fn new_unchecked(
+ hw_addr_type: ArpHardwareId,
+ proto_addr_type: EtherType,
+ operation: ArpOperation,
+ sender_hw_addr: &[u8],
+ sender_protocol_addr: &[u8],
+ target_hw_addr: &[u8],
+ target_protocol_addr: &[u8],
+ ) -> ArpPacket {
+ debug_assert!(sender_hw_addr.len() == target_hw_addr.len());
+ debug_assert!(sender_protocol_addr.len() == target_protocol_addr.len());
+ debug_assert!(sender_hw_addr.len() <= 255);
+ debug_assert!(sender_protocol_addr.len() <= 255);
+
+ ArpPacket {
+ hw_addr_type,
+ proto_addr_type,
+ // cast ok as we verfied the len to be less equal then 255.
+ hw_addr_size: sender_hw_addr.len() as u8,
+ // cast ok as we verfied the len to be less equal then 255.
+ proto_addr_size: sender_protocol_addr.len() as u8,
+ operation,
+ sender_hw_addr_buf: {
+ let mut buf: [MaybeUninit<u8>; 255] = [const { MaybeUninit::uninit() }; 255];
+ // SAFETY: Safe as
+ // * the caller must gurantee that sender_hw_addr.len() is <= 255
+ // * memory areas guranteed to be non overlapping (buf created in this function).
+ unsafe {
+ core::ptr::copy_nonoverlapping(
+ sender_hw_addr.as_ptr(),
+ buf.as_mut_ptr() as *mut u8,
+ sender_hw_addr.len(),
+ );
+ }
+ buf
+ },
+ sender_protocol_addr_buf: {
+ let mut buf: [MaybeUninit<u8>; 255] = [const { MaybeUninit::uninit() }; 255];
+ // SAFETY: Safe as
+ // * the caller must gurantee that sender_protocol_addr.len() is <= 255
+ // * memory areas guranteed to be non overlapping (buf created in this function).
+ unsafe {
+ core::ptr::copy_nonoverlapping(
+ sender_protocol_addr.as_ptr(),
+ buf.as_mut_ptr() as *mut u8,
+ sender_protocol_addr.len(),
+ );
+ }
+ buf
+ },
+ target_hw_addr_buf: {
+ let mut buf: [MaybeUninit<u8>; 255] = [const { MaybeUninit::uninit() }; 255];
+ // SAFETY: Safe as
+ // * the caller must gurantee that target_hw_addr.len() is <= 255
+ // * memory areas guranteed to be non overlapping (buf created in this function).
+ unsafe {
+ core::ptr::copy_nonoverlapping(
+ target_hw_addr.as_ptr(),
+ buf.as_mut_ptr() as *mut u8,
+ target_hw_addr.len(),
+ );
+ }
+ buf
+ },
+ target_protocol_addr_buf: {
+ let mut buf: [MaybeUninit<u8>; 255] = [const { MaybeUninit::uninit() }; 255];
+ // SAFETY: Safe as
+ // * the caller must gurantee that target_protocol_addr.len() is <= 255
+ // * memory areas guranteed to be non overlapping (buf created in this function).
+ unsafe {
+ core::ptr::copy_nonoverlapping(
+ target_protocol_addr.as_ptr(),
+ buf.as_mut_ptr() as *mut u8,
+ target_protocol_addr.len(),
+ );
+ }
+ buf
+ },
+ }
+ }
+
+ /// Reads an ARP packet from a slice.
+ pub fn from_slice(slice: &[u8]) -> Result<ArpPacket, err::LenError> {
+ ArpPacketSlice::from_slice(slice).map(|v| v.to_packet())
+ }
+
+ /// Length (in octets) of a hardware address (e.g. 6 for Ethernet).
+ #[inline]
+ pub const fn hw_addr_size(&self) -> u8 {
+ self.hw_addr_size
+ }
+
+ /// Length (in octets) of internetwork addresses (e.g. 4 for IPv4 or 16 for IPv6).
+ #[inline]
+ pub const fn protocol_addr_size(&self) -> u8 {
+ self.proto_addr_size
+ }
+
+ /// Sender hardware address (e.g. MAC address).
+ #[inline]
+ pub const fn sender_hw_addr(&self) -> &[u8] {
+ unsafe {
+ core::slice::from_raw_parts(
+ self.sender_hw_addr_buf.as_ptr() as *const u8,
+ self.hw_addr_size as usize,
+ )
+ }
+ }
+
+ /// Sender protocol address (e.g. IPv4 address).
+ #[inline]
+ pub const fn sender_protocol_addr(&self) -> &[u8] {
+ unsafe {
+ core::slice::from_raw_parts(
+ self.sender_protocol_addr_buf.as_ptr() as *const u8,
+ self.proto_addr_size as usize,
+ )
+ }
+ }
+
+ /// Target hardware address (e.g. MAC address).
+ #[inline]
+ pub const fn target_hw_addr(&self) -> &[u8] {
+ unsafe {
+ core::slice::from_raw_parts(
+ self.target_hw_addr_buf.as_ptr() as *const u8,
+ self.hw_addr_size as usize,
+ )
+ }
+ }
+
+ /// Target protocol address (e.g. IPv4 address).
+ #[inline]
+ pub const fn target_protocol_addr(&self) -> &[u8] {
+ unsafe {
+ core::slice::from_raw_parts(
+ self.target_protocol_addr_buf.as_ptr() as *const u8,
+ self.proto_addr_size as usize,
+ )
+ }
+ }
+
+ /// Set the sender & target hardware addresses (e.g. MAC address).
+ #[inline]
+ pub const fn set_hw_addrs(
+ &mut self,
+ sender_hw_addr: &[u8],
+ target_hw_addr: &[u8],
+ ) -> Result<(), ArpHwAddrError> {
+ if sender_hw_addr.len() != target_hw_addr.len() {
+ return Err(ArpHwAddrError::LenNonMatching(
+ sender_hw_addr.len(),
+ target_hw_addr.len(),
+ ));
+ }
+ if sender_hw_addr.len() > 255 {
+ return Err(ArpHwAddrError::LenTooBig(sender_hw_addr.len()));
+ }
+ {
+ // SAFETY: Safe as
+ // * the caller must gurantee that sender_hw_addr.len() is <= 255
+ // * memory areas guranteed to be non overlapping (buf created in this function).
+ unsafe {
+ core::ptr::copy_nonoverlapping(
+ sender_hw_addr.as_ptr(),
+ self.sender_hw_addr_buf.as_mut_ptr() as *mut u8,
+ sender_hw_addr.len(),
+ );
+ }
+ }
+ {
+ // SAFETY: Safe as
+ // * the caller must gurantee that target_hw_addr.len() is <= 255
+ // * memory areas guranteed to be non overlapping (buf created in this function).
+ unsafe {
+ core::ptr::copy_nonoverlapping(
+ target_hw_addr.as_ptr(),
+ self.target_hw_addr_buf.as_mut_ptr() as *mut u8,
+ target_hw_addr.len(),
+ );
+ }
+ }
+ self.hw_addr_size = sender_hw_addr.len() as u8;
+ Ok(())
+ }
+
+ /// Set the sender & target protocol addresses (e.g. IPv4 address).
+ #[inline]
+ pub const fn set_protocol_addrs(
+ &mut self,
+ sender_protocol_addr: &[u8],
+ target_protocol_addr: &[u8],
+ ) -> Result<(), ArpProtoAddrError> {
+ if sender_protocol_addr.len() != target_protocol_addr.len() {
+ return Err(ArpProtoAddrError::LenNonMatching(
+ sender_protocol_addr.len(),
+ target_protocol_addr.len(),
+ ));
+ }
+ if sender_protocol_addr.len() > 255 {
+ return Err(ArpProtoAddrError::LenTooBig(sender_protocol_addr.len()));
+ }
+ {
+ // SAFETY: Safe as
+ // * sender_protocol_addr.len() is guranteed to be <= 255 (checked in if above)
+ // * memory areas guranteed to be non overlapping (buf created in this function).
+ unsafe {
+ core::ptr::copy_nonoverlapping(
+ sender_protocol_addr.as_ptr(),
+ self.sender_protocol_addr_buf.as_mut_ptr() as *mut u8,
+ sender_protocol_addr.len(),
+ );
+ }
+ }
+ {
+ // SAFETY: Safe as
+ // * target_protocol_addr.len() is guranteed to be <= 255 (checked in if above)
+ // * memory areas guranteed to be non overlapping (buf created in this function).
+ unsafe {
+ core::ptr::copy_nonoverlapping(
+ target_protocol_addr.as_ptr(),
+ self.target_protocol_addr_buf.as_mut_ptr() as *mut u8,
+ target_protocol_addr.len(),
+ );
+ }
+ }
+ self.proto_addr_size = sender_protocol_addr.len() as u8;
+ Ok(())
+ }
+
+ /// Serialized length of this ARP packet.
+ #[inline]
+ pub fn packet_len(&self) -> usize {
+ 8 + usize::from(self.hw_addr_size) * 2 + usize::from(self.proto_addr_size) * 2
+ }
+
+ /// Returns the serialized header.
+ #[inline]
+ pub fn to_bytes(&self) -> ArrayVec<u8, { ArpPacket::MAX_LEN }> {
+ let hw_addr_type = self.hw_addr_type.0.to_be_bytes();
+ let proto_addr_type = self.proto_addr_type.0.to_be_bytes();
+ let operation = self.operation.0.to_be_bytes();
+ let mut result = ArrayVec::<u8, { ArpPacket::MAX_LEN }>::new_const();
+ result.extend([
+ hw_addr_type[0],
+ hw_addr_type[1],
+ proto_addr_type[0],
+ proto_addr_type[1],
+ self.hw_addr_size,
+ self.proto_addr_size,
+ operation[0],
+ operation[1],
+ ]);
+ result.try_extend_from_slice(self.sender_hw_addr()).unwrap();
+ result
+ .try_extend_from_slice(self.sender_protocol_addr())
+ .unwrap();
+ result.try_extend_from_slice(self.target_hw_addr()).unwrap();
+ result
+ .try_extend_from_slice(self.target_protocol_addr())
+ .unwrap();
+ result
+ }
+
+ /// Writes the header to the given writer.
+ #[cfg(feature = "std")]
+ pub fn write<T: std::io::Write + Sized>(&self, writer: &mut T) -> Result<(), std::io::Error> {
+ writer.write_all(&self.to_bytes())?;
+ Ok(())
+ }
+
+ #[cfg(feature = "std")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
+ pub fn read<T: std::io::Read + std::io::Seek + Sized>(
+ reader: &mut T,
+ ) -> Result<ArpPacket, std::io::Error> {
+ let mut start = [0u8; 8];
+ reader.read_exact(&mut start[..])?;
+
+ let mut result = ArpPacket {
+ hw_addr_type: ArpHardwareId(u16::from_be_bytes([start[0], start[1]])),
+ proto_addr_type: EtherType(u16::from_be_bytes([start[2], start[3]])),
+ hw_addr_size: start[4],
+ proto_addr_size: start[5],
+ operation: ArpOperation(u16::from_be_bytes([start[6], start[7]])),
+ sender_hw_addr_buf: [const { MaybeUninit::uninit() }; 255],
+ sender_protocol_addr_buf: [const { MaybeUninit::uninit() }; 255],
+ target_hw_addr_buf: [const { MaybeUninit::uninit() }; 255],
+ target_protocol_addr_buf: [const { MaybeUninit::uninit() }; 255],
+ };
+
+ {
+ // SAFETY: Safe as the maximum u8 value is equal to the array size 255.
+ let sender_hw_addr_slice = unsafe {
+ core::slice::from_raw_parts_mut(
+ result.sender_hw_addr_buf.as_mut_ptr() as *mut u8,
+ result.hw_addr_size as usize,
+ )
+ };
+ reader.read_exact(sender_hw_addr_slice)?;
+ }
+ {
+ // SAFETY: Safe as the maximum u8 value is equal to the array size 255.
+ let sender_protocol_addr = unsafe {
+ core::slice::from_raw_parts_mut(
+ result.sender_protocol_addr_buf.as_mut_ptr() as *mut u8,
+ result.proto_addr_size as usize,
+ )
+ };
+ reader.read_exact(sender_protocol_addr)?;
+ }
+ {
+ // SAFETY: Safe as the maximum u8 value is equal to the array size 255.
+ let target_hw_addr = unsafe {
+ core::slice::from_raw_parts_mut(
+ result.target_hw_addr_buf.as_mut_ptr() as *mut u8,
+ result.hw_addr_size as usize,
+ )
+ };
+ reader.read_exact(target_hw_addr)?;
+ }
+ {
+ // SAFETY: Safe as the maximum u8 value is equal to the array size 255.
+ let target_protocol_addr = unsafe {
+ core::slice::from_raw_parts_mut(
+ result.target_protocol_addr_buf.as_mut_ptr() as *mut u8,
+ result.proto_addr_size as usize,
+ )
+ };
+ reader.read_exact(target_protocol_addr)?;
+ }
+
+ Ok(result)
+ }
+
+ /// Returns an [`ArpEthIpv4Packet`] if the current packet
+ /// is an ethernet & IPv4 ARP packet.
+ pub fn try_eth_ipv4(&self) -> Result<ArpEthIpv4Packet, err::arp::ArpEthIpv4FromError> {
+ use err::arp::ArpEthIpv4FromError::*;
+ if self.hw_addr_type != ArpHardwareId::ETHERNET {
+ return Err(NonMatchingHwType(self.hw_addr_type));
+ }
+ if self.proto_addr_type != EtherType::IPV4 {
+ return Err(NonMatchingProtocolType(self.proto_addr_type));
+ }
+ if self.hw_addr_size != 6 {
+ return Err(NonMatchingHwAddrSize(self.hw_addr_size));
+ }
+ if self.proto_addr_size != 4 {
+ return Err(NonMatchingProtoAddrSize(self.proto_addr_size));
+ }
+ Ok(ArpEthIpv4Packet {
+ operation: self.operation,
+ sender_mac: unsafe {
+ // SAFE as we check above that hw_addr_size is 6
+ [
+ self.sender_hw_addr_buf[0].assume_init(),
+ self.sender_hw_addr_buf[1].assume_init(),
+ self.sender_hw_addr_buf[2].assume_init(),
+ self.sender_hw_addr_buf[3].assume_init(),
+ self.sender_hw_addr_buf[4].assume_init(),
+ self.sender_hw_addr_buf[5].assume_init(),
+ ]
+ },
+ sender_ipv4: unsafe {
+ // SAFE as we check above that proto_addr_size is 6
+ [
+ self.sender_protocol_addr_buf[0].assume_init(),
+ self.sender_protocol_addr_buf[1].assume_init(),
+ self.sender_protocol_addr_buf[2].assume_init(),
+ self.sender_protocol_addr_buf[3].assume_init(),
+ ]
+ },
+ target_mac: unsafe {
+ // SAFE as we check above that hw_addr_size is 6
+ [
+ self.target_hw_addr_buf[0].assume_init(),
+ self.target_hw_addr_buf[1].assume_init(),
+ self.target_hw_addr_buf[2].assume_init(),
+ self.target_hw_addr_buf[3].assume_init(),
+ self.target_hw_addr_buf[4].assume_init(),
+ self.target_hw_addr_buf[5].assume_init(),
+ ]
+ },
+ target_ipv4: unsafe {
+ // SAFE as we check above that proto_addr_size is 6
+ [
+ self.target_protocol_addr_buf[0].assume_init(),
+ self.target_protocol_addr_buf[1].assume_init(),
+ self.target_protocol_addr_buf[2].assume_init(),
+ self.target_protocol_addr_buf[3].assume_init(),
+ ]
+ },
+ })
+ }
+}
+
+impl core::fmt::Debug for ArpPacket {
+ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ f.debug_struct("ArpPacket")
+ .field("hw_addr_type", &self.hw_addr_type)
+ .field("proto_addr_type", &self.proto_addr_type)
+ .field("hw_addr_size", &self.hw_addr_size)
+ .field("proto_addr_size", &self.proto_addr_size)
+ .field("operation", &self.operation)
+ .field("sender_hw_addr", &self.sender_hw_addr())
+ .field("sender_protocol_addr", &self.sender_protocol_addr())
+ .field("target_hw_addr", &self.target_hw_addr())
+ .field("target_protocol_addr", &self.target_protocol_addr())
+ .finish()
+ }
+}
+
+impl core::cmp::PartialEq for ArpPacket {
+ fn eq(&self, other: &Self) -> bool {
+ self.hw_addr_type == other.hw_addr_type
+ && self.proto_addr_type == other.proto_addr_type
+ && self.hw_addr_size == other.hw_addr_size
+ && self.proto_addr_size == other.proto_addr_size
+ && self.operation == other.operation
+ && self.sender_hw_addr() == other.sender_hw_addr()
+ && self.sender_protocol_addr() == other.sender_protocol_addr()
+ && self.target_hw_addr() == other.target_hw_addr()
+ && self.target_protocol_addr() == other.target_protocol_addr()
+ }
+}
+
+impl core::cmp::Eq for ArpPacket {}
+
+impl core::hash::Hash for ArpPacket {
+ fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
+ self.hw_addr_type.hash(state);
+ self.proto_addr_type.hash(state);
+ self.hw_addr_size.hash(state);
+ self.proto_addr_size.hash(state);
+ self.operation.hash(state);
+ self.sender_hw_addr().hash(state);
+ self.sender_protocol_addr().hash(state);
+ self.target_hw_addr().hash(state);
+ self.target_protocol_addr().hash(state);
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::{test_gens::*, *};
+ use err::arp::{ArpHwAddrError, ArpNewError, ArpProtoAddrError};
+ use proptest::prelude::*;
+
+ #[test]
+ fn new() {
+ // ok case
+ {
+ let actual = ArpPacket::new(
+ ArpHardwareId::ASH,
+ EtherType::PROVIDER_BRIDGING,
+ ArpOperation::REQUEST,
+ &[1, 2, 3],
+ &[4, 5, 6, 7, 8],
+ &[9, 10, 11],
+ &[12, 13, 14, 15, 16],
+ )
+ .unwrap();
+ assert_eq!(3, actual.hw_addr_size());
+ assert_eq!(5, actual.protocol_addr_size());
+ assert_eq!(ArpHardwareId::ASH, actual.hw_addr_type);
+ assert_eq!(EtherType::PROVIDER_BRIDGING, actual.proto_addr_type);
+ assert_eq!(ArpOperation::REQUEST, actual.operation);
+ assert_eq!(&[1, 2, 3], actual.sender_hw_addr());
+ assert_eq!(&[4, 5, 6, 7, 8], actual.sender_protocol_addr());
+ assert_eq!(&[9, 10, 11], actual.target_hw_addr());
+ assert_eq!(&[12, 13, 14, 15, 16], actual.target_protocol_addr());
+ }
+
+ // ok case (upper hw size)
+ {
+ let actual = ArpPacket::new(
+ ArpHardwareId::ASH,
+ EtherType::PROVIDER_BRIDGING,
+ ArpOperation::REQUEST,
+ &[1; 255],
+ &[4, 5, 6, 7, 8],
+ &[2; 255],
+ &[12, 13, 14, 15, 16],
+ )
+ .unwrap();
+ assert_eq!(255, actual.hw_addr_size());
+ assert_eq!(5, actual.protocol_addr_size());
+ assert_eq!(ArpHardwareId::ASH, actual.hw_addr_type);
+ assert_eq!(EtherType::PROVIDER_BRIDGING, actual.proto_addr_type);
+ assert_eq!(ArpOperation::REQUEST, actual.operation);
+ assert_eq!(&[1; 255], actual.sender_hw_addr());
+ assert_eq!(&[4, 5, 6, 7, 8], actual.sender_protocol_addr());
+ assert_eq!(&[2; 255], actual.target_hw_addr());
+ assert_eq!(&[12, 13, 14, 15, 16], actual.target_protocol_addr());
+ }
+
+ // ok case (protocol hw size)
+ {
+ let actual = ArpPacket::new(
+ ArpHardwareId::ASH,
+ EtherType::PROVIDER_BRIDGING,
+ ArpOperation::REQUEST,
+ &[3, 4, 5],
+ &[1; 255],
+ &[6, 7, 8],
+ &[2; 255],
+ )
+ .unwrap();
+ assert_eq!(3, actual.hw_addr_size());
+ assert_eq!(255, actual.protocol_addr_size());
+ assert_eq!(ArpHardwareId::ASH, actual.hw_addr_type);
+ assert_eq!(EtherType::PROVIDER_BRIDGING, actual.proto_addr_type);
+ assert_eq!(ArpOperation::REQUEST, actual.operation);
+ assert_eq!(&[3, 4, 5], actual.sender_hw_addr());
+ assert_eq!(&[1; 255], actual.sender_protocol_addr());
+ assert_eq!(&[6, 7, 8], actual.target_hw_addr());
+ assert_eq!(&[2; 255], actual.target_protocol_addr());
+ }
+
+ // hw slice len differ error
+ {
+ let actual = ArpPacket::new(
+ ArpHardwareId::ASH,
+ EtherType::PROVIDER_BRIDGING,
+ ArpOperation::REQUEST,
+ &[1, 2, 3],
+ &[],
+ &[4, 5, 6, 7],
+ &[],
+ );
+ assert_eq!(
+ Err(ArpNewError::HwAddr(ArpHwAddrError::LenNonMatching(3, 4))),
+ actual
+ );
+ }
+ // protocol slice len differ error
+ {
+ let actual = ArpPacket::new(
+ ArpHardwareId::ASH,
+ EtherType::PROVIDER_BRIDGING,
+ ArpOperation::REQUEST,
+ &[],
+ &[1, 2, 3],
+ &[],
+ &[4, 5, 6, 7],
+ );
+ assert_eq!(
+ Err(ArpNewError::ProtoAddr(ArpProtoAddrError::LenNonMatching(
+ 3, 4
+ ))),
+ actual
+ );
+ }
+
+ // hardware length error
+ {
+ let actual = ArpPacket::new(
+ ArpHardwareId::ASH,
+ EtherType::PROVIDER_BRIDGING,
+ ArpOperation::REQUEST,
+ &[0; 256],
+ &[1, 2, 3, 4],
+ &[0; 256],
+ &[5, 6, 7, 8],
+ );
+ assert_eq!(
+ Err(ArpNewError::HwAddr(ArpHwAddrError::LenTooBig(256))),
+ actual
+ );
+ }
+
+ // protocol length error
+ {
+ let actual = ArpPacket::new(
+ ArpHardwareId::ASH,
+ EtherType::PROVIDER_BRIDGING,
+ ArpOperation::REQUEST,
+ &[1, 2, 3, 4],
+ &[0; 256],
+ &[5, 6, 7, 8],
+ &[0; 256],
+ );
+ assert_eq!(
+ Err(ArpNewError::ProtoAddr(ArpProtoAddrError::LenTooBig(256))),
+ actual
+ );
+ }
+ }
+
+ #[test]
+ fn new_unchecked() {
+ // ok case
+ {
+ let actual = unsafe {
+ ArpPacket::new_unchecked(
+ ArpHardwareId::ASH,
+ EtherType::PROVIDER_BRIDGING,
+ ArpOperation::REQUEST,
+ &[1, 2, 3],
+ &[4, 5, 6, 7, 8],
+ &[9, 10, 11],
+ &[12, 13, 14, 15, 16],
+ )
+ };
+ assert_eq!(3, actual.hw_addr_size());
+ assert_eq!(5, actual.protocol_addr_size());
+ assert_eq!(ArpHardwareId::ASH, actual.hw_addr_type);
+ assert_eq!(EtherType::PROVIDER_BRIDGING, actual.proto_addr_type);
+ assert_eq!(ArpOperation::REQUEST, actual.operation);
+ assert_eq!(&[1, 2, 3], actual.sender_hw_addr());
+ assert_eq!(&[4, 5, 6, 7, 8], actual.sender_protocol_addr());
+ assert_eq!(&[9, 10, 11], actual.target_hw_addr());
+ assert_eq!(&[12, 13, 14, 15, 16], actual.target_protocol_addr());
+ }
+
+ // ok case (upper hw size)
+ {
+ let actual = unsafe {
+ ArpPacket::new_unchecked(
+ ArpHardwareId::ASH,
+ EtherType::PROVIDER_BRIDGING,
+ ArpOperation::REQUEST,
+ &[0; 255],
+ &[4, 5, 6, 7, 8],
+ &[0; 255],
+ &[12, 13, 14, 15, 16],
+ )
+ };
+ assert_eq!(255, actual.hw_addr_size());
+ assert_eq!(5, actual.protocol_addr_size());
+ assert_eq!(ArpHardwareId::ASH, actual.hw_addr_type);
+ assert_eq!(EtherType::PROVIDER_BRIDGING, actual.proto_addr_type);
+ assert_eq!(ArpOperation::REQUEST, actual.operation);
+ assert_eq!(&[0; 255], actual.sender_hw_addr());
+ assert_eq!(&[4, 5, 6, 7, 8], actual.sender_protocol_addr());
+ assert_eq!(&[0; 255], actual.target_hw_addr());
+ assert_eq!(&[12, 13, 14, 15, 16], actual.target_protocol_addr());
+ }
+
+ // ok case (protocol hw size)
+ {
+ let actual = ArpPacket::new(
+ ArpHardwareId::ASH,
+ EtherType::PROVIDER_BRIDGING,
+ ArpOperation::REQUEST,
+ &[1, 2, 3],
+ &[0; 255],
+ &[9, 10, 11],
+ &[0; 255],
+ )
+ .unwrap();
+ assert_eq!(3, actual.hw_addr_size());
+ assert_eq!(255, actual.protocol_addr_size());
+ assert_eq!(ArpHardwareId::ASH, actual.hw_addr_type);
+ assert_eq!(EtherType::PROVIDER_BRIDGING, actual.proto_addr_type);
+ assert_eq!(ArpOperation::REQUEST, actual.operation);
+ assert_eq!(&[1, 2, 3], actual.sender_hw_addr());
+ assert_eq!(&[0; 255], actual.sender_protocol_addr());
+ assert_eq!(&[9, 10, 11], actual.target_hw_addr());
+ assert_eq!(&[0; 255], actual.target_protocol_addr());
+ }
+ }
+
+ proptest! {
+ #[test]
+ fn debug(arp in arp_packet_any()) {
+ use std::format;
+ assert_eq!(
+ format!("{:?}", arp),
+ format!(
+ "ArpPacket {{ hw_addr_type: {:?}, proto_addr_type: {:?}, hw_addr_size: {:?}, proto_addr_size: {:?}, operation: {:?}, sender_hw_addr: {:?}, sender_protocol_addr: {:?}, target_hw_addr: {:?}, target_protocol_addr: {:?} }}",
+ arp.hw_addr_type,
+ arp.proto_addr_type,
+ arp.hw_addr_size(),
+ arp.protocol_addr_size(),
+ arp.operation,
+ arp.sender_hw_addr(),
+ arp.sender_protocol_addr(),
+ arp.target_hw_addr(),
+ arp.target_protocol_addr()
+ )
+ );
+ }
+ }
+
+ proptest! {
+ #[test]
+ fn clone_eq(arp in arp_packet_any()) {
+ assert_eq!(&arp.clone(), &arp);
+ }
+ }
+
+ proptest! {
+ #[test]
+ fn hash(arp in arp_packet_any()) {
+ use core::hash::{Hash, Hasher};
+ use std::collections::hash_map::DefaultHasher;
+
+ let expected_hash = {
+ let mut s = DefaultHasher::new();
+
+ arp.hw_addr_type.hash(&mut s);
+ arp.proto_addr_type.hash(&mut s);
+ arp.hw_addr_size().hash(&mut s);
+ arp.protocol_addr_size().hash(&mut s);
+ arp.operation.hash(&mut s);
+ arp.sender_hw_addr().hash(&mut s);
+ arp.sender_protocol_addr().hash(&mut s);
+ arp.target_hw_addr().hash(&mut s);
+ arp.target_protocol_addr().hash(&mut s);
+
+ s.finish()
+ };
+
+ let actual_hash = {
+ let mut s = DefaultHasher::new();
+ arp.hash(&mut s);
+ s.finish()
+ };
+
+ assert_eq!(expected_hash, actual_hash);
+ }
+ }
+
+ #[test]
+ fn arp_packet_works() {
+ let bytes = [
+ 0, 1, // hardware type
+ 8, 0, // proto type
+ 6, 4, // sizes
+ 0, 1, // arp operation
+ 0x00, 0x1b, 0x21, 0x0f, 0x91, 0x9b, // src mac
+ 10, 10, 1, 135, // src ip
+ 0xde, 0xad, 0xc0, 0x00, 0xff, 0xee, // dest mac
+ 192, 168, 1, 253, // dest ip
+ ];
+
+ let expected = ArpPacket::new(
+ ArpHardwareId::ETHERNET,
+ EtherType::IPV4,
+ ArpOperation::REQUEST,
+ &[0x00, 0x1b, 0x21, 0x0f, 0x91, 0x9b],
+ &[10, 10, 1, 135],
+ &[0xde, 0xad, 0xc0, 0x00, 0xff, 0xee],
+ &[192, 168, 1, 253],
+ )
+ .unwrap();
+
+ let actual = ArpPacket::from_slice(&bytes).unwrap();
+
+ assert_eq!(expected, actual);
+ }
+
+ proptest! {
+ #[test]
+ fn read(
+ arp in arp_packet_any()
+ ) {
+ use std::vec::Vec;
+ use std::io::Cursor;
+
+ // ok case
+ let mut buf = Vec::with_capacity(arp.packet_len());
+ arp.write(&mut buf).unwrap();
+ {
+ let mut cursor = Cursor::new(&buf);
+ let actual = ArpPacket::read(&mut cursor).unwrap();
+ assert_eq!(arp, actual);
+ }
+
+ // len io error
+ for len in 0..arp.packet_len() {
+ let mut cursor = Cursor::new(&buf[..len]);
+ let actual = ArpPacket::read(&mut cursor);
+ assert!(actual.is_err());
+ }
+ }
+ }
+
+ proptest! {
+ #[test]
+ fn write_error(
+ arp in arp_packet_any()
+ ) {
+ use std::vec::Vec;
+ use std::io::Cursor;
+
+ let mut buf = Vec::with_capacity(arp.packet_len());
+ buf.resize(arp.packet_len(), 0u8);
+
+ // check that the write produces an error if not enough memory is present
+ for len in 0..arp.packet_len() {
+ let mut cursor = Cursor::new(&mut buf[..len]);
+ let actual = arp.write(&mut cursor);
+ assert!(actual.is_err());
+ }
+ }
+ }
+
+ #[test]
+ fn set_hw_addrs() {
+ let start = ArpPacket::new(
+ ArpHardwareId::ASH,
+ EtherType::PROVIDER_BRIDGING,
+ ArpOperation::REQUEST,
+ &[1, 2, 3],
+ &[4, 5, 6, 7, 8],
+ &[9, 10, 11],
+ &[12, 13, 14, 15, 16],
+ )
+ .unwrap();
+
+ // ok case
+ {
+ let mut arp = start.clone();
+ arp.set_hw_addrs(&[17, 18], &[19, 20]).unwrap();
+ assert_eq!(2, arp.hw_addr_size());
+ assert_eq!(&[17, 18], arp.sender_hw_addr());
+ assert_eq!(&[19, 20], arp.target_hw_addr());
+ }
+
+ // non matching error
+ {
+ let mut arp = start.clone();
+ assert_eq!(
+ arp.set_hw_addrs(&[17, 18], &[19]),
+ Err(ArpHwAddrError::LenNonMatching(2, 1))
+ );
+ }
+
+ // above 255 error
+ {
+ let mut arp = start.clone();
+ assert_eq!(
+ arp.set_hw_addrs(&[0; 260], &[0; 260]),
+ Err(ArpHwAddrError::LenTooBig(260))
+ );
+ }
+ }
+
+ #[test]
+ fn set_proto_addrs() {
+ let start = ArpPacket::new(
+ ArpHardwareId::ASH,
+ EtherType::PROVIDER_BRIDGING,
+ ArpOperation::REQUEST,
+ &[1, 2, 3],
+ &[4, 5, 6, 7, 8],
+ &[9, 10, 11],
+ &[12, 13, 14, 15, 16],
+ )
+ .unwrap();
+
+ // ok case
+ {
+ let mut arp = start.clone();
+ arp.set_protocol_addrs(&[17, 18], &[19, 20]).unwrap();
+ assert_eq!(2, arp.protocol_addr_size());
+ assert_eq!(&[17, 18], arp.sender_protocol_addr());
+ assert_eq!(&[19, 20], arp.target_protocol_addr());
+ }
+
+ // non matching error
+ {
+ let mut arp = start.clone();
+ assert_eq!(
+ arp.set_protocol_addrs(&[17, 18], &[19]),
+ Err(ArpProtoAddrError::LenNonMatching(2, 1))
+ );
+ }
+
+ // above 255 error
+ {
+ let mut arp = start.clone();
+ assert_eq!(
+ arp.set_protocol_addrs(&[0; 260], &[0; 260]),
+ Err(ArpProtoAddrError::LenTooBig(260))
+ );
+ }
+ }
+
+ proptest! {
+ #[test]
+ fn try_eth_ipv4(
+ arp_eth_ipv4 in arp_eth_ipv4_packet_any()
+ ) {
+ use err::arp::ArpEthIpv4FromError::*;
+
+ // ok case
+ {
+ let arp: ArpPacket = arp_eth_ipv4.clone().into();
+ assert_eq!(arp.try_eth_ipv4(), Ok(arp_eth_ipv4.clone()));
+ }
+
+ // hw type error
+ {
+ let mut arp: ArpPacket = arp_eth_ipv4.clone().into();
+ arp.hw_addr_type = ArpHardwareId::AX25;
+ assert_eq!(
+ arp.try_eth_ipv4(),
+ Err(NonMatchingHwType(ArpHardwareId::AX25))
+ );
+ }
+
+ // proto type error
+ {
+ let mut arp: ArpPacket = arp_eth_ipv4.clone().into();
+ arp.proto_addr_type = EtherType::IPV6;
+ assert_eq!(
+ arp.try_eth_ipv4(),
+ Err(NonMatchingProtocolType(EtherType::IPV6))
+ );
+ }
+
+ // hw address size error
+ {
+ let mut arp: ArpPacket = arp_eth_ipv4.clone().into();
+ arp.set_hw_addrs(&[1], &[2]).unwrap();
+ assert_eq!(
+ arp.try_eth_ipv4(),
+ Err(NonMatchingHwAddrSize(1))
+ );
+ }
+
+ // protocol address size error
+ {
+ let mut arp: ArpPacket = arp_eth_ipv4.clone().into();
+ arp.set_protocol_addrs(&[1], &[2]).unwrap();
+ assert_eq!(
+ arp.try_eth_ipv4(),
+ Err(NonMatchingProtoAddrSize(1))
+ );
+ }
+ }
+ }
+}
diff --git a/crates/etherparse/src/net/arp_packet_slice.rs b/crates/etherparse/src/net/arp_packet_slice.rs
new file mode 100644
index 0000000..87f51bf
--- /dev/null
+++ b/crates/etherparse/src/net/arp_packet_slice.rs
@@ -0,0 +1,231 @@
+use super::{ArpHardwareId, ArpOperation};
+use crate::{
+ err::{Layer, LenError},
+ ArpPacket, EtherType, LenSource,
+};
+
+/// Slice containing an "Address Resolution Protocol" Packet.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct ArpPacketSlice<'a> {
+ slice: &'a [u8],
+}
+
+impl<'a> ArpPacketSlice<'a> {
+ /// Creates an `ArpPacketSlice` from a slice and verfies that the
+ /// given slice has enough data to contain an complete ARP packet.
+ pub fn from_slice(slice: &'a [u8]) -> Result<ArpPacketSlice<'a>, LenError> {
+ if slice.len() < 8 {
+ return Err(LenError {
+ required_len: 8,
+ len: slice.len(),
+ len_source: LenSource::Slice,
+ layer: Layer::Arp,
+ layer_start_offset: 0,
+ });
+ }
+
+ // validate the rest length based on the hardware & protocol lengths
+ let hw_addr_size = unsafe { *slice.as_ptr().add(4) };
+ let protocol_addr_size = unsafe { *slice.as_ptr().add(5) };
+ let min_len = 8 + (hw_addr_size as usize) * 2 + (protocol_addr_size as usize) * 2;
+
+ if slice.len() < min_len {
+ return Err(LenError {
+ required_len: min_len,
+ len: slice.len(),
+ len_source: LenSource::ArpAddrLengths,
+ layer: Layer::Arp,
+ layer_start_offset: 0,
+ });
+ }
+
+ Ok(Self {
+ slice: unsafe {
+ // SAFETY: Safe as slice was verified above to have a
+ // length of at least min_len.
+ core::slice::from_raw_parts(slice.as_ptr(), min_len)
+ },
+ })
+ }
+
+ /// Slice containing the ARP packet.
+ #[inline]
+ pub fn slice(&self) -> &'a [u8] {
+ self.slice
+ }
+
+ /// Network link protocol type (e.g. `ArpHardwareId::ETHERNET`).
+ #[inline]
+ pub const fn hw_addr_type(&self) -> ArpHardwareId {
+ ArpHardwareId(u16::from_be_bytes(
+ // SAFE: As the constructor verified the length
+ // of the slice to be at least 8.
+ unsafe { [*self.slice.as_ptr(), *self.slice.as_ptr().add(1)] },
+ ))
+ }
+
+ /// Protocol for which the ARP request is intended (e.g. `EtherType::IPV4`).
+ #[inline]
+ pub const fn proto_addr_type(&self) -> EtherType {
+ EtherType(u16::from_be_bytes(
+ // SAFE: As the constructor verified the length
+ // of the slice to be at least 8.
+ unsafe { [*self.slice.as_ptr().add(2), *self.slice.as_ptr().add(3)] },
+ ))
+ }
+
+ /// Length (in octets) of a hardware address (e.g. 6 for Ethernet).
+ #[inline]
+ pub const fn hw_addr_size(&self) -> u8 {
+ // SAFE: As the constructor verified the length
+ // of the slice to be at least 8.
+ unsafe { *self.slice.as_ptr().add(4) }
+ }
+
+ /// Length (in octets) of internetwork addresses (e.g. 4 for IPv4 or 16 for IPv6).
+ #[inline]
+ pub const fn proto_addr_size(&self) -> u8 {
+ // SAFE: As the constructor verified the length
+ // of the slice to be at least 8.
+ unsafe { *self.slice.as_ptr().add(5) }
+ }
+
+ /// Specifies the operation that the sender is performing
+ #[inline]
+ pub const fn operation(&self) -> ArpOperation {
+ ArpOperation(u16::from_be_bytes(
+ // SAFE: As the constructor verified the length
+ // of the slice to be at least 8.
+ unsafe { [*self.slice.as_ptr().add(6), *self.slice.as_ptr().add(7)] },
+ ))
+ }
+
+ /// Sender hardware address (e.g. MAC address).
+ #[inline]
+ pub const fn sender_hw_addr(&self) -> &[u8] {
+ // SAFETY: Safe as the constructor verfies the
+ // the slice to be at least 8 + hw_addr_size*2 + protocol_addr_size*2
+ unsafe {
+ core::slice::from_raw_parts(self.slice.as_ptr().add(8), self.hw_addr_size() as usize)
+ }
+ }
+
+ /// Sender protocol address (e.g. IPv4 address).
+ #[inline]
+ pub const fn sender_protocol_addr(&self) -> &[u8] {
+ // SAFETY: Safe as the constructor verfies the
+ // the slice to be at least 8 + hw_addr_size*2 + protocol_addr_size*2
+ unsafe {
+ core::slice::from_raw_parts(
+ self.slice.as_ptr().add(8 + (self.hw_addr_size() as usize)),
+ self.proto_addr_size() as usize,
+ )
+ }
+ }
+
+ /// Target hardware address (e.g. MAC address).
+ #[inline]
+ pub const fn target_hw_addr(&self) -> &[u8] {
+ // SAFETY: Safe as the constructor verfies the
+ // the slice to be at least 8 + hw_addr_size*2 + protocol_addr_size*2
+ unsafe {
+ core::slice::from_raw_parts(
+ self.slice
+ .as_ptr()
+ .add(8 + (self.hw_addr_size() as usize) + (self.proto_addr_size() as usize)),
+ self.hw_addr_size() as usize,
+ )
+ }
+ }
+
+ /// Buffer containing the target protocol address (e.g. IPv4 address)..
+ #[inline]
+ pub const fn target_protocol_addr(&self) -> &[u8] {
+ // SAFETY: Safe as the constructor verfies the
+ // the slice to be at least 8 + hw_addr_size*2 + protocol_addr_size*2
+ unsafe {
+ core::slice::from_raw_parts(
+ self.slice.as_ptr().add(
+ 8 + (self.hw_addr_size() as usize) * 2 + (self.proto_addr_size() as usize),
+ ),
+ self.proto_addr_size() as usize,
+ )
+ }
+ }
+
+ /// Decode fields and return results in an [`ArpPacket`].
+ #[inline]
+ pub fn to_packet(&self) -> ArpPacket {
+ // SAFETY: Safe as all preconditions of new unchecked
+ // are fullfilled by the fact that the on the wire packets already
+ // fullfill them.
+ unsafe {
+ ArpPacket::new_unchecked(
+ self.hw_addr_type(),
+ self.proto_addr_type(),
+ self.operation(),
+ self.sender_hw_addr(),
+ self.sender_protocol_addr(),
+ self.target_hw_addr(),
+ self.target_protocol_addr(),
+ )
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::test_gens::*;
+ use proptest::prelude::*;
+
+ proptest! {
+ #[test]
+ fn from_slice_with_payload(
+ packet in arp_packet_any()
+ ) {
+ // build slice data
+ let data = packet.to_bytes();
+
+ // happy path
+ {
+ let actual = ArpPacketSlice::from_slice(&data).unwrap();
+
+ assert_eq!(actual.hw_addr_type(), packet.hw_addr_type);
+ assert_eq!(actual.proto_addr_type(), packet.proto_addr_type);
+ assert_eq!(actual.hw_addr_size(), packet.hw_addr_size());
+ assert_eq!(actual.proto_addr_size(), packet.protocol_addr_size());
+ assert_eq!(actual.operation(), packet.operation);
+
+ assert_eq!(actual.sender_hw_addr(), packet.sender_hw_addr());
+ assert_eq!(actual.sender_protocol_addr(), packet.sender_protocol_addr());
+ assert_eq!(actual.target_hw_addr(), packet.target_hw_addr());
+ assert_eq!(actual.target_protocol_addr(), packet.target_protocol_addr());
+
+ assert_eq!(&actual.to_packet(), &packet);
+ }
+
+ // length error
+ for len in 0..(8 + (packet.hw_addr_size() as usize)*2 + (packet.protocol_addr_size() as usize)*2) {
+ let err = ArpPacketSlice::from_slice(&data[..len]).unwrap_err();
+ if len < 8 {
+ assert_eq!(err, LenError{
+ required_len: 8,
+ len,
+ len_source: LenSource::Slice,
+ layer: Layer::Arp,
+ layer_start_offset: 0,
+ });
+ } else {
+ assert_eq!(err, LenError{
+ required_len: 8 + (packet.hw_addr_size() as usize)*2 + (packet.protocol_addr_size() as usize)*2,
+ len,
+ len_source: LenSource::ArpAddrLengths,
+ layer: Layer::Arp,
+ layer_start_offset: 0,
+ });
+ }
+ }
+ }
+ }
+}
diff --git a/crates/etherparse/src/net/ip_headers.rs b/crates/etherparse/src/net/ip_headers.rs
index 7b901bc..e8df69a 100644
--- a/crates/etherparse/src/net/ip_headers.rs
+++ b/crates/etherparse/src/net/ip_headers.rs
@@ -1096,16 +1096,16 @@
///
/// The given number will be set as the last "next_header" or
/// protocol number.
- pub fn set_next_headers(&mut self, last_next_header: IpNumber) -> u16 {
+ pub fn set_next_headers(&mut self, last_next_header: IpNumber) -> EtherType {
use IpHeaders::*;
match self {
Ipv4(ref mut header, ref mut extensions) => {
header.protocol = extensions.set_next_headers(last_next_header);
- EtherType::IPV4.0
+ EtherType::IPV4
}
Ipv6(ref mut header, ref mut extensions) => {
header.next_header = extensions.set_next_headers(last_next_header);
- EtherType::IPV4.0
+ EtherType::IPV4
}
}
}
diff --git a/crates/etherparse/src/net/ipv6_ext_slice_iter.rs b/crates/etherparse/src/net/ipv6_ext_slice_iter.rs
index cbf720d..8ac0de1 100644
--- a/crates/etherparse/src/net/ipv6_ext_slice_iter.rs
+++ b/crates/etherparse/src/net/ipv6_ext_slice_iter.rs
@@ -8,7 +8,7 @@
pub(crate) rest: &'a [u8],
}
-impl<'a> Default for Ipv6ExtensionSliceIter<'a> {
+impl Default for Ipv6ExtensionSliceIter<'_> {
fn default() -> Self {
Ipv6ExtensionSliceIter {
// don't use 0 as this is the reserved value
diff --git a/crates/etherparse/src/net/lax_ip_slice.rs b/crates/etherparse/src/net/lax_ip_slice.rs
index 97477dc..491bf60 100644
--- a/crates/etherparse/src/net/lax_ip_slice.rs
+++ b/crates/etherparse/src/net/lax_ip_slice.rs
@@ -99,7 +99,7 @@
/// as far as possible without encountering an error and with less strict length checks.
/// This function is usefull for cut off packet or for packets with unset length fields.
///
- /// If you want to only receive correct IpPayloads use [`IpSlice::from_ip_slice`]
+ /// If you want to only receive correct IpPayloads use [`IpSlice::from_slice`]
/// instead.
///
/// The main usecases for this functions are:
diff --git a/crates/etherparse/src/net/lax_ipv4_slice.rs b/crates/etherparse/src/net/lax_ipv4_slice.rs
index 2c73f58..d9359c7 100644
--- a/crates/etherparse/src/net/lax_ipv4_slice.rs
+++ b/crates/etherparse/src/net/lax_ipv4_slice.rs
@@ -68,7 +68,6 @@
/// if the `len_source` value in the returned [`LaxIpPayloadSlice`] is set to
/// [`LenSource::Slice`]. If a substitution was not needed `len_source`
/// is set to [`LenSource::Ipv4HeaderTotalLen`].
-
pub fn from_slice(
slice: &[u8],
) -> Result<(LaxIpv4Slice, Option<err::ip_auth::HeaderSliceError>), err::ipv4::HeaderSliceError>
diff --git a/crates/etherparse/src/net/lax_net_slice.rs b/crates/etherparse/src/net/lax_net_slice.rs
index 69523f2..9ee2917 100644
--- a/crates/etherparse/src/net/lax_net_slice.rs
+++ b/crates/etherparse/src/net/lax_net_slice.rs
@@ -16,10 +16,12 @@
/// operating system set the length fields).
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum LaxNetSlice<'a> {
- /// The ipv4 header & the decoded extension headers.
+ /// IPv4 header & the decoded extension headers.
Ipv4(LaxIpv4Slice<'a>),
- /// The ipv6 header & the decoded extension headers.
+ /// IPv6 header & the decoded extension headers.
Ipv6(LaxIpv6Slice<'a>),
+ /// "Address Resolution Protocol" Packet,
+ Arp(ArpPacketSlice<'a>),
}
impl<'a> LaxNetSlice<'a> {
@@ -30,6 +32,7 @@
match self {
LaxNetSlice::Ipv4(s) => Some(&s.payload),
LaxNetSlice::Ipv6(s) => Some(&s.payload),
+ LaxNetSlice::Arp(_) => None,
}
}
}
diff --git a/crates/etherparse/src/net/mod.rs b/crates/etherparse/src/net/mod.rs
index cee996f..676f965 100644
--- a/crates/etherparse/src/net/mod.rs
+++ b/crates/etherparse/src/net/mod.rs
@@ -1,3 +1,15 @@
+mod arp_eth_ipv4_packet;
+pub use arp_eth_ipv4_packet::*;
+
+mod arp_hardware_id;
+pub use arp_hardware_id::*;
+
+mod arp_packet;
+pub use arp_packet::*;
+
+mod arp_operation;
+pub use arp_operation::*;
+
mod ip_auth_header;
pub use ip_auth_header::*;
@@ -102,3 +114,6 @@
mod net_slice;
pub use net_slice::*;
+
+mod arp_packet_slice;
+pub use arp_packet_slice::*;
diff --git a/crates/etherparse/src/net/net_headers.rs b/crates/etherparse/src/net/net_headers.rs
index f2af1f4..3389fd7 100644
--- a/crates/etherparse/src/net/net_headers.rs
+++ b/crates/etherparse/src/net/net_headers.rs
@@ -12,9 +12,17 @@
Ipv4(Ipv4Header, Ipv4Extensions),
/// IPv6 header & extension headers.
Ipv6(Ipv6Header, Ipv6Extensions),
+ /// Address Resolution Protocol packet.
+ Arp(ArpPacket),
}
impl NetHeaders {
+ /// Returns true if the NetHeaders contains either IPv4 or IPv6.
+ pub fn is_ip(&self) -> bool {
+ use NetHeaders::*;
+ matches!(self, Ipv4(_, _) | Ipv6(_, _))
+ }
+
/// Returns references to the IPv4 header & extensions if the header contains IPv4 values.
pub fn ipv4_ref(&self) -> Option<(&Ipv4Header, &Ipv4Extensions)> {
if let NetHeaders::Ipv4(header, exts) = self {
@@ -33,12 +41,37 @@
}
}
+ /// Sets all the next_header fields in the ipv4 & ipv6 header
+ /// as well as in all extension headers and returns the ether
+ /// type number.
+ ///
+ /// The given number will be set as the last "next_header" or
+ /// protocol number.
+ pub fn try_set_next_headers(
+ &mut self,
+ last_next_header: IpNumber,
+ ) -> Result<EtherType, err::net::NetSetNextHeaderError> {
+ use NetHeaders::*;
+ match self {
+ Ipv4(ref mut header, ref mut extensions) => {
+ header.protocol = extensions.set_next_headers(last_next_header);
+ Ok(EtherType::IPV4)
+ }
+ Ipv6(ref mut header, ref mut extensions) => {
+ header.next_header = extensions.set_next_headers(last_next_header);
+ Ok(EtherType::IPV4)
+ }
+ Arp(_) => Err(err::net::NetSetNextHeaderError::ArpHeader),
+ }
+ }
+
/// Returns the size when the header & extension headers are serialized
pub fn header_len(&self) -> usize {
use crate::NetHeaders::*;
match *self {
Ipv4(ref header, ref extensions) => header.header_len() + extensions.header_len(),
Ipv6(_, ref extensions) => Ipv6Header::LEN + extensions.header_len(),
+ Arp(ref arp) => arp.packet_len(),
}
}
}
@@ -53,6 +86,13 @@
}
}
+impl From<ArpPacket> for NetHeaders {
+ #[inline]
+ fn from(value: ArpPacket) -> Self {
+ NetHeaders::Arp(value)
+ }
+}
+
#[cfg(test)]
mod tests {
use crate::*;
diff --git a/crates/etherparse/src/net/net_slice.rs b/crates/etherparse/src/net/net_slice.rs
index 3ab8542..c0a1c1b 100644
--- a/crates/etherparse/src/net/net_slice.rs
+++ b/crates/etherparse/src/net/net_slice.rs
@@ -15,9 +15,18 @@
Ipv4(Ipv4Slice<'a>),
/// The ipv6 header & the decoded extension headers.
Ipv6(Ipv6Slice<'a>),
+ /// The arp header & the decoded extension headers.
+ Arp(ArpPacketSlice<'a>),
}
impl<'a> NetSlice<'a> {
+ /// Returns true if the NetSlice contains either IPv4 or IPv6.
+ #[inline]
+ pub fn is_ip(&self) -> bool {
+ use NetSlice::*;
+ matches!(self, Ipv4(_) | Ipv6(_))
+ }
+
/// Returns a reference to ip payload if the net slice contains
/// an ipv4 or ipv6 slice.
#[inline]
@@ -25,6 +34,7 @@
match self {
NetSlice::Ipv4(s) => Some(&s.payload),
NetSlice::Ipv6(s) => Some(&s.payload),
+ NetSlice::Arp(_) => None,
}
}
}
diff --git a/crates/etherparse/src/packet_builder.rs b/crates/etherparse/src/packet_builder.rs
index ee92031..50db0f6 100644
--- a/crates/etherparse/src/packet_builder.rs
+++ b/crates/etherparse/src/packet_builder.rs
@@ -49,6 +49,7 @@
/// * [`PacketBuilder::ipv4`]
/// * [`PacketBuilder::ipv6`]
/// * Options after an Ethernet2 header was added:
+/// * [`PacketBuilderStep<Ethernet2Header>::arp`]
/// * [`PacketBuilderStep<Ethernet2Header>::vlan`]
/// * [`PacketBuilderStep<Ethernet2Header>::single_vlan`]
/// * [`PacketBuilderStep<Ethernet2Header>::double_vlan`]
@@ -140,7 +141,7 @@
ether_type: EtherType(0), //the type identifier
})),
vlan_header: None,
- ip_header: None,
+ net_header: None,
transport_header: None,
},
_marker: marker::PhantomData::<Ethernet2Header> {},
@@ -185,13 +186,13 @@
state: PacketImpl {
link_header: Some(LinkHeader::LinuxSll(LinuxSllHeader {
packet_type,
- arp_hrd_type: ArpHardwareId::ETHER,
+ arp_hrd_type: ArpHardwareId::ETHERNET,
sender_address_valid_length,
sender_address,
protocol_type: LinuxSllProtocolType::EtherType(EtherType(0)), // Will be overwitten when writing depending on the net layer
})),
vlan_header: None,
- ip_header: None,
+ net_header: None,
transport_header: None,
},
_marker: marker::PhantomData::<LinuxSllHeader> {},
@@ -233,7 +234,7 @@
state: PacketImpl {
link_header: None,
vlan_header: None,
- ip_header: None,
+ net_header: None,
transport_header: None,
},
_marker: marker::PhantomData::<Ethernet2Header> {},
@@ -280,7 +281,7 @@
state: PacketImpl {
link_header: None,
vlan_header: None,
- ip_header: None,
+ net_header: None,
transport_header: None,
},
_marker: marker::PhantomData::<Ethernet2Header> {},
@@ -357,7 +358,7 @@
state: PacketImpl {
link_header: None,
vlan_header: None,
- ip_header: None,
+ net_header: None,
transport_header: None,
},
_marker: marker::PhantomData::<Ethernet2Header> {},
@@ -368,7 +369,7 @@
struct PacketImpl {
link_header: Option<LinkHeader>,
- ip_header: Option<IpHeaders>,
+ net_header: Option<NetHeaders>,
vlan_header: Option<VlanHeader>,
transport_header: Option<TransportHeader>,
}
@@ -417,7 +418,7 @@
time_to_live: u8,
) -> PacketBuilderStep<IpHeaders> {
//add ip header
- self.state.ip_header = Some(IpHeaders::Ipv4(
+ self.state.net_header = Some(NetHeaders::Ipv4(
Ipv4Header {
source,
destination,
@@ -479,7 +480,10 @@
/// ```
pub fn ip(mut self, ip_header: IpHeaders) -> PacketBuilderStep<IpHeaders> {
//add ip header
- self.state.ip_header = Some(ip_header);
+ self.state.net_header = Some(match ip_header {
+ IpHeaders::Ipv4(header, exts) => NetHeaders::Ipv4(header, exts),
+ IpHeaders::Ipv6(header, exts) => NetHeaders::Ipv6(header, exts),
+ });
//return for next step
PacketBuilderStep {
state: self.state,
@@ -525,7 +529,7 @@
destination: [u8; 16],
hop_limit: u8,
) -> PacketBuilderStep<IpHeaders> {
- self.state.ip_header = Some(IpHeaders::Ipv6(
+ self.state.net_header = Some(NetHeaders::Ipv6(
Ipv6Header {
traffic_class: 0,
flow_label: Ipv6FlowLabel::ZERO,
@@ -687,6 +691,43 @@
_marker: marker::PhantomData::<VlanHeader> {},
}
}
+
+ /// Adds an ARP packet.
+ ///
+ /// # Example
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// use etherparse::*;
+ ///
+ /// let builder = PacketBuilder::
+ /// ethernet2([1,2,3,4,5,6], // source mac
+ /// [7,8,9,10,11,12]) // destination mac
+ /// .arp(ArpPacket::new(
+ /// ArpHardwareId::ETHERNET,
+ /// EtherType::IPV4,
+ /// ArpOperation::REQUEST,
+ /// &[1,2,3,4,5,6], // sender_hw_addr
+ /// &[7,6,8,9], // sender_protocol_addr
+ /// &[10,11,12,14,15,16], // target_hw_addr
+ /// &[17,18,19,20] // target_protocol_addr
+ /// ).unwrap());
+ ///
+ /// // get some memory to store the result
+ /// let mut result = Vec::<u8>::with_capacity(builder.size());
+ ///
+ /// // serialize
+ /// builder.write(&mut result).unwrap();
+ /// ```
+ pub fn arp(mut self, arp_packet: ArpPacket) -> PacketBuilderStep<ArpPacket> {
+ self.state.net_header = Some(NetHeaders::Arp(arp_packet));
+ //return for next step
+ PacketBuilderStep {
+ state: self.state,
+ _marker: marker::PhantomData::<ArpPacket> {},
+ }
+ }
}
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
@@ -833,6 +874,44 @@
}
.ipv4(source, destination, time_to_live)
}
+
+ /// Adds an ARP packet.
+ ///
+ /// # Example
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// use etherparse::*;
+ ///
+ /// let builder = PacketBuilder::
+ /// linux_sll(LinuxSllPacketType::OTHERHOST, //packet type
+ /// 6, //sender address valid length
+ /// [1,2,3,4,5,6,0,0]) //sender address with padding
+ /// .arp(ArpPacket::new(
+ /// ArpHardwareId::ETHERNET,
+ /// EtherType::IPV4,
+ /// ArpOperation::REQUEST,
+ /// &[1,2,3,4,5,6], // sender_hw_addr
+ /// &[7,6,8,9], // sender_protocol_addr
+ /// &[10,11,12,14,15,16], // target_hw_addr
+ /// &[17,18,19,20] // target_protocol_addr
+ /// ).unwrap());
+ ///
+ /// // get some memory to store the result
+ /// let mut result = Vec::<u8>::with_capacity(builder.size());
+ ///
+ /// // serialize
+ /// builder.write(&mut result).unwrap();
+ /// ```
+ pub fn arp(mut self, arp_packet: ArpPacket) -> PacketBuilderStep<ArpPacket> {
+ self.state.net_header = Some(NetHeaders::Arp(arp_packet));
+ // return for next step
+ PacketBuilderStep {
+ state: self.state,
+ _marker: marker::PhantomData::<ArpPacket> {},
+ }
+ }
}
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
@@ -979,6 +1058,44 @@
}
.ipv4(source, destination, time_to_live)
}
+
+ /// Adds an ARP packet.
+ ///
+ /// # Example
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// use etherparse::*;
+ ///
+ /// let builder = PacketBuilder::
+ /// ethernet2([1,2,3,4,5,6], // source mac
+ /// [7,8,9,10,11,12]) // destination mac
+ /// .single_vlan(0x123.try_into().unwrap()) // vlan identifier
+ /// .arp(ArpPacket::new(
+ /// ArpHardwareId::ETHERNET,
+ /// EtherType::IPV4,
+ /// ArpOperation::REQUEST,
+ /// &[1,2,3,4,5,6], // sender_hw_addr
+ /// &[7,6,8,9], // sender_protocol_addr
+ /// &[10,11,12,14,15,16], // target_hw_addr
+ /// &[17,18,19,20] // target_protocol_addr
+ /// ).unwrap());
+ ///
+ /// // get some memory to store the result
+ /// let mut result = Vec::<u8>::with_capacity(builder.size());
+ ///
+ /// // serialize
+ /// builder.write(&mut result).unwrap();
+ /// ```
+ pub fn arp(mut self, arp_packet: ArpPacket) -> PacketBuilderStep<ArpPacket> {
+ self.state.net_header = Some(NetHeaders::Arp(arp_packet));
+ //return for next step
+ PacketBuilderStep {
+ state: self.state,
+ _marker: marker::PhantomData::<ArpPacket> {},
+ }
+ }
}
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
@@ -1525,12 +1642,16 @@
last_next_header_ip_number: IpNumber,
payload: &[u8],
) -> Result<(), BuildWriteError> {
- self.state
- .ip_header
- .as_mut()
- .unwrap()
- .set_next_headers(last_next_header_ip_number);
- final_write(self, writer, payload)
+ match &mut (self.state.net_header) {
+ Some(NetHeaders::Ipv4(ref mut ip, ref mut exts)) => {
+ ip.protocol = exts.set_next_headers(last_next_header_ip_number);
+ }
+ Some(NetHeaders::Ipv6(ref mut ip, ref mut exts)) => {
+ ip.next_header = exts.set_next_headers(last_next_header_ip_number);
+ }
+ _ => {}
+ }
+ final_write_with_net(self, writer, payload)
}
///Returns the size of the packet when it is serialized
@@ -1547,7 +1668,7 @@
writer: &mut T,
payload: &[u8],
) -> Result<(), BuildWriteError> {
- final_write(self, writer, payload)
+ final_write_with_net(self, writer, payload)
}
/// Returns the size of the packet when it is serialized
@@ -1564,7 +1685,7 @@
writer: &mut T,
payload: &[u8],
) -> Result<(), BuildWriteError> {
- final_write(self, writer, payload)
+ final_write_with_net(self, writer, payload)
}
///Returns the size of the packet when it is serialized
@@ -1581,7 +1702,7 @@
writer: &mut T,
payload: &[u8],
) -> Result<(), BuildWriteError> {
- final_write(self, writer, payload)
+ final_write_with_net(self, writer, payload)
}
///Returns the size of the packet when it is serialized
@@ -1742,7 +1863,7 @@
writer: &mut T,
payload: &[u8],
) -> Result<(), BuildWriteError> {
- final_write(self, writer, payload)
+ final_write_with_net(self, writer, payload)
}
///Returns the size of the packet when it is serialized
@@ -1751,35 +1872,53 @@
}
}
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
+impl PacketBuilderStep<ArpPacket> {
+ pub fn write<T: io::Write + Sized>(self, writer: &mut T) -> Result<(), BuildWriteError> {
+ final_write_with_net(self, writer, &[])?;
+ Ok(())
+ }
+
+ pub fn size(&self) -> usize {
+ final_size(self, 0)
+ }
+}
+
/// Write all the headers and the payload.
-fn final_write<T: io::Write + Sized, B>(
+fn final_write_with_net<T: io::Write + Sized, B>(
builder: PacketBuilderStep<B>,
writer: &mut T,
payload: &[u8],
) -> Result<(), BuildWriteError> {
use BuildWriteError::*;
+ use NetHeaders::*;
- let ip_ether_type = {
- use crate::IpHeaders::*;
- match builder.state.ip_header {
- Some(Ipv4(_, _)) => ether_type::IPV4,
- Some(Ipv6(_, _)) => ether_type::IPV6,
- None => panic!("Missing ip header"),
- }
+ // unpack builder (makes things easier with the borrow checker)
+ let link = builder.state.link_header;
+ let vlan = builder.state.vlan_header;
+ let net = builder.state.net_header;
+ let mut transport = builder.state.transport_header;
+
+ // determine
+ let net_ether_type = match &net {
+ Some(Ipv4(_, _)) => ether_type::IPV4,
+ Some(Ipv6(_, _)) => ether_type::IPV6,
+ Some(Arp(_)) => ether_type::ARP,
+ None => unreachable!(),
};
- //link header
- if let Some(link) = builder.state.link_header {
+ // link header
+ if let Some(link) = link {
match link {
LinkHeader::Ethernet2(mut eth) => {
eth.ether_type = {
use crate::VlanHeader::*;
//determine the ether type depending on if there is a vlan tagging header
- match builder.state.vlan_header {
+ match &vlan {
Some(Single(_)) => ether_type::VLAN_TAGGED_FRAME,
Some(Double(_)) => ether_type::PROVIDER_BRIDGING,
//if no vlan header exists, the id is purely defined by the ip type
- None => ip_ether_type,
+ None => net_ether_type,
}
};
eth.write(writer).map_err(Io)?;
@@ -1787,168 +1926,140 @@
LinkHeader::LinuxSll(mut linux_sll) => {
// Assumes that next layers are ether based. If more types of
// layers are supported, this should be updated
- debug_assert_eq!(linux_sll.arp_hrd_type, ArpHardwareId::ETHER);
+ debug_assert_eq!(linux_sll.arp_hrd_type, ArpHardwareId::ETHERNET);
- linux_sll.protocol_type.change_value(ip_ether_type.into());
+ linux_sll.protocol_type.change_value(net_ether_type.into());
linux_sll.write(writer).map_err(Io)?;
}
}
}
- //write the vlan header if it exists
+ // write the vlan header if it exists
use crate::VlanHeader::*;
- match builder.state.vlan_header {
+ match vlan {
Some(Single(mut value)) => {
//set ether types
- value.ether_type = ip_ether_type;
+ value.ether_type = net_ether_type;
//serialize
value.write(writer).map_err(Io)?;
}
Some(Double(mut value)) => {
//set ether types
value.outer.ether_type = ether_type::VLAN_TAGGED_FRAME;
- value.inner.ether_type = ip_ether_type;
+ value.inner.ether_type = net_ether_type;
//serialize
value.write(writer).map_err(Io)?;
}
None => {}
}
- //ip header
- use crate::IpHeaders::*;
- let ip_header = builder.state.ip_header.unwrap();
-
- //transport header
- let transport = builder.state.transport_header;
- match transport {
- None => {
- // in case no transport header is present the protocol
- // number and next_header fields are set in the write call
- // directly and don't need to be set here again.
- match ip_header {
- Ipv4(mut ip, ext) => {
- ip.set_payload_len(ext.header_len() + payload.len())
- .map_err(PayloadLen)?;
- ip.write(writer).map_err(Io)?;
- ext.write(writer, ip.protocol).map_err(|err| {
- use err::ipv4_exts::HeaderWriteError as I;
- match err {
- I::Io(err) => Io(err),
- I::Content(err) => Ipv4Exts(err),
- }
- })?;
- }
- Ipv6(mut ip, ext) => {
- ip.set_payload_length(ext.header_len() + payload.len())
- .map_err(PayloadLen)?;
- ip.write(writer).map_err(Io)?;
- ext.write(writer, ip.next_header).map_err(|err| {
- use err::ipv6_exts::HeaderWriteError as I;
- match err {
- I::Io(err) => Io(err),
- I::Content(err) => Ipv6Exts(err),
- }
- })?;
- }
- }
+ // set transport header length (needs to be done here
+ // so following steps can correctly calculate the checksum)
+ use TransportHeader::*;
+ match &mut transport {
+ Some(Udp(ref mut udp)) => {
+ udp.length = (UdpHeader::LEN + payload.len()) as u16;
}
- Some(mut transport) => {
- match ip_header {
- Ipv4(mut ip, mut ext) => {
- //set total length & udp payload length (ip checks that the payload length is ok)
- let transport_size = transport.header_len() + payload.len();
- ip.set_payload_len(ext.header_len() + transport_size)
- .map_err(PayloadLen)?;
- use crate::TransportHeader::*;
- match transport {
- Icmpv4(_) => {}
- Icmpv6(_) => {}
- Udp(ref mut udp) => {
- udp.length = transport_size as u16;
- }
- Tcp(_) => {}
- }
-
- //ip protocol number & next header values of the extension header
- ip.protocol = ext.set_next_headers(match transport {
- Icmpv4(_) => ip_number::ICMP,
- Icmpv6(_) => ip_number::IPV6_ICMP,
- Udp(_) => ip_number::UDP,
- Tcp(_) => ip_number::TCP,
- });
-
- //calculate the udp checksum
- transport
- .update_checksum_ipv4(&ip, payload)
- .map_err(|err| {
- use err::packet::TransportChecksumError as I;
- match err {
- I::PayloadLen(err) => PayloadLen(err),
- I::Icmpv6InIpv4 => Icmpv6InIpv4,
- }
- })?;
-
- //write (will automatically calculate the checksum)
- ip.write(writer).map_err(Io)?;
- ext.write(writer, ip.protocol).map_err(|err| {
- use err::ipv4_exts::HeaderWriteError as I;
- match err {
- I::Io(err) => Io(err),
- I::Content(err) => Ipv4Exts(err),
- }
- })?;
- }
- Ipv6(mut ip, mut ext) => {
- //set total length
- let transport_size = transport.header_len() + payload.len();
- ip.set_payload_length(ext.header_len() + transport_size)
- .map_err(PayloadLen)?;
- use crate::TransportHeader::*;
- match transport {
- Icmpv4(_) => {}
- Icmpv6(_) => {}
- Udp(ref mut udp) => {
- udp.length = transport_size as u16;
- }
- Tcp(_) => {}
- }
-
- //set the protocol
- ip.next_header = ext.set_next_headers(match transport {
- Icmpv4(_) => ip_number::ICMP,
- Icmpv6(_) => ip_number::IPV6_ICMP,
- Udp(_) => ip_number::UDP,
- Tcp(_) => ip_number::TCP,
- });
-
- //calculate the udp checksum
- transport
- .update_checksum_ipv6(&ip, payload)
- .map_err(PayloadLen)?;
-
- //write (will automatically calculate the checksum)
- ip.write(writer).map_err(Io)?;
- ext.write(writer, ip.next_header).map_err(|err| {
- use err::ipv6_exts::HeaderWriteError as I;
- match err {
- I::Io(err) => Io(err),
- I::Content(err) => Ipv6Exts(err),
- }
- })?;
- }
- }
-
- //finally write the udp header & payload
- transport.write(writer).map_err(Io)?;
- }
+ Some(Tcp(_)) => {}
+ Some(Icmpv4(_)) => {}
+ Some(Icmpv6(_)) => {}
+ None => {}
}
+
+ // net header
+ match net {
+ Some(NetHeaders::Ipv4(mut ip, mut ip_exts)) => {
+ // set payload length & ip number
+ ip.set_payload_len(
+ ip_exts.header_len()
+ + transport.as_ref().map(|v| v.header_len()).unwrap_or(0)
+ + payload.len(),
+ )
+ .map_err(PayloadLen)?;
+
+ if let Some(transport) = &transport {
+ ip.protocol = ip_exts.set_next_headers(match &transport {
+ Icmpv4(_) => ip_number::ICMP,
+ Icmpv6(_) => ip_number::IPV6_ICMP,
+ Udp(_) => ip_number::UDP,
+ Tcp(_) => ip_number::TCP,
+ });
+ }
+
+ // write ip header & extensions
+ ip.write(writer).map_err(Io)?;
+ ip_exts.write(writer, ip.protocol).map_err(|err| {
+ use err::ipv4_exts::HeaderWriteError as I;
+ match err {
+ I::Io(err) => Io(err),
+ I::Content(err) => Ipv4Exts(err),
+ }
+ })?;
+
+ // update the transport layer checksum
+ if let Some(t) = &mut transport {
+ t.update_checksum_ipv4(&ip, payload).map_err(|err| {
+ use err::packet::TransportChecksumError as I;
+ match err {
+ I::PayloadLen(err) => PayloadLen(err),
+ I::Icmpv6InIpv4 => Icmpv6InIpv4,
+ }
+ })?;
+ }
+ }
+ Some(NetHeaders::Ipv6(mut ip, mut ip_exts)) => {
+ // set payload length & ip number
+ ip.set_payload_length(
+ ip_exts.header_len()
+ + transport.as_ref().map(|v| v.header_len()).unwrap_or(0)
+ + payload.len(),
+ )
+ .map_err(PayloadLen)?;
+
+ if let Some(transport) = &transport {
+ ip.next_header = ip_exts.set_next_headers(match &transport {
+ Icmpv4(_) => ip_number::ICMP,
+ Icmpv6(_) => ip_number::IPV6_ICMP,
+ Udp(_) => ip_number::UDP,
+ Tcp(_) => ip_number::TCP,
+ });
+ }
+
+ // write ip header & extensions
+ ip.write(writer).map_err(Io)?;
+ ip_exts.write(writer, ip.next_header).map_err(|err| {
+ use err::ipv6_exts::HeaderWriteError as I;
+ match err {
+ I::Io(err) => Io(err),
+ I::Content(err) => Ipv6Exts(err),
+ }
+ })?;
+
+ // update the transport layer checksum
+ if let Some(t) = &mut transport {
+ t.update_checksum_ipv6(&ip, payload).map_err(PayloadLen)?;
+ }
+ }
+ Some(NetHeaders::Arp(arp)) => {
+ writer.write_all(&arp.to_bytes()).map_err(Io)?;
+ }
+ None => {}
+ }
+
+ // write transport header
+ if let Some(transport) = transport {
+ transport.write(writer).map_err(Io)?;
+ }
+
+ // and finally the payload
writer.write_all(payload).map_err(Io)?;
+
Ok(())
}
///Returns the size of the packet when it is serialized
fn final_size<B>(builder: &PacketBuilderStep<B>, payload_size: usize) -> usize {
- use crate::IpHeaders::*;
+ use crate::NetHeaders::*;
use crate::TransportHeader::*;
use crate::VlanHeader::*;
(match builder.state.link_header {
@@ -1958,9 +2069,10 @@
Some(Single(_)) => SingleVlanHeader::LEN,
Some(Double(_)) => DoubleVlanHeader::LEN,
None => 0,
- } + match builder.state.ip_header {
+ } + match builder.state.net_header {
Some(Ipv4(ref value, ref ext)) => value.header_len() + ext.header_len(),
Some(Ipv6(_, ref ext)) => Ipv6Header::LEN + ext.header_len(),
+ Some(Arp(ref packet)) => packet.packet_len(),
None => 0,
} + match builder.state.transport_header {
Some(Icmpv4(ref value)) => value.header_len(),
@@ -1984,9 +2096,9 @@
PacketBuilderStep::<UdpHeader> {
state: PacketImpl {
link_header: None,
- ip_header: None,
+ net_header: None,
vlan_header: None,
- transport_header: None
+ transport_header: None,
},
_marker: marker::PhantomData::<UdpHeader> {}
}
@@ -1998,11 +2110,11 @@
#[should_panic]
fn final_write_panic_missing_ip() {
let mut writer = Vec::new();
- final_write(
+ final_write_with_net(
PacketBuilderStep::<UdpHeader> {
state: PacketImpl {
link_header: None,
- ip_header: None,
+ net_header: None,
vlan_header: None,
transport_header: None,
},
@@ -2024,6 +2136,108 @@
use std::io::Read;
#[test]
+ fn eth_arp() {
+ let expected_header = ArpPacket::new(
+ ArpHardwareId::ETHERNET,
+ EtherType::IPV4,
+ ArpOperation::REQUEST,
+ &[20, 30, 40, 50, 60, 70],
+ &[10, 1, 1, 5],
+ &[00, 01, 02, 03, 04, 05],
+ &[192, 168, 1, 2],
+ )
+ .unwrap();
+
+ let mut serialized = Vec::new();
+
+ let pkg = PacketBuilder::ethernet2(
+ [0x00, 0x1b, 0x21, 0x0f, 0x91, 0x9b],
+ [0xde, 0xad, 0xc0, 0x00, 0xff, 0xee],
+ )
+ .arp(expected_header.clone());
+
+ let target_size = pkg.size();
+ pkg.write(&mut serialized).unwrap();
+
+ // validate that the predicted size was matching
+ assert_eq!(serialized.len(), target_size);
+
+ // deserialize each part of the message and check it
+ use std::io::Cursor;
+ let mut cursor = Cursor::new(&serialized);
+
+ // ethernet 2 header
+ assert_eq!(
+ Ethernet2Header::read(&mut cursor).unwrap(),
+ Ethernet2Header {
+ source: [0x00, 0x1b, 0x21, 0x0f, 0x91, 0x9b],
+ destination: [0xde, 0xad, 0xc0, 0x00, 0xff, 0xee],
+ ether_type: ether_type::ARP
+ }
+ );
+
+ // arp packet
+ assert_eq!(ArpPacket::read(&mut cursor).unwrap(), expected_header);
+ }
+
+ #[test]
+ fn eth_vlan_arp() {
+ let expected_arp = ArpPacket::new(
+ ArpHardwareId::ETHERNET,
+ EtherType::IPV4,
+ ArpOperation::REQUEST,
+ &[20, 30, 40, 50, 60, 70],
+ &[10, 1, 1, 5],
+ &[00, 01, 02, 03, 04, 05],
+ &[192, 168, 1, 2],
+ )
+ .unwrap();
+ let vlan = SingleVlanHeader {
+ pcp: VlanPcp::ZERO,
+ drop_eligible_indicator: false,
+ vlan_id: VlanId::try_new(123).unwrap(),
+ ether_type: EtherType(0), // should get overwritten
+ };
+
+ let mut serialized = Vec::new();
+
+ let pkg = PacketBuilder::ethernet2(
+ [0x00, 0x1b, 0x21, 0x0f, 0x91, 0x9b],
+ [0xde, 0xad, 0xc0, 0x00, 0xff, 0xee],
+ )
+ .vlan(VlanHeader::Single(vlan.clone()))
+ .arp(expected_arp.clone());
+
+ let target_size = pkg.size();
+ pkg.write(&mut serialized).unwrap();
+
+ // validate that the predicted size was matching
+ assert_eq!(serialized.len(), target_size);
+
+ // deserialize each part of the message and check it
+ use std::io::Cursor;
+ let mut cursor = Cursor::new(&serialized);
+
+ // ethernet 2 header
+ assert_eq!(
+ Ethernet2Header::read(&mut cursor).unwrap(),
+ Ethernet2Header {
+ source: [0x00, 0x1b, 0x21, 0x0f, 0x91, 0x9b],
+ destination: [0xde, 0xad, 0xc0, 0x00, 0xff, 0xee],
+ ether_type: ether_type::VLAN_TAGGED_FRAME
+ }
+ );
+
+ // vlan header
+ let mut expected_vlan = vlan.clone();
+ expected_vlan.ether_type = EtherType::ARP;
+ assert_eq!(SingleVlanHeader::read(&mut cursor).unwrap(), expected_vlan);
+
+ // arp packet
+ assert_eq!(ArpPacket::read(&mut cursor).unwrap(), expected_arp);
+ }
+
+ #[test]
fn eth_ipv4_udp() {
//generate
let in_payload = [24, 25, 26, 27];
@@ -2109,7 +2323,7 @@
LinuxSllHeader::read(&mut cursor).unwrap(),
LinuxSllHeader {
packet_type: LinuxSllPacketType::OUTGOING,
- arp_hrd_type: ArpHardwareId::ETHER,
+ arp_hrd_type: ArpHardwareId::ETHERNET,
sender_address_valid_length: 6,
sender_address: [7, 8, 9, 10, 11, 12, 0, 0],
protocol_type: LinuxSllProtocolType::EtherType(EtherType::IPV4)
@@ -2142,6 +2356,52 @@
}
#[test]
+ fn linuxsll_arp() {
+ let expected_arp = ArpPacket::new(
+ ArpHardwareId::ETHERNET,
+ EtherType::IPV4,
+ ArpOperation::REQUEST,
+ &[20, 30, 40, 50, 60, 70],
+ &[10, 1, 1, 5],
+ &[00, 01, 02, 03, 04, 05],
+ &[192, 168, 1, 2],
+ )
+ .unwrap();
+
+ // build packet
+ let builder =
+ PacketBuilder::linux_sll(LinuxSllPacketType::OUTGOING, 6, [7, 8, 9, 10, 11, 12, 0, 0])
+ .arp(expected_arp.clone());
+
+ let predicted_size = builder.size();
+
+ let mut serialized = Vec::with_capacity(builder.size());
+ builder.write(&mut serialized).unwrap();
+
+ // validate predicted size
+ assert_eq!(predicted_size, serialized.len());
+
+ // deserialize each part of the message and check it
+ use std::io::Cursor;
+ let mut cursor = Cursor::new(&serialized);
+
+ // linux sll header
+ assert_eq!(
+ LinuxSllHeader::read(&mut cursor).unwrap(),
+ LinuxSllHeader {
+ packet_type: LinuxSllPacketType::OUTGOING,
+ arp_hrd_type: ArpHardwareId::ETHERNET,
+ sender_address_valid_length: 6,
+ sender_address: [7, 8, 9, 10, 11, 12, 0, 0],
+ protocol_type: LinuxSllProtocolType::EtherType(EtherType::ARP)
+ }
+ );
+
+ // arp
+ assert_eq!(ArpPacket::read(&mut cursor).unwrap(), expected_arp);
+ }
+
+ #[test]
fn ipv4() {
let auth_ext = IpAuthHeader::new(0.into(), 1, 2, &[3, 4, 5, 6]).unwrap();
@@ -2470,7 +2730,7 @@
}
#[test]
- fn udp_builder_eth_ipv6_udp() {
+ fn eth_ipv6_udp() {
//generate
let in_payload = [50, 51, 52, 53];
let mut serialized = Vec::new();
@@ -2540,7 +2800,7 @@
}
#[test]
- fn udp_builder_linuxsll_ipv6_udp() {
+ fn linuxsll_ipv6_udp() {
//generate
let in_payload = [50, 51, 52, 53];
let mut serialized = Vec::new();
@@ -2575,7 +2835,7 @@
LinuxSllHeader::read(&mut cursor).unwrap(),
LinuxSllHeader {
packet_type: LinuxSllPacketType::OUTGOING,
- arp_hrd_type: ArpHardwareId::ETHER,
+ arp_hrd_type: ArpHardwareId::ETHERNET,
sender_address_valid_length: 6,
sender_address: [7, 8, 9, 10, 11, 12, 0, 0],
protocol_type: LinuxSllProtocolType::EtherType(EtherType::IPV6)
@@ -2612,7 +2872,7 @@
}
#[test]
- fn udp_builder_eth_single_vlan_ipv4_udp() {
+ fn eth_single_vlan_ipv4_udp() {
//generate
let in_payload = [50, 51, 52, 53];
let mut serialized = Vec::new();
@@ -2685,7 +2945,7 @@
}
#[test]
- fn udp_builder_eth_double_vlan_ipv6_udp() {
+ fn eth_double_vlan_ipv6_udp() {
//generate
let in_payload = [50, 51, 52, 53];
let mut serialized = Vec::new();
@@ -2783,7 +3043,7 @@
}
#[test]
- fn udp_builder_eth_ip_udp() {
+ fn eth_ip_udp() {
//generate
let in_payload = [50, 51, 52, 53];
let mut serialized = Vec::new();
@@ -2861,7 +3121,7 @@
}
#[test]
- fn udp_builder_linuxsll_ip_udp() {
+ fn linuxsll_ip_udp() {
//generate
let in_payload = [50, 51, 52, 53];
let mut serialized = Vec::new();
@@ -2904,7 +3164,7 @@
LinuxSllHeader::read(&mut cursor).unwrap(),
LinuxSllHeader {
packet_type: LinuxSllPacketType::OUTGOING,
- arp_hrd_type: ArpHardwareId::ETHER,
+ arp_hrd_type: ArpHardwareId::ETHERNET,
sender_address_valid_length: 6,
sender_address: [7, 8, 9, 10, 11, 12, 0, 0],
protocol_type: LinuxSllProtocolType::EtherType(EtherType::IPV6)
@@ -2941,7 +3201,7 @@
}
#[test]
- fn udp_builder_eth_vlan_ip_udp() {
+ fn eth_vlan_ip_udp() {
//generate
let in_payload = [50, 51, 52, 53];
let mut serialized = Vec::new();
@@ -3260,7 +3520,7 @@
}
#[test]
- fn tcp_options() {
+ fn eth_ipv4_tcp_options() {
let mut serialized = Vec::new();
use crate::TcpOptionElement::*;
@@ -3286,6 +3546,34 @@
}
#[test]
+ fn eth_ipv4_tcp_header() {
+ let mut serialized = Vec::new();
+
+ let tcp_header = TcpHeader {
+ source_port: 1234,
+ destination_port: 2345,
+ sequence_number: 3456,
+ acknowledgment_number: 4567,
+ ..Default::default()
+ };
+
+ PacketBuilder::ethernet2([1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12])
+ .ipv4([13, 14, 15, 16], [17, 18, 19, 20], 21)
+ .tcp_header(tcp_header.clone())
+ .write(&mut serialized, &[])
+ .unwrap();
+
+ let decoded = PacketHeaders::from_ethernet_slice(&serialized[..]).unwrap();
+
+ let mut expected = tcp_header;
+ expected.checksum = expected
+ .calc_checksum_ipv4_raw([13, 14, 15, 16], [17, 18, 19, 20], &[])
+ .unwrap();
+
+ assert_eq!(decoded.transport, Some(TransportHeader::Tcp(expected)));
+ }
+
+ #[test]
fn size() {
//ipv4 no vlan ethernet
assert_eq!(
diff --git a/crates/etherparse/src/packet_headers.rs b/crates/etherparse/src/packet_headers.rs
index a14f805..2f0ba58 100644
--- a/crates/etherparse/src/packet_headers.rs
+++ b/crates/etherparse/src/packet_headers.rs
@@ -92,6 +92,7 @@
/// The result is returned as a [`PacketHeaders`] struct. Currently supported
/// ether type numbers are:
///
+ /// * `ether_type::ARP`
/// * `ether_type::IPV4`
/// * `ether_type::IPV6`
/// * `ether_type::VLAN_TAGGED_FRAME`
@@ -166,7 +167,6 @@
}),
};
- //parse vlan header(s)
use ether_type::*;
result.vlan = match ether_type {
@@ -265,6 +265,13 @@
result.transport = transport;
result.payload = payload;
}
+ ARP => {
+ result.net = Some(NetHeaders::Arp(
+ ArpPacket::from_slice(rest).map_err(|err| Len(add_offset(err, rest)))?,
+ ));
+
+ result.payload = PayloadSlice::Empty;
+ }
_ => {}
};
@@ -936,6 +943,7 @@
let mut ip = match ip {
NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
+ NetHeaders::Arp(_) => unreachable!(),
};
ip.set_next_headers(ip_number::UDP);
ip.into()
@@ -965,6 +973,7 @@
len_source: match test.net.as_ref().unwrap() {
NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
+ NetHeaders::Arp(_) => unreachable!(),
},
layer: err::Layer::UdpHeader,
layer_start_offset: base_len,
@@ -986,6 +995,7 @@
let mut ip = match ip {
NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
+ NetHeaders::Arp(_) => unreachable!(),
};
ip.set_next_headers(ip_number::TCP);
ip.into()
@@ -1013,6 +1023,7 @@
len_source: match test.net.as_ref().unwrap() {
NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
+ NetHeaders::Arp(_) => unreachable!(),
},
layer: err::Layer::TcpHeader,
layer_start_offset: base_len,
@@ -1047,6 +1058,7 @@
let mut ip = match ip {
NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
+ NetHeaders::Arp(_) => unreachable!(),
};
ip.set_next_headers(ip_number::ICMP);
ip.into()
@@ -1072,6 +1084,7 @@
len_source: match test.net.as_ref().unwrap() {
NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
+ NetHeaders::Arp(_) => unreachable!(),
},
layer: err::Layer::Icmpv4,
layer_start_offset: base_len,
@@ -1094,6 +1107,7 @@
let mut ip = match ip {
NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
+ NetHeaders::Arp(_) => unreachable!(),
};
ip.set_next_headers(ip_number::IPV6_ICMP);
ip.into()
@@ -1119,6 +1133,7 @@
len_source: match test.net.as_ref().unwrap() {
NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
+ NetHeaders::Arp(_) => unreachable!(),
},
layer: err::Layer::Icmpv6,
layer_start_offset: base_len,
@@ -1185,6 +1200,7 @@
match ip {
NetHeaders::Ipv4(_, _) => ether_type::IPV4,
NetHeaders::Ipv6(_, _) => ether_type::IPV6,
+ NetHeaders::Arp(_) => ether_type::ARP,
},
&data,
)
@@ -1241,6 +1257,7 @@
match ip {
NetHeaders::Ipv4(_, _) => ether_type::IPV4,
NetHeaders::Ipv6(_, _) => ether_type::IPV6,
+ NetHeaders::Arp(_) => ether_type::ARP,
},
&data,
)
diff --git a/crates/etherparse/src/payload_slice.rs b/crates/etherparse/src/payload_slice.rs
index 3715e54..07fa702 100644
--- a/crates/etherparse/src/payload_slice.rs
+++ b/crates/etherparse/src/payload_slice.rs
@@ -3,6 +3,8 @@
/// Payload together with an identifier the type of content.
#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
pub enum PayloadSlice<'a> {
+ /// No specific payload (e.g. ARP packet).
+ Empty,
/// Payload with it's type identified by an ether type number
/// (e.g. after an ethernet II or vlan header).
Ether(EtherPayloadSlice<'a>),
@@ -24,6 +26,7 @@
impl<'a> PayloadSlice<'a> {
pub fn slice(&self) -> &'a [u8] {
match self {
+ PayloadSlice::Empty => &[],
PayloadSlice::Ether(s) => s.payload,
PayloadSlice::Ip(s) => s.payload,
PayloadSlice::Udp(s) => s,
diff --git a/crates/etherparse/src/sliced_packet.rs b/crates/etherparse/src/sliced_packet.rs
index 63c7382..e975602 100644
--- a/crates/etherparse/src/sliced_packet.rs
+++ b/crates/etherparse/src/sliced_packet.rs
@@ -142,6 +142,7 @@
/// The result is returned as a [`SlicedPacket`] struct. Currently supported
/// ether type numbers are:
///
+ /// * `ether_type::ARP`
/// * `ether_type::IPV4`
/// * `ether_type::IPV6`
/// * `ether_type::VLAN_TAGGED_FRAME`
@@ -202,6 +203,7 @@
IPV4 => cursor.slice_ipv4(),
IPV6 => cursor.slice_ipv6(),
VLAN_TAGGED_FRAME | PROVIDER_BRIDGING | VLAN_DOUBLE_TAGGED_FRAME => cursor.slice_vlan(),
+ ARP => cursor.slice_arp(),
_ => Ok(cursor.result),
}
}
@@ -332,6 +334,7 @@
match net {
Ipv4(v) => Some(v.payload()),
Ipv6(v) => Some(v.payload()),
+ Arp(_) => None,
}
} else {
None
@@ -344,7 +347,7 @@
match &self.net {
Some(Ipv4(v)) => v.is_payload_fragmented(),
Some(Ipv6(v)) => v.is_payload_fragmented(),
- None => false,
+ Some(Arp(_)) | None => false,
}
}
}
@@ -457,7 +460,7 @@
buf.extend_from_slice(
&LinuxSllHeader {
packet_type: LinuxSllPacketType::HOST,
- arp_hrd_type: ArpHardwareId::ETHER,
+ arp_hrd_type: ArpHardwareId::ETHERNET,
sender_address_valid_length: 6,
sender_address: [1, 2, 3, 4, 5, 6, 0, 0],
protocol_type: LinuxSllProtocolType::EtherType(EtherType::WAKE_ON_LAN),
@@ -575,6 +578,33 @@
None
);
+ // arp
+ {
+ let mut buf = Vec::with_capacity(Ethernet2Header::LEN + ArpEthIpv4Packet::LEN);
+ buf.extend_from_slice(
+ &Ethernet2Header {
+ source: [0; 6],
+ destination: [0; 6],
+ ether_type: EtherType::ARP,
+ }
+ .to_bytes(),
+ );
+ buf.extend_from_slice(
+ &ArpEthIpv4Packet {
+ operation: ArpOperation::REPLY,
+ sender_mac: [0; 6],
+ sender_ipv4: [0; 4],
+ target_mac: [0; 6],
+ target_ipv4: [0; 4],
+ }
+ .to_bytes(),
+ );
+ assert_eq!(
+ SlicedPacket::from_ethernet(&buf).unwrap().ip_payload(),
+ None
+ );
+ }
+
// ipv4
{
let payload = [1, 2, 3, 4];
@@ -625,6 +655,141 @@
}
#[test]
+ fn is_ip_payload_fragmented() {
+ use alloc::vec::*;
+
+ // no content
+ assert_eq!(
+ SlicedPacket {
+ link: None,
+ vlan: None,
+ net: None,
+ transport: None,
+ }
+ .is_ip_payload_fragmented(),
+ false
+ );
+
+ // arp
+ {
+ let mut buf = Vec::with_capacity(Ethernet2Header::LEN + ArpEthIpv4Packet::LEN);
+ buf.extend_from_slice(
+ &Ethernet2Header {
+ source: [0; 6],
+ destination: [0; 6],
+ ether_type: EtherType::ARP,
+ }
+ .to_bytes(),
+ );
+ buf.extend_from_slice(
+ &ArpEthIpv4Packet {
+ operation: ArpOperation::REPLY,
+ sender_mac: [0; 6],
+ sender_ipv4: [0; 4],
+ target_mac: [0; 6],
+ target_ipv4: [0; 4],
+ }
+ .to_bytes(),
+ );
+ assert_eq!(
+ SlicedPacket::from_ethernet(&buf)
+ .unwrap()
+ .is_ip_payload_fragmented(),
+ false
+ );
+ }
+
+ // ipv4 (non fragmented)
+ {
+ let payload = [1, 2, 3, 4];
+ let mut buf = Vec::with_capacity(Ipv4Header::MIN_LEN + 4);
+ buf.extend_from_slice(
+ &Ipv4Header {
+ protocol: IpNumber::ARIS,
+ total_len: Ipv4Header::MIN_LEN_U16 + 4,
+ ..Default::default()
+ }
+ .to_bytes(),
+ );
+ buf.extend_from_slice(&payload);
+ assert_eq!(
+ SlicedPacket::from_ip(&buf)
+ .unwrap()
+ .is_ip_payload_fragmented(),
+ false
+ );
+ }
+
+ // ipv4 (fragmented)
+ {
+ let payload = [1, 2, 3, 4];
+ let mut buf = Vec::with_capacity(Ipv4Header::MIN_LEN + 4);
+ buf.extend_from_slice(
+ &Ipv4Header {
+ protocol: IpNumber::ARIS,
+ total_len: Ipv4Header::MIN_LEN_U16 + 4,
+ more_fragments: true,
+ fragment_offset: IpFragOffset::ZERO,
+ ..Default::default()
+ }
+ .to_bytes(),
+ );
+ buf.extend_from_slice(&payload);
+ assert!(SlicedPacket::from_ip(&buf)
+ .unwrap()
+ .is_ip_payload_fragmented());
+ }
+
+ // ipv6 (non fragmented)
+ {
+ let payload = [1, 2, 3, 4];
+ let mut buf = Vec::with_capacity(Ipv6Header::LEN + 4);
+ buf.extend_from_slice(
+ &Ipv6Header {
+ payload_length: 4,
+ next_header: IpNumber::ARGUS,
+ ..Default::default()
+ }
+ .to_bytes(),
+ );
+ buf.extend_from_slice(&payload);
+ assert_eq!(
+ SlicedPacket::from_ip(&buf)
+ .unwrap()
+ .is_ip_payload_fragmented(),
+ false
+ );
+ }
+
+ // ipv6 (fragmented)
+ {
+ let payload = [1, 2, 3, 4];
+ let mut buf = Vec::with_capacity(Ipv6Header::LEN + 4);
+ buf.extend_from_slice(
+ &Ipv6Header {
+ payload_length: Ipv6FragmentHeader::LEN as u16 + 4,
+ next_header: IpNumber::IPV6_FRAGMENTATION_HEADER,
+ ..Default::default()
+ }
+ .to_bytes(),
+ );
+ buf.extend_from_slice(
+ &Ipv6FragmentHeader {
+ next_header: IpNumber::ARGUS,
+ fragment_offset: IpFragOffset::ZERO,
+ more_fragments: true,
+ identification: 0,
+ }
+ .to_bytes(),
+ );
+ buf.extend_from_slice(&payload);
+ assert!(SlicedPacket::from_ip(&buf)
+ .unwrap()
+ .is_ip_payload_fragmented());
+ }
+ }
+
+ #[test]
fn from_x_slice() {
// no eth
from_x_slice_vlan_variants(&TestPacket {
@@ -690,7 +855,7 @@
{
let linux_sll = LinuxSllHeader {
packet_type: LinuxSllPacketType::HOST,
- arp_hrd_type: ArpHardwareId::ETHER,
+ arp_hrd_type: ArpHardwareId::ETHERNET,
sender_address_valid_length: 6,
sender_address: [1, 2, 3, 4, 5, 6, 0, 0],
protocol_type: LinuxSllProtocolType::EtherType(EtherType::WAKE_ON_LAN),
@@ -1165,6 +1330,7 @@
let mut ip = match ip {
NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
+ NetHeaders::Arp(_) => unreachable!(),
};
ip.set_next_headers(ip_number::UDP);
ip.into()
@@ -1194,6 +1360,7 @@
len_source: match test.net.as_ref().unwrap() {
NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
+ NetHeaders::Arp(_) => unreachable!(),
},
layer: Layer::UdpHeader,
layer_start_offset: base_len,
@@ -1215,6 +1382,7 @@
let mut ip = match ip {
NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
+ NetHeaders::Arp(_) => unreachable!(),
};
ip.set_next_headers(ip_number::TCP);
ip.into()
@@ -1243,6 +1411,7 @@
len_source: match test.net.as_ref().unwrap() {
NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
+ NetHeaders::Arp(_) => unreachable!(),
},
layer: Layer::TcpHeader,
layer_start_offset: base_len,
@@ -1278,6 +1447,7 @@
let mut ip = match ip {
NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
+ NetHeaders::Arp(_) => unreachable!(),
};
ip.set_next_headers(ip_number::ICMP);
ip.into()
@@ -1304,6 +1474,7 @@
len_source: match test.net.as_ref().unwrap() {
NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
+ NetHeaders::Arp(_) => unreachable!(),
},
layer: Layer::Icmpv4,
layer_start_offset: base_len,
@@ -1326,6 +1497,7 @@
let mut ip = match ip {
NetHeaders::Ipv4(h, e) => IpHeaders::Ipv4(h.clone(), e.clone()),
NetHeaders::Ipv6(h, e) => IpHeaders::Ipv6(h.clone(), e.clone()),
+ NetHeaders::Arp(_) => unreachable!(),
};
ip.set_next_headers(ip_number::IPV6_ICMP);
ip.into()
@@ -1352,6 +1524,7 @@
len_source: match test.net.as_ref().unwrap() {
NetHeaders::Ipv4(_, _) => LenSource::Ipv4HeaderTotalLen,
NetHeaders::Ipv6(_, _) => LenSource::Ipv6HeaderPayloadLen,
+ NetHeaders::Arp(_) => unreachable!(),
},
layer: Layer::Icmpv6,
layer_start_offset: base_len,
@@ -1403,6 +1576,7 @@
.unwrap()
.0,
),
+ NetSlice::Arp(arp) => NetHeaders::Arp(arp.to_packet()),
}
})
);
@@ -1473,6 +1647,7 @@
let ether_type = match ip {
NetHeaders::Ipv4(_, _) => ether_type::IPV4,
NetHeaders::Ipv6(_, _) => ether_type::IPV6,
+ NetHeaders::Arp(_) => ether_type::ARP,
};
let result = SlicedPacket::from_ether_type(ether_type, &data).unwrap();
assert_eq!(
@@ -1523,6 +1698,7 @@
match ip {
NetHeaders::Ipv4(_, _) => ether_type::IPV4,
NetHeaders::Ipv6(_, _) => ether_type::IPV6,
+ NetHeaders::Arp(_) => ether_type::ARP,
},
&data,
)
diff --git a/crates/etherparse/src/sliced_packet_cursor.rs b/crates/etherparse/src/sliced_packet_cursor.rs
index fb1a364..b6db378 100644
--- a/crates/etherparse/src/sliced_packet_cursor.rs
+++ b/crates/etherparse/src/sliced_packet_cursor.rs
@@ -48,6 +48,7 @@
//continue parsing (if required)
match ether_type {
+ ARP => self.slice_arp(),
IPV4 => self.slice_ipv4(),
IPV6 => self.slice_ipv6(),
VLAN_TAGGED_FRAME | PROVIDER_BRIDGING | VLAN_DOUBLE_TAGGED_FRAME => self.slice_vlan(),
@@ -74,6 +75,7 @@
//continue parsing (if required)
match protocol_type {
+ LinuxSllProtocolType::EtherType(EtherType::ARP) => self.slice_arp(),
LinuxSllProtocolType::EtherType(EtherType::IPV4) => self.slice_ipv4(),
LinuxSllProtocolType::EtherType(EtherType::IPV6) => self.slice_ipv6(),
_ => Ok(self.result),
@@ -107,11 +109,13 @@
}));
match inner_ether_type {
+ ARP => self.slice_arp(),
IPV4 => self.slice_ipv4(),
IPV6 => self.slice_ipv6(),
_ => Ok(self.result),
}
}
+ ARP => self.slice_arp(),
IPV4 => self.slice_ipv4(),
IPV6 => self.slice_ipv6(),
_ => Ok(self.result),
@@ -274,6 +278,19 @@
}
}
+ pub fn slice_arp(mut self) -> Result<SlicedPacket<'a>, err::packet::SliceError> {
+ let result = ArpPacketSlice::from_slice(self.slice).map_err(|mut err| {
+ err.layer_start_offset += self.offset;
+ err::packet::SliceError::Len(err)
+ })?;
+
+ //set the new data
+ self.move_by(result.slice().len());
+ self.result.net = Some(NetSlice::Arp(result.clone()));
+
+ Ok(self.result)
+ }
+
pub fn slice_icmp4(mut self) -> Result<SlicedPacket<'a>, err::LenError> {
use crate::TransportSlice::*;
diff --git a/crates/etherparse/src/test_gens/mod.rs b/crates/etherparse/src/test_gens/mod.rs
index c677a35..48ddeb6 100644
--- a/crates/etherparse/src/test_gens/mod.rs
+++ b/crates/etherparse/src/test_gens/mod.rs
@@ -150,6 +150,7 @@
}
pub static ETHERNET_KNOWN_ETHER_TYPES: &'static [EtherType] = &[
+ ether_type::ARP,
ether_type::IPV4,
ether_type::IPV6,
ether_type::VLAN_TAGGED_FRAME,
@@ -226,6 +227,54 @@
}
prop_compose! {
+ pub fn arp_packet_any()
+ (
+ hw_addr_size in any::<u8>(),
+ proto_addr_size in any::<u8>()
+ )
+ (
+ hw_addr_type in any::<u16>(),
+ proto_addr_type in any::<u16>(),
+ operation in any::<u16>(),
+ sender_hw_addr in prop::collection::vec(any::<u8>(), hw_addr_size as usize),
+ sender_protocol_addr in prop::collection::vec(any::<u8>(), proto_addr_size as usize),
+ target_hw_addr in prop::collection::vec(any::<u8>(), hw_addr_size as usize),
+ target_protocol_addr in prop::collection::vec(any::<u8>(), proto_addr_size as usize)
+ ) -> ArpPacket
+ {
+ ArpPacket::new(
+ ArpHardwareId(hw_addr_type),
+ EtherType(proto_addr_type),
+ ArpOperation(operation),
+ &sender_hw_addr[..],
+ &sender_protocol_addr[..],
+ &target_hw_addr[..],
+ &target_protocol_addr[..]
+ ).unwrap()
+ }
+}
+
+prop_compose! {
+ pub fn arp_eth_ipv4_packet_any()
+ (
+ operation in any::<u16>(),
+ sender_mac in prop::array::uniform6(any::<u8>()),
+ sender_ipv4 in prop::array::uniform4(any::<u8>()),
+ target_mac in prop::array::uniform6(any::<u8>()),
+ target_ipv4 in prop::array::uniform4(any::<u8>())
+ ) -> ArpEthIpv4Packet
+ {
+ ArpEthIpv4Packet {
+ operation: ArpOperation(operation),
+ sender_mac,
+ sender_ipv4,
+ target_mac,
+ target_ipv4,
+ }
+ }
+}
+
+prop_compose! {
pub fn ipv4_options_any()
(
len_div_4 in 0u8..10,
diff --git a/crates/etherparse/src/test_packet.rs b/crates/etherparse/src/test_packet.rs
index 13691d6..73b16fb 100644
--- a/crates/etherparse/src/test_packet.rs
+++ b/crates/etherparse/src/test_packet.rs
@@ -26,8 +26,8 @@
if let Some(vlan) = &self.vlan {
vlan.write(&mut result).unwrap();
}
- if let Some(ip) = &self.net {
- match ip {
+ if let Some(net) = &self.net {
+ match net {
NetHeaders::Ipv4(ipv4, exts) => {
ipv4.write_raw(&mut result).unwrap();
exts.write(&mut result, ipv4.protocol).unwrap();
@@ -36,6 +36,9 @@
ipv6.write(&mut result).unwrap();
exts.write(&mut result, ipv6.next_header).unwrap();
}
+ NetHeaders::Arp(arp) => {
+ arp.write(&mut result).unwrap();
+ }
}
}
if let Some(transport) = &self.transport {
@@ -88,6 +91,7 @@
)
.unwrap();
}
+ Some(Arp(_)) => {}
}
use TransportHeader::*;
@@ -118,6 +122,7 @@
)
.unwrap();
}
+ Arp(_) => {}
}
}
@@ -125,6 +130,7 @@
self.net.as_ref().map_or(false, |net| match net {
NetHeaders::Ipv4(h, _) => h.is_fragmenting_payload(),
NetHeaders::Ipv6(_, e) => e.is_fragmenting_payload(),
+ NetHeaders::Arp(_) => false,
})
}
}
diff --git a/crates/etherparse/src/transport/mod.rs b/crates/etherparse/src/transport/mod.rs
index c09d57f..45e36b1 100644
--- a/crates/etherparse/src/transport/mod.rs
+++ b/crates/etherparse/src/transport/mod.rs
@@ -1,25 +1,68 @@
-pub mod icmp_echo_header;
/// Module containing ICMPv4 related types and constants.
pub mod icmpv4;
-pub mod icmpv4_header;
-pub mod icmpv4_slice;
-pub mod icmpv4_type;
+
/// Module containing ICMPv6 related types and constants
pub mod icmpv6;
-pub mod icmpv6_header;
-pub mod icmpv6_slice;
-pub mod icmpv6_type;
-pub mod tcp_header;
-pub mod tcp_header_slice;
-pub mod tcp_option_element;
-pub mod tcp_option_impl;
-pub mod tcp_option_read_error;
-pub mod tcp_option_write_error;
-pub mod tcp_options;
-pub mod tcp_options_iterator;
-pub mod tcp_slice;
-pub mod transport_header;
-pub mod transport_slice;
-pub mod udp_header;
-pub mod udp_header_slice;
-pub mod udp_slice;
+
+mod icmp_echo_header;
+pub use icmp_echo_header::*;
+
+mod icmpv4_header;
+pub use icmpv4_header::*;
+
+mod icmpv4_slice;
+pub use icmpv4_slice::*;
+
+mod icmpv4_type;
+pub use icmpv4_type::*;
+
+mod icmpv6_header;
+pub use icmpv6_header::*;
+
+mod icmpv6_slice;
+pub use icmpv6_slice::*;
+
+mod icmpv6_type;
+pub use icmpv6_type::*;
+
+mod tcp_header;
+pub use tcp_header::*;
+
+mod tcp_header_slice;
+pub use tcp_header_slice::*;
+
+mod tcp_option_element;
+pub use tcp_option_element::*;
+
+mod tcp_option_impl;
+pub use tcp_option_impl::*;
+
+mod tcp_option_read_error;
+pub use tcp_option_read_error::*;
+
+mod tcp_option_write_error;
+pub use tcp_option_write_error::*;
+
+mod tcp_options;
+pub use tcp_options::*;
+
+mod tcp_options_iterator;
+pub use tcp_options_iterator::*;
+
+mod tcp_slice;
+pub use tcp_slice::*;
+
+mod transport_header;
+pub use transport_header::*;
+
+mod transport_slice;
+pub use transport_slice::*;
+
+mod udp_header;
+pub use udp_header::*;
+
+mod udp_header_slice;
+pub use udp_header_slice::*;
+
+mod udp_slice;
+pub use udp_slice::*;
diff --git a/crates/etherparse/src/transport/tcp_options_iterator.rs b/crates/etherparse/src/transport/tcp_options_iterator.rs
index defc2ff..e132136 100644
--- a/crates/etherparse/src/transport/tcp_options_iterator.rs
+++ b/crates/etherparse/src/transport/tcp_options_iterator.rs
@@ -18,7 +18,7 @@
}
}
-impl<'a> Iterator for TcpOptionsIterator<'a> {
+impl Iterator for TcpOptionsIterator<'_> {
type Item = Result<TcpOptionElement, TcpOptionReadError>;
fn next(&mut self) -> Option<Self::Item> {
@@ -181,7 +181,7 @@
}
}
-impl<'a> core::fmt::Debug for TcpOptionsIterator<'a> {
+impl core::fmt::Debug for TcpOptionsIterator<'_> {
fn fmt(&self, fmt: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
let mut list = fmt.debug_list();
diff --git a/crates/etherparse/src/transport/tcp_slice.rs b/crates/etherparse/src/transport/tcp_slice.rs
index c867a72..f25479f 100644
--- a/crates/etherparse/src/transport/tcp_slice.rs
+++ b/crates/etherparse/src/transport/tcp_slice.rs
@@ -408,7 +408,7 @@
}
}
-impl<'a> core::fmt::Debug for TcpSlice<'a> {
+impl core::fmt::Debug for TcpSlice<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("TcpSlice")
.field("header", &self.to_header())
diff --git a/crates/etherparse/src/transport/udp_slice.rs b/crates/etherparse/src/transport/udp_slice.rs
index 28937f9..f839745 100644
--- a/crates/etherparse/src/transport/udp_slice.rs
+++ b/crates/etherparse/src/transport/udp_slice.rs
@@ -456,4 +456,30 @@
}
}
}
+
+ proptest! {
+ #[test]
+ fn header_len(
+ udp in udp_any()
+ ) {
+ let mut udp = udp.clone();
+ udp.length = UdpHeader::LEN_U16;
+ let bytes = udp.to_bytes();
+ let slice = UdpSlice::from_slice(&bytes).unwrap();
+ assert_eq!(UdpHeader::LEN, slice.header_len());
+ }
+ }
+
+ proptest! {
+ #[test]
+ fn header_len_u16(
+ udp in udp_any()
+ ) {
+ let mut udp = udp.clone();
+ udp.length = UdpHeader::LEN_U16;
+ let bytes = udp.to_bytes();
+ let slice = UdpSlice::from_slice(&bytes).unwrap();
+ assert_eq!(UdpHeader::LEN_U16, slice.header_len_u16());
+ }
+ }
}
diff --git a/pseudo_crate/Cargo.lock b/pseudo_crate/Cargo.lock
index 4609e58..da184ce 100644
--- a/pseudo_crate/Cargo.lock
+++ b/pseudo_crate/Cargo.lock
@@ -2048,9 +2048,9 @@
[[package]]
name = "etherparse"
-version = "0.16.0"
+version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8d8a704b617484e9d867a0423cd45f7577f008c4068e2e33378f8d3860a6d73"
+checksum = "b14e4ac78394e3ea04edbbc412099cf54f2f52ded51efb79c466a282729399d2"
dependencies = [
"arrayvec",
]
diff --git a/pseudo_crate/Cargo.toml b/pseudo_crate/Cargo.toml
index 50a66c3..0d0e79d 100644
--- a/pseudo_crate/Cargo.toml
+++ b/pseudo_crate/Cargo.toml
@@ -107,7 +107,7 @@
epoll = "=4.3.3"
equivalent = "=1.0.2"
errno = "=0.3.10"
-etherparse = "=0.16.0"
+etherparse = "=0.17.0"
fallible-iterator = "=0.3.0"
fallible-streaming-iterator = "=0.1.9"
fastrand = "=2.3.0"