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
46pub struct UdpPacket<B> {
55 header: Ref<B, Header>,
56 body: B,
57}
58
59pub struct UdpParseArgs<A: IpAddress> {
61 src_ip: A,
62 dst_ip: A,
63}
64
65impl<A: IpAddress> UdpParseArgs<A> {
66 pub fn new(src_ip: A, dst_ip: A) -> UdpParseArgs<A> {
68 UdpParseArgs { src_ip, dst_ip }
69 }
70}
71
72impl<B: SplitByteSlice, A: IpAddress> FromRaw<UdpPacketRaw<B>, UdpParseArgs<A>> for UdpPacket<B> {
73 type Error = ParseError;
74
75 fn try_from_raw_with(raw: UdpPacketRaw<B>, args: UdpParseArgs<A>) -> Result<Self, Self::Error> {
76 let header = raw
78 .header
79 .ok_or_else(|_| debug_err!(ParseError::Format, "too few bytes for header"))?;
80 let body = raw.body.ok_or_else(|_| debug_err!(ParseError::Format, "incomplete body"))?;
81
82 let checksum = header.checksum;
83 if checksum != [0, 0] {
87 let parts = [Ref::bytes(&header), body.deref().as_ref()];
88 let checksum = compute_transport_checksum_parts(
89 args.src_ip,
90 args.dst_ip,
91 IpProto::Udp.into(),
92 parts.iter(),
93 )
94 .ok_or_else(debug_err_fn!(ParseError::Format, "packet too large"))?;
95
96 if checksum != [0, 0] {
104 return debug_err!(
105 Err(ParseError::Checksum),
106 "invalid checksum {:X?}",
107 header.checksum,
108 );
109 }
110 } else if A::Version::VERSION.is_v6() {
111 return debug_err!(Err(ParseError::Format), "missing checksum");
112 }
113
114 if header.dst_port.get() == 0 {
115 return debug_err!(Err(ParseError::Format), "zero destination port");
116 }
117
118 Ok(UdpPacket { header, body })
119 }
120}
121
122impl<B: SplitByteSlice, A: IpAddress> ParsablePacket<B, UdpParseArgs<A>> for UdpPacket<B> {
123 type Error = ParseError;
124
125 fn parse_metadata(&self) -> ParseMetadata {
126 ParseMetadata::from_packet(Ref::bytes(&self.header).len(), self.body.len(), 0)
127 }
128
129 fn parse<BV: BufferView<B>>(buffer: BV, args: UdpParseArgs<A>) -> ParseResult<Self> {
130 UdpPacketRaw::<B>::parse(buffer, IpVersionMarker::<A::Version>::default())
131 .and_then(|u| UdpPacket::try_from_raw_with(u, args))
132 }
133}
134
135impl<B: SplitByteSlice> UdpPacket<B> {
136 pub fn body(&self) -> &[u8] {
138 self.body.deref()
139 }
140
141 pub fn into_body(self) -> B {
149 self.body
150 }
151
152 pub fn src_port(&self) -> Option<NonZeroU16> {
156 NonZeroU16::new(self.header.src_port.get())
157 }
158
159 pub fn dst_port(&self) -> NonZeroU16 {
161 NonZeroU16::new(self.header.dst_port.get()).unwrap()
163 }
164
165 pub fn checksummed(&self) -> bool {
175 self.header.checksum != U16::ZERO
176 }
177
178 pub fn builder<A: IpAddress>(&self, src_ip: A, dst_ip: A) -> UdpPacketBuilder<A> {
180 UdpPacketBuilder {
181 src_ip,
182 dst_ip,
183 src_port: self.src_port(),
184 dst_port: Some(self.dst_port()),
185 }
186 }
187
188 pub fn into_serializer<'a, A: IpAddress>(
202 self,
203 src_ip: A,
204 dst_ip: A,
205 ) -> impl Serializer<Buffer = EmptyBuf> + Debug + 'a
206 where
207 B: 'a,
208 {
209 let builder = self.builder(src_ip, dst_ip);
210 ByteSliceInnerPacketBuilder(self.body).into_serializer().encapsulate(builder)
211 }
212}
213
214impl<B: SplitByteSliceMut> UdpPacket<B> {
215 pub fn set_src_port(&mut self, new: u16) {
217 let old = self.header.src_port;
218 let new = U16::from(new);
219 self.header.src_port = new;
220 if self.checksummed() {
221 self.header.checksum =
222 internet_checksum::update(self.header.checksum, old.as_bytes(), new.as_bytes());
223 }
224 }
225
226 pub fn set_dst_port(&mut self, new: NonZeroU16) {
228 let old = self.header.dst_port;
229 let new = U16::from(new.get());
230 self.header.dst_port = new;
231 if self.checksummed() {
232 self.header.checksum =
233 internet_checksum::update(self.header.checksum, old.as_bytes(), new.as_bytes());
234 }
235 }
236
237 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
239 if self.checksummed() {
240 self.header.checksum =
241 internet_checksum::update(self.header.checksum, old.bytes(), new.bytes());
242 }
243 }
244}
245
246#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
251#[repr(C)]
252struct UdpFlowHeader {
253 src_port: U16,
254 dst_port: U16,
255}
256
257#[derive(Debug)]
259struct PartialHeader<B: SplitByteSlice> {
260 flow: Ref<B, UdpFlowHeader>,
261 rest: B,
262}
263
264pub struct UdpPacketRaw<B: SplitByteSlice> {
278 header: MaybeParsed<Ref<B, Header>, PartialHeader<B>>,
279 body: MaybeParsed<B, B>,
280}
281
282impl<B, I> ParsablePacket<B, IpVersionMarker<I>> for UdpPacketRaw<B>
283where
284 B: SplitByteSlice,
285 I: Ip,
286{
287 type Error = ParseError;
288
289 fn parse_metadata(&self) -> ParseMetadata {
290 let header_len = match &self.header {
291 MaybeParsed::Complete(h) => Ref::bytes(&h).len(),
292 MaybeParsed::Incomplete(h) => Ref::bytes(&h.flow).len() + h.rest.len(),
293 };
294 ParseMetadata::from_packet(header_len, self.body.len(), 0)
295 }
296
297 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: IpVersionMarker<I>) -> ParseResult<Self> {
298 let header = if let Some(header) = buffer.take_obj_front::<Header>() {
301 header
302 } else {
303 let flow = buffer
304 .take_obj_front::<UdpFlowHeader>()
305 .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for flow header"))?;
306 return Ok(UdpPacketRaw {
309 header: MaybeParsed::Incomplete(PartialHeader {
310 flow,
311 rest: buffer.take_rest_front(),
312 }),
313 body: MaybeParsed::Incomplete(buffer.into_rest()),
314 });
315 };
316 let buffer_len = buffer.len();
317
318 fn get_udp_body_length<I: Ip>(header: &Header, remaining_buff_len: usize) -> Option<usize> {
319 if I::VERSION.is_v6()
327 && header.length.get() == 0
328 && remaining_buff_len.saturating_add(HEADER_BYTES) >= (core::u16::MAX as usize)
329 {
330 return Some(remaining_buff_len);
331 }
332
333 usize::from(header.length.get()).checked_sub(HEADER_BYTES)
334 }
335
336 let body = if let Some(body_len) = get_udp_body_length::<I>(&header, buffer_len) {
337 if body_len <= buffer_len {
338 let _: B = buffer.take_back(buffer_len - body_len).unwrap();
342 MaybeParsed::Complete(buffer.into_rest())
343 } else {
344 MaybeParsed::Incomplete(buffer.into_rest())
346 }
347 } else {
348 let _: B = buffer.take_rest_back();
352 MaybeParsed::Incomplete(buffer.into_rest())
353 };
354
355 Ok(UdpPacketRaw { header: MaybeParsed::Complete(header), body })
356 }
357}
358
359impl<B: SplitByteSlice> UdpPacketRaw<B> {
360 pub fn src_port(&self) -> Option<NonZeroU16> {
364 NonZeroU16::new(
365 self.header
366 .as_ref()
367 .map(|header| header.src_port)
368 .map_incomplete(|partial_header| partial_header.flow.src_port)
369 .into_inner()
370 .get(),
371 )
372 }
373
374 pub fn dst_port(&self) -> Option<NonZeroU16> {
379 NonZeroU16::new(
380 self.header
381 .as_ref()
382 .map(|header| header.dst_port)
383 .map_incomplete(|partial_header| partial_header.flow.dst_port)
384 .into_inner()
385 .get(),
386 )
387 }
388
389 pub fn builder<A: IpAddress>(&self, src_ip: A, dst_ip: A) -> UdpPacketBuilder<A> {
396 UdpPacketBuilder { src_ip, dst_ip, src_port: self.src_port(), dst_port: self.dst_port() }
397 }
398
399 pub fn into_serializer<'a, A: IpAddress>(
418 self,
419 src_ip: A,
420 dst_ip: A,
421 ) -> Option<impl Serializer<Buffer = EmptyBuf> + 'a>
422 where
423 B: 'a,
424 {
425 let builder = self.builder(src_ip, dst_ip);
426 self.body
427 .complete()
428 .ok()
429 .map(|body| ByteSliceInnerPacketBuilder(body).into_serializer().encapsulate(builder))
430 }
431}
432
433#[derive(Copy, Clone, Debug, PartialEq)]
441pub struct UdpPacketBuilder<A: IpAddress> {
442 src_ip: A,
443 dst_ip: A,
444 src_port: Option<NonZeroU16>,
445 dst_port: Option<NonZeroU16>,
446}
447
448impl<A: IpAddress> UdpPacketBuilder<A> {
449 pub fn new(
451 src_ip: A,
452 dst_ip: A,
453 src_port: Option<NonZeroU16>,
454 dst_port: NonZeroU16,
455 ) -> UdpPacketBuilder<A> {
456 UdpPacketBuilder { src_ip, dst_ip, src_port, dst_port: Some(dst_port) }
457 }
458
459 pub fn src_port(&self) -> Option<NonZeroU16> {
461 self.src_port
462 }
463
464 pub fn dst_port(&self) -> Option<NonZeroU16> {
466 self.dst_port
467 }
468
469 pub fn set_src_ip(&mut self, addr: A) {
471 self.src_ip = addr;
472 }
473
474 pub fn set_dst_ip(&mut self, addr: A) {
476 self.dst_ip = addr;
477 }
478
479 pub fn set_src_port(&mut self, port: u16) {
481 self.src_port = NonZeroU16::new(port);
482 }
483
484 pub fn set_dst_port(&mut self, port: NonZeroU16) {
486 self.dst_port = Some(port);
487 }
488}
489
490impl<A: IpAddress> PacketBuilder for UdpPacketBuilder<A> {
491 fn constraints(&self) -> PacketConstraints {
492 PacketConstraints::new(
493 HEADER_BYTES,
494 0,
495 0,
496 if A::Version::VERSION.is_v4() {
497 (1 << 16) - 1
498 } else {
499 core::usize::MAX
505 },
506 )
507 }
508
509 fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
510 let total_len = target.header.len() + body.len() + target.footer.len();
513
514 (&mut &mut target.header[..]).write_obj_front(&Header {
520 src_port: U16::new(self.src_port.map_or(0, NonZeroU16::get)),
521 dst_port: U16::new(self.dst_port.map_or(0, NonZeroU16::get)),
522 length: U16::new(total_len.try_into().unwrap_or_else(|_| {
523 if A::Version::VERSION.is_v6() {
524 0u16
526 } else {
527 panic!(
528 "total UDP packet length of {} bytes overflows 16-bit length field of UDP header",
529 total_len)
530 }
531 })),
532 checksum: [0, 0],
535 }).expect("too few bytes for UDP header");
536
537 let mut checksum = compute_transport_checksum_serialize(
538 self.src_ip,
539 self.dst_ip,
540 IpProto::Udp.into(),
541 target,
542 body,
543 )
544 .unwrap_or_else(|| {
545 panic!(
546 "total UDP packet length of {} bytes overflows length field of pseudo-header",
547 total_len
548 )
549 });
550 if checksum == [0, 0] {
551 checksum = [0xFF, 0xFF];
552 }
553 target.header[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
554 }
555}
556
557#[cfg(test)]
559impl<B> Debug for UdpPacket<B> {
560 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
561 write!(fmt, "UdpPacket")
562 }
563}
564
565#[cfg(test)]
566mod tests {
567 use byteorder::{ByteOrder, NetworkEndian};
568 use net_types::ip::{Ipv4, Ipv4Addr, Ipv6, Ipv6Addr};
569 use packet::{Buf, ParseBuffer};
570
571 use super::*;
572 use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
573 use crate::ipv4::{Ipv4Header, Ipv4Packet};
574 use crate::ipv6::{Ipv6Header, Ipv6Packet};
575 use crate::testutil::benchmarks::{black_box, Bencher};
576 use crate::testutil::*;
577
578 const TEST_SRC_IPV4: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
579 const TEST_DST_IPV4: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
580 const TEST_SRC_IPV6: Ipv6Addr =
581 Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
582 const TEST_DST_IPV6: Ipv6Addr =
583 Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
584
585 #[test]
586 fn test_parse_serialize_full_ipv4() {
587 use crate::testdata::dns_request_v4::*;
588
589 let mut buf = ETHERNET_FRAME.bytes;
590 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
591 verify_ethernet_frame(&frame, ETHERNET_FRAME);
592
593 let mut body = frame.body();
594 let ip_packet = body.parse::<Ipv4Packet<_>>().unwrap();
595 verify_ipv4_packet(&ip_packet, IPV4_PACKET);
596
597 let mut body = ip_packet.body();
598 let udp_packet = body
599 .parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(
600 ip_packet.src_ip(),
601 ip_packet.dst_ip(),
602 ))
603 .unwrap();
604 verify_udp_packet(&udp_packet, UDP_PACKET);
605
606 let buffer = udp_packet
607 .body()
608 .into_serializer()
609 .encapsulate(udp_packet.builder(ip_packet.src_ip(), ip_packet.dst_ip()))
610 .encapsulate(ip_packet.builder())
611 .encapsulate(frame.builder())
612 .serialize_vec_outer()
613 .unwrap();
614 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
615 }
616
617 #[test]
618 fn test_parse_serialize_full_ipv6() {
619 use crate::testdata::dns_request_v6::*;
620
621 let mut buf = ETHERNET_FRAME.bytes;
622 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
623 verify_ethernet_frame(&frame, ETHERNET_FRAME);
624
625 let mut body = frame.body();
626 let ip_packet = body.parse::<Ipv6Packet<_>>().unwrap();
627 verify_ipv6_packet(&ip_packet, IPV6_PACKET);
628
629 let mut body = ip_packet.body();
630 let udp_packet = body
631 .parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(
632 ip_packet.src_ip(),
633 ip_packet.dst_ip(),
634 ))
635 .unwrap();
636 verify_udp_packet(&udp_packet, UDP_PACKET);
637
638 let buffer = udp_packet
639 .body()
640 .into_serializer()
641 .encapsulate(udp_packet.builder(ip_packet.src_ip(), ip_packet.dst_ip()))
642 .encapsulate(ip_packet.builder())
643 .encapsulate(frame.builder())
644 .serialize_vec_outer()
645 .unwrap();
646 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
647 }
648
649 #[test]
650 fn test_parse() {
651 let mut buf = &[0, 0, 1, 2, 0, 8, 0, 0][..];
653 let packet = buf
654 .parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
655 .unwrap();
656 assert!(packet.src_port().is_none());
657 assert_eq!(packet.dst_port().get(), NetworkEndian::read_u16(&[1, 2]));
658 assert!(!packet.checksummed());
659 assert!(packet.body().is_empty());
660
661 let mut buf = vec![0_u8, 0, 1, 2, 0, 0, 0xBF, 0x12];
663 buf.extend((0..core::u16::MAX).into_iter().map(|p| p as u8));
664 let bv = &mut &buf[..];
665 let packet = bv
666 .parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(TEST_SRC_IPV6, TEST_DST_IPV6))
667 .unwrap();
668 assert!(packet.src_port().is_none());
669 assert_eq!(packet.dst_port().get(), NetworkEndian::read_u16(&[1, 2]));
670 assert!(packet.checksummed());
671 assert_eq!(packet.body().len(), core::u16::MAX as usize);
672 }
673
674 #[test]
675 fn test_serialize() {
676 let mut buf = (&[])
677 .into_serializer()
678 .encapsulate(UdpPacketBuilder::new(
679 TEST_SRC_IPV4,
680 TEST_DST_IPV4,
681 NonZeroU16::new(1),
682 NonZeroU16::new(2).unwrap(),
683 ))
684 .serialize_vec_outer()
685 .unwrap();
686 assert_eq!(buf.as_ref(), [0, 1, 0, 2, 0, 8, 239, 199]);
687 let packet = buf
688 .parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
689 .unwrap();
690 assert_eq!(packet.src_port().unwrap().get(), 1);
693 assert_eq!(packet.dst_port().get(), 2);
694 assert!(packet.checksummed());
695 }
696
697 #[test]
698 fn test_serialize_zeroes() {
699 let mut buf_0 = [0; HEADER_BYTES];
702 let _: Buf<&mut [u8]> = Buf::new(&mut buf_0[..], HEADER_BYTES..)
703 .encapsulate(UdpPacketBuilder::new(
704 TEST_SRC_IPV4,
705 TEST_DST_IPV4,
706 NonZeroU16::new(1),
707 NonZeroU16::new(2).unwrap(),
708 ))
709 .serialize_vec_outer()
710 .unwrap()
711 .unwrap_a();
712 let mut buf_1 = [0xFF; HEADER_BYTES];
713 let _: Buf<&mut [u8]> = Buf::new(&mut buf_1[..], HEADER_BYTES..)
714 .encapsulate(UdpPacketBuilder::new(
715 TEST_SRC_IPV4,
716 TEST_DST_IPV4,
717 NonZeroU16::new(1),
718 NonZeroU16::new(2).unwrap(),
719 ))
720 .serialize_vec_outer()
721 .unwrap()
722 .unwrap_a();
723 assert_eq!(buf_0, buf_1);
724 }
725
726 #[test]
727 fn test_parse_error() {
728 fn test_zero<I: IpAddress>(
732 src: I,
733 dst: I,
734 succeeds: bool,
735 zero: &[usize],
736 err: ParseError,
737 ) {
738 let mut buf = [1, 2, 3, 4, 0, 8, 0, 0];
741 if succeeds {
742 let mut buf = &buf[..];
743 assert!(buf.parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(src, dst)).is_ok());
744 }
745 for idx in zero {
746 buf[*idx] = 0;
747 }
748 let mut buf = &buf[..];
749 assert_eq!(
750 buf.parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(src, dst)).unwrap_err(),
751 err
752 );
753 }
754
755 test_zero(TEST_SRC_IPV4, TEST_DST_IPV4, true, &[2, 3], ParseError::Format);
757 test_zero(TEST_SRC_IPV4, TEST_DST_IPV4, true, &[4, 5], ParseError::Format);
759 test_zero(TEST_SRC_IPV6, TEST_DST_IPV6, false, &[], ParseError::Format);
762
763 #[cfg(target_pointer_width = "64")]
765 {
766 let mut buf = vec![0u8; 1 << 32];
768 (&mut buf[..HEADER_BYTES]).copy_from_slice(&[0, 0, 1, 2, 0, 0, 0xFF, 0xE4]);
769 assert_eq!(
770 (&buf[..])
771 .parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(TEST_SRC_IPV6, TEST_DST_IPV6))
772 .unwrap_err(),
773 ParseError::Format
774 );
775 }
776 }
777
778 #[test]
779 #[should_panic(expected = "too few bytes for UDP header")]
780 fn test_serialize_fail_header_too_short() {
781 let mut buf = [0u8; 7];
782 let mut buf = [&mut buf[..]];
783 let buf = FragmentedBytesMut::new(&mut buf[..]);
784 let (header, body, footer) = buf.try_split_contiguous(..).unwrap();
785 let builder =
786 UdpPacketBuilder::new(TEST_SRC_IPV4, TEST_DST_IPV4, None, NonZeroU16::new(1).unwrap());
787 builder.serialize(&mut SerializeTarget { header, footer }, body);
788 }
789
790 #[test]
791 #[should_panic(expected = "total UDP packet length of 65536 bytes overflows 16-bit length \
792 field of UDP header")]
793 fn test_serialize_fail_packet_too_long_ipv4() {
794 let ser = (&[0; (1 << 16) - HEADER_BYTES][..]).into_serializer().encapsulate(
795 UdpPacketBuilder::new(TEST_SRC_IPV4, TEST_DST_IPV4, None, NonZeroU16::new(1).unwrap()),
796 );
797 let _ = ser.serialize_vec_outer();
798 }
799
800 #[test]
801 fn test_partial_parse() {
802 use core::ops::Deref as _;
803
804 let buf = [0, 0, 1, 2, 10, 20];
806 let mut bv = &buf[..];
807 let packet =
808 bv.parse_with::<_, UdpPacketRaw<_>>(IpVersionMarker::<Ipv4>::default()).unwrap();
809 let UdpPacketRaw { header, body } = &packet;
810 let PartialHeader { flow, rest } = header.as_ref().incomplete().unwrap();
811 assert_eq!(
812 flow.deref(),
813 &UdpFlowHeader { src_port: U16::new(0), dst_port: U16::new(0x0102) }
814 );
815 assert_eq!(*rest, &buf[4..]);
816 assert_eq!(body.incomplete().unwrap(), []);
817 assert!(UdpPacket::try_from_raw_with(
818 packet,
819 UdpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4)
820 )
821 .is_err());
822
823 let mut buf = &[0, 0, 1][..];
825 assert!(buf.parse_with::<_, UdpPacketRaw<_>>(IpVersionMarker::<Ipv4>::default()).is_err());
826
827 let buf = [0, 0, 1, 2, 0, 30, 0, 0, 10, 20];
829 let mut bv = &buf[..];
830 let packet =
831 bv.parse_with::<_, UdpPacketRaw<_>>(IpVersionMarker::<Ipv4>::default()).unwrap();
832 let UdpPacketRaw { header, body } = &packet;
833 assert_eq!(Ref::bytes(&header.as_ref().complete().unwrap()), &buf[..8]);
834 assert_eq!(body.incomplete().unwrap(), &buf[8..]);
835 assert!(UdpPacket::try_from_raw_with(
836 packet,
837 UdpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4)
838 )
839 .is_err());
840
841 let buf = [0, 0, 1, 2, 0, 6, 0, 0, 10, 20];
843 let mut bv = &buf[..];
844 let packet =
845 bv.parse_with::<_, UdpPacketRaw<_>>(IpVersionMarker::<Ipv4>::default()).unwrap();
846 let UdpPacketRaw { header, body } = &packet;
847 assert_eq!(Ref::bytes(&header.as_ref().complete().unwrap()), &buf[..8]);
848 assert_eq!(body.incomplete().unwrap(), []);
849 assert!(UdpPacket::try_from_raw_with(
850 packet,
851 UdpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4)
852 )
853 .is_err());
854
855 let buf = [0, 0, 1, 2, 0, 0, 0, 0, 10, 20];
859 let mut bv = &buf[..];
860 let packet =
861 bv.parse_with::<_, UdpPacketRaw<_>>(IpVersionMarker::<Ipv6>::default()).unwrap();
862 let UdpPacketRaw { header, body } = &packet;
863 assert_eq!(Ref::bytes(&header.as_ref().complete().unwrap()), &buf[..8]);
864 assert_eq!(body.incomplete().unwrap(), []);
865 let mut buf = vec![0, 0, 1, 2, 0, 0, 0, 0, 10, 20];
868 buf.extend((0..core::u16::MAX).into_iter().map(|x| x as u8));
869 let bv = &mut &buf[..];
870 let packet =
871 bv.parse_with::<_, UdpPacketRaw<_>>(IpVersionMarker::<Ipv6>::default()).unwrap();
872 let UdpPacketRaw { header, body } = &packet;
873 assert_eq!(Ref::bytes(header.as_ref().complete().unwrap()), &buf[..8]);
874 assert_eq!(body.complete().unwrap(), &buf[8..]);
875 }
876
877 #[test]
878 fn test_udp_checksum_0xffff() {
879 let builder = (&[0xff, 0xd9]).into_serializer().encapsulate(UdpPacketBuilder::new(
882 Ipv4Addr::new([0, 0, 0, 0]),
883 Ipv4Addr::new([0, 0, 0, 0]),
884 None,
885 NonZeroU16::new(1).unwrap(),
886 ));
887 let buf = builder.serialize_vec_outer().unwrap();
888 assert_eq!(buf.as_ref()[7], 0xFF);
893 assert_eq!(buf.as_ref()[8], 0xFF);
894
895 let mut c = internet_checksum::Checksum::new();
897 c.add_bytes(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 10]);
898 c.add_bytes(buf.as_ref());
899 assert!(c.checksum() == [0, 0]);
900 }
901
902 fn bench_parse_inner<B: Bencher>(b: &mut B) {
907 use crate::testdata::dns_request_v4::*;
908 let bytes = parse_ip_packet_in_ethernet_frame::<Ipv4>(
909 ETHERNET_FRAME.bytes,
910 EthernetFrameLengthCheck::Check,
911 )
912 .unwrap()
913 .0;
914
915 b.iter(|| {
916 let buf = bytes;
917 let _: UdpPacket<_> = black_box(
918 black_box(buf)
919 .parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(
920 IPV4_PACKET.metadata.src_ip,
921 IPV4_PACKET.metadata.dst_ip,
922 ))
923 .unwrap(),
924 );
925 })
926 }
927
928 bench!(bench_parse, bench_parse_inner);
929
930 fn bench_serialize_inner<B: Bencher>(b: &mut B) {
931 use crate::testdata::dns_request_v4::*;
932 let builder = UdpPacketBuilder::new(
933 IPV4_PACKET.metadata.src_ip,
934 IPV4_PACKET.metadata.dst_ip,
935 None,
936 NonZeroU16::new(UDP_PACKET.metadata.dst_port).unwrap(),
937 );
938 let header_len = builder.constraints().header_len();
939 let total_len = header_len + UDP_PACKET.bytes[UDP_PACKET.body_range].len();
940 let mut buf = vec![0; total_len];
941 buf[header_len..].copy_from_slice(&UDP_PACKET.bytes[UDP_PACKET.body_range]);
942
943 b.iter(|| {
944 let _: Buf<_> = black_box(
945 black_box(Buf::new(&mut buf[..], header_len..total_len).encapsulate(builder))
946 .serialize_no_alloc_outer(),
947 )
948 .unwrap();
949 })
950 }
951
952 bench!(bench_serialize, bench_serialize_inner);
953}