JulianSchmid / etherparse

A rust library for parsing ethernet & ethernet using protocols.
Apache License 2.0
299 stars 53 forks source link

No good way to get transport layer protocol for ipv6 #24

Closed agrover closed 2 years ago

agrover commented 2 years ago

given:

pub enum InternetSlice<'a> {
    Ipv4(Ipv4HeaderSlice<'a>, Ipv4ExtensionsSlice<'a>),
    Ipv6(Ipv6HeaderSlice<'a>, Ipv6ExtensionsSlice<'a>),
}

transport layer protocol is in Ipv6HeaderSlice, unless there are extension headers, in which case one must iterate through extensions to get the last. The shortest I've managed is let (_, next_proto, _) = Ipv6Extensions::from_slice(v6.next_header(), v6_ext.slice()).

Breaking change, but I'm wondering if putting the extensionsslice back inside the headerslice would make sense. This would allow a method on ipv6headerslice to have access to extensionslice and do the calculations to return the correct result.

JulianSchmid commented 2 years ago

Hi @agrover ,

Yeah that is a fair point. It is non intuitive.

Currently you can indirectly get the last ip_number by looking at the transport slice (although only implicitly for tcp & udp):

https://github.com/JulianSchmid/etherparse/blob/82e959c8dce672a47e4538bf60d04ddea1ae3456/src/packet_slicing.rs#L12-L19

When the transport slice is Udp & Tcp they are implicitly ip_number::TCP & ip_number::UDP. In the Unknown case the final next_header value is the u8 contained in Unknown.

Combining the IP headers with the extensions is quite a big change, so I would not like to do that. I would have to put a lot of thought into before doing it to see if there are not unforeseen consequences.

But what I could do is add an u8 with the final next_header to the two internet slice values to make it easier to retrieve the next_header number. something along the lines of:

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum InternetSlice<'a> {
    /// The ipv6 header & the decoded extension headers and last ip_number indicating the next header after the ip & extension headers.
    Ipv4(Ipv4HeaderSlice<'a>, Ipv4ExtensionsSlice<'a>, u8),
    /// The ipv6 header & the decoded extension headers and last ip_number indicating the next header after the ip & extension headers.
    Ipv6(Ipv6HeaderSlice<'a>, Ipv6ExtensionsSlice<'a>, u8),
}

and probably some helper methods to retrieve the the final next_header ip_number from the slice, extensions and so on.

Would that solve your problem?

Greets Julian

agrover commented 2 years ago

Hmm! I hadn't made the connection about just looking at TransportSlice. That works for me. Thanks.