1use core::fmt::Debug;
12#[cfg(test)]
13use core::fmt::{self, Formatter};
14use core::num::NonZeroU16;
15use core::ops::Range;
16
17use net_types::ip::{Ip, IpAddress, IpVersionMarker};
18use packet::{
19 BufferView, BufferViewMut, ByteSliceInnerPacketBuilder, EmptyBuf, FragmentedBytesMut, FromRaw,
20 InnerPacketBuilder, MaybeParsed, PacketBuilder, PacketConstraints, ParsablePacket,
21 ParseMetadata, PartialPacketBuilder, SerializeTarget, Serializer,
22};
23use zerocopy::byteorder::network_endian::U16;
24use zerocopy::{
25 FromBytes, Immutable, IntoBytes, KnownLayout, Ref, SplitByteSlice, SplitByteSliceMut, Unaligned,
26};
27
28use crate::error::{ParseError, ParseResult};
29use crate::ip::IpProto;
30use crate::{compute_transport_checksum_parts, compute_transport_checksum_serialize};
31
32pub const HEADER_BYTES: usize = 8;
34const CHECKSUM_OFFSET: usize = 6;
35const CHECKSUM_RANGE: Range<usize> = CHECKSUM_OFFSET..CHECKSUM_OFFSET + 2;
36
37#[derive(Debug, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned)]
38#[repr(C)]
39struct Header {
40 src_port: U16,
41 dst_port: U16,
42 length: U16,
43 checksum: [u8; 2],
44}
45
46impl Header {
47 fn checksummed(&self) -> bool {
48 self.checksum != U16::ZERO
49 }
50
51 pub fn set_src_port(&mut self, new: u16) {
52 let old = self.src_port;
53 let new = U16::from(new);
54 self.src_port = new;
55 if self.checksummed() {
56 self.checksum =
57 internet_checksum::update(self.checksum, old.as_bytes(), new.as_bytes());
58 }
59 }
60
61 pub fn set_dst_port(&mut self, new: NonZeroU16) {
62 let old = self.dst_port;
63 let new = U16::from(new.get());
64 self.dst_port = new;
65 if self.checksummed() {
66 self.checksum =
67 internet_checksum::update(self.checksum, old.as_bytes(), new.as_bytes());
68 }
69 }
70
71 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
72 if self.checksummed() {
73 self.checksum = internet_checksum::update(self.checksum, old.bytes(), new.bytes());
74 }
75 }
76}
77
78pub struct UdpPacket<B> {
87 header: Ref<B, Header>,
88 body: B,
89}
90
91pub struct UdpParseArgs<A: IpAddress> {
93 src_ip: A,
94 dst_ip: A,
95}
96
97impl<A: IpAddress> UdpParseArgs<A> {
98 pub fn new(src_ip: A, dst_ip: A) -> UdpParseArgs<A> {
100 UdpParseArgs { src_ip, dst_ip }
101 }
102}
103
104impl<B: SplitByteSlice, A: IpAddress> FromRaw<UdpPacketRaw<B>, UdpParseArgs<A>> for UdpPacket<B> {
105 type Error = ParseError;
106
107 fn try_from_raw_with(raw: UdpPacketRaw<B>, args: UdpParseArgs<A>) -> Result<Self, Self::Error> {
108 let header = raw
110 .header
111 .ok_or_else(|_| debug_err!(ParseError::Format, "too few bytes for header"))?;
112 let body = raw.body.ok_or_else(|_| debug_err!(ParseError::Format, "incomplete body"))?;
113
114 let checksum = header.checksum;
115 if checksum != [0, 0] {
119 let parts = [Ref::bytes(&header), body.deref().as_ref()];
120 let checksum = compute_transport_checksum_parts(
121 args.src_ip,
122 args.dst_ip,
123 IpProto::Udp.into(),
124 parts.iter(),
125 )
126 .ok_or_else(debug_err_fn!(ParseError::Format, "packet too large"))?;
127
128 if checksum != [0, 0] {
136 return debug_err!(
137 Err(ParseError::Checksum),
138 "invalid checksum {:X?}",
139 header.checksum,
140 );
141 }
142 } else if A::Version::VERSION.is_v6() {
143 return debug_err!(Err(ParseError::Format), "missing checksum");
144 }
145
146 if header.dst_port.get() == 0 {
147 return debug_err!(Err(ParseError::Format), "zero destination port");
148 }
149
150 Ok(UdpPacket { header, body })
151 }
152}
153
154impl<B: SplitByteSlice, A: IpAddress> ParsablePacket<B, UdpParseArgs<A>> for UdpPacket<B> {
155 type Error = ParseError;
156
157 fn parse_metadata(&self) -> ParseMetadata {
158 ParseMetadata::from_packet(Ref::bytes(&self.header).len(), self.body.len(), 0)
159 }
160
161 fn parse<BV: BufferView<B>>(buffer: BV, args: UdpParseArgs<A>) -> ParseResult<Self> {
162 UdpPacketRaw::<B>::parse(buffer, IpVersionMarker::<A::Version>::default())
163 .and_then(|u| UdpPacket::try_from_raw_with(u, args))
164 }
165}
166
167impl<B: SplitByteSlice> UdpPacket<B> {
168 pub fn body(&self) -> &[u8] {
170 self.body.deref()
171 }
172
173 pub fn as_bytes(&self) -> [&[u8]; 2] {
175 [&Ref::bytes(&self.header), self.body.deref()]
176 }
177
178 pub fn into_body(self) -> B {
186 self.body
187 }
188
189 pub fn src_port(&self) -> Option<NonZeroU16> {
193 NonZeroU16::new(self.header.src_port.get())
194 }
195
196 pub fn dst_port(&self) -> NonZeroU16 {
198 NonZeroU16::new(self.header.dst_port.get()).unwrap()
200 }
201
202 pub fn checksummed(&self) -> bool {
212 self.header.checksummed()
213 }
214
215 pub fn builder<A: IpAddress>(&self, src_ip: A, dst_ip: A) -> UdpPacketBuilder<A> {
217 UdpPacketBuilder {
218 src_ip,
219 dst_ip,
220 src_port: self.src_port(),
221 dst_port: Some(self.dst_port()),
222 }
223 }
224
225 pub fn into_serializer<'a, A: IpAddress>(
239 self,
240 src_ip: A,
241 dst_ip: A,
242 ) -> impl Serializer<Buffer = EmptyBuf> + Debug + 'a
243 where
244 B: 'a,
245 {
246 self.builder(src_ip, dst_ip)
247 .wrap_body(ByteSliceInnerPacketBuilder(self.body).into_serializer())
248 }
249}
250
251impl<B: SplitByteSliceMut> UdpPacket<B> {
252 pub fn set_src_port(&mut self, new: u16) {
254 self.header.set_src_port(new)
255 }
256
257 pub fn set_dst_port(&mut self, new: NonZeroU16) {
259 self.header.set_dst_port(new);
260 }
261
262 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
264 self.header.update_checksum_pseudo_header_address(old, new);
265 }
266}
267
268impl<B: zerocopy::CloneableByteSlice + Clone> Clone for UdpPacket<B> {
269 fn clone(&self) -> Self {
270 UdpPacket { header: self.header.clone(), body: self.body.clone() }
271 }
272}
273
274#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
279#[repr(C)]
280struct UdpFlowHeader {
281 src_port: U16,
282 dst_port: U16,
283}
284
285#[derive(Debug)]
287struct PartialHeader<B: SplitByteSlice> {
288 flow: Ref<B, UdpFlowHeader>,
289 rest: B,
290}
291
292pub struct UdpPacketRaw<B: SplitByteSlice> {
306 header: MaybeParsed<Ref<B, Header>, PartialHeader<B>>,
307 body: MaybeParsed<B, B>,
308}
309
310impl<B, I> ParsablePacket<B, IpVersionMarker<I>> for UdpPacketRaw<B>
311where
312 B: SplitByteSlice,
313 I: Ip,
314{
315 type Error = ParseError;
316
317 fn parse_metadata(&self) -> ParseMetadata {
318 let header_len = match &self.header {
319 MaybeParsed::Complete(h) => Ref::bytes(&h).len(),
320 MaybeParsed::Incomplete(h) => Ref::bytes(&h.flow).len() + h.rest.len(),
321 };
322 ParseMetadata::from_packet(header_len, self.body.len(), 0)
323 }
324
325 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: IpVersionMarker<I>) -> ParseResult<Self> {
326 let header = if let Some(header) = buffer.take_obj_front::<Header>() {
329 header
330 } else {
331 let flow = buffer
332 .take_obj_front::<UdpFlowHeader>()
333 .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for flow header"))?;
334 return Ok(UdpPacketRaw {
337 header: MaybeParsed::Incomplete(PartialHeader {
338 flow,
339 rest: buffer.take_rest_front(),
340 }),
341 body: MaybeParsed::Incomplete(buffer.into_rest()),
342 });
343 };
344 let buffer_len = buffer.len();
345
346 fn get_udp_body_length<I: Ip>(header: &Header, remaining_buff_len: usize) -> Option<usize> {
347 if I::VERSION.is_v6()
355 && header.length.get() == 0
356 && remaining_buff_len.saturating_add(HEADER_BYTES) >= (core::u16::MAX as usize)
357 {
358 return Some(remaining_buff_len);
359 }
360
361 usize::from(header.length.get()).checked_sub(HEADER_BYTES)
362 }
363
364 let body = if let Some(body_len) = get_udp_body_length::<I>(&header, buffer_len) {
365 if body_len <= buffer_len {
366 let _: B = buffer.take_back(buffer_len - body_len).unwrap();
370 MaybeParsed::Complete(buffer.into_rest())
371 } else {
372 MaybeParsed::Incomplete(buffer.into_rest())
374 }
375 } else {
376 let _: B = buffer.take_rest_back();
380 MaybeParsed::Incomplete(buffer.into_rest())
381 };
382
383 Ok(UdpPacketRaw { header: MaybeParsed::Complete(header), body })
384 }
385}
386
387impl<B: SplitByteSlice> UdpPacketRaw<B> {
388 pub fn src_port(&self) -> Option<NonZeroU16> {
392 NonZeroU16::new(
393 self.header
394 .as_ref()
395 .map(|header| header.src_port)
396 .map_incomplete(|partial_header| partial_header.flow.src_port)
397 .into_inner()
398 .get(),
399 )
400 }
401
402 pub fn dst_port(&self) -> Option<NonZeroU16> {
407 NonZeroU16::new(
408 self.header
409 .as_ref()
410 .map(|header| header.dst_port)
411 .map_incomplete(|partial_header| partial_header.flow.dst_port)
412 .into_inner()
413 .get(),
414 )
415 }
416
417 pub fn builder<A: IpAddress>(&self, src_ip: A, dst_ip: A) -> UdpPacketBuilder<A> {
424 UdpPacketBuilder { src_ip, dst_ip, src_port: self.src_port(), dst_port: self.dst_port() }
425 }
426
427 pub fn into_serializer<'a, A: IpAddress>(
446 self,
447 src_ip: A,
448 dst_ip: A,
449 ) -> Option<impl Serializer<Buffer = EmptyBuf> + 'a>
450 where
451 B: 'a,
452 {
453 let builder = self.builder(src_ip, dst_ip);
454 self.body
455 .complete()
456 .ok()
457 .map(|body| builder.wrap_body(ByteSliceInnerPacketBuilder(body).into_serializer()))
458 }
459}
460
461impl<B: SplitByteSliceMut> UdpPacketRaw<B> {
462 pub fn set_src_port(&mut self, new: u16) {
464 match &mut self.header {
465 MaybeParsed::Complete(h) => h.set_src_port(new),
466 MaybeParsed::Incomplete(h) => {
467 h.flow.src_port = U16::from(new);
468
469 }
471 }
472 }
473
474 pub fn set_dst_port(&mut self, new: NonZeroU16) {
476 match &mut self.header {
477 MaybeParsed::Complete(h) => h.set_dst_port(new),
478 MaybeParsed::Incomplete(h) => {
479 h.flow.dst_port = U16::from(new.get());
480
481 }
483 }
484 }
485
486 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
488 match &mut self.header {
489 MaybeParsed::Complete(h) => h.update_checksum_pseudo_header_address(old, new),
490 MaybeParsed::Incomplete(_) => {
491 }
493 }
494 }
495}
496
497#[derive(Copy, Clone, Debug, PartialEq)]
505pub struct UdpPacketBuilder<A: IpAddress> {
506 src_ip: A,
507 dst_ip: A,
508 src_port: Option<NonZeroU16>,
509 dst_port: Option<NonZeroU16>,
510}
511
512impl<A: IpAddress> UdpPacketBuilder<A> {
513 pub fn new(
515 src_ip: A,
516 dst_ip: A,
517 src_port: Option<NonZeroU16>,
518 dst_port: NonZeroU16,
519 ) -> UdpPacketBuilder<A> {
520 UdpPacketBuilder { src_ip, dst_ip, src_port, dst_port: Some(dst_port) }
521 }
522
523 pub fn src_port(&self) -> Option<NonZeroU16> {
525 self.src_port
526 }
527
528 pub fn dst_port(&self) -> Option<NonZeroU16> {
530 self.dst_port
531 }
532
533 pub fn set_src_ip(&mut self, addr: A) {
535 self.src_ip = addr;
536 }
537
538 pub fn set_dst_ip(&mut self, addr: A) {
540 self.dst_ip = addr;
541 }
542
543 pub fn set_src_port(&mut self, port: u16) {
545 self.src_port = NonZeroU16::new(port);
546 }
547
548 pub fn set_dst_port(&mut self, port: NonZeroU16) {
550 self.dst_port = Some(port);
551 }
552
553 fn serialize_header(&self, body_len: usize, mut buffer: &mut [u8]) {
554 let total_len = buffer.len() + body_len;
557
558 (&mut buffer)
564 .write_obj_front(&Header {
565 src_port: U16::new(self.src_port.map_or(0, NonZeroU16::get)),
566 dst_port: U16::new(self.dst_port.map_or(0, NonZeroU16::get)),
567 length: U16::new(total_len.try_into().unwrap_or_else(|_| {
568 if A::Version::VERSION.is_v6() {
569 0u16
571 } else {
572 panic!(
573 "total UDP packet length of {total_len} bytes \
574 overflows 16-bit length field of UDP header"
575 )
576 }
577 })),
578 checksum: [0, 0],
581 })
582 .expect("too few bytes for UDP header");
583 }
584}
585
586impl<A: IpAddress> PacketBuilder for UdpPacketBuilder<A> {
587 fn constraints(&self) -> PacketConstraints {
588 PacketConstraints::new(
589 HEADER_BYTES,
590 0,
591 0,
592 if A::Version::VERSION.is_v4() {
593 (1 << 16) - 1
594 } else {
595 core::usize::MAX
601 },
602 )
603 }
604
605 fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
606 self.serialize_header(body.len(), target.header);
607
608 let mut checksum = compute_transport_checksum_serialize(
609 self.src_ip,
610 self.dst_ip,
611 IpProto::Udp.into(),
612 target,
613 body,
614 )
615 .unwrap(); if checksum == [0, 0] {
618 checksum = [0xFF, 0xFF];
619 }
620 target.header[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
621 }
622}
623
624impl<A: IpAddress> PartialPacketBuilder for UdpPacketBuilder<A> {
625 fn partial_serialize(&self, body_len: usize, buffer: &mut [u8]) {
626 self.serialize_header(body_len, buffer);
627 }
628}
629
630#[cfg(test)]
632impl<B> Debug for UdpPacket<B> {
633 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
634 write!(fmt, "UdpPacket")
635 }
636}
637
638#[cfg(test)]
639mod tests {
640 use byteorder::{ByteOrder, NetworkEndian};
641 use net_types::ip::{Ipv4, Ipv4Addr, Ipv6, Ipv6Addr};
642 use packet::{Buf, ParseBuffer};
643
644 use super::*;
645 use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
646 use crate::ipv4::{Ipv4Header, Ipv4Packet};
647 use crate::ipv6::{Ipv6Header, Ipv6Packet};
648 use crate::testutil::benchmarks::{black_box, Bencher};
649 use crate::testutil::*;
650
651 const TEST_SRC_IPV4: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
652 const TEST_DST_IPV4: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
653 const TEST_SRC_IPV6: Ipv6Addr =
654 Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
655 const TEST_DST_IPV6: Ipv6Addr =
656 Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
657
658 #[test]
659 fn test_parse_serialize_full_ipv4() {
660 use crate::testdata::dns_request_v4::*;
661
662 let mut buf = ETHERNET_FRAME.bytes;
663 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
664 verify_ethernet_frame(&frame, ETHERNET_FRAME);
665
666 let mut body = frame.body();
667 let ip_packet = body.parse::<Ipv4Packet<_>>().unwrap();
668 verify_ipv4_packet(&ip_packet, IPV4_PACKET);
669
670 let mut body = ip_packet.body();
671 let udp_packet = body
672 .parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(
673 ip_packet.src_ip(),
674 ip_packet.dst_ip(),
675 ))
676 .unwrap();
677 verify_udp_packet(&udp_packet, UDP_PACKET);
678
679 let buffer = udp_packet
680 .body()
681 .into_serializer()
682 .wrap_in(udp_packet.builder(ip_packet.src_ip(), ip_packet.dst_ip()))
683 .wrap_in(ip_packet.builder())
684 .wrap_in(frame.builder())
685 .serialize_vec_outer()
686 .unwrap();
687 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
688 }
689
690 #[test]
691 fn test_parse_serialize_full_ipv6() {
692 use crate::testdata::dns_request_v6::*;
693
694 let mut buf = ETHERNET_FRAME.bytes;
695 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
696 verify_ethernet_frame(&frame, ETHERNET_FRAME);
697
698 let mut body = frame.body();
699 let ip_packet = body.parse::<Ipv6Packet<_>>().unwrap();
700 verify_ipv6_packet(&ip_packet, IPV6_PACKET);
701
702 let mut body = ip_packet.body();
703 let udp_packet = body
704 .parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(
705 ip_packet.src_ip(),
706 ip_packet.dst_ip(),
707 ))
708 .unwrap();
709 verify_udp_packet(&udp_packet, UDP_PACKET);
710
711 let buffer = udp_packet
712 .body()
713 .into_serializer()
714 .wrap_in(udp_packet.builder(ip_packet.src_ip(), ip_packet.dst_ip()))
715 .wrap_in(ip_packet.builder())
716 .wrap_in(frame.builder())
717 .serialize_vec_outer()
718 .unwrap();
719 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
720 }
721
722 #[test]
723 fn test_parse() {
724 let mut buf = &[0, 0, 1, 2, 0, 8, 0, 0][..];
726 let packet = buf
727 .parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
728 .unwrap();
729 assert!(packet.src_port().is_none());
730 assert_eq!(packet.dst_port().get(), NetworkEndian::read_u16(&[1, 2]));
731 assert!(!packet.checksummed());
732 assert!(packet.body().is_empty());
733
734 let mut buf = vec![0_u8, 0, 1, 2, 0, 0, 0xBF, 0x12];
736 buf.extend((0..core::u16::MAX).into_iter().map(|p| p as u8));
737 let bv = &mut &buf[..];
738 let packet = bv
739 .parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(TEST_SRC_IPV6, TEST_DST_IPV6))
740 .unwrap();
741 assert!(packet.src_port().is_none());
742 assert_eq!(packet.dst_port().get(), NetworkEndian::read_u16(&[1, 2]));
743 assert!(packet.checksummed());
744 assert_eq!(packet.body().len(), core::u16::MAX as usize);
745 }
746
747 fn new_test_udp_builder() -> UdpPacketBuilder<Ipv4Addr> {
748 UdpPacketBuilder::new(
749 TEST_SRC_IPV4,
750 TEST_DST_IPV4,
751 NonZeroU16::new(1),
752 NonZeroU16::new(2).unwrap(),
753 )
754 }
755
756 #[test]
757 fn test_serialize() {
758 let mut buf = new_test_udp_builder().wrap_body(EmptyBuf).serialize_vec_outer().unwrap();
759 assert_eq!(buf.as_ref(), [0, 1, 0, 2, 0, 8, 239, 199]);
760 let packet = buf
761 .parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
762 .unwrap();
763 assert_eq!(packet.src_port().unwrap().get(), 1);
766 assert_eq!(packet.dst_port().get(), 2);
767 assert!(packet.checksummed());
768 }
769
770 #[test]
771 fn test_serialize_zeroes() {
772 let mut buf_0 = [0; HEADER_BYTES];
775 let _: Buf<&mut [u8]> = new_test_udp_builder()
776 .wrap_body(Buf::new(&mut buf_0[..], HEADER_BYTES..))
777 .serialize_vec_outer()
778 .unwrap()
779 .unwrap_a();
780 let mut buf_1 = [0xFF; HEADER_BYTES];
781 let _: Buf<&mut [u8]> = new_test_udp_builder()
782 .wrap_body(Buf::new(&mut buf_1[..], HEADER_BYTES..))
783 .serialize_vec_outer()
784 .unwrap()
785 .unwrap_a();
786 assert_eq!(buf_0, buf_1);
787 }
788
789 #[test]
790 fn test_parse_error() {
791 fn test_zero<I: IpAddress>(
795 src: I,
796 dst: I,
797 succeeds: bool,
798 zero: &[usize],
799 err: ParseError,
800 ) {
801 let mut buf = [1, 2, 3, 4, 0, 8, 0, 0];
804 if succeeds {
805 let mut buf = &buf[..];
806 assert!(buf.parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(src, dst)).is_ok());
807 }
808 for idx in zero {
809 buf[*idx] = 0;
810 }
811 let mut buf = &buf[..];
812 assert_eq!(
813 buf.parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(src, dst)).unwrap_err(),
814 err
815 );
816 }
817
818 test_zero(TEST_SRC_IPV4, TEST_DST_IPV4, true, &[2, 3], ParseError::Format);
820 test_zero(TEST_SRC_IPV4, TEST_DST_IPV4, true, &[4, 5], ParseError::Format);
822 test_zero(TEST_SRC_IPV6, TEST_DST_IPV6, false, &[], ParseError::Format);
825
826 #[cfg(target_pointer_width = "64")]
828 {
829 let mut buf = vec![0u8; 1 << 32];
831 (&mut buf[..HEADER_BYTES]).copy_from_slice(&[0, 0, 1, 2, 0, 0, 0xFF, 0xE4]);
832 assert_eq!(
833 (&buf[..])
834 .parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(TEST_SRC_IPV6, TEST_DST_IPV6))
835 .unwrap_err(),
836 ParseError::Format
837 );
838 }
839 }
840
841 #[test]
842 #[should_panic(expected = "too few bytes for UDP header")]
843 fn test_serialize_fail_header_too_short() {
844 let mut buf = [0u8; 7];
845 let mut buf = [&mut buf[..]];
846 let buf = FragmentedBytesMut::new(&mut buf[..]);
847 let (header, body, footer) = buf.try_split_contiguous(..).unwrap();
848 let builder =
849 UdpPacketBuilder::new(TEST_SRC_IPV4, TEST_DST_IPV4, None, NonZeroU16::new(1).unwrap());
850 builder.serialize(&mut SerializeTarget { header, footer }, body);
851 }
852
853 #[test]
854 #[should_panic(expected = "total UDP packet length of 65536 bytes overflows 16-bit length \
855 field of UDP header")]
856 fn test_serialize_fail_packet_too_long_ipv4() {
857 let ser =
858 UdpPacketBuilder::new(TEST_SRC_IPV4, TEST_DST_IPV4, None, NonZeroU16::new(1).unwrap())
859 .wrap_body((&[0; (1 << 16) - HEADER_BYTES][..]).into_serializer());
860 let _ = ser.serialize_vec_outer();
861 }
862
863 #[test]
864 fn test_partial_parse() {
865 use core::ops::Deref as _;
866
867 let buf = [0, 0, 1, 2, 10, 20];
869 let mut bv = &buf[..];
870 let packet =
871 bv.parse_with::<_, UdpPacketRaw<_>>(IpVersionMarker::<Ipv4>::default()).unwrap();
872 let UdpPacketRaw { header, body } = &packet;
873 let PartialHeader { flow, rest } = header.as_ref().incomplete().unwrap();
874 assert_eq!(
875 flow.deref(),
876 &UdpFlowHeader { src_port: U16::new(0), dst_port: U16::new(0x0102) }
877 );
878 assert_eq!(*rest, &buf[4..]);
879 assert_eq!(body.incomplete().unwrap(), []);
880 assert!(UdpPacket::try_from_raw_with(
881 packet,
882 UdpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4)
883 )
884 .is_err());
885
886 let mut buf = &[0, 0, 1][..];
888 assert!(buf.parse_with::<_, UdpPacketRaw<_>>(IpVersionMarker::<Ipv4>::default()).is_err());
889
890 let buf = [0, 0, 1, 2, 0, 30, 0, 0, 10, 20];
892 let mut bv = &buf[..];
893 let packet =
894 bv.parse_with::<_, UdpPacketRaw<_>>(IpVersionMarker::<Ipv4>::default()).unwrap();
895 let UdpPacketRaw { header, body } = &packet;
896 assert_eq!(Ref::bytes(&header.as_ref().complete().unwrap()), &buf[..8]);
897 assert_eq!(body.incomplete().unwrap(), &buf[8..]);
898 assert!(UdpPacket::try_from_raw_with(
899 packet,
900 UdpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4)
901 )
902 .is_err());
903
904 let buf = [0, 0, 1, 2, 0, 6, 0, 0, 10, 20];
906 let mut bv = &buf[..];
907 let packet =
908 bv.parse_with::<_, UdpPacketRaw<_>>(IpVersionMarker::<Ipv4>::default()).unwrap();
909 let UdpPacketRaw { header, body } = &packet;
910 assert_eq!(Ref::bytes(&header.as_ref().complete().unwrap()), &buf[..8]);
911 assert_eq!(body.incomplete().unwrap(), []);
912 assert!(UdpPacket::try_from_raw_with(
913 packet,
914 UdpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4)
915 )
916 .is_err());
917
918 let buf = [0, 0, 1, 2, 0, 0, 0, 0, 10, 20];
922 let mut bv = &buf[..];
923 let packet =
924 bv.parse_with::<_, UdpPacketRaw<_>>(IpVersionMarker::<Ipv6>::default()).unwrap();
925 let UdpPacketRaw { header, body } = &packet;
926 assert_eq!(Ref::bytes(&header.as_ref().complete().unwrap()), &buf[..8]);
927 assert_eq!(body.incomplete().unwrap(), []);
928 let mut buf = vec![0, 0, 1, 2, 0, 0, 0, 0, 10, 20];
931 buf.extend((0..core::u16::MAX).into_iter().map(|x| x as u8));
932 let bv = &mut &buf[..];
933 let packet =
934 bv.parse_with::<_, UdpPacketRaw<_>>(IpVersionMarker::<Ipv6>::default()).unwrap();
935 let UdpPacketRaw { header, body } = &packet;
936 assert_eq!(Ref::bytes(header.as_ref().complete().unwrap()), &buf[..8]);
937 assert_eq!(body.complete().unwrap(), &buf[8..]);
938 }
939
940 #[test]
941 fn test_udp_checksum_0xffff() {
942 let serializer = UdpPacketBuilder::new(
944 Ipv4Addr::new([0, 0, 0, 0]),
945 Ipv4Addr::new([0, 0, 0, 0]),
946 None,
947 NonZeroU16::new(1).unwrap(),
948 )
949 .wrap_body((&[0xff, 0xd9]).into_serializer());
950 let buf = serializer.serialize_vec_outer().unwrap();
951 assert_eq!(buf.as_ref()[7], 0xFF);
956 assert_eq!(buf.as_ref()[8], 0xFF);
957
958 let mut c = internet_checksum::Checksum::new();
960 c.add_bytes(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 10]);
961 c.add_bytes(buf.as_ref());
962 assert!(c.checksum() == [0, 0]);
963 }
964
965 fn bench_parse_inner<B: Bencher>(b: &mut B) {
970 use crate::testdata::dns_request_v4::*;
971 let bytes = parse_ip_packet_in_ethernet_frame::<Ipv4>(
972 ETHERNET_FRAME.bytes,
973 EthernetFrameLengthCheck::Check,
974 )
975 .unwrap()
976 .0;
977
978 b.iter(|| {
979 let buf = bytes;
980 let _: UdpPacket<_> = black_box(
981 black_box(buf)
982 .parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(
983 IPV4_PACKET.metadata.src_ip,
984 IPV4_PACKET.metadata.dst_ip,
985 ))
986 .unwrap(),
987 );
988 })
989 }
990
991 bench!(bench_parse, bench_parse_inner);
992
993 fn bench_serialize_inner<B: Bencher>(b: &mut B) {
994 use crate::testdata::dns_request_v4::*;
995 let builder = UdpPacketBuilder::new(
996 IPV4_PACKET.metadata.src_ip,
997 IPV4_PACKET.metadata.dst_ip,
998 None,
999 NonZeroU16::new(UDP_PACKET.metadata.dst_port).unwrap(),
1000 );
1001 let header_len = builder.constraints().header_len();
1002 let total_len = header_len + UDP_PACKET.bytes[UDP_PACKET.body_range].len();
1003 let mut buf = vec![0; total_len];
1004 buf[header_len..].copy_from_slice(&UDP_PACKET.bytes[UDP_PACKET.body_range]);
1005
1006 b.iter(|| {
1007 let _: Buf<_> = black_box(
1008 black_box(builder.wrap_body(Buf::new(&mut buf[..], header_len..total_len)))
1009 .serialize_no_alloc_outer(),
1010 )
1011 .unwrap();
1012 })
1013 }
1014
1015 bench!(bench_serialize, bench_serialize_inner);
1016}