Struct etherparse::LaxPacketHeaders

source ·
pub struct LaxPacketHeaders<'a> {
    pub link: Option<LinkHeader>,
    pub vlan: Option<VlanHeader>,
    pub net: Option<NetHeaders>,
    pub transport: Option<TransportHeader>,
    pub payload: LaxPayloadSlice<'a>,
    pub stop_err: Option<(SliceError, Layer)>,
}
Expand description

Decoded packet headers (data link layer and lower) with lax length checks.

You can use

depending on your starting header to parse the headers in a slice and get this struct as a result.

Fields§

§link: Option<LinkHeader>

Ethernet II header if present.

§vlan: Option<VlanHeader>

Single or double vlan headers if present.

§net: Option<NetHeaders>

IPv4 or IPv6 header and IP extension headers if present.

§transport: Option<TransportHeader>

TCP or UDP header if present.

§payload: LaxPayloadSlice<'a>

Payload of the last parsed layer.

§stop_err: Option<(SliceError, Layer)>

Error that stopped the parsing and the layer on which the stop occurred.

Implementations§

source§

impl<'a> LaxPacketHeaders<'a>

source

pub fn from_ethernet(slice: &'a [u8]) -> Result<LaxPacketHeaders<'a>, LenError>

Separates a network packet into different headers from the ethernet header downwards with lax length checks and non-terminating errors.

§Example

Basic usage:

 use etherparse::{ether_type, LaxPacketHeaders, LenSource, LaxPayloadSlice};

 match LaxPacketHeaders::from_ethernet(&packet) {
     Err(value) => {
         // An error is returned in case the ethernet II header could
         // not be parsed (other errors are stored in the "stop_err" field)
         println!("Err {:?}", value)
     },
     Ok(value) => {
         if let Some((stop_err, error_layer)) = value.stop_err.as_ref() {
             // error was encountered after parsing the ethernet 2 header
             println!("Error on layer {}: {:?}", error_layer, stop_err);
         }

         // parts that could be parsed without error
         println!("link: {:?}", value.link);
         println!("vlan: {:?}", value.vlan);
         println!("net: {:?}", value.net);
         println!("transport: {:?}", value.transport);

         // net (ip) & transport (udp or tcp)
         println!("net: {:?}", value.net);
         match value.payload {
             LaxPayloadSlice::Ether(e) => {
                 println!("ether payload (ether type {:?}): {:?}", e.ether_type, e.payload);
             }
             LaxPayloadSlice::Ip(ip) => {
                 println!("IP payload (IP number {:?}): {:?}", ip.ip_number, ip.payload);
                 if ip.incomplete {
                     println!("  IP payload incomplete (length in IP header indicated more data should be present)");
                 }
                 if ip.fragmented {
                     println!("  IP payload fragmented");
                 }
             }
             LaxPayloadSlice::Udp{ payload, incomplete } => {
                 println!("UDP payload: {:?}", payload);
                 if incomplete {
                     println!("  UDP payload incomplete (length in UDP or IP header indicated more data should be present)");
                 }
             }
             LaxPayloadSlice::Tcp{ payload, incomplete } => {
                 println!("TCP payload: {:?}", payload);
                 if incomplete {
                     println!("  TCP payload incomplete (length in IP header indicated more data should be present)");
                 }
             }
             LaxPayloadSlice::Icmpv4{ payload, incomplete } => {
                 println!("Icmpv4 payload: {:?}", payload);
                 if incomplete {
                     println!("  Icmpv4 payload incomplete (length in IP header indicated more data should be present)");
                 }
             }
             LaxPayloadSlice::Icmpv6{ payload, incomplete } => {
                 println!("Icmpv6 payload: {:?}", payload);
                 if incomplete {
                     println!("  Icmpv6 payload incomplete (length in IP header indicated more data should be present)");
                 }
             }
         }
     }
 }
source

pub fn from_ether_type( ether_type: EtherType, slice: &'a [u8] ) -> LaxPacketHeaders<'a>

Separates a network packet into different headers using the given ether_type number to identify the first header with lax length checks and non-terminating errors.

The result is returned as a LaxSlicedPacket struct. Currently supported ether type numbers are:

  • ether_type::IPV4
  • ether_type::IPV6
  • ether_type::VLAN_TAGGED_FRAME
  • ether_type::PROVIDER_BRIDGING
  • ether_type::VLAN_DOUBLE_TAGGED_FRAME

If an unsupported ether type is given the given slice will be set as payload and all other fields will be set to None.

§Example

Basic usage:

 use etherparse::{ether_type, LaxPacketHeaders, LenSource, LaxPayloadSlice};

 let value = LaxPacketHeaders::from_ether_type(ether_type::IPV4, &packet);

 if let Some((stop_err, error_layer)) = value.stop_err.as_ref() {
     // error was encountered after parsing the ethernet 2 header
     println!("Error on layer {}: {:?}", error_layer, stop_err);
 }

 // link is unfilled
 assert_eq!(value.link, None);

 // parts that could be parsed without error
 println!("vlan: {:?}", value.vlan);
 println!("net: {:?}", value.net);
 println!("transport: {:?}", value.transport);

 // net (ip) & transport (udp or tcp)
 println!("net: {:?}", value.net);
 match value.payload {
     LaxPayloadSlice::Ether(e) => {
         println!("ether payload (ether type {:?}): {:?}", e.ether_type, e.payload);
     }
     LaxPayloadSlice::Ip(ip) => {
         println!("IP payload (IP number {:?}): {:?}", ip.ip_number, ip.payload);
         if ip.incomplete {
             println!("  IP payload incomplete (length in IP header indicated more data should be present)");
         }
         if ip.fragmented {
             println!("  IP payload fragmented");
         }
     }
     LaxPayloadSlice::Udp{ payload, incomplete } => {
         println!("UDP payload: {:?}", payload);
         if incomplete {
             println!("  UDP payload incomplete (length in UDP or IP header indicated more data should be present)");
         }
     }
     LaxPayloadSlice::Tcp{ payload, incomplete } => {
         println!("TCP payload: {:?}", payload);
         if incomplete {
             println!("  TCP payload incomplete (length in IP header indicated more data should be present)");
         }
     }
     LaxPayloadSlice::Icmpv4{ payload, incomplete } => {
         println!("Icmpv4 payload: {:?}", payload);
         if incomplete {
             println!("  Icmpv4 payload incomplete (length in IP header indicated more data should be present)");
         }
     }
     LaxPayloadSlice::Icmpv6{ payload, incomplete } => {
         println!("Icmpv6 payload: {:?}", payload);
         if incomplete {
             println!("  Icmpv6 payload incomplete (length in IP header indicated more data should be present)");
         }
     }
 }
source

pub fn from_ip( slice: &'a [u8] ) -> Result<LaxPacketHeaders<'_>, LaxHeaderSliceError>

Separates a network packet slice into different headers from the ip header downwards with lax length checks and will still return a result even if an error is encountered in a layer (except IP).

This function has two main differences to PacketHeaders::from_ip_slice:

  • Errors encountered bellow the IpHeader will only stop the parsing and return an Ok with the successfully parsed parts and the error as optional. Only if an unrecoverable error is encountered in the IP header itself an Err is returned.
  • Length in the IP header & UDP headers are allowed to be inconsistent with the given slice length (e.g. data is missing from the slice). In this case it falls back to the length of slice. See LaxIpSlice::from_slice for a detailed description of when the slice length is used as a fallback.

The result is returned as a SlicedPacket struct. This function assumes the given data starts with an IPv4 or IPv6 header.

§Examples

Basic usage:

 use etherparse::{ether_type, LaxPacketHeaders, LenSource, LaxPayloadSlice};

 match LaxPacketHeaders::from_ip(&packet) {
     Err(value) => {
         // An error is returned in case the ip header could
         // not be parsed (other errors are stored in the "stop_err" field)
         println!("Err {:?}", value)
     },
     Ok(value) => {
         if let Some((stop_err, error_layer)) = value.stop_err.as_ref() {
             // error was encountered after parsing the ethernet 2 header
             println!("Error on layer {}: {:?}", error_layer, stop_err);
         }

         // link & vlan is unfilled
         assert_eq!(value.link, None);
         assert_eq!(value.vlan, None);

         // parts that could be parsed without error
         println!("net: {:?}", value.net);
         println!("transport: {:?}", value.transport);

         // 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!(),
             LaxPayloadSlice::Ip(ip) => {
                 println!("IP payload (IP number {:?}): {:?}", ip.ip_number, ip.payload);
                 if ip.incomplete {
                     println!("  IP payload incomplete (length in IP header indicated more data should be present)");
                 }
                 if ip.fragmented {
                     println!("  IP payload fragmented");
                 }
             }
             LaxPayloadSlice::Udp{ payload, incomplete } => {
                 println!("UDP payload: {:?}", payload);
                 if incomplete {
                     println!("  UDP payload incomplete (length in UDP or IP header indicated more data should be present)");
                 }
             }
             LaxPayloadSlice::Tcp{ payload, incomplete } => {
                 println!("TCP payload: {:?}", payload);
                 if incomplete {
                     println!("  TCP payload incomplete (length in IP header indicated more data should be present)");
                 }
             }
             LaxPayloadSlice::Icmpv4{ payload, incomplete } => {
                 println!("Icmpv4 payload: {:?}", payload);
                 if incomplete {
                     println!("  Icmpv4 payload incomplete (length in IP header indicated more data should be present)");
                 }
             }
             LaxPayloadSlice::Icmpv6{ payload, incomplete } => {
                 println!("Icmpv6 payload: {:?}", payload);
                 if incomplete {
                     println!("  Icmpv6 payload incomplete (length in IP header indicated more data should be present)");
                 }
             }
         }
     }
 }

Trait Implementations§

source§

impl<'a> Clone for LaxPacketHeaders<'a>

source§

fn clone(&self) -> LaxPacketHeaders<'a>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<'a> Debug for LaxPacketHeaders<'a>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'a> PartialEq for LaxPacketHeaders<'a>

source§

fn eq(&self, other: &LaxPacketHeaders<'a>) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl<'a> Eq for LaxPacketHeaders<'a>

source§

impl<'a> StructuralPartialEq for LaxPacketHeaders<'a>

Auto Trait Implementations§

§

impl<'a> Freeze for LaxPacketHeaders<'a>

§

impl<'a> RefUnwindSafe for LaxPacketHeaders<'a>

§

impl<'a> Send for LaxPacketHeaders<'a>

§

impl<'a> Sync for LaxPacketHeaders<'a>

§

impl<'a> Unpin for LaxPacketHeaders<'a>

§

impl<'a> UnwindSafe for LaxPacketHeaders<'a>

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.