1use bytes::Buf;
2
3use crate::checksum_utils;
4use crate::ipv4::{Ipv4Addr, Ipv4PseudoHeader};
5use crate::{Cursor, CursorMut};
6use crate::{PktBuf, PktMut};
7
8use super::header::{UdpHeader, UDP_HEADER_LEN};
9
10packet_base! {
11 pub struct UdpPacket: UdpHeader {
12 header_len: UDP_HEADER_LEN,
13 get_methods: [
14 (source_port, u16),
15 (dest_port, u16),
16 (packet_len, u16),
17 (checksum, u16),
18 ],
19 set_methods: [
20 (set_source_port, val: u16),
21 (set_dest_port, val: u16),
22 (set_checksum, val: u16),
23 ],
24 unchecked_set_methods:[
25 (set_packet_len_unchecked, set_packet_len, value: u16)
26 ]
27 }
28}
29
30impl<T: Buf> UdpPacket<T> {
31 #[inline]
32 pub fn parse(buf: T) -> Result<UdpPacket<T>, T> {
33 if buf.chunk().len() < UDP_HEADER_LEN {
34 return Err(buf);
35 }
36
37 let packet = UdpPacket::parse_unchecked(buf);
38
39 if usize::from(packet.packet_len()) >= UDP_HEADER_LEN
40 && usize::from(packet.packet_len()) <= packet.buf.remaining()
41 {
42 Ok(packet)
43 } else {
44 Err(packet.release())
45 }
46 }
47}
48
49impl<T: PktBuf> UdpPacket<T> {
50 pub fn calc_checksum(&mut self) -> u16 {
51 let total_len = self.packet_len();
52
53 let result = checksum_utils::from_buf(&mut self.buf, total_len.into());
54 self.buf.move_back(total_len.into());
55 result
56 }
57
58 #[inline]
59 pub fn verify_ipv4_checksum(&mut self, src_addr: Ipv4Addr, dst_addr: Ipv4Addr) -> bool {
60 if self.checksum() == 0 {
61 return true;
62 }
63
64 let phdr = Ipv4PseudoHeader::from_udp_pkt(src_addr, dst_addr, self);
65
66 let cksum = checksum_utils::combine(&[phdr.calc_checksum(), self.calc_checksum()]);
67
68 cksum == !0
69 }
70
71 #[inline]
72 pub fn payload(self) -> T {
73 assert!(usize::from(self.packet_len()) <= self.buf.remaining());
74 let trim_size = self.buf.remaining() - usize::from(self.packet_len());
75
76 let mut buf = self.release();
77 if trim_size > 0 {
78 buf.trim_off(trim_size);
79 }
80
81 buf.advance(UDP_HEADER_LEN);
82
83 buf
84 }
85}
86
87impl<T: PktMut> UdpPacket<T> {
88 #[inline]
89 pub fn adjust_ipv4_checksum(&mut self, src_addr: Ipv4Addr, dst_addr: Ipv4Addr) {
90 self.set_checksum(0);
91
92 let phdr = Ipv4PseudoHeader::from_udp_pkt(src_addr, dst_addr, self);
93
94 let cksum = !checksum_utils::combine(&[phdr.calc_checksum(), self.calc_checksum()]);
95
96 self.set_checksum(if cksum == 0 { 0xffff } else { cksum })
101 }
102
103 #[inline]
104 pub fn prepend_header<TH: AsRef<[u8]>>(mut buf: T, header: &UdpHeader<TH>) -> UdpPacket<T> {
105 assert!(buf.chunk_headroom() >= UDP_HEADER_LEN);
106 buf.move_back(UDP_HEADER_LEN);
107
108 let data = &mut buf.chunk_mut()[0..UDP_HEADER_LEN];
109 data.copy_from_slice(header.as_bytes());
110
111 let mut udppkt = UdpPacket::parse_unchecked(buf);
112 udppkt.set_packet_len_unchecked(u16::try_from(udppkt.buf().remaining()).unwrap());
113 udppkt
114 }
115}
116
117impl<'a> UdpPacket<Cursor<'a>> {
118 #[inline]
119 pub fn cursor_header(&self) -> UdpHeader<&'a [u8]> {
120 let data = &self.buf.chunk_shared_lifetime()[..UDP_HEADER_LEN];
121 UdpHeader::new_unchecked(data)
122 }
123
124 #[inline]
125 pub fn cursor_payload(&self) -> Cursor<'a> {
126 Cursor::new(
127 &self.buf.chunk_shared_lifetime()[UDP_HEADER_LEN..usize::from(self.packet_len())],
128 )
129 }
130}
131
132impl<'a> UdpPacket<CursorMut<'a>> {
133 #[inline]
134 pub fn split(self) -> (UdpHeader<&'a mut [u8]>, CursorMut<'a>) {
135 let packet_len = self.packet_len();
136
137 let (buf_mut, _) = self
138 .buf
139 .chunk_mut_shared_lifetime()
140 .split_at_mut(usize::from(packet_len));
141 let (hdr, payload) = buf_mut.split_at_mut(UDP_HEADER_LEN);
142
143 (UdpHeader::new_unchecked(hdr), CursorMut::new(payload))
144 }
145}
146
147#[cfg(test)]
148mod tests {
149 use super::*;
150 use crate::ether::*;
151 use crate::ipv4::*;
152 use crate::udp::UDP_HEADER_TEMPLATE;
153 use crate::{Cursor, CursorMut};
154
155 static FRAME_BYTES: [u8; 110] = [
156 0x00, 0x0b, 0x86, 0x64, 0x8b, 0xa0, 0x00, 0x50, 0x56, 0xae, 0x76, 0xf5, 0x08, 0x00, 0x45,
157 0x00, 0x00, 0x5e, 0x5c, 0x65, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0xc0, 0xa8, 0x1d, 0x3a,
158 0xc0, 0xa8, 0x1d, 0xa0, 0xeb, 0xd8, 0x00, 0xa1, 0x00, 0x4a, 0xbc, 0x86, 0x30, 0x40, 0x02,
159 0x01, 0x03, 0x30, 0x0f, 0x02, 0x03, 0x00, 0x91, 0xc8, 0x02, 0x02, 0x05, 0xdc, 0x04, 0x01,
160 0x04, 0x02, 0x01, 0x03, 0x04, 0x15, 0x30, 0x13, 0x04, 0x00, 0x02, 0x01, 0x00, 0x02, 0x01,
161 0x00, 0x04, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x04, 0x00, 0x04, 0x00, 0x30, 0x13, 0x04,
162 0x00, 0x04, 0x00, 0xa0, 0x0d, 0x02, 0x03, 0x00, 0x91, 0xc8, 0x02, 0x01, 0x00, 0x02, 0x01,
163 0x00, 0x30, 0x00, 0x00, 0x00,
164 ];
165
166 #[test]
167 fn packet_parse() {
168 let buf = Cursor::new(&FRAME_BYTES[..]);
169
170 let ethpkt = EtherPacket::parse(buf).unwrap();
171 assert_eq!(ethpkt.ethertype(), EtherType::IPV4);
172
173 let ippkt = Ipv4Packet::parse(ethpkt.payload()).unwrap();
174 assert_eq!(ippkt.protocol(), IpProtocol::UDP);
175 assert_eq!(ippkt.source_ip(), Ipv4Addr([192, 168, 29, 58]));
176 assert_eq!(ippkt.dest_ip(), Ipv4Addr([192, 168, 29, 160]));
177
178 let udppkt = UdpPacket::parse(ippkt.payload()).unwrap();
179 assert_eq!(udppkt.source_port(), 60376);
180 assert_eq!(udppkt.dest_port(), 161);
181 assert_eq!(udppkt.packet_len(), 74);
182 assert_eq!(udppkt.checksum(), 0xbc86);
183
184 let payload = udppkt.payload();
185 assert_eq!(
186 payload.chunk(),
187 &FRAME_BYTES[ETHER_HEADER_LEN + IPV4_HEADER_LEN + UDP_HEADER_LEN..108]
188 );
189 }
190
191 #[test]
192 fn packet_build() {
193 let mut bytes = [0xff; 108];
194 (&mut bytes[ETHER_HEADER_LEN + IPV4_HEADER_LEN + UDP_HEADER_LEN..108]).copy_from_slice(
195 &FRAME_BYTES[ETHER_HEADER_LEN + IPV4_HEADER_LEN + UDP_HEADER_LEN..108],
196 );
197
198 let mut pktbuf = CursorMut::new(&mut bytes[..]);
199 pktbuf.advance(ETHER_HEADER_LEN + IPV4_HEADER_LEN + UDP_HEADER_LEN);
200
201 let mut udppkt = UdpPacket::prepend_header(pktbuf, &UDP_HEADER_TEMPLATE);
202 udppkt.set_source_port(60376);
203 udppkt.set_dest_port(161);
204 udppkt.set_checksum(0xbc86);
205
206 let mut ippkt = Ipv4Packet::prepend_header(udppkt.release(), &IPV4_HEADER_TEMPLATE);
207 ippkt.adjust_version();
208 ippkt.set_dscp(0);
209 ippkt.set_ecn(0);
210 ippkt.set_ident(0x5c65);
211 ippkt.clear_flags();
212 ippkt.set_dont_frag(false);
213 ippkt.set_more_frags(false);
214 ippkt.set_frag_offset(0);
215 ippkt.set_time_to_live(128);
216 ippkt.set_protocol(IpProtocol::UDP);
217 ippkt.set_checksum(0x0000);
218 ippkt.set_source_ip(Ipv4Addr([192, 168, 29, 58]));
219 ippkt.set_dest_ip(Ipv4Addr([192, 168, 29, 160]));
220
221 let mut ethpkt = EtherPacket::prepend_header(ippkt.release(), ÐER_HEADER_TEMPLATE);
222 ethpkt.set_dest_mac(MacAddr([0x00, 0x0b, 0x86, 0x64, 0x8b, 0xa0]));
223 ethpkt.set_source_mac(MacAddr([0x00, 0x50, 0x56, 0xae, 0x76, 0xf5]));
224 ethpkt.set_ethertype(EtherType::IPV4);
225
226 let v = ethpkt.release();
227 assert_eq!(v.chunk(), &FRAME_BYTES[..108]);
228 }
229
230 #[test]
231 fn cursor_parse1() {
232 let buf = Cursor::new(&FRAME_BYTES[..]);
233
234 let ethpkt = EtherPacket::parse(buf).unwrap();
235 let ipv4_pkt = Ipv4Packet::parse(ethpkt.cursor_payload()).unwrap();
236 let udp_pkt = UdpPacket::parse(ipv4_pkt.cursor_payload()).unwrap();
237
238 assert_eq!(ethpkt.ethertype(), EtherType::IPV4);
239 assert_eq!(ipv4_pkt.protocol(), IpProtocol::UDP);
240 assert_eq!(udp_pkt.checksum(), 0xbc86);
241 }
242
243 #[test]
244 fn cursor_parse2() {
245 let buf = Cursor::new(&FRAME_BYTES[..]);
246
247 let ethpkt = EtherPacket::parse(buf).unwrap();
248 let eth_hdr = ethpkt.cursor_header();
249
250 let ipv4_pkt = Ipv4Packet::parse(ethpkt.payload()).unwrap();
251 let ipv4_hdr = ipv4_pkt.cursor_header();
252
253 let udp_pkt = UdpPacket::parse(ipv4_pkt.payload()).unwrap();
254 let udp_hdr = udp_pkt.cursor_header();
255
256 assert_eq!(eth_hdr.ethertype(), EtherType::IPV4);
257 assert_eq!(ipv4_hdr.protocol(), IpProtocol::UDP);
258 assert_eq!(udp_hdr.checksum(), 0xbc86);
259 }
260
261 #[test]
262 fn fake_nat() {
263 let mut buf = [0; 110];
264 buf.copy_from_slice(&FRAME_BYTES[..]);
265
266 let pkt = CursorMut::new(&mut buf[..]);
267
268 let ethpkt = EtherPacket::parse(pkt).unwrap();
269 let (eth_hdr, payload) = ethpkt.split();
270
271 let ippkt = Ipv4Packet::parse(payload).unwrap();
272 let ip_hdr_cursor = ippkt.buf().cursor() + eth_hdr.as_bytes().len();
273
274 let (mut ip_hdr, _, payload) = ippkt.split();
275 let udp_hdr_cursor = ip_hdr_cursor + usize::from(ip_hdr.header_len());
276
277 let udppkt = UdpPacket::parse(payload).unwrap();
278 let (mut udp_hdr, _) = udppkt.split();
279
280 ip_hdr.set_source_ip(Ipv4Addr([127, 0, 0, 1]));
281 udp_hdr.set_source_port(1024);
282 assert_eq!(ip_hdr_cursor, 14);
283 assert_eq!(udp_hdr_cursor, 34);
284
285 let pkt = Cursor::new(&buf[..]);
286 let ethpkt = EtherPacket::parse(pkt).unwrap();
287
288 let ippkt = Ipv4Packet::parse(ethpkt.payload()).unwrap();
289 assert_eq!(ippkt.source_ip(), Ipv4Addr([127, 0, 0, 1]));
290
291 let udppkt = UdpPacket::parse(ippkt.payload()).unwrap();
292 assert_eq!(udppkt.source_port(), 1024);
293 }
294}