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, 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 into_body(self) -> B {
181 self.body
182 }
183
184 pub fn src_port(&self) -> Option<NonZeroU16> {
188 NonZeroU16::new(self.header.src_port.get())
189 }
190
191 pub fn dst_port(&self) -> NonZeroU16 {
193 NonZeroU16::new(self.header.dst_port.get()).unwrap()
195 }
196
197 pub fn checksummed(&self) -> bool {
207 self.header.checksummed()
208 }
209
210 pub fn builder<A: IpAddress>(&self, src_ip: A, dst_ip: A) -> UdpPacketBuilder<A> {
212 UdpPacketBuilder {
213 src_ip,
214 dst_ip,
215 src_port: self.src_port(),
216 dst_port: Some(self.dst_port()),
217 }
218 }
219
220 pub fn into_serializer<'a, A: IpAddress>(
234 self,
235 src_ip: A,
236 dst_ip: A,
237 ) -> impl Serializer<Buffer = EmptyBuf> + Debug + 'a
238 where
239 B: 'a,
240 {
241 let builder = self.builder(src_ip, dst_ip);
242 ByteSliceInnerPacketBuilder(self.body).into_serializer().encapsulate(builder)
243 }
244}
245
246impl<B: SplitByteSliceMut> UdpPacket<B> {
247 pub fn set_src_port(&mut self, new: u16) {
249 self.header.set_src_port(new)
250 }
251
252 pub fn set_dst_port(&mut self, new: NonZeroU16) {
254 self.header.set_dst_port(new);
255 }
256
257 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
259 self.header.update_checksum_pseudo_header_address(old, new);
260 }
261}
262
263#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
268#[repr(C)]
269struct UdpFlowHeader {
270 src_port: U16,
271 dst_port: U16,
272}
273
274#[derive(Debug)]
276struct PartialHeader<B: SplitByteSlice> {
277 flow: Ref<B, UdpFlowHeader>,
278 rest: B,
279}
280
281pub struct UdpPacketRaw<B: SplitByteSlice> {
295 header: MaybeParsed<Ref<B, Header>, PartialHeader<B>>,
296 body: MaybeParsed<B, B>,
297}
298
299impl<B, I> ParsablePacket<B, IpVersionMarker<I>> for UdpPacketRaw<B>
300where
301 B: SplitByteSlice,
302 I: Ip,
303{
304 type Error = ParseError;
305
306 fn parse_metadata(&self) -> ParseMetadata {
307 let header_len = match &self.header {
308 MaybeParsed::Complete(h) => Ref::bytes(&h).len(),
309 MaybeParsed::Incomplete(h) => Ref::bytes(&h.flow).len() + h.rest.len(),
310 };
311 ParseMetadata::from_packet(header_len, self.body.len(), 0)
312 }
313
314 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: IpVersionMarker<I>) -> ParseResult<Self> {
315 let header = if let Some(header) = buffer.take_obj_front::<Header>() {
318 header
319 } else {
320 let flow = buffer
321 .take_obj_front::<UdpFlowHeader>()
322 .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for flow header"))?;
323 return Ok(UdpPacketRaw {
326 header: MaybeParsed::Incomplete(PartialHeader {
327 flow,
328 rest: buffer.take_rest_front(),
329 }),
330 body: MaybeParsed::Incomplete(buffer.into_rest()),
331 });
332 };
333 let buffer_len = buffer.len();
334
335 fn get_udp_body_length<I: Ip>(header: &Header, remaining_buff_len: usize) -> Option<usize> {
336 if I::VERSION.is_v6()
344 && header.length.get() == 0
345 && remaining_buff_len.saturating_add(HEADER_BYTES) >= (core::u16::MAX as usize)
346 {
347 return Some(remaining_buff_len);
348 }
349
350 usize::from(header.length.get()).checked_sub(HEADER_BYTES)
351 }
352
353 let body = if let Some(body_len) = get_udp_body_length::<I>(&header, buffer_len) {
354 if body_len <= buffer_len {
355 let _: B = buffer.take_back(buffer_len - body_len).unwrap();
359 MaybeParsed::Complete(buffer.into_rest())
360 } else {
361 MaybeParsed::Incomplete(buffer.into_rest())
363 }
364 } else {
365 let _: B = buffer.take_rest_back();
369 MaybeParsed::Incomplete(buffer.into_rest())
370 };
371
372 Ok(UdpPacketRaw { header: MaybeParsed::Complete(header), body })
373 }
374}
375
376impl<B: SplitByteSlice> UdpPacketRaw<B> {
377 pub fn src_port(&self) -> Option<NonZeroU16> {
381 NonZeroU16::new(
382 self.header
383 .as_ref()
384 .map(|header| header.src_port)
385 .map_incomplete(|partial_header| partial_header.flow.src_port)
386 .into_inner()
387 .get(),
388 )
389 }
390
391 pub fn dst_port(&self) -> Option<NonZeroU16> {
396 NonZeroU16::new(
397 self.header
398 .as_ref()
399 .map(|header| header.dst_port)
400 .map_incomplete(|partial_header| partial_header.flow.dst_port)
401 .into_inner()
402 .get(),
403 )
404 }
405
406 pub fn builder<A: IpAddress>(&self, src_ip: A, dst_ip: A) -> UdpPacketBuilder<A> {
413 UdpPacketBuilder { src_ip, dst_ip, src_port: self.src_port(), dst_port: self.dst_port() }
414 }
415
416 pub fn into_serializer<'a, A: IpAddress>(
435 self,
436 src_ip: A,
437 dst_ip: A,
438 ) -> Option<impl Serializer<Buffer = EmptyBuf> + 'a>
439 where
440 B: 'a,
441 {
442 let builder = self.builder(src_ip, dst_ip);
443 self.body
444 .complete()
445 .ok()
446 .map(|body| ByteSliceInnerPacketBuilder(body).into_serializer().encapsulate(builder))
447 }
448}
449
450impl<B: SplitByteSliceMut> UdpPacketRaw<B> {
451 pub fn set_src_port(&mut self, new: u16) {
453 match &mut self.header {
454 MaybeParsed::Complete(h) => h.set_src_port(new),
455 MaybeParsed::Incomplete(h) => {
456 h.flow.src_port = U16::from(new);
457
458 }
460 }
461 }
462
463 pub fn set_dst_port(&mut self, new: NonZeroU16) {
465 match &mut self.header {
466 MaybeParsed::Complete(h) => h.set_dst_port(new),
467 MaybeParsed::Incomplete(h) => {
468 h.flow.dst_port = U16::from(new.get());
469
470 }
472 }
473 }
474
475 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
477 match &mut self.header {
478 MaybeParsed::Complete(h) => h.update_checksum_pseudo_header_address(old, new),
479 MaybeParsed::Incomplete(_) => {
480 }
482 }
483 }
484}
485
486#[derive(Copy, Clone, Debug, PartialEq)]
494pub struct UdpPacketBuilder<A: IpAddress> {
495 src_ip: A,
496 dst_ip: A,
497 src_port: Option<NonZeroU16>,
498 dst_port: Option<NonZeroU16>,
499}
500
501impl<A: IpAddress> UdpPacketBuilder<A> {
502 pub fn new(
504 src_ip: A,
505 dst_ip: A,
506 src_port: Option<NonZeroU16>,
507 dst_port: NonZeroU16,
508 ) -> UdpPacketBuilder<A> {
509 UdpPacketBuilder { src_ip, dst_ip, src_port, dst_port: Some(dst_port) }
510 }
511
512 pub fn src_port(&self) -> Option<NonZeroU16> {
514 self.src_port
515 }
516
517 pub fn dst_port(&self) -> Option<NonZeroU16> {
519 self.dst_port
520 }
521
522 pub fn set_src_ip(&mut self, addr: A) {
524 self.src_ip = addr;
525 }
526
527 pub fn set_dst_ip(&mut self, addr: A) {
529 self.dst_ip = addr;
530 }
531
532 pub fn set_src_port(&mut self, port: u16) {
534 self.src_port = NonZeroU16::new(port);
535 }
536
537 pub fn set_dst_port(&mut self, port: NonZeroU16) {
539 self.dst_port = Some(port);
540 }
541}
542
543impl<A: IpAddress> PacketBuilder for UdpPacketBuilder<A> {
544 fn constraints(&self) -> PacketConstraints {
545 PacketConstraints::new(
546 HEADER_BYTES,
547 0,
548 0,
549 if A::Version::VERSION.is_v4() {
550 (1 << 16) - 1
551 } else {
552 core::usize::MAX
558 },
559 )
560 }
561
562 fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
563 let total_len = target.header.len() + body.len() + target.footer.len();
566
567 (&mut &mut target.header[..]).write_obj_front(&Header {
573 src_port: U16::new(self.src_port.map_or(0, NonZeroU16::get)),
574 dst_port: U16::new(self.dst_port.map_or(0, NonZeroU16::get)),
575 length: U16::new(total_len.try_into().unwrap_or_else(|_| {
576 if A::Version::VERSION.is_v6() {
577 0u16
579 } else {
580 panic!(
581 "total UDP packet length of {} bytes overflows 16-bit length field of UDP header",
582 total_len)
583 }
584 })),
585 checksum: [0, 0],
588 }).expect("too few bytes for UDP header");
589
590 let mut checksum = compute_transport_checksum_serialize(
591 self.src_ip,
592 self.dst_ip,
593 IpProto::Udp.into(),
594 target,
595 body,
596 )
597 .unwrap_or_else(|| {
598 panic!(
599 "total UDP packet length of {} bytes overflows length field of pseudo-header",
600 total_len
601 )
602 });
603 if checksum == [0, 0] {
604 checksum = [0xFF, 0xFF];
605 }
606 target.header[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
607 }
608}
609
610#[cfg(test)]
612impl<B> Debug for UdpPacket<B> {
613 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
614 write!(fmt, "UdpPacket")
615 }
616}
617
618#[cfg(test)]
619mod tests {
620 use byteorder::{ByteOrder, NetworkEndian};
621 use net_types::ip::{Ipv4, Ipv4Addr, Ipv6, Ipv6Addr};
622 use packet::{Buf, ParseBuffer};
623
624 use super::*;
625 use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
626 use crate::ipv4::{Ipv4Header, Ipv4Packet};
627 use crate::ipv6::{Ipv6Header, Ipv6Packet};
628 use crate::testutil::benchmarks::{black_box, Bencher};
629 use crate::testutil::*;
630
631 const TEST_SRC_IPV4: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
632 const TEST_DST_IPV4: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
633 const TEST_SRC_IPV6: Ipv6Addr =
634 Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
635 const TEST_DST_IPV6: Ipv6Addr =
636 Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
637
638 #[test]
639 fn test_parse_serialize_full_ipv4() {
640 use crate::testdata::dns_request_v4::*;
641
642 let mut buf = ETHERNET_FRAME.bytes;
643 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
644 verify_ethernet_frame(&frame, ETHERNET_FRAME);
645
646 let mut body = frame.body();
647 let ip_packet = body.parse::<Ipv4Packet<_>>().unwrap();
648 verify_ipv4_packet(&ip_packet, IPV4_PACKET);
649
650 let mut body = ip_packet.body();
651 let udp_packet = body
652 .parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(
653 ip_packet.src_ip(),
654 ip_packet.dst_ip(),
655 ))
656 .unwrap();
657 verify_udp_packet(&udp_packet, UDP_PACKET);
658
659 let buffer = udp_packet
660 .body()
661 .into_serializer()
662 .encapsulate(udp_packet.builder(ip_packet.src_ip(), ip_packet.dst_ip()))
663 .encapsulate(ip_packet.builder())
664 .encapsulate(frame.builder())
665 .serialize_vec_outer()
666 .unwrap();
667 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
668 }
669
670 #[test]
671 fn test_parse_serialize_full_ipv6() {
672 use crate::testdata::dns_request_v6::*;
673
674 let mut buf = ETHERNET_FRAME.bytes;
675 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
676 verify_ethernet_frame(&frame, ETHERNET_FRAME);
677
678 let mut body = frame.body();
679 let ip_packet = body.parse::<Ipv6Packet<_>>().unwrap();
680 verify_ipv6_packet(&ip_packet, IPV6_PACKET);
681
682 let mut body = ip_packet.body();
683 let udp_packet = body
684 .parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(
685 ip_packet.src_ip(),
686 ip_packet.dst_ip(),
687 ))
688 .unwrap();
689 verify_udp_packet(&udp_packet, UDP_PACKET);
690
691 let buffer = udp_packet
692 .body()
693 .into_serializer()
694 .encapsulate(udp_packet.builder(ip_packet.src_ip(), ip_packet.dst_ip()))
695 .encapsulate(ip_packet.builder())
696 .encapsulate(frame.builder())
697 .serialize_vec_outer()
698 .unwrap();
699 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
700 }
701
702 #[test]
703 fn test_parse() {
704 let mut buf = &[0, 0, 1, 2, 0, 8, 0, 0][..];
706 let packet = buf
707 .parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
708 .unwrap();
709 assert!(packet.src_port().is_none());
710 assert_eq!(packet.dst_port().get(), NetworkEndian::read_u16(&[1, 2]));
711 assert!(!packet.checksummed());
712 assert!(packet.body().is_empty());
713
714 let mut buf = vec![0_u8, 0, 1, 2, 0, 0, 0xBF, 0x12];
716 buf.extend((0..core::u16::MAX).into_iter().map(|p| p as u8));
717 let bv = &mut &buf[..];
718 let packet = bv
719 .parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(TEST_SRC_IPV6, TEST_DST_IPV6))
720 .unwrap();
721 assert!(packet.src_port().is_none());
722 assert_eq!(packet.dst_port().get(), NetworkEndian::read_u16(&[1, 2]));
723 assert!(packet.checksummed());
724 assert_eq!(packet.body().len(), core::u16::MAX as usize);
725 }
726
727 #[test]
728 fn test_serialize() {
729 let mut buf = (&[])
730 .into_serializer()
731 .encapsulate(UdpPacketBuilder::new(
732 TEST_SRC_IPV4,
733 TEST_DST_IPV4,
734 NonZeroU16::new(1),
735 NonZeroU16::new(2).unwrap(),
736 ))
737 .serialize_vec_outer()
738 .unwrap();
739 assert_eq!(buf.as_ref(), [0, 1, 0, 2, 0, 8, 239, 199]);
740 let packet = buf
741 .parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
742 .unwrap();
743 assert_eq!(packet.src_port().unwrap().get(), 1);
746 assert_eq!(packet.dst_port().get(), 2);
747 assert!(packet.checksummed());
748 }
749
750 #[test]
751 fn test_serialize_zeroes() {
752 let mut buf_0 = [0; HEADER_BYTES];
755 let _: Buf<&mut [u8]> = Buf::new(&mut buf_0[..], HEADER_BYTES..)
756 .encapsulate(UdpPacketBuilder::new(
757 TEST_SRC_IPV4,
758 TEST_DST_IPV4,
759 NonZeroU16::new(1),
760 NonZeroU16::new(2).unwrap(),
761 ))
762 .serialize_vec_outer()
763 .unwrap()
764 .unwrap_a();
765 let mut buf_1 = [0xFF; HEADER_BYTES];
766 let _: Buf<&mut [u8]> = Buf::new(&mut buf_1[..], HEADER_BYTES..)
767 .encapsulate(UdpPacketBuilder::new(
768 TEST_SRC_IPV4,
769 TEST_DST_IPV4,
770 NonZeroU16::new(1),
771 NonZeroU16::new(2).unwrap(),
772 ))
773 .serialize_vec_outer()
774 .unwrap()
775 .unwrap_a();
776 assert_eq!(buf_0, buf_1);
777 }
778
779 #[test]
780 fn test_parse_error() {
781 fn test_zero<I: IpAddress>(
785 src: I,
786 dst: I,
787 succeeds: bool,
788 zero: &[usize],
789 err: ParseError,
790 ) {
791 let mut buf = [1, 2, 3, 4, 0, 8, 0, 0];
794 if succeeds {
795 let mut buf = &buf[..];
796 assert!(buf.parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(src, dst)).is_ok());
797 }
798 for idx in zero {
799 buf[*idx] = 0;
800 }
801 let mut buf = &buf[..];
802 assert_eq!(
803 buf.parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(src, dst)).unwrap_err(),
804 err
805 );
806 }
807
808 test_zero(TEST_SRC_IPV4, TEST_DST_IPV4, true, &[2, 3], ParseError::Format);
810 test_zero(TEST_SRC_IPV4, TEST_DST_IPV4, true, &[4, 5], ParseError::Format);
812 test_zero(TEST_SRC_IPV6, TEST_DST_IPV6, false, &[], ParseError::Format);
815
816 #[cfg(target_pointer_width = "64")]
818 {
819 let mut buf = vec![0u8; 1 << 32];
821 (&mut buf[..HEADER_BYTES]).copy_from_slice(&[0, 0, 1, 2, 0, 0, 0xFF, 0xE4]);
822 assert_eq!(
823 (&buf[..])
824 .parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(TEST_SRC_IPV6, TEST_DST_IPV6))
825 .unwrap_err(),
826 ParseError::Format
827 );
828 }
829 }
830
831 #[test]
832 #[should_panic(expected = "too few bytes for UDP header")]
833 fn test_serialize_fail_header_too_short() {
834 let mut buf = [0u8; 7];
835 let mut buf = [&mut buf[..]];
836 let buf = FragmentedBytesMut::new(&mut buf[..]);
837 let (header, body, footer) = buf.try_split_contiguous(..).unwrap();
838 let builder =
839 UdpPacketBuilder::new(TEST_SRC_IPV4, TEST_DST_IPV4, None, NonZeroU16::new(1).unwrap());
840 builder.serialize(&mut SerializeTarget { header, footer }, body);
841 }
842
843 #[test]
844 #[should_panic(expected = "total UDP packet length of 65536 bytes overflows 16-bit length \
845 field of UDP header")]
846 fn test_serialize_fail_packet_too_long_ipv4() {
847 let ser = (&[0; (1 << 16) - HEADER_BYTES][..]).into_serializer().encapsulate(
848 UdpPacketBuilder::new(TEST_SRC_IPV4, TEST_DST_IPV4, None, NonZeroU16::new(1).unwrap()),
849 );
850 let _ = ser.serialize_vec_outer();
851 }
852
853 #[test]
854 fn test_partial_parse() {
855 use core::ops::Deref as _;
856
857 let buf = [0, 0, 1, 2, 10, 20];
859 let mut bv = &buf[..];
860 let packet =
861 bv.parse_with::<_, UdpPacketRaw<_>>(IpVersionMarker::<Ipv4>::default()).unwrap();
862 let UdpPacketRaw { header, body } = &packet;
863 let PartialHeader { flow, rest } = header.as_ref().incomplete().unwrap();
864 assert_eq!(
865 flow.deref(),
866 &UdpFlowHeader { src_port: U16::new(0), dst_port: U16::new(0x0102) }
867 );
868 assert_eq!(*rest, &buf[4..]);
869 assert_eq!(body.incomplete().unwrap(), []);
870 assert!(UdpPacket::try_from_raw_with(
871 packet,
872 UdpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4)
873 )
874 .is_err());
875
876 let mut buf = &[0, 0, 1][..];
878 assert!(buf.parse_with::<_, UdpPacketRaw<_>>(IpVersionMarker::<Ipv4>::default()).is_err());
879
880 let buf = [0, 0, 1, 2, 0, 30, 0, 0, 10, 20];
882 let mut bv = &buf[..];
883 let packet =
884 bv.parse_with::<_, UdpPacketRaw<_>>(IpVersionMarker::<Ipv4>::default()).unwrap();
885 let UdpPacketRaw { header, body } = &packet;
886 assert_eq!(Ref::bytes(&header.as_ref().complete().unwrap()), &buf[..8]);
887 assert_eq!(body.incomplete().unwrap(), &buf[8..]);
888 assert!(UdpPacket::try_from_raw_with(
889 packet,
890 UdpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4)
891 )
892 .is_err());
893
894 let buf = [0, 0, 1, 2, 0, 6, 0, 0, 10, 20];
896 let mut bv = &buf[..];
897 let packet =
898 bv.parse_with::<_, UdpPacketRaw<_>>(IpVersionMarker::<Ipv4>::default()).unwrap();
899 let UdpPacketRaw { header, body } = &packet;
900 assert_eq!(Ref::bytes(&header.as_ref().complete().unwrap()), &buf[..8]);
901 assert_eq!(body.incomplete().unwrap(), []);
902 assert!(UdpPacket::try_from_raw_with(
903 packet,
904 UdpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4)
905 )
906 .is_err());
907
908 let buf = [0, 0, 1, 2, 0, 0, 0, 0, 10, 20];
912 let mut bv = &buf[..];
913 let packet =
914 bv.parse_with::<_, UdpPacketRaw<_>>(IpVersionMarker::<Ipv6>::default()).unwrap();
915 let UdpPacketRaw { header, body } = &packet;
916 assert_eq!(Ref::bytes(&header.as_ref().complete().unwrap()), &buf[..8]);
917 assert_eq!(body.incomplete().unwrap(), []);
918 let mut buf = vec![0, 0, 1, 2, 0, 0, 0, 0, 10, 20];
921 buf.extend((0..core::u16::MAX).into_iter().map(|x| x as u8));
922 let bv = &mut &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.complete().unwrap(), &buf[8..]);
928 }
929
930 #[test]
931 fn test_udp_checksum_0xffff() {
932 let builder = (&[0xff, 0xd9]).into_serializer().encapsulate(UdpPacketBuilder::new(
935 Ipv4Addr::new([0, 0, 0, 0]),
936 Ipv4Addr::new([0, 0, 0, 0]),
937 None,
938 NonZeroU16::new(1).unwrap(),
939 ));
940 let buf = builder.serialize_vec_outer().unwrap();
941 assert_eq!(buf.as_ref()[7], 0xFF);
946 assert_eq!(buf.as_ref()[8], 0xFF);
947
948 let mut c = internet_checksum::Checksum::new();
950 c.add_bytes(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 10]);
951 c.add_bytes(buf.as_ref());
952 assert!(c.checksum() == [0, 0]);
953 }
954
955 fn bench_parse_inner<B: Bencher>(b: &mut B) {
960 use crate::testdata::dns_request_v4::*;
961 let bytes = parse_ip_packet_in_ethernet_frame::<Ipv4>(
962 ETHERNET_FRAME.bytes,
963 EthernetFrameLengthCheck::Check,
964 )
965 .unwrap()
966 .0;
967
968 b.iter(|| {
969 let buf = bytes;
970 let _: UdpPacket<_> = black_box(
971 black_box(buf)
972 .parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(
973 IPV4_PACKET.metadata.src_ip,
974 IPV4_PACKET.metadata.dst_ip,
975 ))
976 .unwrap(),
977 );
978 })
979 }
980
981 bench!(bench_parse, bench_parse_inner);
982
983 fn bench_serialize_inner<B: Bencher>(b: &mut B) {
984 use crate::testdata::dns_request_v4::*;
985 let builder = UdpPacketBuilder::new(
986 IPV4_PACKET.metadata.src_ip,
987 IPV4_PACKET.metadata.dst_ip,
988 None,
989 NonZeroU16::new(UDP_PACKET.metadata.dst_port).unwrap(),
990 );
991 let header_len = builder.constraints().header_len();
992 let total_len = header_len + UDP_PACKET.bytes[UDP_PACKET.body_range].len();
993 let mut buf = vec![0; total_len];
994 buf[header_len..].copy_from_slice(&UDP_PACKET.bytes[UDP_PACKET.body_range]);
995
996 b.iter(|| {
997 let _: Buf<_> = black_box(
998 black_box(Buf::new(&mut buf[..], header_len..total_len).encapsulate(builder))
999 .serialize_no_alloc_outer(),
1000 )
1001 .unwrap();
1002 })
1003 }
1004
1005 bench!(bench_serialize, bench_serialize_inner);
1006}