rips_packets/
ipv4.rs

1use std::net::Ipv4Addr;
2use types::*;
3use ip::Protocol;
4
5packet!(Ipv4Packet, MutIpv4Packet, 20);
6
7getters!(Ipv4Packet
8    pub fn version(&self) -> u4 {
9        read_offset!(self.0, 0, u8) >> 4
10    }
11
12    pub fn header_length(&self) -> u4 {
13        read_offset!(self.0, 0, u8) & 0x0f
14    }
15
16    pub fn dscp(&self) -> u6 {
17        read_offset!(self.0, 1, u8) >> 2
18    }
19
20    pub fn ecn(&self) -> u2 {
21        read_offset!(self.0, 1, u8) & 0x03
22    }
23
24    pub fn total_length(&self) -> u16 {
25        read_offset!(self.0, 2, u16, from_be)
26    }
27
28    pub fn identification(&self) -> u16 {
29        read_offset!(self.0, 4, u16, from_be)
30    }
31
32    pub fn flags(&self) -> Flags {
33        Flags::from_bits_truncate(read_offset!(self.0, 6, u8) >> 5)
34    }
35
36    pub fn dont_fragment(&self) -> bool {
37        self.flags().contains(Flags::DF)
38    }
39
40    pub fn more_fragments(&self) -> bool {
41        self.flags().contains(Flags::MF)
42    }
43
44    pub fn fragment_offset(&self) -> u13 {
45        read_offset!(self.0, 6, u16, from_be) & 0x1fff
46    }
47
48    pub fn ttl(&self) -> u8 {
49        read_offset!(self.0, 8, u8)
50    }
51
52    pub fn protocol(&self) -> Protocol {
53        Protocol(read_offset!(self.0, 9, u8))
54    }
55
56    pub fn header_checksum(&self) -> u16 {
57        read_offset!(self.0, 10, u16, from_be)
58    }
59
60    pub fn source(&self) -> Ipv4Addr {
61        Ipv4Addr::from(read_offset!(self.0, 12, [u8; 4]))
62    }
63
64    pub fn destination(&self) -> Ipv4Addr {
65        Ipv4Addr::from(read_offset!(self.0, 16, [u8; 4]))
66    }
67);
68
69setters!(MutIpv4Packet
70    pub fn set_version(&mut self, version: u4) {
71        let new_byte = (version << 4) | (read_offset!(self.0, 0, u8) & 0x0f);
72        write_offset!(self.0, 0, new_byte, u8);
73    }
74
75    pub fn set_header_length(&mut self, header_length: u4) {
76        let new_byte = (read_offset!(self.0, 0, u8) & 0xf0) | (header_length & 0x0f);
77        write_offset!(self.0, 0, new_byte, u8);
78    }
79
80    pub fn set_dscp(&mut self, dscp: u6) {
81        let new_byte = (dscp << 2) | (read_offset!(self.0, 1, u8) & 0x03);
82        write_offset!(self.0, 1, new_byte, u8);
83    }
84
85    pub fn set_ecn(&mut self, ecn: u2) {
86        let new_byte = (read_offset!(self.0, 1, u8) & 0xfc) | (ecn & 0x03);
87        write_offset!(self.0, 1, new_byte, u8);
88    }
89
90    pub fn set_total_length(&mut self, total_length: u16) {
91        write_offset!(self.0, 2, total_length, u16, to_be);
92    }
93
94    pub fn set_identification(&mut self, identification: u16) {
95        write_offset!(self.0, 4, identification, u16, to_be);
96    }
97
98    pub fn set_flags(&mut self, flags: Flags) {
99        let new_byte = (flags.bits() << 5) | (read_offset!(self.0, 6, u8) & 0x1f);
100        write_offset!(self.0, 6, new_byte, u8);
101    }
102
103    pub fn set_fragment_offset(&mut self, fragment_offset: u13) {
104        let new_byte = (read_offset!(self.0, 6, u16, from_be) & 0xe000) |
105            (fragment_offset & 0x1fff);
106        write_offset!(self.0, 6, new_byte, u16, to_be);
107    }
108
109    pub fn set_ttl(&mut self, ttl: u8) {
110        write_offset!(self.0, 8, ttl, u8);
111    }
112
113    pub fn set_protocol(&mut self, protocol: Protocol) {
114        write_offset!(self.0, 9, protocol.value(), u8);
115    }
116
117    pub fn set_header_checksum(&mut self, checksum: u16) {
118        write_offset!(self.0, 10, checksum, u16, to_be);
119    }
120
121    pub fn set_source(&mut self, source: Ipv4Addr) {
122        write_offset!(self.0, 12, source.octets(), [u8; 4]);
123    }
124
125    pub fn set_destination(&mut self, destination: Ipv4Addr) {
126        write_offset!(self.0, 16, destination.octets(), [u8; 4]);
127    }
128);
129
130
131bitflags! {
132    /// Bitmasks for the three bit flags field in IPv4
133    pub struct Flags: u3 {
134        /// A bitmask with a one in the "Reserved" position.
135        const RESERVED = 0b100;
136        /// A bitmask with a one in the "Don't fragment" position.
137        const DF = 0b010;
138        /// A bitmask with a one in the "More fragments" position.
139        const MF = 0b001;
140    }
141}
142
143
144#[cfg(test)]
145mod tests {
146    use super::*;
147
148    #[test]
149    fn min_length() {
150        assert_eq!(Ipv4Packet::MIN_LEN, 20);
151    }
152
153    #[test]
154    fn too_short_slice() {
155        assert!(Ipv4Packet::new(&[0; 19]).is_none());
156    }
157
158    #[test]
159    fn exactly_20_bytes_slice() {
160        let packet = Ipv4Packet::new(&[1; 20]).expect("Ipv4Packet to accept 20 bytes");
161        assert_eq!(packet.data(), &[1; 20]);
162        assert_eq!(packet.header(), &[1; 20]);
163        assert!(packet.payload().is_empty());
164    }
165
166    #[test]
167    fn correct_payload() {
168        let mut data = vec![2; 19];
169        data.push(3);
170        data.push(4);
171        let packet = Ipv4Packet::new(&data[..]).expect("Ipv4Packet to accept 21 bytes");
172        assert_eq!(packet.data(), &data[..]);
173        assert_eq!(packet.header(), &data[..20]);
174        assert_eq!(packet.payload(), &[4]);
175    }
176
177    macro_rules! ipv4_setget_test {
178        ($name:ident, $set_name:ident, $value:expr, $offset:expr, $expected:expr) => {
179            setget_test!(MutIpv4Packet, $name, $set_name, $value, $offset, $expected);
180        }
181    }
182
183    ipv4_setget_test!(version, set_version, 0xf, 0, [0xf0]);
184    ipv4_setget_test!(header_length, set_header_length, 0xf, 0, [0x0f]);
185    ipv4_setget_test!(dscp, set_dscp, 0x3f, 1, [0xfc]);
186    ipv4_setget_test!(ecn, set_ecn, 0x3, 1, [0x3]);
187    ipv4_setget_test!(total_length, set_total_length, 0xffbf, 2, [0xff, 0xbf]);
188    ipv4_setget_test!(identification, set_identification, 0xffaf, 4, [0xff, 0xaf]);
189    ipv4_setget_test!(flags, set_flags, Flags::all(), 6, [0xe0]);
190    ipv4_setget_test!(
191        fragment_offset,
192        set_fragment_offset,
193        0x1faf,
194        6,
195        [0x1f, 0xaf]
196    );
197    ipv4_setget_test!(ttl, set_ttl, 0xff, 8, [0xff]);
198    ipv4_setget_test!(protocol, set_protocol, Protocol(0xff), 9, [0xff]);
199    ipv4_setget_test!(
200        header_checksum,
201        set_header_checksum,
202        0xfeff,
203        10,
204        [0xfe, 0xff]
205    );
206    ipv4_setget_test!(
207        source,
208        set_source,
209        Ipv4Addr::new(192, 168, 15, 1),
210        12,
211        [192, 168, 15, 1]
212    );
213    ipv4_setget_test!(
214        destination,
215        set_destination,
216        Ipv4Addr::new(168, 254, 99, 88),
217        16,
218        [168, 254, 99, 88]
219    );
220
221    #[test]
222    fn getters_alternating_bits() {
223        let backing_data = [0b1010_1010; 20];
224        let testee = Ipv4Packet::new(&backing_data).unwrap();
225        assert_eq!(0b1010, testee.version());
226        assert_eq!(0b1010, testee.header_length());
227        assert_eq!(0b101010, testee.dscp());
228        assert_eq!(0b10, testee.ecn());
229        assert_eq!(0b1010_1010_1010_1010, testee.total_length());
230        assert_eq!(0b1010_1010_1010_1010, testee.identification());
231        assert_eq!(Flags::RESERVED | Flags::MF, testee.flags());
232        assert!(!testee.dont_fragment());
233        assert!(testee.more_fragments());
234        assert_eq!(0b0_1010_1010_1010, testee.fragment_offset());
235    }
236}