Skip to main content

iris_core/protocols/packet/
udp.rs

1//! UDP packet.
2
3use crate::memory::mbuf::Mbuf;
4use crate::protocols::packet::{Packet, PacketHeader, PacketParseError};
5use crate::utils::types::*;
6
7use anyhow::{bail, Result};
8
9/// UDP assigned protocol number.
10pub const UDP_PROTOCOL: usize = 17;
11const UDP_HEADER_LEN: usize = 8;
12
13/// A UDP packet.
14#[derive(Debug)]
15pub struct Udp<'a> {
16    /// Fixed header.
17    header: UdpHeader,
18    /// Offset to `header` from the start of `mbuf`.
19    offset: usize,
20    /// Packet buffer.
21    mbuf: &'a Mbuf,
22}
23
24impl Udp<'_> {
25    /// Returns the sending port.
26    #[inline]
27    pub fn src_port(&self) -> u16 {
28        self.header.src_port.into()
29    }
30
31    /// Returns the receiving port.
32    #[inline]
33    pub fn dst_port(&self) -> u16 {
34        self.header.dst_port.into()
35    }
36
37    /// Returns the length of packet (both header and payload) in bytes.
38    #[inline]
39    pub fn length(&self) -> u16 {
40        self.header.length.into()
41    }
42
43    /// Returns the UDP checksum.
44    #[inline]
45    pub fn checksum(&self) -> u16 {
46        self.header.checksum.into()
47    }
48}
49
50impl<'a> Packet<'a> for Udp<'a> {
51    fn mbuf(&self) -> &Mbuf {
52        self.mbuf
53    }
54
55    fn header_len(&self) -> usize {
56        self.header.length()
57    }
58
59    fn next_header_offset(&self) -> usize {
60        self.offset + self.header_len()
61    }
62
63    fn next_header(&self) -> Option<usize> {
64        None
65    }
66
67    fn parse_from(outer: &'a impl Packet<'a>) -> Result<Self>
68    where
69        Self: Sized,
70    {
71        let offset = outer.next_header_offset();
72        if let Ok(header) = outer.mbuf().get_data(offset) {
73            match outer.next_header() {
74                Some(UDP_PROTOCOL) => Ok(Udp {
75                    header: unsafe { *header },
76                    offset,
77                    mbuf: outer.mbuf(),
78                }),
79                _ => bail!(PacketParseError::InvalidProtocol),
80            }
81        } else {
82            bail!(PacketParseError::InvalidRead)
83        }
84    }
85}
86
87/// UDP header.
88#[derive(Debug, Clone, Copy)]
89#[repr(C, packed)]
90struct UdpHeader {
91    src_port: u16be,
92    dst_port: u16be,
93    length: u16be,
94    checksum: u16be,
95}
96
97impl PacketHeader for UdpHeader {
98    /// Header length measured in bytes. Equivalent to the payload offset.
99    fn length(&self) -> usize {
100        UDP_HEADER_LEN
101    }
102}