Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update changelog #85

Merged
merged 3 commits into from
Feb 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Etherparse is intended to provide the basic network parsing functions that allow

Some key points are:

* It is completly written in Rust and thoroughly tested.
* It is completely written in Rust and thoroughly tested.
* Special attention has been paid to not use allocations or syscalls.
* The package is still in development and can & will still change.
* The current focus of development is on the most popular protocols in the internet & transport layer.
Expand All @@ -40,7 +40,7 @@ Some key points are:
Etherparse gives you two options for parsing network packages automatically:

### Slicing the packet
Here the different components in a packet are seperated without parsing all their fields. For each header a slice is generated that allows access to the fields of a header.
Here the different components in a packet are separated without parsing all their fields. For each header a slice is generated that allows access to the fields of a header.
```rust
match SlicedPacket::from_ethernet(&packet) {
Err(value) => println!("Err {:?}", value),
Expand All @@ -67,7 +67,7 @@ In case you want to parse cut off packets (e.g. packets returned in in ICMP mess
* [`LaxSlicedPacket::from_ip`](https://docs.rs/etherparse/~0/etherparse/struct.LaxSlicedPacket.html#method.from_ip) for parsing from an IPv4 or IPv6 downwards

### Deserializing all headers into structs
This option deserializes all known headers and transferes their contents to header structs.
This option deserializes all known headers and transfers their contents to header structs.
```rust
match PacketHeaders::from_ethernet_slice(&packet) {
Err(value) => println!("Err {:?}", value),
Expand Down Expand Up @@ -108,8 +108,8 @@ It is also possible to only slice one packet layer:
* [`Icmpv6Slice::from_slice`](https://docs.rs/etherparse/~0/etherparse/struct.Icmpv6Slice.html#method.from_slice)

The resulting data types allow access to both the header(s) and the payload of the layer
and will automatially limit the length of payload if the layer has a length field limiting the
paylod (e.g. the payload of IPv6 packets will be limited by the "payload length" field in
and will automatically limit the length of payload if the layer has a length field limiting the
payload (e.g. the payload of IPv6 packets will be limited by the "payload length" field in
an IPv6 header).

### Manually slicing & parsing only headers
Expand Down Expand Up @@ -162,10 +162,10 @@ let builder = PacketBuilder::
ethernet2([1,2,3,4,5,6], //source mac
[7,8,9,10,11,12]) //destination mac
.ipv4([192,168,1,1], //source ip
[192,168,1,2], //desitination ip
[192,168,1,2], //destination ip
20) //time to life
.udp(21, //source port
1234); //desitnation port
1234); //destination port

//payload of the udp packet
let payload = [1,2,3,4,5,6,7,8];
Expand All @@ -181,10 +181,10 @@ builder.write(&mut result, &payload).unwrap();

There is also an [example for TCP packets](etherparse/examples/write_tcp.rs) available.

Check out the [PacketBuilder documentation](https://docs.rs/etherparse/~0/etherparse/struct.PacketBuilder.html) for more informations.
Check out the [PacketBuilder documentation](https://docs.rs/etherparse/~0/etherparse/struct.PacketBuilder.html) for more information.

### Manually serialising each header
Alternativly it is possible to manually build a packet ([example](etherparse/examples/write_ipv4_udp.rs)). Generally each struct representing a header has a "write" method that allows it to be serialized. These write methods sometimes automatically calculate checksums and fill them in. In case this is unwanted behavior (e.g. if you want to generate a packet with an invalid checksum), it is also possible to call a "write_raw" method that will simply serialize the data without doing checksum calculations.
### Manually serializing each header
Alternatively it is possible to manually build a packet ([example](etherparse/examples/write_ipv4_udp.rs)). Generally each struct representing a header has a "write" method that allows it to be serialized. These write methods sometimes automatically calculate checksums and fill them in. In case this is unwanted behavior (e.g. if you want to generate a packet with an invalid checksum), it is also possible to call a "write_raw" method that will simply serialize the data without doing checksum calculations.

Read the documentations of the different methods for a more details:

Expand Down
37 changes: 31 additions & 6 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,47 @@

## 0.14.0

### Highlights

* `SlicedPacket` & `PacketHeaders` now use the length fields in the headers to determine the payload length.
* The payload(s) in `SlicedPacket` now can be accessed via the layer slices (e.g. `link.unwrap().payload()`).
* Added `LaxSlicedPacket` & `LaxPacketHeaders` to allow for parsing of packets without length checks & other inconsistency checks present in `SlicedPacket` & `PacketHeaders`.
* `SlicedPacket.ip` & `PacketHeaders.ip` have been renamed to `SlicedPacket.net` & `PacketHeaders.net`
* Added `no_std` support.
* Errors are now more fine granular (in case you want a general error type you can convert all errors via `into` & `from` into `err::FromSliceError` or `err::ReadError`).
* Added `to_bytes()` methods to most header types.
* Added slice types which contain both the header(s) and payload (e.g. `IpSlice`, `UdpSlice`).
* Added payload types (e.g. `IpPayloadSlice`, `EtherPayloadSlice`) which contain the slice & information about the payload type (e.g. the IpNumber in case of an `IpPayloadSlice`).

### What happened?

This version took more then a year to complete. Which for sure was not my plan when starting out.

I started out trying to implement correct handing of "payload lengths" (aka actually using the length fields in headers to determine the payload). This was needed, as without it, incorrect data would sometimes creep into the payload of and IP packet (see https://github.com/JulianSchmid/etherparse/issues/35 ). But this "simple" feature triggered a chain reaction of changes that required me to re-architect big parts of the crate. Specifically the error types were an major issue, which I did not forsee costing so much time and at some time.

But no matter, now it is done. Sadly there are quiet some breaking changes, but I think the crate is now in a better position for future changes & behaves correcter then in the past. There are also quiet a lot of quality of life changes.

### New

* Added non-allocating `to_bytes()` methods that return `arrayvec::ArrayVec<u8, Header::MAX_LEN>` to the following headers:
* `Ipv4Header`
* TODO Add to all headers that have write methods
* Added `LaxSlicedPacket` & `LaxPacketHeaders` to allow for parsing of packets without length checks & other inconsistency checks present in `SlicedPacket` & `PacketHeaders`.
* `no_std` Support was added. To enable use etherparse without default features: `etherparse = { version = "0.14", default-features = false }`
* Added `LEN` or `MIN_LEN` & `MAX_LEN` constants to all headers & packets.
* Added `InternetSlice::source_addr` & `InternetSlice::destination_addr` to get the source & destination as `std::net::IpAddr` (thanks to @nagy)

### Changes in Behavior

* `SlicedPacket` & `PacketHeaders` now also verify the total_length and payload length fields present in the IPv4 & IPv6 header. This means the `*from_slice*` methods newly throw an error not enough data is present and also newly limit the resulting payload size.
* The payload(s) in `SlicedPacket` now can be accessed via the layer fields (e.g. `link.unwrap().payload()`).
* The payload in `PacketHeaders` now is an enum that indicates from which layer the payload came.
* Removed `ReadError::Ipv6TooManyHeaderExtensions` error when calling `Ipv6Header::skip_all_header_extensions` and `Ipv6Header::skip_all_header_extensions_in_slice`.
* The slice returned by `IpHeader::from_slice`is now the payload of the IP packet (determined by the length specified in the IP header). Previously whatever was left over from the input slice after parsing the IP header and extensions was returned. Now the slice length is limited based on the "payload length" field (IPv6) or "total length" field IPv4.
* `Ipv4Header::from_slice` no longer verifies that the `total_len` has enough data to contain the header itself. This check is done when the complete packet is parsed. The check was removed as the `total_len` is sometimes set at a later stage (e.g. in the kernel) in some systems and I would still like to enable people to at least decode the header even if the total length was not yet set.

### Breaking Changes:

* `ip` as been renamed to `net` in `SlicedPacket` and `PacketHeaders`
* `packet_filter` has been removed
* Refactored error types so functions & methods (mostly) only return error types that they can cause.
* Removed `SerializedSize` trait and deprecated `SERIALIZED_SIZE`. Newly added constants `Header::LEN`, `Header::MIN_LEN` & `Header::MAX_LEN` to the headers as an replacement.
Expand All @@ -30,7 +54,7 @@
* `Ipv4Header.fragments_offset` renamed to `Ipv4Header.fragment_offset`.
* `SingleVlanHeader.vlan_identifier` renamed to `SingleVlanHeader.vlan_id`.
* Type of `vlan_id` in `SingleVlanHeader` changed from `u16` to `VlanId`.
* Moved options of `Ipv4Header` and `TcpHeader` into seperate structs and made all fields in `Ipv4Header` & `TcpHeader` public for easier default initialisation.
* Moved options of `Ipv4Header` and `TcpHeader` into separate structs and made all fields in `Ipv4Header` & `TcpHeader` public for easier default initialization.

### Bugfixes

Expand All @@ -39,24 +63,25 @@
* `Ipv6Header::skip_header_extension_in_slice`
* `Ipv6Header::skip_all_header_extensions_in_slice`

* Previously the manual `core::fmt::Debug` implementations for some types were not correctly inserting newlines & identation when `{:#?}` was used for debug printing. This has been corrected for the following types:
* Previously the manual `core::fmt::Debug` implementations for some types were not correctly inserting newlines & indentation when `{:#?}` was used for debug printing. This has been corrected for the following types:
* `Ipv4Header`
* `IpAuthHeader`
* `Ipv6RawExtHeader`

### Deprecations / Renames:

* The following types have been renamed (alias with the old name exist for backwards compatibility but will trigger a deprecation warning):
* `InternetSlice` to `IpSlice`
* `InternetSlice` to `NetSlice` & `IpSlice`
* `IpAuthenticationHeader` to `IpAuthHeader`
* `IpAuthenticationHeaderSlice` to `IpAuthHeaderSlice`
* `Ipv6RawExtensionHeader` to `Ipv6RawExtHeader`
* `Ipv6RawExtensionHeaderSlice` to `Ipv6RawExtHeaderSlice`

### Internal Changes:

* Seperated proptest generators into seperate library `etherparse_proptest_generators`
* TODO Split modules up into one file per struct/enum and moved tests there
* Separated proptest generators into separate library `etherparse_proptest_generators`
* Split modules up into one file per struct/enum and moved tests there
* Applied rust fmt

## 0.13.0

Expand Down
24 changes: 12 additions & 12 deletions etherparse/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
//!
//! Some key points are:
//!
//! * It is completly written in Rust and thoroughly tested.
//! * It is completely written in Rust and thoroughly tested.
//! * Special attention has been paid to not use allocations or syscalls.
//! * The package is still in development and can & will still change.
//! * The current focus of development is on the most popular protocols in the internet & transport layer.
Expand All @@ -33,7 +33,7 @@
//! Etherparse gives you two options for parsing network packages automatically:
//!
//! ## Slicing the packet
//! Here the different components in a packet are seperated without parsing all their fields. For each header a slice is generated that allows access to the fields of a header.
//! Here the different components in a packet are separated without parsing all their fields. For each header a slice is generated that allows access to the fields of a header.
//! ```
//! # use etherparse::{SlicedPacket, PacketBuilder};
//! # let builder = PacketBuilder::
Expand All @@ -43,7 +43,7 @@
//! # [192,168,1,2], //destination ip
//! # 20) //time to life
//! # .udp(21, //source port
//! # 1234); //desitnation port
//! # 1234); //destination port
//! # //payload of the udp packet
//! # let payload = [1,2,3,4,5,6,7,8];
//! # //get some memory to store the serialized data
Expand Down Expand Up @@ -76,7 +76,7 @@
//!
//! ## Deserializing all headers into structs
//!
//! This option deserializes all known headers and transferes their contents to header structs.
//! This option deserializes all known headers and transfers their contents to header structs.
//! ```rust
//! # use etherparse::{PacketHeaders, PacketBuilder};
//! # let builder = PacketBuilder::
Expand All @@ -86,7 +86,7 @@
//! # [192,168,1,2], //destination ip
//! # 20) //time to life
//! # .udp(21, //source port
//! # 1234); //desitnation port
//! # 1234); //destination port
//! # //payload of the udp packet
//! # let payload = [1,2,3,4,5,6,7,8];
//! # //get some memory to store the serialized data
Expand Down Expand Up @@ -132,8 +132,8 @@
//! * [`Icmpv6Slice::from_slice`]
//!
//! The resulting data types allow access to both the header(s) and the payload of the layer
//! and will automatially limit the length of payload if the layer has a length field limiting the
//! paylod (e.g. the payload of IPv6 packets will be limited by the "payload length" field in
//! and will automatically limit the length of payload if the layer has a length field limiting the
//! payload (e.g. the payload of IPv6 packets will be limited by the "payload length" field in
//! an IPv6 header).
//!
//! ## Manually slicing & parsing only headers
Expand Down Expand Up @@ -186,10 +186,10 @@
//! ethernet2([1,2,3,4,5,6], //source mac
//! [7,8,9,10,11,12]) //destination mac
//! .ipv4([192,168,1,1], //source ip
//! [192,168,1,2], //desitination ip
//! [192,168,1,2], //destination ip
//! 20) //time to life
//! .udp(21, //source port
//! 1234); //desitnation port
//! 1234); //destination port
//!
//! //payload of the udp packet
//! let payload = [1,2,3,4,5,6,7,8];
Expand All @@ -205,11 +205,11 @@
//!
//! There is also an [example for TCP packets](https://github.com/JulianSchmid/etherparse/blob/0.14.0/examples/write_tcp.rs) available.
//!
//! Check out the [PacketBuilder documentation](struct.PacketBuilder.html) for more informations.
//! Check out the [PacketBuilder documentation](struct.PacketBuilder.html) for more information.
//!
//! ## Manually serialising each header
//! ## Manually serializing each header
//!
//! Alternativly it is possible to manually build a packet
//! Alternatively it is possible to manually build a packet
//! ([example](https://github.com/JulianSchmid/etherparse/blob/0.14.0/examples/write_ipv4_udp.rs)).
//! Generally each struct representing a header has a "write" method that allows it to be
//! serialized. These write methods sometimes automatically calculate checksums and fill them
Expand Down
Loading