xenet_packet_builder/
ipv4.rs

1use std::net::Ipv4Addr;
2use xenet_packet::ip::IpNextLevelProtocol;
3use xenet_packet::ipv4::Ipv4Flags;
4use xenet_packet::ipv4::MutableIpv4Packet;
5use xenet_packet::ipv4::IPV4_HEADER_LEN;
6use xenet_packet::ipv4::IPV4_HEADER_LENGTH_BYTE_UNITS;
7use xenet_packet::Packet;
8
9/// Build IPv4 packet.
10pub(crate) fn build_ipv4_packet(
11    ipv4_packet: &mut MutableIpv4Packet,
12    src_ip: Ipv4Addr,
13    dst_ip: Ipv4Addr,
14    next_protocol: IpNextLevelProtocol,
15) {
16    ipv4_packet.set_header_length((IPV4_HEADER_LEN / IPV4_HEADER_LENGTH_BYTE_UNITS) as u8);
17    ipv4_packet.set_source(src_ip);
18    ipv4_packet.set_destination(dst_ip);
19    ipv4_packet.set_identification(rand::random::<u16>());
20    ipv4_packet.set_ttl(64);
21    ipv4_packet.set_version(4);
22    ipv4_packet.set_flags(Ipv4Flags::DontFragment);
23    match next_protocol {
24        IpNextLevelProtocol::Tcp => {
25            ipv4_packet.set_total_length(52);
26            ipv4_packet.set_next_level_protocol(IpNextLevelProtocol::Tcp);
27        }
28        IpNextLevelProtocol::Udp => {
29            ipv4_packet.set_total_length(28);
30            ipv4_packet.set_next_level_protocol(IpNextLevelProtocol::Udp);
31        }
32        IpNextLevelProtocol::Icmp => {
33            ipv4_packet.set_total_length(28);
34            ipv4_packet.set_next_level_protocol(IpNextLevelProtocol::Icmp);
35        }
36        _ => {}
37    }
38    let checksum = xenet_packet::ipv4::checksum(&ipv4_packet.to_immutable());
39    ipv4_packet.set_checksum(checksum);
40}
41
42/// IPv4 Packet Builder.
43#[derive(Clone, Debug)]
44pub struct Ipv4PacketBuilder {
45    pub src_ip: Ipv4Addr,
46    pub dst_ip: Ipv4Addr,
47    pub next_protocol: IpNextLevelProtocol,
48    pub total_length: Option<u16>,
49    pub identification: Option<u16>,
50    pub ttl: Option<u8>,
51    pub flags: Option<u8>,
52}
53
54impl Ipv4PacketBuilder {
55    /// Constructs a new Ipv4PacketBuilder.
56    pub fn new(src_ip: Ipv4Addr, dst_ip: Ipv4Addr, next_protocol: IpNextLevelProtocol) -> Self {
57        Ipv4PacketBuilder {
58            src_ip,
59            dst_ip,
60            next_protocol,
61            total_length: None,
62            identification: None,
63            ttl: None,
64            flags: None,
65        }
66    }
67    /// Builds IPv4 packet and return bytes
68    pub fn build(&self) -> Vec<u8> {
69        let mut buffer = vec![0; IPV4_HEADER_LEN];
70        let mut ipv4_packet = MutableIpv4Packet::new(&mut buffer).unwrap();
71        ipv4_packet.set_header_length((IPV4_HEADER_LEN / IPV4_HEADER_LENGTH_BYTE_UNITS) as u8);
72        ipv4_packet.set_source(self.src_ip);
73        ipv4_packet.set_destination(self.dst_ip);
74        ipv4_packet.set_identification(self.identification.unwrap_or(rand::random::<u16>()));
75        ipv4_packet.set_ttl(self.ttl.unwrap_or(64));
76        ipv4_packet.set_version(4);
77        ipv4_packet.set_next_level_protocol(self.next_protocol);
78        if let Some(flags) = self.flags {
79            match flags {
80                Ipv4Flags::DontFragment => {
81                    ipv4_packet.set_flags(Ipv4Flags::DontFragment);
82                }
83                Ipv4Flags::MoreFragments => {
84                    ipv4_packet.set_flags(Ipv4Flags::MoreFragments);
85                }
86                _ => {}
87            }
88        } else {
89            ipv4_packet.set_flags(Ipv4Flags::DontFragment);
90        }
91        match self.next_protocol {
92            IpNextLevelProtocol::Tcp => {
93                if let Some(total_length) = self.total_length {
94                    ipv4_packet.set_total_length(total_length);
95                } else {
96                    ipv4_packet.set_total_length(52);
97                }
98            }
99            IpNextLevelProtocol::Udp => {
100                if let Some(total_length) = self.total_length {
101                    ipv4_packet.set_total_length(total_length);
102                } else {
103                    ipv4_packet.set_total_length(28);
104                }
105            }
106            IpNextLevelProtocol::Icmp => {
107                if let Some(total_length) = self.total_length {
108                    ipv4_packet.set_total_length(total_length);
109                } else {
110                    ipv4_packet.set_total_length(28);
111                }
112            }
113            _ => {}
114        }
115        let checksum = xenet_packet::ipv4::checksum(&ipv4_packet.to_immutable());
116        ipv4_packet.set_checksum(checksum);
117        ipv4_packet.packet().to_vec()
118    }
119}