xenet_packet_builder/
udp.rs

1use std::net::{IpAddr, SocketAddr};
2use xenet_packet::ethernet::ETHERNET_HEADER_LEN;
3use xenet_packet::ipv4::IPV4_HEADER_LEN;
4use xenet_packet::ipv6::IPV6_HEADER_LEN;
5use xenet_packet::udp::MutableUdpPacket;
6use xenet_packet::udp::UDP_HEADER_LEN;
7use xenet_packet::Packet;
8
9/// UDP BASE Destination Port. Usually used for traceroute.
10pub const UDP_BASE_DST_PORT: u16 = 33435;
11
12/// UDP (IPv4) Minimum Packet Length.
13pub const UDPV4_PACKET_LEN: usize = ETHERNET_HEADER_LEN + IPV4_HEADER_LEN + UDP_HEADER_LEN;
14/// UDP (IPv4) Minimum IP Packet Length.
15pub const UDPV4_IP_PACKET_LEN: usize = IPV4_HEADER_LEN + UDP_HEADER_LEN;
16/// UDP (IPv6) Minimum Packet Length.
17pub const UDPV6_PACKET_LEN: usize = ETHERNET_HEADER_LEN + IPV6_HEADER_LEN + UDP_HEADER_LEN;
18/// UDP (IPv6) Minimum IP Packet Length.
19pub const UDPV6_IP_PACKET_LEN: usize = IPV6_HEADER_LEN + UDP_HEADER_LEN;
20
21pub(crate) fn build_udp_packet(
22    udp_packet: &mut xenet_packet::udp::MutableUdpPacket,
23    src_ip: IpAddr,
24    src_port: u16,
25    dst_ip: IpAddr,
26    dst_port: u16,
27) {
28    udp_packet.set_length(8);
29    udp_packet.set_source(src_port);
30    udp_packet.set_destination(dst_port);
31    match src_ip {
32        IpAddr::V4(src_ip) => match dst_ip {
33            IpAddr::V4(dst_ip) => {
34                let checksum =
35                    xenet_packet::udp::ipv4_checksum(&udp_packet.to_immutable(), &src_ip, &dst_ip);
36                udp_packet.set_checksum(checksum);
37            }
38            IpAddr::V6(_) => {}
39        },
40        IpAddr::V6(src_ip) => match dst_ip {
41            IpAddr::V4(_) => {}
42            IpAddr::V6(dst_ip) => {
43                let checksum =
44                    xenet_packet::udp::ipv6_checksum(&udp_packet.to_immutable(), &src_ip, &dst_ip);
45                udp_packet.set_checksum(checksum);
46            }
47        },
48    }
49}
50
51/// UDP Packet Builder.
52#[derive(Clone, Debug)]
53pub struct UdpPacketBuilder {
54    /// Source IP address.
55    pub src_ip: IpAddr,
56    /// Source Port.
57    pub src_port: u16,
58    /// Destination IP address.
59    pub dst_ip: IpAddr,
60    /// Destination Port.
61    pub dst_port: u16,
62    /// Payload.
63    pub payload: Vec<u8>,
64}
65
66impl UdpPacketBuilder {
67    /// Constructs a new UdpPacketBuilder.
68    pub fn new(src_addr: SocketAddr, dst_addr: SocketAddr) -> Self {
69        UdpPacketBuilder {
70            src_ip: src_addr.ip(),
71            src_port: src_addr.port(),
72            dst_ip: dst_addr.ip(),
73            dst_port: dst_addr.port(),
74            payload: Vec::new(),
75        }
76    }
77    /// Builds a new UdpPacket and return bytes.
78    pub fn build(&self) -> Vec<u8> {
79        let mut buffer: Vec<u8> = vec![0; UDP_HEADER_LEN + self.payload.len()];
80        let mut udp_packet = MutableUdpPacket::new(&mut buffer).unwrap();
81        udp_packet.set_source(self.src_port);
82        udp_packet.set_destination(self.dst_port);
83        if self.payload.len() > 0 {
84            udp_packet.set_payload(&self.payload);
85        }
86        udp_packet.set_length(UDP_HEADER_LEN as u16 + self.payload.len() as u16);
87        match self.src_ip {
88            IpAddr::V4(src_ip) => match self.dst_ip {
89                IpAddr::V4(dst_ip) => {
90                    let checksum = xenet_packet::udp::ipv4_checksum(
91                        &udp_packet.to_immutable(),
92                        &src_ip,
93                        &dst_ip,
94                    );
95                    udp_packet.set_checksum(checksum);
96                }
97                IpAddr::V6(_) => {}
98            },
99            IpAddr::V6(src_ip) => match self.dst_ip {
100                IpAddr::V4(_) => {}
101                IpAddr::V6(dst_ip) => {
102                    let checksum = xenet_packet::udp::ipv6_checksum(
103                        &udp_packet.to_immutable(),
104                        &src_ip,
105                        &dst_ip,
106                    );
107                    udp_packet.set_checksum(checksum);
108                }
109            },
110        }
111        udp_packet.packet().to_vec()
112    }
113}