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 if old == new {
55 return; }
57
58 self.src_port = new;
59 if self.checksummed() {
60 self.checksum =
61 internet_checksum::update(self.checksum, old.as_bytes(), new.as_bytes());
62 sanitize_checksum(&mut self.checksum);
63 }
64 }
65
66 pub fn set_dst_port(&mut self, new: NonZeroU16) {
67 let old = self.dst_port;
68 let new = U16::from(new.get());
69 if old == new {
70 return; }
72
73 self.dst_port = new;
74 if self.checksummed() {
75 self.checksum =
76 internet_checksum::update(self.checksum, old.as_bytes(), new.as_bytes());
77 sanitize_checksum(&mut self.checksum);
78 }
79 }
80
81 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
82 if old == new {
83 return; }
85
86 if self.checksummed() {
87 self.checksum = internet_checksum::update(self.checksum, old.bytes(), new.bytes());
88 sanitize_checksum(&mut self.checksum);
89 }
90 }
91}
92
93pub struct UdpPacket<B> {
102 header: Ref<B, Header>,
103 body: B,
104}
105
106pub struct UdpParseArgs<A: IpAddress> {
108 src_ip: A,
109 dst_ip: A,
110}
111
112impl<A: IpAddress> UdpParseArgs<A> {
113 pub fn new(src_ip: A, dst_ip: A) -> UdpParseArgs<A> {
115 UdpParseArgs { src_ip, dst_ip }
116 }
117}
118
119impl<B: SplitByteSlice, A: IpAddress> FromRaw<UdpPacketRaw<B>, UdpParseArgs<A>> for UdpPacket<B> {
120 type Error = ParseError;
121
122 fn try_from_raw_with(raw: UdpPacketRaw<B>, args: UdpParseArgs<A>) -> Result<Self, Self::Error> {
123 let header = raw
125 .header
126 .ok_or_else(|_| debug_err!(ParseError::Format, "too few bytes for header"))?;
127 let body = raw.body.ok_or_else(|_| debug_err!(ParseError::Format, "incomplete body"))?;
128
129 let checksum = header.checksum;
130 if checksum != [0, 0] {
134 let parts = [Ref::bytes(&header), body.deref().as_ref()];
135 let checksum = compute_transport_checksum_parts(
136 args.src_ip,
137 args.dst_ip,
138 IpProto::Udp.into(),
139 parts.iter(),
140 )
141 .ok_or_else(debug_err_fn!(ParseError::Format, "packet too large"))?;
142
143 if checksum != [0, 0] {
151 return debug_err!(
152 Err(ParseError::Checksum),
153 "invalid checksum {:X?}",
154 header.checksum,
155 );
156 }
157 } else if A::Version::VERSION.is_v6() {
158 return debug_err!(Err(ParseError::Format), "missing checksum");
159 }
160
161 if header.dst_port.get() == 0 {
162 return debug_err!(Err(ParseError::Format), "zero destination port");
163 }
164
165 Ok(UdpPacket { header, body })
166 }
167}
168
169impl<B: SplitByteSlice, A: IpAddress> ParsablePacket<B, UdpParseArgs<A>> for UdpPacket<B> {
170 type Error = ParseError;
171
172 fn parse_metadata(&self) -> ParseMetadata {
173 ParseMetadata::from_packet(Ref::bytes(&self.header).len(), self.body.len(), 0)
174 }
175
176 fn parse<BV: BufferView<B>>(buffer: BV, args: UdpParseArgs<A>) -> ParseResult<Self> {
177 UdpPacketRaw::<B>::parse(buffer, IpVersionMarker::<A::Version>::default())
178 .and_then(|u| UdpPacket::try_from_raw_with(u, args))
179 }
180}
181
182impl<B: SplitByteSlice> UdpPacket<B> {
183 pub fn body(&self) -> &[u8] {
185 self.body.deref()
186 }
187
188 pub fn as_bytes(&self) -> [&[u8]; 2] {
190 [&Ref::bytes(&self.header), self.body.deref()]
191 }
192
193 pub fn into_body(self) -> B {
201 self.body
202 }
203
204 pub fn src_port(&self) -> Option<NonZeroU16> {
208 NonZeroU16::new(self.header.src_port.get())
209 }
210
211 pub fn dst_port(&self) -> NonZeroU16 {
213 NonZeroU16::new(self.header.dst_port.get()).unwrap()
215 }
216
217 pub fn checksummed(&self) -> bool {
227 self.header.checksummed()
228 }
229
230 pub fn builder<A: IpAddress>(&self, src_ip: A, dst_ip: A) -> UdpPacketBuilder<A> {
232 UdpPacketBuilder {
233 src_ip,
234 dst_ip,
235 src_port: self.src_port(),
236 dst_port: Some(self.dst_port()),
237 }
238 }
239
240 pub fn into_serializer<'a, A: IpAddress>(
254 self,
255 src_ip: A,
256 dst_ip: A,
257 ) -> impl Serializer<Buffer = EmptyBuf> + Debug + 'a
258 where
259 B: 'a,
260 {
261 self.builder(src_ip, dst_ip)
262 .wrap_body(ByteSliceInnerPacketBuilder(self.body).into_serializer())
263 }
264}
265
266impl<B: SplitByteSliceMut> UdpPacket<B> {
267 pub fn set_src_port(&mut self, new: u16) {
269 self.header.set_src_port(new)
270 }
271
272 pub fn set_dst_port(&mut self, new: NonZeroU16) {
274 self.header.set_dst_port(new);
275 }
276
277 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
279 self.header.update_checksum_pseudo_header_address(old, new);
280 }
281}
282
283impl<B: zerocopy::CloneableByteSlice + Clone> Clone for UdpPacket<B> {
284 fn clone(&self) -> Self {
285 UdpPacket { header: self.header.clone(), body: self.body.clone() }
286 }
287}
288
289#[derive(Debug, Default, KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq)]
294#[repr(C)]
295struct UdpFlowHeader {
296 src_port: U16,
297 dst_port: U16,
298}
299
300#[derive(Debug)]
302struct PartialHeader<B: SplitByteSlice> {
303 flow: Ref<B, UdpFlowHeader>,
304 rest: B,
305}
306
307pub struct UdpPacketRaw<B: SplitByteSlice> {
321 header: MaybeParsed<Ref<B, Header>, PartialHeader<B>>,
322 body: MaybeParsed<B, B>,
323}
324
325impl<B, I> ParsablePacket<B, IpVersionMarker<I>> for UdpPacketRaw<B>
326where
327 B: SplitByteSlice,
328 I: Ip,
329{
330 type Error = ParseError;
331
332 fn parse_metadata(&self) -> ParseMetadata {
333 let header_len = match &self.header {
334 MaybeParsed::Complete(h) => Ref::bytes(&h).len(),
335 MaybeParsed::Incomplete(h) => Ref::bytes(&h.flow).len() + h.rest.len(),
336 };
337 ParseMetadata::from_packet(header_len, self.body.len(), 0)
338 }
339
340 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: IpVersionMarker<I>) -> ParseResult<Self> {
341 let header = if let Some(header) = buffer.take_obj_front::<Header>() {
344 header
345 } else {
346 let flow = buffer
347 .take_obj_front::<UdpFlowHeader>()
348 .ok_or_else(debug_err_fn!(ParseError::Format, "too few bytes for flow header"))?;
349 return Ok(UdpPacketRaw {
352 header: MaybeParsed::Incomplete(PartialHeader {
353 flow,
354 rest: buffer.take_rest_front(),
355 }),
356 body: MaybeParsed::Incomplete(buffer.into_rest()),
357 });
358 };
359 let buffer_len = buffer.len();
360
361 fn get_udp_body_length<I: Ip>(header: &Header, remaining_buff_len: usize) -> Option<usize> {
362 if I::VERSION.is_v6()
370 && header.length.get() == 0
371 && remaining_buff_len.saturating_add(HEADER_BYTES) >= (core::u16::MAX as usize)
372 {
373 return Some(remaining_buff_len);
374 }
375
376 usize::from(header.length.get()).checked_sub(HEADER_BYTES)
377 }
378
379 let body = if let Some(body_len) = get_udp_body_length::<I>(&header, buffer_len) {
380 if body_len <= buffer_len {
381 let _: B = buffer.take_back(buffer_len - body_len).unwrap();
385 MaybeParsed::Complete(buffer.into_rest())
386 } else {
387 MaybeParsed::Incomplete(buffer.into_rest())
389 }
390 } else {
391 let _: B = buffer.take_rest_back();
395 MaybeParsed::Incomplete(buffer.into_rest())
396 };
397
398 Ok(UdpPacketRaw { header: MaybeParsed::Complete(header), body })
399 }
400}
401
402impl<B: SplitByteSlice> UdpPacketRaw<B> {
403 pub fn src_port(&self) -> Option<NonZeroU16> {
407 NonZeroU16::new(
408 self.header
409 .as_ref()
410 .map(|header| header.src_port)
411 .map_incomplete(|partial_header| partial_header.flow.src_port)
412 .into_inner()
413 .get(),
414 )
415 }
416
417 pub fn dst_port(&self) -> Option<NonZeroU16> {
422 NonZeroU16::new(
423 self.header
424 .as_ref()
425 .map(|header| header.dst_port)
426 .map_incomplete(|partial_header| partial_header.flow.dst_port)
427 .into_inner()
428 .get(),
429 )
430 }
431
432 pub fn builder<A: IpAddress>(&self, src_ip: A, dst_ip: A) -> UdpPacketBuilder<A> {
439 UdpPacketBuilder { src_ip, dst_ip, src_port: self.src_port(), dst_port: self.dst_port() }
440 }
441
442 pub fn into_serializer<'a, A: IpAddress>(
461 self,
462 src_ip: A,
463 dst_ip: A,
464 ) -> Option<impl Serializer<Buffer = EmptyBuf> + 'a>
465 where
466 B: 'a,
467 {
468 let builder = self.builder(src_ip, dst_ip);
469 self.body
470 .complete()
471 .ok()
472 .map(|body| builder.wrap_body(ByteSliceInnerPacketBuilder(body).into_serializer()))
473 }
474}
475
476impl<B: SplitByteSliceMut> UdpPacketRaw<B> {
477 pub fn set_src_port(&mut self, new: u16) {
479 match &mut self.header {
480 MaybeParsed::Complete(h) => h.set_src_port(new),
481 MaybeParsed::Incomplete(h) => {
482 h.flow.src_port = U16::from(new);
483
484 }
486 }
487 }
488
489 pub fn set_dst_port(&mut self, new: NonZeroU16) {
491 match &mut self.header {
492 MaybeParsed::Complete(h) => h.set_dst_port(new),
493 MaybeParsed::Incomplete(h) => {
494 h.flow.dst_port = U16::from(new.get());
495
496 }
498 }
499 }
500
501 pub fn update_checksum_pseudo_header_address<A: IpAddress>(&mut self, old: A, new: A) {
503 match &mut self.header {
504 MaybeParsed::Complete(h) => h.update_checksum_pseudo_header_address(old, new),
505 MaybeParsed::Incomplete(_) => {
506 }
508 }
509 }
510}
511
512#[derive(Copy, Clone, Debug, PartialEq)]
520pub struct UdpPacketBuilder<A: IpAddress> {
521 src_ip: A,
522 dst_ip: A,
523 src_port: Option<NonZeroU16>,
524 dst_port: Option<NonZeroU16>,
525}
526
527impl<A: IpAddress> UdpPacketBuilder<A> {
528 pub fn new(
530 src_ip: A,
531 dst_ip: A,
532 src_port: Option<NonZeroU16>,
533 dst_port: NonZeroU16,
534 ) -> UdpPacketBuilder<A> {
535 UdpPacketBuilder { src_ip, dst_ip, src_port, dst_port: Some(dst_port) }
536 }
537
538 pub fn src_port(&self) -> Option<NonZeroU16> {
540 self.src_port
541 }
542
543 pub fn dst_port(&self) -> Option<NonZeroU16> {
545 self.dst_port
546 }
547
548 pub fn set_src_ip(&mut self, addr: A) {
550 self.src_ip = addr;
551 }
552
553 pub fn set_dst_ip(&mut self, addr: A) {
555 self.dst_ip = addr;
556 }
557
558 pub fn set_src_port(&mut self, port: u16) {
560 self.src_port = NonZeroU16::new(port);
561 }
562
563 pub fn set_dst_port(&mut self, port: NonZeroU16) {
565 self.dst_port = Some(port);
566 }
567
568 fn serialize_header(&self, body_len: usize, mut buffer: &mut [u8]) {
569 let total_len = buffer.len() + body_len;
572
573 (&mut buffer)
579 .write_obj_front(&Header {
580 src_port: U16::new(self.src_port.map_or(0, NonZeroU16::get)),
581 dst_port: U16::new(self.dst_port.map_or(0, NonZeroU16::get)),
582 length: U16::new(total_len.try_into().unwrap_or_else(|_| {
583 if A::Version::VERSION.is_v6() {
584 0u16
586 } else {
587 panic!(
588 "total UDP packet length of {total_len} bytes \
589 overflows 16-bit length field of UDP header"
590 )
591 }
592 })),
593 checksum: [0, 0],
596 })
597 .expect("too few bytes for UDP header");
598 }
599}
600
601impl<A: IpAddress> PacketBuilder for UdpPacketBuilder<A> {
602 fn constraints(&self) -> PacketConstraints {
603 PacketConstraints::new(
604 HEADER_BYTES,
605 0,
606 0,
607 if A::Version::VERSION.is_v4() {
608 (1 << 16) - 1
609 } else {
610 core::usize::MAX
616 },
617 )
618 }
619
620 fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
621 self.serialize_header(body.len(), target.header);
622
623 let mut checksum = compute_transport_checksum_serialize(
624 self.src_ip,
625 self.dst_ip,
626 IpProto::Udp.into(),
627 target,
628 body,
629 )
630 .unwrap(); sanitize_checksum(&mut checksum);
633 target.header[CHECKSUM_RANGE].copy_from_slice(&checksum[..]);
634 }
635}
636
637impl<A: IpAddress> PartialPacketBuilder for UdpPacketBuilder<A> {
638 fn partial_serialize(&self, body_len: usize, buffer: &mut [u8]) {
639 self.serialize_header(body_len, buffer);
640 }
641}
642
643#[inline]
644fn sanitize_checksum(checksum_bytes: &mut [u8; 2]) {
645 if *checksum_bytes == [0, 0] {
649 *checksum_bytes = [0xFF, 0xFF];
650 }
651}
652
653#[cfg(test)]
655impl<B> Debug for UdpPacket<B> {
656 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
657 write!(fmt, "UdpPacket")
658 }
659}
660
661#[cfg(test)]
662mod tests {
663 use byteorder::{ByteOrder, NetworkEndian};
664 use net_types::ip::{Ipv4, Ipv4Addr, Ipv6, Ipv6Addr};
665 use packet::{Buf, ParseBuffer, ParseBufferMut};
666
667 use super::*;
668 use crate::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
669 use crate::ipv4::{Ipv4Header, Ipv4Packet};
670 use crate::ipv6::{Ipv6Header, Ipv6Packet};
671 use crate::testutil::*;
672
673 const TEST_SRC_IPV4: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
674 const TEST_DST_IPV4: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
675 const TEST_SRC_IPV6: Ipv6Addr =
676 Ipv6Addr::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
677 const TEST_DST_IPV6: Ipv6Addr =
678 Ipv6Addr::from_bytes([17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]);
679
680 #[test]
681 fn test_parse_serialize_full_ipv4() {
682 use crate::testdata::dns_request_v4::*;
683
684 let mut buf = ETHERNET_FRAME.bytes;
685 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
686 verify_ethernet_frame(&frame, ETHERNET_FRAME);
687
688 let mut body = frame.body();
689 let ip_packet = body.parse::<Ipv4Packet<_>>().unwrap();
690 verify_ipv4_packet(&ip_packet, IPV4_PACKET);
691
692 let mut body = ip_packet.body();
693 let udp_packet = body
694 .parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(
695 ip_packet.src_ip(),
696 ip_packet.dst_ip(),
697 ))
698 .unwrap();
699 verify_udp_packet(&udp_packet, UDP_PACKET);
700
701 let buffer = udp_packet
702 .body()
703 .into_serializer()
704 .wrap_in(udp_packet.builder(ip_packet.src_ip(), ip_packet.dst_ip()))
705 .wrap_in(ip_packet.builder())
706 .wrap_in(frame.builder())
707 .serialize_vec_outer()
708 .unwrap();
709 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
710 }
711
712 #[test]
713 fn test_parse_serialize_full_ipv6() {
714 use crate::testdata::dns_request_v6::*;
715
716 let mut buf = ETHERNET_FRAME.bytes;
717 let frame = buf.parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check).unwrap();
718 verify_ethernet_frame(&frame, ETHERNET_FRAME);
719
720 let mut body = frame.body();
721 let ip_packet = body.parse::<Ipv6Packet<_>>().unwrap();
722 verify_ipv6_packet(&ip_packet, IPV6_PACKET);
723
724 let mut body = ip_packet.body();
725 let udp_packet = body
726 .parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(
727 ip_packet.src_ip(),
728 ip_packet.dst_ip(),
729 ))
730 .unwrap();
731 verify_udp_packet(&udp_packet, UDP_PACKET);
732
733 let buffer = udp_packet
734 .body()
735 .into_serializer()
736 .wrap_in(udp_packet.builder(ip_packet.src_ip(), ip_packet.dst_ip()))
737 .wrap_in(ip_packet.builder())
738 .wrap_in(frame.builder())
739 .serialize_vec_outer()
740 .unwrap();
741 assert_eq!(buffer.as_ref(), ETHERNET_FRAME.bytes);
742 }
743
744 #[test]
745 fn test_parse() {
746 let mut buf = &[0, 0, 1, 2, 0, 8, 0, 0][..];
748 let packet = buf
749 .parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
750 .unwrap();
751 assert!(packet.src_port().is_none());
752 assert_eq!(packet.dst_port().get(), NetworkEndian::read_u16(&[1, 2]));
753 assert!(!packet.checksummed());
754 assert!(packet.body().is_empty());
755
756 let mut buf = vec![0_u8, 0, 1, 2, 0, 0, 0xBF, 0x12];
758 buf.extend((0..core::u16::MAX).into_iter().map(|p| p as u8));
759 let bv = &mut &buf[..];
760 let packet = bv
761 .parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(TEST_SRC_IPV6, TEST_DST_IPV6))
762 .unwrap();
763 assert!(packet.src_port().is_none());
764 assert_eq!(packet.dst_port().get(), NetworkEndian::read_u16(&[1, 2]));
765 assert!(packet.checksummed());
766 assert_eq!(packet.body().len(), core::u16::MAX as usize);
767 }
768
769 fn new_test_udp_builder() -> UdpPacketBuilder<Ipv4Addr> {
770 UdpPacketBuilder::new(
771 TEST_SRC_IPV4,
772 TEST_DST_IPV4,
773 NonZeroU16::new(1),
774 NonZeroU16::new(2).unwrap(),
775 )
776 }
777
778 #[test]
779 fn test_serialize() {
780 let mut buf = new_test_udp_builder().wrap_body(EmptyBuf).serialize_vec_outer().unwrap();
781 assert_eq!(buf.as_ref(), [0, 1, 0, 2, 0, 8, 239, 199]);
782 let packet = buf
783 .parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
784 .unwrap();
785 assert_eq!(packet.src_port().unwrap().get(), 1);
788 assert_eq!(packet.dst_port().get(), 2);
789 assert!(packet.checksummed());
790 }
791
792 #[test]
793 fn test_serialize_zeroes() {
794 let mut buf_0 = [0; HEADER_BYTES];
797 let _: Buf<&mut [u8]> = new_test_udp_builder()
798 .wrap_body(Buf::new(&mut buf_0[..], HEADER_BYTES..))
799 .serialize_vec_outer()
800 .unwrap()
801 .unwrap_a();
802 let mut buf_1 = [0xFF; HEADER_BYTES];
803 let _: Buf<&mut [u8]> = new_test_udp_builder()
804 .wrap_body(Buf::new(&mut buf_1[..], HEADER_BYTES..))
805 .serialize_vec_outer()
806 .unwrap()
807 .unwrap_a();
808 assert_eq!(buf_0, buf_1);
809 }
810
811 #[test]
812 fn test_parse_error() {
813 fn test_zero<I: IpAddress>(
817 src: I,
818 dst: I,
819 succeeds: bool,
820 zero: &[usize],
821 err: ParseError,
822 ) {
823 let mut buf = [1, 2, 3, 4, 0, 8, 0, 0];
826 if succeeds {
827 let mut buf = &buf[..];
828 assert!(buf.parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(src, dst)).is_ok());
829 }
830 for idx in zero {
831 buf[*idx] = 0;
832 }
833 let mut buf = &buf[..];
834 assert_eq!(
835 buf.parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(src, dst)).unwrap_err(),
836 err
837 );
838 }
839
840 test_zero(TEST_SRC_IPV4, TEST_DST_IPV4, true, &[2, 3], ParseError::Format);
842 test_zero(TEST_SRC_IPV4, TEST_DST_IPV4, true, &[4, 5], ParseError::Format);
844 test_zero(TEST_SRC_IPV6, TEST_DST_IPV6, false, &[], ParseError::Format);
847
848 #[cfg(target_pointer_width = "64")]
850 {
851 let mut buf = vec![0u8; 1 << 32];
853 (&mut buf[..HEADER_BYTES]).copy_from_slice(&[0, 0, 1, 2, 0, 0, 0xFF, 0xE4]);
854 assert_eq!(
855 (&buf[..])
856 .parse_with::<_, UdpPacket<_>>(UdpParseArgs::new(TEST_SRC_IPV6, TEST_DST_IPV6))
857 .unwrap_err(),
858 ParseError::Format
859 );
860 }
861 }
862
863 #[test]
864 #[should_panic(expected = "too few bytes for UDP header")]
865 fn test_serialize_fail_header_too_short() {
866 let mut buf = [0u8; 7];
867 let mut buf = [&mut buf[..]];
868 let buf = FragmentedBytesMut::new(&mut buf[..]);
869 let (header, body, footer) = buf.try_split_contiguous(..).unwrap();
870 let builder =
871 UdpPacketBuilder::new(TEST_SRC_IPV4, TEST_DST_IPV4, None, NonZeroU16::new(1).unwrap());
872 builder.serialize(&mut SerializeTarget { header, footer }, body);
873 }
874
875 #[test]
876 #[should_panic(expected = "total UDP packet length of 65536 bytes overflows 16-bit length \
877 field of UDP header")]
878 fn test_serialize_fail_packet_too_long_ipv4() {
879 let ser =
880 UdpPacketBuilder::new(TEST_SRC_IPV4, TEST_DST_IPV4, None, NonZeroU16::new(1).unwrap())
881 .wrap_body((&[0; (1 << 16) - HEADER_BYTES][..]).into_serializer());
882 let _ = ser.serialize_vec_outer();
883 }
884
885 #[test]
886 fn test_partial_parse() {
887 use core::ops::Deref as _;
888
889 let buf = [0, 0, 1, 2, 10, 20];
891 let mut bv = &buf[..];
892 let packet =
893 bv.parse_with::<_, UdpPacketRaw<_>>(IpVersionMarker::<Ipv4>::default()).unwrap();
894 let UdpPacketRaw { header, body } = &packet;
895 let PartialHeader { flow, rest } = header.as_ref().incomplete().unwrap();
896 assert_eq!(
897 flow.deref(),
898 &UdpFlowHeader { src_port: U16::new(0), dst_port: U16::new(0x0102) }
899 );
900 assert_eq!(*rest, &buf[4..]);
901 assert_eq!(body.incomplete().unwrap(), []);
902 assert!(
903 UdpPacket::try_from_raw_with(packet, UdpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
904 .is_err()
905 );
906
907 let mut buf = &[0, 0, 1][..];
909 assert!(buf.parse_with::<_, UdpPacketRaw<_>>(IpVersionMarker::<Ipv4>::default()).is_err());
910
911 let buf = [0, 0, 1, 2, 0, 30, 0, 0, 10, 20];
913 let mut bv = &buf[..];
914 let packet =
915 bv.parse_with::<_, UdpPacketRaw<_>>(IpVersionMarker::<Ipv4>::default()).unwrap();
916 let UdpPacketRaw { header, body } = &packet;
917 assert_eq!(Ref::bytes(&header.as_ref().complete().unwrap()), &buf[..8]);
918 assert_eq!(body.incomplete().unwrap(), &buf[8..]);
919 assert!(
920 UdpPacket::try_from_raw_with(packet, UdpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
921 .is_err()
922 );
923
924 let buf = [0, 0, 1, 2, 0, 6, 0, 0, 10, 20];
926 let mut bv = &buf[..];
927 let packet =
928 bv.parse_with::<_, UdpPacketRaw<_>>(IpVersionMarker::<Ipv4>::default()).unwrap();
929 let UdpPacketRaw { header, body } = &packet;
930 assert_eq!(Ref::bytes(&header.as_ref().complete().unwrap()), &buf[..8]);
931 assert_eq!(body.incomplete().unwrap(), []);
932 assert!(
933 UdpPacket::try_from_raw_with(packet, UdpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
934 .is_err()
935 );
936
937 let buf = [0, 0, 1, 2, 0, 0, 0, 0, 10, 20];
941 let mut bv = &buf[..];
942 let packet =
943 bv.parse_with::<_, UdpPacketRaw<_>>(IpVersionMarker::<Ipv6>::default()).unwrap();
944 let UdpPacketRaw { header, body } = &packet;
945 assert_eq!(Ref::bytes(&header.as_ref().complete().unwrap()), &buf[..8]);
946 assert_eq!(body.incomplete().unwrap(), []);
947 let mut buf = vec![0, 0, 1, 2, 0, 0, 0, 0, 10, 20];
950 buf.extend((0..core::u16::MAX).into_iter().map(|x| x as u8));
951 let bv = &mut &buf[..];
952 let packet =
953 bv.parse_with::<_, UdpPacketRaw<_>>(IpVersionMarker::<Ipv6>::default()).unwrap();
954 let UdpPacketRaw { header, body } = &packet;
955 assert_eq!(Ref::bytes(header.as_ref().complete().unwrap()), &buf[..8]);
956 assert_eq!(body.complete().unwrap(), &buf[8..]);
957 }
958
959 #[test]
960 fn test_udp_checksum_0xffff() {
961 let serializer = UdpPacketBuilder::new(
963 Ipv4Addr::new([0, 0, 0, 0]),
964 Ipv4Addr::new([0, 0, 0, 0]),
965 None,
966 NonZeroU16::new(1).unwrap(),
967 )
968 .wrap_body((&[0xff, 0xd9]).into_serializer());
969 let buf = serializer.serialize_vec_outer().unwrap();
970 assert_eq!(buf.as_ref()[7], 0xFF);
975 assert_eq!(buf.as_ref()[8], 0xFF);
976
977 let mut c = internet_checksum::Checksum::new();
979 c.add_bytes(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 10]);
980 c.add_bytes(buf.as_ref());
981 assert!(c.checksum() == [0, 0]);
982 }
983
984 #[test]
985 fn test_udp_checksum_partial_update_0xffff() {
986 const DST_PORT: NonZeroU16 = NonZeroU16::new(1).unwrap();
987 const ADDR: Ipv4Addr = Ipv4::UNSPECIFIED_ADDRESS;
988 let serializer = UdpPacketBuilder::new(ADDR, ADDR, None, DST_PORT)
989 .wrap_body((&[0xff, 0xd9]).into_serializer());
990 let mut buf = serializer.serialize_vec_outer().unwrap();
991 let mut packet = buf
992 .parse_with_mut::<_, UdpPacket<_>>(UdpParseArgs::new(ADDR, ADDR))
993 .expect("parse should succeed");
994 assert_eq!(packet.header.checksum, [0xFF, 0xFF]);
995
996 packet.set_src_port(0); assert_eq!(packet.header.checksum, [0xFF, 0xFF]);
999 packet.set_src_port(1234);
1000 assert_ne!(packet.header.checksum, [0xFF, 0xFF]);
1001 packet.set_src_port(0); assert_eq!(packet.header.checksum, [0xFF, 0xFF]);
1003
1004 packet.set_dst_port(DST_PORT); assert_eq!(packet.header.checksum, [0xFF, 0xFF]);
1007 packet.set_dst_port(NonZeroU16::new(1234).unwrap());
1008 assert_ne!(packet.header.checksum, [0xFF, 0xFF]);
1009 packet.set_dst_port(DST_PORT); assert_eq!(packet.header.checksum, [0xFF, 0xFF]);
1011
1012 packet.update_checksum_pseudo_header_address(ADDR, ADDR); assert_eq!(packet.header.checksum, [0xFF, 0xFF]);
1015 const OTHER_ADDR: Ipv4Addr = Ipv4Addr::new([123, 124, 125, 126]);
1016 packet.update_checksum_pseudo_header_address(ADDR, OTHER_ADDR);
1017 assert_ne!(packet.header.checksum, [0xFF, 0xFF]);
1018 packet.update_checksum_pseudo_header_address(OTHER_ADDR, ADDR); assert_eq!(packet.header.checksum, [0xFF, 0xFF]);
1020 }
1021}