packet_formats/
udp.rs

1// Copyright 2018 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Parsing and serialization of UDP packets.
6//!
7//! The UDP packet format is defined in [RFC 768].
8//!
9//! [RFC 768]: https://datatracker.ietf.org/doc/html/rfc768
10
11use 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
32/// The size of a UDP header in bytes.
33pub 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; // Short-circuit to skip checksum work.
56        }
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; // Short-circuit to skip checksum work.
71        }
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; // Short-circuit to skip checksum work.
84        }
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
93/// A UDP packet.
94///
95/// A `UdpPacket` shares its underlying memory with the byte slice it was parsed
96/// from or serialized to, meaning that no copying or extra allocation is
97/// necessary.
98///
99/// A `UdpPacket` - whether parsed using `parse` or created using `serialize` -
100/// maintains the invariant that the checksum is always valid.
101pub struct UdpPacket<B> {
102    header: Ref<B, Header>,
103    body: B,
104}
105
106/// Arguments required to parse a UDP packet.
107pub struct UdpParseArgs<A: IpAddress> {
108    src_ip: A,
109    dst_ip: A,
110}
111
112impl<A: IpAddress> UdpParseArgs<A> {
113    /// Construct a new `UdpParseArgs`.
114    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        // See for details: https://en.wikipedia.org/wiki/User_Datagram_Protocol#Packet_structure
124        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        // A 0 checksum indicates that the checksum wasn't computed. In IPv4,
131        // this means that it shouldn't be validated. In IPv6, the checksum is
132        // mandatory, so this is an error.
133        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            // Even the checksum is transmitted as 0xFFFF, the checksum of the whole
144            // UDP packet should still be 0. This is because in 1's complement, it is
145            // not possible to produce +0(0) from adding non-zero 16-bit words.
146            // Since our 0xFFFF ensures there is at least one non-zero 16-bit word,
147            // the addition can only produce -0(0xFFFF) and after negation, it is
148            // still 0. A test `test_udp_checksum_0xffff` is included to make sure
149            // this is true.
150            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    /// The packet body.
184    pub fn body(&self) -> &[u8] {
185        self.body.deref()
186    }
187
188    /// Returns the contents of the packet as a pair of slices.
189    pub fn as_bytes(&self) -> [&[u8]; 2] {
190        [&Ref::bytes(&self.header), self.body.deref()]
191    }
192
193    /// Consumes this packet and returns the body.
194    ///
195    /// Note that the returned `B` has the same lifetime as the buffer from
196    /// which this packet was parsed. By contrast, the [`body`] method returns a
197    /// slice with the same lifetime as the receiver.
198    ///
199    /// [`body`]: UdpPacket::body
200    pub fn into_body(self) -> B {
201        self.body
202    }
203
204    /// The source UDP port, if any.
205    ///
206    /// The source port is optional, and may have been omitted by the sender.
207    pub fn src_port(&self) -> Option<NonZeroU16> {
208        NonZeroU16::new(self.header.src_port.get())
209    }
210
211    /// The destination UDP port.
212    pub fn dst_port(&self) -> NonZeroU16 {
213        // Infallible because it was validated in parse.
214        NonZeroU16::new(self.header.dst_port.get()).unwrap()
215    }
216
217    /// Did this packet have a checksum?
218    ///
219    /// On IPv4, the sender may optionally omit the checksum. If this function
220    /// returns false, the sender omitted the checksum, and `parse` will not
221    /// have validated it.
222    ///
223    /// On IPv6, it is guaranteed that `checksummed` will return true because
224    /// IPv6 requires a checksum, and so any UDP packet missing one will fail
225    /// validation in `parse`.
226    pub fn checksummed(&self) -> bool {
227        self.header.checksummed()
228    }
229
230    /// Constructs a builder with the same contents as this packet.
231    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    /// Consumes this packet and constructs a [`Serializer`] with the same
241    /// contents.
242    ///
243    /// The returned `Serializer` has the [`Buffer`] type [`EmptyBuf`], which
244    /// means it is not able to reuse the buffer backing this `UdpPacket` when
245    /// serializing, and will always need to allocate a new buffer.
246    ///
247    /// By consuming `self` instead of taking it by-reference, `into_serializer`
248    /// is able to return a `Serializer` whose lifetime is restricted by the
249    /// lifetime of the buffer from which this `UdpPacket` was parsed rather
250    /// than by the lifetime on `&self`, which may be more restricted.
251    ///
252    /// [`Buffer`]: packet::Serializer::Buffer
253    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    /// Set the source port of the UDP packet.
268    pub fn set_src_port(&mut self, new: u16) {
269        self.header.set_src_port(new)
270    }
271
272    /// Set the destination port of the UDP packet.
273    pub fn set_dst_port(&mut self, new: NonZeroU16) {
274        self.header.set_dst_port(new);
275    }
276
277    /// Update the checksum to reflect an updated address in the pseudo header.
278    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/// The minimal information required from a UDP packet header.
290///
291/// A `UdpPacketHeader` may be the result of a partially parsed UDP packet in
292/// [`UdpPacketRaw`].
293#[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/// A partially parsed UDP packet header.
301#[derive(Debug)]
302struct PartialHeader<B: SplitByteSlice> {
303    flow: Ref<B, UdpFlowHeader>,
304    rest: B,
305}
306
307/// A partially-parsed and not yet validated UDP packet.
308///
309/// A `UdpPacketRaw` shares its underlying memory with the byte slice it was
310/// parsed from or serialized to, meaning that no copying or extra allocation is
311/// necessary.
312///
313/// Parsing a `UdpPacketRaw` from raw data will succeed as long as at least 4
314/// bytes are available, which will be extracted as a [`UdpFlowHeader`] that
315/// contains the UDP source and destination ports. A `UdpPacketRaw` is, then,
316/// guaranteed to always have at least that minimal information available.
317///
318/// [`UdpPacket`] provides a [`FromRaw`] implementation that can be used to
319/// validate a `UdpPacketRaw`.
320pub 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        // See for details: https://en.wikipedia.org/wiki/User_Datagram_Protocol#Packet_structure
342
343        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            // if we can't parse an entire header, just return early since
350            // there's no way to look into how many body bytes to consume:
351            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            // IPv6 supports jumbograms, so a UDP packet may be greater than
363            // 2^16 bytes in size. In this case, the size doesn't fit in the
364            // 16-bit length field in the header, and so the length field is set
365            // to zero to indicate this.
366            //
367            // Per RFC 2675 Section 4, we only do that if the UDP header plus
368            // data is actually more than 65535.
369            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                // Discard any padding left by the previous layer. The unwrap is safe
382                // and the subtraction is always valid because body_len is guaranteed
383                // to not exceed buffer.len()
384                let _: B = buffer.take_back(buffer_len - body_len).unwrap();
385                MaybeParsed::Complete(buffer.into_rest())
386            } else {
387                // buffer does not contain all the body bytes
388                MaybeParsed::Incomplete(buffer.into_rest())
389            }
390        } else {
391            // body_len can't be calculated because it's less than the header
392            // length, consider all the rest of the buffer padding and return
393            // an incomplete empty body.
394            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    /// The source UDP port, if any.
404    ///
405    /// The source port is optional, and may have been omitted by the sender.
406    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    /// The destination UDP port.
418    ///
419    /// UDP packets must not have a destination port of 0; thus, if this
420    /// function returns `None`, then the packet is malformed.
421    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    /// Constructs a builder with the same contents as this packet.
433    ///
434    /// Note that, since `UdpPacketRaw` does not validate its header fields,
435    /// it's possible for `builder` to produce a `UdpPacketBuilder` which
436    /// describes an invalid UDP packet. In particular, it's possible that its
437    /// destination port will be zero, which is illegal.
438    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    /// Consumes this packet and constructs a [`Serializer`] with the same
443    /// contents.
444    ///
445    /// Returns `None` if the body was not fully parsed.
446    ///
447    /// This method has the same validity caveats as [`builder`].
448    ///
449    /// The returned `Serializer` has the [`Buffer`] type [`EmptyBuf`], which
450    /// means it is not able to reuse the buffer backing this `UdpPacket` when
451    /// serializing, and will always need to allocate a new buffer.
452    ///
453    /// By consuming `self` instead of taking it by-reference, `into_serializer`
454    /// is able to return a `Serializer` whose lifetime is restricted by the
455    /// lifetime of the buffer from which this `UdpPacket` was parsed rather
456    /// than by the lifetime on `&self`, which may be more restricted.
457    ///
458    /// [`builder`]: UdpPacketRaw::builder
459    /// [`Buffer`]: packet::Serializer::Buffer
460    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    /// Set the source port of the UDP packet.
478    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                // We don't have the checksum, so there's nothing to update.
485            }
486        }
487    }
488
489    /// Set the destination port of the UDP packet.
490    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                // We don't have the checksum, so there's nothing to update.
497            }
498        }
499    }
500
501    /// Update the checksum to reflect an updated address in the pseudo header.
502    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                // We don't have the checksum, so there's nothing to update.
507            }
508        }
509    }
510}
511
512// NOTE(joshlf): In order to ensure that the checksum is always valid, we don't
513// expose any setters for the fields of the UDP packet; the only way to set them
514// is via UdpPacketBuilder::serialize. This, combined with checksum validation
515// performed in UdpPacket::parse, provides the invariant that a UdpPacket always
516// has a valid checksum.
517
518/// A builder for UDP packets.
519#[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    /// Constructs a new `UdpPacketBuilder`.
529    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    /// Returns the source port for the builder.
539    pub fn src_port(&self) -> Option<NonZeroU16> {
540        self.src_port
541    }
542
543    /// Returns the destination port for the builder.
544    pub fn dst_port(&self) -> Option<NonZeroU16> {
545        self.dst_port
546    }
547
548    /// Sets the source IP address for the builder.
549    pub fn set_src_ip(&mut self, addr: A) {
550        self.src_ip = addr;
551    }
552
553    /// Sets the destination IP address for the builder.
554    pub fn set_dst_ip(&mut self, addr: A) {
555        self.dst_ip = addr;
556    }
557
558    /// Sets the source port for the builder.
559    pub fn set_src_port(&mut self, port: u16) {
560        self.src_port = NonZeroU16::new(port);
561    }
562
563    /// Sets the destination port for the builder.
564    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        // See for details: https://en.wikipedia.org/wiki/User_Datagram_Protocol#Packet_structure
570
571        let total_len = buffer.len() + body_len;
572
573        // `write_obj_front` consumes the extent of the receiving slice, but
574        // that behavior is undesirable here: at the end of this method, we
575        // write the checksum back into the header. To avoid this, we re-slice
576        // header before calling `write_obj_front`; the re-slice will be
577        // consumed, but `target.header` is unaffected.
578        (&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                        // See comment in `constraints()`.
585                        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                // Initialize the checksum to 0 so that we will get the correct
594                // value when we compute it below.
595                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                // IPv6 supports jumbograms, so a UDP packet may be greater than
611                // 2^16 bytes. In this case, the size doesn't fit in the 16-bit
612                // length field in the header, and so the length field is set to
613                // zero. That means that, from this packet's perspective,
614                // there's no effective limit on the body size.
615                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(); // Not expected to fail since we were able to serialize the packet.
631
632        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    // As Per RFC 768:
646    //   If the computed checksum is zero, it is transmitted as all ones
647    //   (the equivalent in one's complement arithmetic).
648    if *checksum_bytes == [0, 0] {
649        *checksum_bytes = [0xFF, 0xFF];
650    }
651}
652
653// needed by Result::unwrap_err in the tests below
654#[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        // source port of 0 (meaning none) is allowed, as is a missing checksum
747        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        // length of 0 is allowed in IPv6 if the body is long enough
757        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 that when we parse those bytes, we get the values we set in
786        // the builder
787        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        // Test that UdpPacket::serialize properly zeroes memory before serializing
795        // the header.
796        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        // Test that while a given byte pattern optionally succeeds, zeroing out
814        // certain bytes causes failure. `zero` is a list of byte indices to
815        // zero out that should cause failure.
816        fn test_zero<I: IpAddress>(
817            src: I,
818            dst: I,
819            succeeds: bool,
820            zero: &[usize],
821            err: ParseError,
822        ) {
823            // Set checksum to zero so that, in IPV4, it will be ignored. In
824            // IPv6, this /is/ the test.
825            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        // destination port of 0 is disallowed
841        test_zero(TEST_SRC_IPV4, TEST_DST_IPV4, true, &[2, 3], ParseError::Format);
842        // length of 0 is disallowed in IPv4
843        test_zero(TEST_SRC_IPV4, TEST_DST_IPV4, true, &[4, 5], ParseError::Format);
844        // missing checksum is disallowed in IPv6; this won't succeed ahead of
845        // time because the checksum bytes are already zero
846        test_zero(TEST_SRC_IPV6, TEST_DST_IPV6, false, &[], ParseError::Format);
847
848        // 2^32 overflows on 32-bit platforms
849        #[cfg(target_pointer_width = "64")]
850        {
851            // total length of 2^32 or greater is disallowed in IPv6
852            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        // Try to get something with only the flow header:
890        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        // check that we fail if flow header is not retrievable:
908        let mut buf = &[0, 0, 1][..];
909        assert!(buf.parse_with::<_, UdpPacketRaw<_>>(IpVersionMarker::<Ipv4>::default()).is_err());
910
911        // Get an incomplete body:
912        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        // Incomplete empty body if total length in header is less than 8:
925        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        // IPv6 allows zero-length body, which will just be the rest of the
938        // buffer, but only as long as it has more than 65535 bytes, otherwise
939        // it'll just be interpreted as an invalid length:
940        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        // Now try same thing but with a body that's actually big enough to
948        // justify len being 0.
949        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        // Test the behavior when a UDP packet has to flip its checksum field.
962        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        // The serializer has flipped the bits for us.
971        // Normally, 0xFFFF can't be checksum because -0
972        // can not be produced by adding non-negtive 16-bit
973        // words
974        assert_eq!(buf.as_ref()[7], 0xFF);
975        assert_eq!(buf.as_ref()[8], 0xFF);
976
977        // When validating the checksum, just add'em up.
978        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        // Verify 0x0000 is set to 0xFFFF when updating the source port.
997        packet.set_src_port(0); // No-Op.
998        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); // Real Change.
1002        assert_eq!(packet.header.checksum, [0xFF, 0xFF]);
1003
1004        // Verify 0x0000 is set to 0xFFFF when updating the destination port.
1005        packet.set_dst_port(DST_PORT); // No-Op.
1006        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); // Real Change.
1010        assert_eq!(packet.header.checksum, [0xFF, 0xFF]);
1011
1012        // Verify 0x0000 is set to 0xFFFF when updating the pseudo header addr.
1013        packet.update_checksum_pseudo_header_address(ADDR, ADDR); // No-Op.
1014        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); // Real Change.
1019        assert_eq!(packet.header.checksum, [0xFF, 0xFF]);
1020    }
1021}