pkts/layers/
sctp.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2//
3// Copyright (c) 2024 Nathaniel Bennett <me[at]nathanielbennett[dotcom]>
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11//! The Stream Control Transmission Protocol (SCTP) and related data structures.
12//!
13//!
14
15use core::cmp;
16#[cfg(feature = "alloc")]
17use core::convert::TryFrom;
18#[cfg(feature = "alloc")]
19use core::iter::FromIterator;
20use core::iter::Iterator;
21#[cfg(feature = "alloc")]
22use core::{mem, slice};
23
24use crate::layers::dev_traits::*;
25use crate::layers::traits::*;
26use crate::layers::*;
27use crate::utils;
28use crate::writer::PacketWritable;
29
30use bitflags::bitflags;
31
32#[cfg(feature = "alloc")]
33use pkts_macros::Layer;
34use pkts_macros::{LayerRef, StatelessLayer};
35
36#[cfg(all(not(feature = "std"), feature = "alloc"))]
37use alloc::boxed::Box;
38#[cfg(all(not(feature = "std"), feature = "alloc"))]
39use alloc::vec::Vec;
40
41// Chunk Types
42const CHUNK_TYPE_DATA: u8 = 0;
43const CHUNK_TYPE_INIT: u8 = 1;
44const CHUNK_TYPE_INIT_ACK: u8 = 2;
45const CHUNK_TYPE_SACK: u8 = 3;
46const CHUNK_TYPE_HEARTBEAT: u8 = 4;
47const CHUNK_TYPE_HEARTBEAT_ACK: u8 = 5;
48const CHUNK_TYPE_ABORT: u8 = 6;
49const CHUNK_TYPE_SHUTDOWN: u8 = 7;
50const CHUNK_TYPE_SHUTDOWN_ACK: u8 = 8;
51const CHUNK_TYPE_ERROR: u8 = 9;
52const CHUNK_TYPE_COOKIE_ECHO: u8 = 10;
53const CHUNK_TYPE_COOKIE_ACK: u8 = 11;
54const CHUNK_TYPE_SHUTDOWN_COMPLETE: u8 = 14;
55
56// INIT Chunk Options
57const INIT_OPT_IPV4_ADDRESS: u16 = 5;
58const INIT_OPT_IPV6_ADDRESS: u16 = 6;
59const INIT_OPT_COOKIE_PRESERVATIVE: u16 = 9;
60const INIT_OPT_HOSTNAME_ADDR: u16 = 11;
61const INIT_OPT_SUPP_ADDR_TYPES: u16 = 12;
62
63// INIT ACK Chunk Options
64const INIT_ACK_OPT_STATE_COOKIE: u16 = 7;
65const INIT_ACK_OPT_IPV4_ADDRESS: u16 = 5;
66const INIT_ACK_OPT_IPV6_ADDRESS: u16 = 6;
67const INIT_ACK_OPT_UNRECOGNIZED_PARAM: u16 = 8;
68const INIT_ACK_OPT_HOSTNAME_ADDR: u16 = 11;
69
70// ERROR/ABORT Chunk Options
71const ERR_CODE_INVALID_STREAM_ID: u16 = 1;
72const ERR_CODE_MISSING_MAND_PARAM: u16 = 2;
73const ERR_CODE_STALE_COOKIE: u16 = 3;
74const ERR_CODE_OUT_OF_RESOURCE: u16 = 4;
75const ERR_CODE_UNRESOLVABLE_ADDRESS: u16 = 5;
76const ERR_CODE_UNRECOGNIZED_CHUNK: u16 = 6;
77const ERR_CODE_INVALID_MAND_PARAM: u16 = 7;
78const ERR_CODE_UNRECOGNIZED_PARAMS: u16 = 8;
79const ERR_CODE_NO_USER_DATA: u16 = 9;
80const ERR_CODE_COOKIE_RCVD_SHUTTING_DOWN: u16 = 10;
81const ERR_CODE_RESTART_ASSOC_NEW_ADDR: u16 = 11;
82const ERR_CODE_USER_INITIATED_ABORT: u16 = 12;
83const ERR_CODE_PROTOCOL_VIOLATION: u16 = 13;
84
85/// An SCTP (Stream Control Transmission Protocol) packet.
86///
87/// ## Packet Layout
88/// ```txt
89///    .    Octet 0    .    Octet 1    .    Octet 2    .    Octet 3    .
90///    |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
91///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
92///  0 |          Source Port          |        Destination Port       |
93///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
94///  4 |                        Verification Tag                       |
95///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
96///  8 |                            Checksum                           |
97///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
98/// 12 Z                             Chunks                            Z
99///    Z                                                               Z
100/// .. .                              ...                              .
101///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
102/// ```
103#[derive(Clone, Debug, Layer, StatelessLayer)]
104#[metadata_type(TcpMetadata)]
105#[ref_type(SctpRef)]
106#[cfg(feature = "alloc")]
107pub struct Sctp {
108    sport: u16,
109    dport: u16,
110    verify_tag: u32,
111    chksum: Option<u32>,
112    control_chunks: Vec<SctpControlChunk>,
113    payload_chunks: Vec<Box<dyn LayerObject>>,
114}
115
116#[cfg(feature = "alloc")]
117impl Sctp {
118    /// The SCTP port number from which the packet has been sent (i.e. Source Port).
119    #[inline]
120    pub fn sport(&self) -> u16 {
121        self.sport
122    }
123
124    /// Sets the SCTP Source Port of the packet to the given value.
125    #[inline]
126    pub fn set_sport(&mut self, sport: u16) {
127        self.sport = sport;
128    }
129
130    /// The SCTP port number to which the packet is destined (i.e. Destination Port).
131    #[inline]
132    pub fn dport(&self) -> u16 {
133        self.dport
134    }
135
136    /// Sets the SCTP Destination Port of the packet.
137    #[inline]
138    pub fn set_dport(&mut self, dport: u16) {
139        self.dport = dport;
140    }
141
142    /// The Verification Tag of the packet.
143    ///
144    /// The recipient of an SCTP packet uses the Verification Tag to validate the packet's source.
145    #[inline]
146    pub fn verify_tag(&self) -> u32 {
147        self.verify_tag
148    }
149
150    /// Sets the Verification Tag of the packet.
151    #[inline]
152    pub fn set_verify_tag(&mut self, verify_tag: u32) {
153        self.verify_tag = verify_tag;
154    }
155
156    /// Retrieves the assigned CRC32c checksum for the packet, or `None` if no checksum has
157    /// been assigned to the packet.
158    ///
159    /// By default, the SCTP checksum is automatically calculated when an [`struct@Sctp`] instance
160    /// is converted to bytes, unless a checksum is pre-assigned to the instance prior to
161    /// conversion. If a checksum has already been assigned to the packet, this method will return
162    /// it; otherwise, it will return `None`. This means that an [`struct@Sctp`] instance created
163    /// from bytes or from a [`SctpRef`] instance will still have a checksum of `None` by default,
164    /// regardless of the checksum value of the underlying bytes it was created from.
165    #[inline]
166    pub fn chksum(&self) -> Option<u32> {
167        self.chksum
168    }
169
170    /// Assigns the CRC32c checksum to be used for the packet.
171    ///
172    /// By default, the SCTP checksum is automatically calculated when an [`struct@Sctp`] instance
173    /// is converted to bytes. This method overrides that behavior so that the provided checksum is
174    /// used instead. You generally shouldn't need to use this method unless:
175    ///   1. You know the expected checksum of the packet in advance and don't want the checksum
176    ///      calculation to automatically run again (since it can be a costly operation), or
177    ///   2. Checksum offloading is being employed for the SCTP packet and you want to zero out the
178    ///      checksum field (again, avoiding unnecessary extra computation), or
179    ///   3. You want to explicitly set an invalid checksum.
180    #[inline]
181    pub fn set_chksum(&mut self, chksum: u32) {
182        self.chksum = Some(chksum);
183    }
184
185    /// Clears any previously assigned CRC32c checksum for the packet.
186    ///
187    /// This method guarantees that the SCTP checksum will be automatically calculated for this
188    /// [`struct@Sctp`] instance whenever the packet is converted to bytes. You shouldn't need to
189    /// call this method unless you've previously explicitly assigned a checksum to the packet--either
190    /// through a call to [`Sctp::set_chksum()`] or through a Builder pattern. Packets converted
191    /// from bytes into [`struct@Sctp`] instances from bytes or from a [`SctpRef`] instance will
192    /// have a checksum of `None` by default.
193    #[inline]
194    pub fn clear_chksum(&mut self) {
195        self.chksum = None;
196    }
197
198    /// Recalculates the checksum of the given `Sctp` packet and sets the checksum field accordingly.
199    #[inline]
200    pub fn generate_chksum(&mut self) {
201        todo!() // TODO: should we do this, or automatically calculate the checksum when we generate the packet bytes? It's more efficient that way...
202    }
203
204    /// The list of Control Chunks contained within the packet.
205    ///
206    /// These chunks can be arranged in any order. Control chunks are evaluated by the peer in the
207    /// same order that they are sent. All control chunks are ordered before payload chunks. Some
208    /// control chunks have restrictions on what other chunks they can be bundled in the same message with:
209    ///
210    /// - [`SctpControlChunk::Shutdown`] and [`SctpControlChunk::ShutdownAck`] must not be bundled with any [`struct@SctpDataChunk`].
211    /// This is because the Shutdown is evaulated first, and data cannot be sent after a Shutdown message.
212    ///
213    /// - [`SctpControlChunk::Init`], [`SctpControlChunk::InitAck`], and [`SctpControlChunk::ShutdownComplete`] must not be bundled
214    /// with any other control or payload chunks.
215    ///
216    /// These constraints will be enforced by this library by default.
217    #[inline]
218    pub fn control_chunks(&self) -> &Vec<SctpControlChunk> {
219        &self.control_chunks
220    }
221
222    /// The mutable list of Control Chunks contained within the packet.
223    ///
224    /// These chunks can be arranged in any order. Control chunks are evaluated by the peer in the
225    /// same order that they are sent. All control chunks are ordered before payload chunks. Some
226    /// control chunks have restrictions on what other chunks they can be bundled in the same message with:
227    ///
228    /// - [`SctpControlChunk::Shutdown`] and [`SctpControlChunk::ShutdownAck`] must not be bundled with any [`struct@SctpDataChunk`].
229    /// This is because the Shutdown is evaulated first, and data cannot be sent after a Shutdown message.
230    ///
231    /// - [`SctpControlChunk::Init`], [`SctpControlChunk::InitAck`], and [`SctpControlChunk::ShutdownComplete`] must not be bundled
232    /// with any other control or payload chunks.
233    ///
234    /// Although the `rscap` library enforces these constraints where it can, this particular API may be used in such a way that
235    /// they are violated. It is the responsibility of the caller of this method to ensure that the above constraints are upheld.
236    #[inline]
237    pub fn control_chunks_mut(&mut self) -> &mut Vec<SctpControlChunk> {
238        &mut self.control_chunks
239    }
240
241    /*
242    /// The list of Payload Data (DATA) Chunks contained within the packet.
243    ///
244    /// These chunks are ordered by increasing TSN value, and are always placed after any control chunks in the packet.
245    /// A packet MUST NOT have any Payload Data Chunks when any of the below Control Chunks are present:
246    ///
247    /// - [`SctpControlChunk::Shutdown`]
248    /// - [`SctpControlChunk::ShutdownAck`]
249    /// - [`SctpControlChunk::Init`]
250    /// - [`SctpControlChunk::InitAck`]
251    /// - [`SctpControlChunk::ShutdownComplete`]
252    ///
253    /// These constraints will be enforced by this library by default.
254    #[inline]
255    pub fn payload_chunks(&self) -> &Vec<SctpDataChunk> {
256        &self.payload_chunks
257    }
258
259    /// The list of Payload Data (DATA) Chunks contained within the packet.
260    ///
261    /// Payload DATA chunks are ordered by increasing TSN value, and are always placed after any Control Chunks in the packet.
262    /// A packet MUST NOT have any Payload Data Chunks when any of the below Control Chunks are present:
263    ///
264    /// - [`SctpControlChunk::Shutdown`]
265    /// - [`SctpControlChunk::ShutdownAck`]
266    /// - [`SctpControlChunk::Init`]
267    /// - [`SctpControlChunk::InitAck`]
268    /// - [`SctpControlChunk::ShutdownComplete`]
269    ///
270    /// Although the `rscap` library enforces these constraints where it can, this particular API may be used in such a way that
271    /// they are violated. It is the responsibility of the caller of this method to ensure that the above constraints are upheld.
272    #[inline]
273    pub fn payload_chunks_mut(&mut self) -> &mut Vec<SctpDataChunk> {
274        &mut self.payload_chunks
275    }
276    */
277}
278
279#[cfg(feature = "alloc")]
280#[doc(hidden)]
281impl FromBytesCurrent for Sctp {
282    fn from_bytes_current_layer_unchecked(bytes: &[u8]) -> Self {
283        let sctp = SctpRef::from_bytes_unchecked(bytes);
284
285        let mut control_chunks = Vec::new();
286        let control_iter = sctp.control_chunks();
287        for chunk in control_iter {
288            control_chunks.push(chunk.into());
289        }
290
291        let mut payload_chunks = Vec::new();
292        let payload_iter = sctp.payload_chunks();
293        for chunk in payload_iter {
294            payload_chunks.push(chunk.to_boxed_layer());
295        }
296
297        Sctp {
298            sport: sctp.sport(),
299            dport: sctp.dport(),
300            verify_tag: sctp.verify_tag(),
301            chksum: None,
302            control_chunks,
303            payload_chunks,
304        }
305    }
306
307    fn payload_from_bytes_unchecked_default(&mut self, _bytes: &[u8]) {}
308}
309
310#[cfg(feature = "alloc")]
311impl LayerLength for Sctp {
312    fn len(&self) -> usize {
313        8 + self.control_chunks.iter().map(|c| c.len()).sum::<usize>()
314            + self.payload_chunks.iter().map(|c| c.len()).sum::<usize>()
315    }
316}
317
318#[cfg(feature = "alloc")]
319impl LayerObject for Sctp {
320    #[inline]
321    fn can_add_payload_default(&self, payload: &dyn LayerObject) -> bool {
322        payload.as_any().downcast_ref::<&SctpDataChunk>().is_some()
323    }
324
325    #[inline]
326    fn add_payload_unchecked(&mut self, payload: Box<dyn LayerObject>) {
327        self.payload_chunks.push(payload);
328    }
329
330    #[inline]
331    fn payloads(&self) -> &[Box<dyn LayerObject>] {
332        &self.payload_chunks
333    }
334
335    #[inline]
336    fn payloads_mut(&mut self) -> &mut [Box<dyn LayerObject>] {
337        &mut self.payload_chunks
338    }
339
340    fn remove_payload_at(&mut self, index: usize) -> Option<Box<dyn LayerObject>> {
341        if index < self.payload_chunks.len() {
342            Some(self.payload_chunks.remove(index))
343        } else {
344            None
345        }
346    }
347}
348
349#[cfg(feature = "alloc")]
350impl ToBytes for Sctp {
351    fn to_bytes_checksummed(
352        &self,
353        writer: &mut PacketWriter<'_, Vec<u8>>,
354        _prev: Option<(LayerId, usize)>,
355    ) -> Result<(), SerializationError> {
356        let start = writer.len();
357        writer.update_layer::<Sctp>();
358        writer.write_slice(&self.sport.to_be_bytes())?;
359        writer.write_slice(&self.dport.to_be_bytes())?;
360        writer.write_slice(&self.verify_tag.to_be_bytes())?;
361        writer.write_slice(&self.chksum.unwrap_or(0).to_be_bytes())?;
362        for chunk in &self.control_chunks {
363            chunk.to_bytes_extended(writer)?;
364        }
365
366        for chunk in &self.payload_chunks {
367            chunk.to_bytes_checksummed(writer, Some((Self::layer_id(), start)))?;
368        }
369
370        // TODO: set checksum here
371
372        Ok(())
373    }
374}
375
376/// An SCTP (Stream Control Transmission Protocol) packet.
377///
378/// ## Packet Layout
379/// ```txt
380///    .    Octet 0    .    Octet 1    .    Octet 2    .    Octet 3    .
381///    |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
382///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
383///  0 |          Source Port          |        Destination Port       |
384///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
385///  4 |                        Verification Tag                       |
386///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
387///  8 |                            Checksum                           |
388///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
389/// 12 Z                             Chunks                            Z
390///    Z                                                               Z
391/// .. .                              ...                              .
392///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
393/// ```
394#[derive(Clone, Copy, Debug, LayerRef, StatelessLayer)]
395#[owned_type(Sctp)]
396#[metadata_type(SctpMetadata)]
397pub struct SctpRef<'a> {
398    #[data_field]
399    data: &'a [u8],
400}
401
402impl<'a> SctpRef<'a> {
403    /// The SCTP port number from which the packet has been sent (i.e. Source Port).
404    #[inline]
405    pub fn sport(&self) -> u16 {
406        u16::from_be_bytes(utils::to_array(self.data, 0).unwrap())
407    }
408
409    /// The SCTP port number to which the packet is destined (i.e. Destination Port).
410    #[inline]
411    pub fn dport(&self) -> u16 {
412        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
413    }
414
415    /// The Verification Tag assigned to the packet.
416    ///
417    /// The recipient of an SCTP packet uses the Verification Tag to validate the packet's source.
418    #[inline]
419    pub fn verify_tag(&self) -> u32 {
420        u32::from_be_bytes(utils::to_array(self.data, 4).unwrap())
421    }
422
423    /// The CRC32c Checksum of the SCTP packet.
424    #[inline]
425    pub fn chksum(&self) -> u32 {
426        u32::from_be_bytes(utils::to_array(self.data, 8).unwrap())
427    }
428
429    /// An iterator over the list of Control Chunks contained within the packet.
430    ///
431    /// These chunks can be arranged in any order. Control chunks are evaluated by the peer in the
432    /// same order that they are sent. All control chunks are ordered before payload chunks. Some
433    /// control chunks have restrictions on what other chunks they can be bundled in the same message with:
434    ///
435    /// - [`SctpControlChunk::Shutdown`] and [`SctpControlChunk::ShutdownAck`] must not be bundled with any [`struct@SctpDataChunk`].
436    /// This is because the Shutdown is evaulated first, and data cannot be sent after a Shutdown message.
437    ///
438    /// - [`SctpControlChunk::Init`], [`SctpControlChunk::InitAck`], and [`SctpControlChunk::ShutdownComplete`] must not be bundled
439    /// with any other control or payload chunks.
440    ///
441    /// These constraints will be enforced by this library by default.
442    #[inline]
443    pub fn control_chunks(&self) -> ControlChunksIterRef<'a> {
444        ControlChunksIterRef {
445            chunk_iter: self.chunks(),
446        }
447    }
448
449    /// The list of Payload Data (DATA) Chunks contained within the packet.
450    ///
451    /// These chunks are ordered by increasing TSN value, and are always placed after any control chunks in the packet.
452    /// A packet MUST NOT have any Payload Data Chunks when any of the below Control Chunks are present:
453    ///
454    /// - [`SctpControlChunk::Shutdown`]
455    /// - [`SctpControlChunk::ShutdownAck`]
456    /// - [`SctpControlChunk::Init`]
457    /// - [`SctpControlChunk::InitAck`]
458    /// - [`SctpControlChunk::ShutdownComplete`]
459    ///
460    /// These constraints will be enforced by this library by default.
461    #[inline]
462    pub fn payload_chunks(&self) -> DataChunksIterRef<'a> {
463        DataChunksIterRef {
464            chunk_iter: self.chunks(),
465        }
466    }
467
468    /// The list of Control or Payload Chunks contained within the packet.
469    ///
470    /// These chunks should be ordered such that Control Chunks are all before Payload Chunks.
471    /// However, if this `SctpRef` was created with `from_bytes_unchecked`, it is possible that
472    /// these chunks may not be ordered correctly.
473    #[inline]
474    pub fn chunks(&self) -> ChunksIterRef<'a> {
475        ChunksIterRef {
476            bytes: &self.data[12..],
477        }
478    }
479}
480
481impl<'a> FromBytesRef<'a> for SctpRef<'a> {
482    #[inline]
483    fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
484        SctpRef { data: bytes }
485    }
486}
487
488#[doc(hidden)]
489impl LayerOffset for SctpRef<'_> {
490    #[inline]
491    fn payload_byte_index_default(_bytes: &[u8], _layer_type: LayerId) -> Option<usize> {
492        None // SCTP makes no indiciation of what protocol is used for its payloads
493             // If we did need to provide an index, we'll want to provide an end index too...
494    }
495}
496
497impl Validate for SctpRef<'_> {
498    fn validate_current_layer(curr_layer: &[u8]) -> Result<(), ValidationError> {
499        let mut remaining = match curr_layer.get(12..) {
500            Some(rem) => rem,
501            None => {
502                return Err(ValidationError {
503                    layer: Self::name(),
504                    class: ValidationErrorClass::InsufficientBytes,
505                    #[cfg(feature = "error_string")]
506                    reason: "insufficient bytes in SCTP packet for Common Header",
507                })
508            }
509        };
510
511        let mut data_reached = false;
512        let mut single_chunk = false;
513        let mut shutdown = false;
514        let mut chunk_cnt = 0;
515
516        while let Some(&chunk_type) = remaining.first() {
517            chunk_cnt += 1;
518            let chunk_validation = match chunk_type {
519                CHUNK_TYPE_DATA => {
520                    data_reached = true;
521                    SctpDataChunkRef::validate(remaining)
522                }
523                _ if data_reached => {
524                    return Err(ValidationError {
525                        layer: Self::name(),
526                        class: ValidationErrorClass::InvalidValue,
527                        #[cfg(feature = "error_string")]
528                        reason: "SCTP Control Chunk not allowed after DATA Chunk in Chunks field",
529                    })
530                }
531                CHUNK_TYPE_INIT => {
532                    single_chunk = true;
533                    InitChunkRef::validate(remaining)
534                }
535                CHUNK_TYPE_INIT_ACK => {
536                    single_chunk = true;
537                    InitAckChunkRef::validate(remaining)
538                }
539                CHUNK_TYPE_SACK => SackChunkRef::validate(remaining),
540                CHUNK_TYPE_HEARTBEAT => HeartbeatChunkRef::validate(remaining),
541                CHUNK_TYPE_HEARTBEAT_ACK => HeartbeatAckChunkRef::validate(remaining),
542                CHUNK_TYPE_ABORT => AbortChunkRef::validate(remaining),
543                CHUNK_TYPE_SHUTDOWN => {
544                    shutdown = true;
545                    ShutdownChunkRef::validate(remaining)
546                }
547                CHUNK_TYPE_SHUTDOWN_ACK => {
548                    shutdown = true;
549                    ShutdownAckChunkRef::validate(remaining)
550                }
551                CHUNK_TYPE_ERROR => ErrorChunkRef::validate(remaining),
552                CHUNK_TYPE_COOKIE_ECHO => CookieEchoChunkRef::validate(remaining),
553                CHUNK_TYPE_COOKIE_ACK => CookieAckChunkRef::validate(remaining),
554                CHUNK_TYPE_SHUTDOWN_COMPLETE => {
555                    single_chunk = true;
556                    ShutdownCompleteChunkRef::validate(remaining)
557                }
558                _ => UnknownChunkRef::validate(remaining),
559            };
560
561            match chunk_validation {
562                Err(e) => {
563                    if let ValidationErrorClass::ExcessBytes(l) = e.class {
564                        remaining = &remaining[remaining.len() - l..];
565                    } else {
566                        return Err(e);
567                    }
568                }
569                Ok(()) => return Ok(()),
570            }
571        }
572
573        if single_chunk && chunk_cnt > 1 {
574            return Err(ValidationError {
575                layer: Self::name(),
576                class: ValidationErrorClass::InvalidValue,
577                #[cfg(feature = "error_string")]
578                reason: "multiple chunks bundled in one SCTP message where only one was allowed (chunk types INIT, INIT_ACK and SHUTDOWN_COMPLETE cannot be bundled with other chunks)",
579            });
580        }
581
582        if shutdown && data_reached {
583            return Err(ValidationError {
584                layer: Self::name(),
585                class: ValidationErrorClass::InvalidValue,
586                #[cfg(feature = "error_string")]
587                reason:
588                    "SCTP SHUTDOWN/SHUTDOWN_ACK Chunk cannot be bundled with DATA (Payload) Chunks",
589            });
590        }
591
592        Ok(()) // No optional data was found
593    }
594
595    #[inline]
596    fn validate_payload_default(_curr_layer: &[u8]) -> Result<(), ValidationError> {
597        Ok(()) // Payload is always assumed to be Raw
598    }
599}
600
601/// An iterator over the Control chunks of an SCTP packet.
602#[derive(Clone, Copy, Debug)]
603pub struct ControlChunksIterRef<'a> {
604    chunk_iter: ChunksIterRef<'a>,
605}
606
607impl<'a> Iterator for ControlChunksIterRef<'a> {
608    type Item = SctpControlChunkRef<'a>;
609
610    #[inline]
611    fn next(&mut self) -> Option<Self::Item> {
612        for chunk in self.chunk_iter.by_ref() {
613            if let ChunkRef::Control(c) = chunk {
614                return Some(c);
615            }
616        }
617        None
618    }
619}
620
621/// An iterator over the Payload chunks (i.e. the DATA chunks) of an SCTP packet.
622#[derive(Clone, Copy, Debug)]
623pub struct DataChunksIterRef<'a> {
624    chunk_iter: ChunksIterRef<'a>,
625}
626
627impl<'a> Iterator for DataChunksIterRef<'a> {
628    type Item = SctpDataChunkRef<'a>;
629
630    #[inline]
631    fn next(&mut self) -> Option<Self::Item> {
632        for chunk in self.chunk_iter.by_ref() {
633            if let ChunkRef::Payload(c) = chunk {
634                return Some(c);
635            }
636        }
637        None
638    }
639}
640
641/// An SCTP chunk (may be a Control chunk or a Payload chunk).
642#[derive(Clone, Copy, Debug)]
643pub enum ChunkRef<'a> {
644    Control(SctpControlChunkRef<'a>),
645    Payload(SctpDataChunkRef<'a>),
646}
647
648/// An iterator over all the chunks of an SCTP packet.
649#[derive(Clone, Copy, Debug)]
650pub struct ChunksIterRef<'a> {
651    bytes: &'a [u8],
652}
653
654impl<'a> Iterator for ChunksIterRef<'a> {
655    type Item = ChunkRef<'a>;
656
657    fn next(&mut self) -> Option<Self::Item> {
658        let (chunk_type, unpadded_len) =
659            match (self.bytes.first(), utils::get_array::<2>(self.bytes, 2)) {
660                (Some(&t), Some(&l)) => (t, u16::from_be_bytes(l)),
661                _ => return None,
662            };
663
664        let len = utils::padded_length::<4>(unpadded_len as usize);
665        match (self.bytes.get(..len), self.bytes.get(len..)) {
666            (Some(chunk_bytes), Some(rem)) => {
667                self.bytes = rem;
668                if chunk_type == CHUNK_TYPE_DATA {
669                    Some(ChunkRef::Payload(SctpDataChunkRef::from_bytes_unchecked(
670                        chunk_bytes,
671                    )))
672                } else {
673                    Some(ChunkRef::Control(
674                        SctpControlChunkRef::from_bytes_unchecked(chunk_bytes),
675                    ))
676                }
677            }
678            _ => {
679                panic!("insufficient bytes for ChunkRef in iterator.");
680            }
681        }
682    }
683}
684
685// =============================================================================
686//                             Non-Layer Components
687// =============================================================================
688
689/// An SCTP Control chunk.
690#[derive(Clone, Debug)]
691#[cfg(feature = "alloc")]
692pub enum SctpControlChunk {
693    Init(InitChunk),
694    InitAck(InitAckChunk),
695    Sack(SackChunk),
696    Heartbeat(HeartbeatChunk),
697    HeartbeatAck(HeartbeatAckChunk),
698    Abort(AbortChunk),
699    Shutdown(ShutdownChunk),
700    ShutdownAck(ShutdownAckChunk),
701    Error(ErrorChunk),
702    CookieEcho(CookieEchoChunk),
703    CookieAck(CookieAckChunk),
704    ShutdownComplete(ShutdownCompleteChunk),
705    Unknown(UnknownChunk),
706}
707
708#[cfg(feature = "alloc")]
709impl SctpControlChunk {
710    #[inline]
711    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
712        Self::validate(bytes)?;
713        Ok(Self::from_bytes_unchecked(bytes))
714    }
715
716    #[inline]
717    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
718        Self::from(SctpControlChunkRef::from_bytes_unchecked(bytes))
719    }
720
721    #[inline]
722    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
723        SctpControlChunkRef::validate(bytes)
724    }
725
726    pub fn chunk_type(&self) -> u8 {
727        match self {
728            SctpControlChunk::Init(c) => c.chunk_type(),
729            SctpControlChunk::InitAck(c) => c.chunk_type(),
730            SctpControlChunk::Sack(c) => c.chunk_type(),
731            SctpControlChunk::Heartbeat(c) => c.chunk_type(),
732            SctpControlChunk::HeartbeatAck(c) => c.chunk_type(),
733            SctpControlChunk::Abort(c) => c.chunk_type(),
734            SctpControlChunk::Shutdown(c) => c.chunk_type(),
735            SctpControlChunk::ShutdownAck(c) => c.chunk_type(),
736            SctpControlChunk::Error(c) => c.chunk_type(),
737            SctpControlChunk::CookieEcho(c) => c.chunk_type(),
738            SctpControlChunk::CookieAck(c) => c.chunk_type(),
739            SctpControlChunk::ShutdownComplete(c) => c.chunk_type(),
740            SctpControlChunk::Unknown(c) => c.chunk_type(),
741        }
742    }
743
744    pub fn len(&self) -> usize {
745        match self {
746            SctpControlChunk::Init(c) => c.len(),
747            SctpControlChunk::InitAck(c) => c.len(),
748            SctpControlChunk::Sack(c) => c.len(),
749            SctpControlChunk::Heartbeat(c) => c.len(),
750            SctpControlChunk::HeartbeatAck(c) => c.len(),
751            SctpControlChunk::Abort(c) => c.len(),
752            SctpControlChunk::Shutdown(c) => c.len(),
753            SctpControlChunk::ShutdownAck(c) => c.len(),
754            SctpControlChunk::Error(c) => c.len(),
755            SctpControlChunk::CookieEcho(c) => c.len(),
756            SctpControlChunk::CookieAck(c) => c.len(),
757            SctpControlChunk::ShutdownComplete(c) => c.len(),
758            SctpControlChunk::Unknown(c) => c.len(),
759        }
760    }
761
762    pub fn to_bytes_extended<T: PacketWritable>(
763        &self,
764        writer: &mut PacketWriter<'_, T>,
765    ) -> Result<(), SerializationError> {
766        match self {
767            SctpControlChunk::Init(c) => c.to_bytes_extended(writer),
768            SctpControlChunk::InitAck(c) => c.to_bytes_extended(writer),
769            SctpControlChunk::Sack(c) => c.to_bytes_extended(writer),
770            SctpControlChunk::Heartbeat(c) => c.to_bytes_extended(writer),
771            SctpControlChunk::HeartbeatAck(c) => c.to_bytes_extended(writer),
772            SctpControlChunk::Abort(c) => c.to_bytes_extended(writer),
773            SctpControlChunk::Shutdown(c) => c.to_bytes_extended(writer),
774            SctpControlChunk::ShutdownAck(c) => c.to_bytes_extended(writer),
775            SctpControlChunk::Error(c) => c.to_bytes_extended(writer),
776            SctpControlChunk::CookieEcho(c) => c.to_bytes_extended(writer),
777            SctpControlChunk::CookieAck(c) => c.to_bytes_extended(writer),
778            SctpControlChunk::ShutdownComplete(c) => c.to_bytes_extended(writer),
779            SctpControlChunk::Unknown(c) => c.to_bytes_extended(writer),
780        }
781    }
782}
783
784#[cfg(feature = "alloc")]
785impl From<SctpControlChunkRef<'_>> for SctpControlChunk {
786    #[inline]
787    fn from(value: SctpControlChunkRef<'_>) -> Self {
788        SctpControlChunk::from(&value)
789    }
790}
791
792#[cfg(feature = "alloc")]
793impl From<&SctpControlChunkRef<'_>> for SctpControlChunk {
794    fn from(value: &SctpControlChunkRef<'_>) -> Self {
795        match value {
796            SctpControlChunkRef::Init(c) => SctpControlChunk::Init(c.into()),
797            SctpControlChunkRef::InitAck(c) => SctpControlChunk::InitAck(c.into()),
798            SctpControlChunkRef::Sack(c) => SctpControlChunk::Sack(c.into()),
799            SctpControlChunkRef::Heartbeat(c) => SctpControlChunk::Heartbeat(c.into()),
800            SctpControlChunkRef::HeartbeatAck(c) => SctpControlChunk::HeartbeatAck(c.into()),
801            SctpControlChunkRef::Abort(c) => SctpControlChunk::Abort(c.into()),
802            SctpControlChunkRef::Shutdown(c) => SctpControlChunk::Shutdown(c.into()),
803            SctpControlChunkRef::ShutdownAck(c) => SctpControlChunk::ShutdownAck(c.into()),
804            SctpControlChunkRef::Error(c) => SctpControlChunk::Error(c.into()),
805            SctpControlChunkRef::CookieEcho(c) => SctpControlChunk::CookieEcho(c.into()),
806            SctpControlChunkRef::CookieAck(c) => SctpControlChunk::CookieAck(c.into()),
807            SctpControlChunkRef::ShutdownComplete(c) => {
808                SctpControlChunk::ShutdownComplete(c.into())
809            }
810            SctpControlChunkRef::Unknown(c) => SctpControlChunk::Unknown(c.into()),
811        }
812    }
813}
814
815/// An SCTP Control chunk reference.
816#[derive(Clone, Copy, Debug)]
817pub enum SctpControlChunkRef<'a> {
818    Init(InitChunkRef<'a>),
819    InitAck(InitAckChunkRef<'a>),
820    Sack(SackChunkRef<'a>),
821    Heartbeat(HeartbeatChunkRef<'a>),
822    HeartbeatAck(HeartbeatAckChunkRef<'a>),
823    Abort(AbortChunkRef<'a>),
824    Shutdown(ShutdownChunkRef<'a>),
825    ShutdownAck(ShutdownAckChunkRef<'a>),
826    Error(ErrorChunkRef<'a>),
827    CookieEcho(CookieEchoChunkRef<'a>),
828    CookieAck(CookieAckChunkRef<'a>),
829    ShutdownComplete(ShutdownCompleteChunkRef<'a>),
830    Unknown(UnknownChunkRef<'a>),
831}
832
833impl<'a> SctpControlChunkRef<'a> {
834    #[inline]
835    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
836        Self::validate(bytes)?;
837        Ok(Self::from_bytes_unchecked(bytes))
838    }
839
840    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
841        let chunk_type = bytes[0];
842        match chunk_type {
843            CHUNK_TYPE_INIT => Self::Init(InitChunkRef { data: bytes }),
844            CHUNK_TYPE_INIT_ACK => Self::InitAck(InitAckChunkRef { data: bytes }),
845            CHUNK_TYPE_SACK => Self::Sack(SackChunkRef { data: bytes }),
846            CHUNK_TYPE_HEARTBEAT => Self::Heartbeat(HeartbeatChunkRef { data: bytes }),
847            CHUNK_TYPE_HEARTBEAT_ACK => Self::HeartbeatAck(HeartbeatAckChunkRef { data: bytes }),
848            CHUNK_TYPE_ABORT => Self::Abort(AbortChunkRef { data: bytes }),
849            CHUNK_TYPE_SHUTDOWN => Self::Shutdown(ShutdownChunkRef { data: bytes }),
850            CHUNK_TYPE_SHUTDOWN_ACK => Self::ShutdownAck(ShutdownAckChunkRef { data: bytes }),
851            CHUNK_TYPE_ERROR => Self::Error(ErrorChunkRef { data: bytes }),
852            CHUNK_TYPE_COOKIE_ECHO => Self::CookieEcho(CookieEchoChunkRef { data: bytes }),
853            CHUNK_TYPE_COOKIE_ACK => Self::CookieAck(CookieAckChunkRef { data: bytes }),
854            CHUNK_TYPE_SHUTDOWN_COMPLETE => {
855                Self::ShutdownComplete(ShutdownCompleteChunkRef { data: bytes })
856            }
857            _ => Self::Unknown(UnknownChunkRef { data: bytes }),
858        }
859    }
860
861    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
862        let chunk_type = bytes[0];
863        match chunk_type {
864            CHUNK_TYPE_INIT => InitChunkRef::validate(bytes),
865            CHUNK_TYPE_INIT_ACK => InitAckChunkRef::validate(bytes),
866            CHUNK_TYPE_SACK => SackChunkRef::validate(bytes),
867            CHUNK_TYPE_HEARTBEAT => HeartbeatChunkRef::validate(bytes),
868            CHUNK_TYPE_HEARTBEAT_ACK => HeartbeatAckChunkRef::validate(bytes),
869            CHUNK_TYPE_ABORT => AbortChunkRef::validate(bytes),
870            CHUNK_TYPE_SHUTDOWN => ShutdownChunkRef::validate(bytes),
871            CHUNK_TYPE_SHUTDOWN_ACK => ShutdownAckChunkRef::validate(bytes),
872            CHUNK_TYPE_ERROR => ErrorChunkRef::validate(bytes),
873            CHUNK_TYPE_COOKIE_ECHO => CookieEchoChunkRef::validate(bytes),
874            CHUNK_TYPE_COOKIE_ACK => CookieAckChunkRef::validate(bytes),
875            CHUNK_TYPE_SHUTDOWN_COMPLETE => ShutdownCompleteChunkRef::validate(bytes),
876            _ => UnknownChunkRef::validate(bytes),
877        }
878    }
879}
880
881/// An SCTP INIT chunk.
882///
883/// ## Packet Layout
884/// ```txt
885///    .    Octet 0    .    Octet 1    .    Octet 2    .    Octet 3    .
886///    |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
887///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
888///  0 |    Type (1)   |  Chunk Flags  |             Length            |
889///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
890///  4 |                            Init Tag                           |
891///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
892///  8 |           Advertised Receiver Window Credit (a_rwnd)          |
893///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
894///  8 |        Outbound Streams       |        Inbound Streams        |
895///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
896/// 12 |           Initial Transmission Sequence Number (TSN)          |
897///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
898/// 16 Z             Optional or Variable-Length Parameters            Z
899///    Z                                                               Z
900/// .. .                              ...                              .
901///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
902/// ```
903#[derive(Clone, Debug)]
904#[cfg(feature = "alloc")]
905pub struct InitChunk {
906    flags: u8,
907    init_tag: u32,
908    a_rwnd: u32,
909    ostreams: u16,
910    istreams: u16,
911    init_tsn: u32,
912    options: Vec<InitOption>,
913}
914
915#[cfg(feature = "alloc")]
916impl InitChunk {
917    /// Converts the given bytes into an [`InitChunk`] instance, returning an error if the bytes are
918    /// not well-formed.
919    #[inline]
920    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
921        Self::validate(bytes)?;
922        Ok(Self::from_bytes_unchecked(bytes))
923    }
924
925    /// Converts the given bytes into an [`InitChunk`] instance without validating the bytes.
926    ///
927    /// # Panics
928    ///
929    /// The following method may panic if the bytes being passed in do not represent a well-formed
930    /// INIT chunk (i.e. if a call to [`InitChunk::validate()`] would return an error).
931    #[inline]
932    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
933        Self::from(InitChunkRef::from_bytes_unchecked(bytes))
934    }
935
936    /// Validates the given bytes against the expected structure and syntactic values of an
937    /// INIT chunk. If the bytes represent a well-formed INIT chunk, this method will return
938    /// `Ok()`; otherwise, it will return a [`ValidationError`] indicating what part of the
939    /// chunk was invalid.
940    #[inline]
941    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
942        InitChunkRef::validate(bytes)
943    }
944
945    /// The Type field of the INIT chunk.
946    #[inline]
947    pub fn chunk_type(&self) -> u8 {
948        CHUNK_TYPE_INIT
949    }
950
951    /// The flags of the INIT chunk (in bytes).
952    #[inline]
953    pub fn flags_raw(&self) -> u8 {
954        self.flags
955    }
956
957    /// Sets the flags of the INIT chunk.
958    #[inline]
959    pub fn set_flags_raw(&mut self, flags: u8) {
960        self.flags = flags;
961    }
962
963    /// The length (without padding) of the INIT chunk.
964    #[inline]
965    pub fn unpadded_len(&self) -> usize {
966        20 + self.options.iter().map(|o| o.len()).sum::<usize>()
967    }
968
969    /// The length (including padding) of the INIT chunk.
970    #[inline]
971    pub fn len(&self) -> usize {
972        utils::padded_length::<4>(self.unpadded_len())
973    }
974
975    /// The Initiate Tag of the chunk.
976    ///
977    /// The Initiate Tag is stored by the recipient of the INIT tag and is subsequently transmitted
978    /// as the Verification Tag of every SCTP packet for the duration of the association.
979    #[inline]
980    pub fn init_tag(&self) -> u32 {
981        self.init_tag
982    }
983
984    /// Sets the Initiate Tag of the chunk.
985    #[inline]
986    pub fn set_init_tag(&mut self, init_tag: u32) {
987        self.init_tag = init_tag;
988    }
989
990    /// The Advertised Receiver Window Credit (a_rwnd).
991    ///
992    /// This field represents the number of bytes the sender has reserved as a window for messages
993    /// received in this association.
994    #[inline]
995    pub fn a_rwnd(&self) -> u32 {
996        self.a_rwnd
997    }
998
999    /// Sets the Advertised Receiver Window Credit (a_rwnd).
1000    #[inline]
1001    pub fn set_a_rwnd(&mut self, a_rwnd: u32) {
1002        self.a_rwnd = a_rwnd;
1003    }
1004
1005    /// The number of Outbound Streams the sender of the INIT chunk wishes to create for the
1006    /// association.
1007    #[inline]
1008    pub fn ostreams(&self) -> u16 {
1009        self.ostreams
1010    }
1011
1012    /// Sets the number of Outbound Streams advertised by the INIT chunk.
1013    #[inline]
1014    pub fn set_ostreams(&mut self, ostreams: u16) {
1015        self.ostreams = ostreams;
1016    }
1017
1018    /// The number of Inbound Streams the sender of the INIT chunk will allow its peer to create for
1019    /// the association.
1020    #[inline]
1021    pub fn istreams(&self) -> u16 {
1022        self.istreams
1023    }
1024
1025    /// Sets the number of Inbound Streams advertised by the INIT chunk.
1026    #[inline]
1027    pub fn set_istreams(&mut self, istreams: u16) {
1028        self.istreams = istreams;
1029    }
1030
1031    /// The Initial Transmission Sequence Number (TSN).
1032    ///
1033    /// Indicates the TSN that the sender of the INIT chunk will begin its association with.
1034    #[inline]
1035    pub fn init_tsn(&self) -> u32 {
1036        self.init_tsn
1037    }
1038
1039    /// Sets the Initial Transmission Sequence Number (TSN) of the INIT chunk.
1040    #[inline]
1041    pub fn set_init_tsn(&mut self, init_tsn: u32) {
1042        self.init_tsn = init_tsn;
1043    }
1044
1045    /// The optional or variable-length parameters of the INIT chunk.
1046    #[inline]
1047    pub fn options(&self) -> &Vec<InitOption> {
1048        &self.options
1049    }
1050
1051    /// A mutable reference to the optional or variable-length parameters of the INIT chunk.
1052    #[inline]
1053    pub fn options_mut(&mut self) -> &mut Vec<InitOption> {
1054        &mut self.options
1055    }
1056
1057    pub fn to_bytes_extended<T: PacketWritable>(
1058        &self,
1059        writer: &mut PacketWriter<'_, T>,
1060    ) -> Result<(), SerializationError> {
1061        writer.write_slice(&[CHUNK_TYPE_INIT])?;
1062        writer.write_slice(&[self.flags])?;
1063        writer.write_slice(&self.unpadded_len().to_be_bytes())?;
1064        writer.write_slice(&self.init_tag.to_be_bytes())?;
1065        writer.write_slice(&self.a_rwnd.to_be_bytes())?;
1066        writer.write_slice(&self.ostreams.to_be_bytes())?;
1067        writer.write_slice(&self.istreams.to_be_bytes())?;
1068        writer.write_slice(&self.init_tsn.to_be_bytes())?;
1069        for option in &self.options {
1070            option.to_bytes_extended(writer)?;
1071        }
1072        // No padding needed--options are guaranteed to be padded to 4 bytes.
1073
1074        Ok(())
1075    }
1076}
1077
1078#[cfg(feature = "alloc")]
1079impl From<InitChunkRef<'_>> for InitChunk {
1080    #[inline]
1081    fn from(value: InitChunkRef<'_>) -> Self {
1082        Self::from(&value)
1083    }
1084}
1085
1086#[cfg(feature = "alloc")]
1087impl From<&InitChunkRef<'_>> for InitChunk {
1088    fn from(value: &InitChunkRef<'_>) -> Self {
1089        let mut options = Vec::new();
1090        let iter = value.options_iter();
1091        for option in iter {
1092            options.push(option.into());
1093        }
1094
1095        InitChunk {
1096            flags: value.flags_raw(),
1097            init_tag: value.init_tag(),
1098            a_rwnd: value.a_rwnd(),
1099            ostreams: value.ostreams(),
1100            istreams: value.istreams(),
1101            init_tsn: value.init_tsn(),
1102            options,
1103        }
1104    }
1105}
1106
1107/// An SCTP INIT chunk reference.
1108///
1109/// ## Packet Layout
1110/// ```txt
1111///    .    Octet 0    .    Octet 1    .    Octet 2    .    Octet 3    .
1112///    |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
1113///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1114///  0 |    Type (1)   |  Chunk Flags  |             Length            |
1115///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1116///  4 |                            Init Tag                           |
1117///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1118///  8 |           Advertised Receiver Window Credit (a_rwnd)          |
1119///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1120///  8 |        Outbound Streams       |        Inbound Streams        |
1121///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1122/// 12 |           Initial Transmission Sequence Number (TSN)          |
1123///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1124/// 16 Z             Optional or Variable-Length Parameters            Z
1125///    Z                                                               Z
1126/// .. .                              ...                              .
1127///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1128/// ```
1129#[derive(Clone, Copy, Debug)]
1130pub struct InitChunkRef<'a> {
1131    data: &'a [u8],
1132}
1133
1134impl<'a> InitChunkRef<'a> {
1135    #[inline]
1136    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
1137        Self::validate(bytes)?;
1138        Ok(Self::from_bytes_unchecked(bytes))
1139    }
1140
1141    #[inline]
1142    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
1143        InitChunkRef { data: bytes }
1144    }
1145
1146    pub fn validate(bytes: &'a [u8]) -> Result<(), ValidationError> {
1147        match utils::to_array(bytes, 2) {
1148            Some(unpadded_len_arr) => {
1149                let len = u16::from_be_bytes(unpadded_len_arr) as usize;
1150
1151                if bytes.len() < cmp::max(len, 20) {
1152                    return Err(ValidationError {
1153                        layer: SctpRef::name(),
1154                        class: ValidationErrorClass::InsufficientBytes,
1155                        #[cfg(feature = "error_string")]        
1156                        reason: "insufficient bytes in SCTP INIT chunk for header and optional parameters",
1157                    });
1158                }
1159
1160                if len % 4 != 0 {
1161                    return Err(ValidationError {
1162                        layer: SctpRef::name(),
1163                        class: ValidationErrorClass::InvalidValue,
1164                        #[cfg(feature = "error_string")]
1165                        reason: "SCTP INIT chunk length was not a multiple of 4",
1166                    });
1167                }
1168
1169                if len < 20 {
1170                    return Err(ValidationError {
1171                        layer: SctpRef::name(),
1172                        class: ValidationErrorClass::InvalidValue,
1173                        #[cfg(feature = "error_string")]
1174                        reason:
1175                            "length field of SCTP INIT chunk was too short to cover entire header",
1176                    });
1177                }
1178
1179                let mut options = &bytes[20..];
1180                while !options.is_empty() {
1181                    match InitOptionRef::validate(options) {
1182                        Err(e) => {
1183                            if let ValidationErrorClass::ExcessBytes(extra) = e.class {
1184                                options = &options[options.len() - extra..];
1185                            } else {
1186                                return Err(ValidationError {
1187                                    layer: SctpRef::name(),
1188                                    class: ValidationErrorClass::InvalidValue,
1189                                    #[cfg(feature = "error_string")]
1190                                    reason: e.reason,
1191                                });
1192                            }
1193                        }
1194                        _ => break,
1195                    }
1196                }
1197
1198                if len < bytes.len() {
1199                    Err(ValidationError {
1200                        layer: SctpRef::name(),
1201                        class: ValidationErrorClass::ExcessBytes(bytes.len() - len),
1202                        #[cfg(feature = "error_string")]
1203                        reason: "extra bytes remain at end of SCTP INIT chunk",
1204                    })
1205                } else {
1206                    Ok(())
1207                }
1208            }
1209            _ => Err(ValidationError {
1210                layer: SctpRef::name(),
1211                class: ValidationErrorClass::InsufficientBytes,
1212                #[cfg(feature = "error_string")]
1213                reason: "insufficient bytes in SCTP INIT chunk for header Length field",
1214            }),
1215        }
1216    }
1217
1218    #[inline]
1219    pub fn chunk_type(&self) -> u8 {
1220        self.data[0]
1221    }
1222
1223    #[inline]
1224    pub fn flags_raw(&self) -> u8 {
1225        self.data[1]
1226    }
1227
1228    #[inline]
1229    pub fn unpadded_len(&self) -> u16 {
1230        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
1231    }
1232
1233    #[inline]
1234    pub fn len(&self) -> usize {
1235        utils::padded_length::<4>(self.unpadded_len() as usize)
1236    }
1237
1238    #[inline]
1239    pub fn init_tag(&self) -> u32 {
1240        u32::from_be_bytes(utils::to_array(self.data, 4).unwrap())
1241    }
1242
1243    #[inline]
1244    pub fn a_rwnd(&self) -> u32 {
1245        u32::from_be_bytes(utils::to_array(self.data, 8).unwrap())
1246    }
1247
1248    #[inline]
1249    pub fn ostreams(&self) -> u16 {
1250        u16::from_be_bytes(utils::to_array(self.data, 12).unwrap())
1251    }
1252
1253    #[inline]
1254    pub fn istreams(&self) -> u16 {
1255        u16::from_be_bytes(utils::to_array(self.data, 14).unwrap())
1256    }
1257
1258    #[inline]
1259    pub fn init_tsn(&self) -> u32 {
1260        u32::from_be_bytes(utils::to_array(self.data, 16).unwrap())
1261    }
1262
1263    #[inline]
1264    pub fn options_iter(&self) -> InitOptionsIterRef<'a> {
1265        InitOptionsIterRef { bytes: self.data }
1266    }
1267}
1268
1269#[derive(Clone, Copy, Debug)]
1270pub struct InitOptionsIterRef<'a> {
1271    bytes: &'a [u8],
1272}
1273
1274impl<'a> Iterator for InitOptionsIterRef<'a> {
1275    type Item = InitOptionRef<'a>;
1276
1277    fn next(&mut self) -> Option<Self::Item> {
1278        let (opt_type, unpadded_len) = match (
1279            utils::get_array(self.bytes, 0).map(|&a| u16::from_be_bytes(a)),
1280            utils::get_array(self.bytes, 2).map(|&a| u16::from_be_bytes(a)),
1281        ) {
1282            (Some(t), Some(l)) => (t, l),
1283            _ => return None,
1284        };
1285
1286        let min_len = match opt_type {
1287            INIT_OPT_IPV4_ADDRESS | INIT_OPT_COOKIE_PRESERVATIVE => 8,
1288            INIT_OPT_IPV6_ADDRESS => 20,
1289            INIT_OPT_HOSTNAME_ADDR | INIT_OPT_SUPP_ADDR_TYPES => 4,
1290            _ => 4,
1291        };
1292
1293        if self.bytes.len() < min_len {
1294            self.bytes = &[]; // Not needed, but this helps further calls to the iterator to short-circuit
1295            return None;
1296        }
1297
1298        let len = cmp::max(min_len, utils::padded_length::<4>(unpadded_len as usize));
1299        match (self.bytes.get(..len), self.bytes.get(len..)) {
1300            (Some(opt_bytes), Some(rem)) => {
1301                self.bytes = rem;
1302                Some(InitOptionRef::from_bytes_unchecked(opt_bytes))
1303            }
1304            _ => {
1305                // Just take whatever remaining bytes we can for the payload
1306                let opt_bytes = self.bytes;
1307                self.bytes = &[];
1308                Some(InitOptionRef::from_bytes_unchecked(opt_bytes))
1309            }
1310        }
1311    }
1312}
1313
1314#[derive(Clone, Debug)]
1315#[cfg(feature = "alloc")]
1316pub enum InitOption {
1317    Ipv4Address(u32),
1318    Ipv6Address(u128),
1319    CookiePreservative(u32),
1320    HostnameAddress(Vec<u8>),
1321    SupportedAddressTypes(Vec<u16>),
1322    Unknown(u16, Vec<u8>),
1323}
1324
1325#[cfg(feature = "alloc")]
1326impl InitOption {
1327    #[inline]
1328    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
1329        Self::validate(bytes)?;
1330        Ok(Self::from_bytes_unchecked(bytes))
1331    }
1332
1333    #[inline]
1334    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
1335        Self::from(InitOptionRef::from_bytes_unchecked(bytes))
1336    }
1337
1338    #[inline]
1339    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
1340        InitOptionRef::validate(bytes)
1341    }
1342
1343    #[inline]
1344    pub fn new_ipv4_address(addr: u32) -> Self {
1345        Self::Ipv4Address(addr)
1346    }
1347
1348    #[inline]
1349    pub fn new_ipv6_address(addr: u128) -> Self {
1350        Self::Ipv6Address(addr)
1351    }
1352
1353    #[inline]
1354    pub fn new_cookie_preservative(cookie_lifespan: u32) -> Self {
1355        Self::CookiePreservative(cookie_lifespan)
1356    }
1357
1358    pub fn option_type(&self) -> u16 {
1359        match self {
1360            Self::Ipv4Address(_) => INIT_OPT_IPV4_ADDRESS,
1361            Self::Ipv6Address(_) => INIT_OPT_IPV6_ADDRESS,
1362            Self::CookiePreservative(_) => INIT_OPT_COOKIE_PRESERVATIVE,
1363            Self::HostnameAddress(_) => INIT_OPT_HOSTNAME_ADDR,
1364            Self::SupportedAddressTypes(_) => INIT_OPT_SUPP_ADDR_TYPES,
1365            Self::Unknown(t, _) => *t,
1366        }
1367    }
1368
1369    pub fn unpadded_len(&self) -> usize {
1370        match self {
1371            Self::Ipv4Address(_) => 8,
1372            Self::Ipv6Address(_) => 20,
1373            Self::CookiePreservative(_) => 8,
1374            Self::HostnameAddress(h) => 4 + h.len(),
1375            Self::SupportedAddressTypes(addr_types) => 4 + (2 * addr_types.len()),
1376            Self::Unknown(_, d) => 4 + d.len(),
1377        }
1378    }
1379
1380    #[inline]
1381    pub fn len(&self) -> usize {
1382        utils::padded_length::<4>(self.unpadded_len())
1383    }
1384
1385    pub fn to_bytes_extended<T: PacketWritable>(
1386        &self,
1387        writer: &mut PacketWriter<'_, T>,
1388    ) -> Result<(), SerializationError> {
1389        match self {
1390            Self::Ipv4Address(ipv4) => {
1391                writer.write_slice(&INIT_OPT_IPV4_ADDRESS.to_be_bytes())?;
1392                writer.write_slice(&8u16.to_be_bytes())?;
1393                writer.write_slice(&ipv4.to_be_bytes())?;
1394            }
1395            Self::Ipv6Address(ipv6) => {
1396                writer.write_slice(&INIT_OPT_IPV6_ADDRESS.to_be_bytes())?;
1397                writer.write_slice(&20u16.to_be_bytes())?;
1398                writer.write_slice(&ipv6.to_be_bytes())?;
1399            }
1400            Self::CookiePreservative(cookie_lifespan) => {
1401                writer.write_slice(&INIT_OPT_COOKIE_PRESERVATIVE.to_be_bytes())?;
1402                writer.write_slice(&8u16.to_be_bytes())?;
1403                writer.write_slice(&cookie_lifespan.to_be_bytes())?;
1404            }
1405            Self::HostnameAddress(addr) => {
1406                let unpadded_len = u16::try_from(self.unpadded_len())
1407                    .map_err(|_| SerializationError::length_encoding(SctpRef::name()))?;
1408                writer.write_slice(&INIT_OPT_HOSTNAME_ADDR.to_be_bytes())?;
1409                writer.write_slice(&unpadded_len.to_be_bytes())?;
1410                writer.write_slice(&addr)?;
1411                for _ in unpadded_len as usize..utils::padded_length::<4>(unpadded_len as usize) {
1412                    writer.write_slice(&[0])?;
1413                }
1414            }
1415            Self::SupportedAddressTypes(addr_types) => {
1416                let unpadded_len = u16::try_from(self.unpadded_len())
1417                    .map_err(|_| SerializationError::length_encoding(SctpRef::name()))?;
1418                writer.write_slice(&INIT_OPT_SUPP_ADDR_TYPES.to_be_bytes())?;
1419                writer.write_slice(&unpadded_len.to_be_bytes())?;
1420                for addr_type in addr_types {
1421                    writer.write_slice(&addr_type.to_be_bytes())?;
1422                }
1423
1424                for _ in unpadded_len as usize..utils::padded_length::<4>(unpadded_len as usize) {
1425                    writer.write_slice(&[0])?;
1426                }
1427            }
1428            Self::Unknown(opt_type, data) => {
1429                let unpadded_len = u16::try_from(self.unpadded_len())
1430                    .map_err(|_| SerializationError::length_encoding(SctpRef::name()))?;
1431                writer.write_slice(&opt_type.to_be_bytes())?;
1432                writer.write_slice(&unpadded_len.to_be_bytes())?;
1433                writer.write_slice(data)?;
1434                for _ in unpadded_len as usize..utils::padded_length::<4>(unpadded_len as usize) {
1435                    writer.write_slice(&[0])?;
1436                }
1437            }
1438        }
1439        Ok(())
1440    }
1441}
1442
1443#[cfg(feature = "alloc")]
1444impl From<InitOptionRef<'_>> for InitOption {
1445    #[inline]
1446    fn from(value: InitOptionRef<'_>) -> Self {
1447        Self::from(&value)
1448    }
1449}
1450
1451#[cfg(feature = "alloc")]
1452impl From<&InitOptionRef<'_>> for InitOption {
1453    fn from(value: &InitOptionRef<'_>) -> Self {
1454        match value.payload() {
1455            InitOptionPayloadRef::Ipv4Address(ipv4) => InitOption::Ipv4Address(ipv4),
1456            InitOptionPayloadRef::Ipv6Address(ipv6) => InitOption::Ipv6Address(ipv6),
1457            InitOptionPayloadRef::CookiePreservative(cookie) => {
1458                InitOption::CookiePreservative(cookie)
1459            }
1460            InitOptionPayloadRef::HostnameAddress(addr) => {
1461                InitOption::HostnameAddress(Vec::from(addr))
1462            }
1463            InitOptionPayloadRef::SupportedAddressTypes(mut addr_bytes) => {
1464                let mut v = Vec::new();
1465                while let (Some(&addr_arr), Some(remaining)) =
1466                    (utils::get_array(addr_bytes, 0), addr_bytes.get(2..))
1467                {
1468                    v.push(u16::from_be_bytes(addr_arr));
1469                    addr_bytes = remaining;
1470                }
1471                InitOption::SupportedAddressTypes(v)
1472            }
1473            InitOptionPayloadRef::Unknown(opt_type, value) => {
1474                InitOption::Unknown(opt_type, Vec::from(value))
1475            }
1476        }
1477    }
1478}
1479
1480#[derive(Clone, Copy, Debug)]
1481pub struct InitOptionRef<'a> {
1482    data: &'a [u8],
1483}
1484
1485impl<'a> InitOptionRef<'a> {
1486    #[inline]
1487    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
1488        Self::validate(bytes)?;
1489        Ok(Self::from_bytes_unchecked(bytes))
1490    }
1491
1492    #[inline]
1493    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
1494        InitOptionRef { data: bytes }
1495    }
1496
1497    pub fn validate(bytes: &'a [u8]) -> Result<(), ValidationError> {
1498        let header = (utils::to_array(bytes, 0), utils::to_array(bytes, 2));
1499        match header {
1500            (Some(opt_type_arr), Some(unpadded_len_arr)) => {
1501                let opt_type = u16::from_be_bytes(opt_type_arr);
1502                let unpadded_len = u16::from_be_bytes(unpadded_len_arr);
1503                let len = utils::padded_length::<4>(unpadded_len as usize);
1504
1505                if bytes.len() < len {
1506                    return Err(ValidationError {
1507                        layer: SctpRef::name(),
1508                        class: ValidationErrorClass::InsufficientBytes,
1509                        #[cfg(feature = "error_string")]
1510                        reason:
1511                            "insufficient bytes in SCTP INIT option for payload + padding bytes",
1512                    });
1513                }
1514
1515                let expected_unpadded_len = match opt_type {
1516                    INIT_OPT_IPV4_ADDRESS => Some(8),
1517                    INIT_OPT_IPV6_ADDRESS => Some(20),
1518                    INIT_OPT_COOKIE_PRESERVATIVE => Some(8),
1519                    _ => None,
1520                };
1521
1522                if let Some(e_len) = expected_unpadded_len {
1523                    if unpadded_len != e_len {
1524                        return Err(ValidationError {
1525                            layer: SctpRef::name(),
1526                            class: ValidationErrorClass::InvalidValue,
1527                            #[cfg(feature = "error_string")]            
1528                            reason: "SCTP INIT option Length field didn't match expected length based on Option Type",
1529                        });
1530                    }
1531                }
1532
1533                if opt_type == INIT_OPT_SUPP_ADDR_TYPES && unpadded_len % 2 != 0 {
1534                    return Err(ValidationError {
1535                        layer: SctpRef::name(),
1536                        class: ValidationErrorClass::InvalidValue,
1537                        #[cfg(feature = "error_string")]        
1538                        reason: "SCTP INIT option payload had missing or trailing byte for Supported Address Types option",
1539                    });
1540                }
1541
1542                if len < bytes.len() {
1543                    Err(ValidationError {
1544                        layer: SctpRef::name(),
1545                        class: ValidationErrorClass::ExcessBytes(bytes.len() - len),
1546                        #[cfg(feature = "error_string")]
1547                        reason: "extra bytes remain at end of SCTP INIT option",
1548                    })
1549                } else {
1550                    Ok(())
1551                }
1552            }
1553            _ => Err(ValidationError {
1554                layer: SctpRef::name(),
1555                class: ValidationErrorClass::InsufficientBytes,
1556                #[cfg(feature = "error_string")]
1557                reason: "insufficient bytes in SCTP INIT option for header",
1558            }),
1559        }
1560    }
1561
1562    #[inline]
1563    pub fn opt_type(&self) -> u16 {
1564        u16::from_be_bytes(utils::to_array(self.data, 0).unwrap())
1565    }
1566
1567    #[inline]
1568    pub fn unpadded_len(&self) -> u16 {
1569        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
1570    }
1571
1572    #[inline]
1573    pub fn len(&self) -> usize {
1574        utils::padded_length::<4>(self.unpadded_len() as usize)
1575    }
1576
1577    pub fn payload(&self) -> InitOptionPayloadRef<'a> {
1578        match self.opt_type() {
1579            INIT_OPT_IPV4_ADDRESS => InitOptionPayloadRef::Ipv4Address(u32::from_be_bytes(
1580                utils::to_array(self.data, 4).unwrap(),
1581            )),
1582            INIT_OPT_IPV6_ADDRESS => InitOptionPayloadRef::Ipv6Address(u128::from_be_bytes(
1583                utils::to_array::<16>(self.data, 4).unwrap(),
1584            )),
1585            INIT_OPT_COOKIE_PRESERVATIVE => InitOptionPayloadRef::CookiePreservative(
1586                u32::from_be_bytes(utils::to_array(self.data, 4).unwrap()),
1587            ),
1588            INIT_OPT_HOSTNAME_ADDR => InitOptionPayloadRef::HostnameAddress(
1589                self.data
1590                    .get(4..4 + self.unpadded_len().checked_sub(4).unwrap() as usize)
1591                    .unwrap(),
1592            ),
1593            INIT_OPT_SUPP_ADDR_TYPES => InitOptionPayloadRef::SupportedAddressTypes(
1594                self.data
1595                    .get(4..4 + self.unpadded_len().checked_sub(4).unwrap() as usize)
1596                    .unwrap(),
1597            ),
1598            _ => InitOptionPayloadRef::Unknown(
1599                self.opt_type(),
1600                self.data
1601                    .get(4..4 + self.unpadded_len().checked_sub(4).unwrap() as usize)
1602                    .unwrap(),
1603            ),
1604        }
1605    }
1606}
1607
1608pub enum InitOptionPayloadRef<'a> {
1609    Ipv4Address(u32),
1610    Ipv6Address(u128),
1611    CookiePreservative(u32),
1612    HostnameAddress(&'a [u8]),
1613    SupportedAddressTypes(&'a [u8]),
1614    Unknown(u16, &'a [u8]),
1615}
1616
1617#[derive(Clone, Debug)]
1618#[cfg(feature = "alloc")]
1619pub struct InitAckChunk {
1620    flags: u8,
1621    init_tag: u32,
1622    a_rwnd: u32,
1623    ostreams: u16,
1624    istreams: u16,
1625    init_tsn: u32,
1626    options: Vec<InitAckOption>,
1627}
1628
1629#[cfg(feature = "alloc")]
1630impl InitAckChunk {
1631    #[inline]
1632    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
1633        Self::validate(bytes)?;
1634        Ok(Self::from_bytes_unchecked(bytes))
1635    }
1636
1637    #[inline]
1638    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
1639        Self::from(InitAckChunkRef::from_bytes_unchecked(bytes))
1640    }
1641
1642    #[inline]
1643    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
1644        InitAckChunkRef::validate(bytes)
1645    }
1646
1647    #[inline]
1648    pub fn chunk_type(&self) -> u8 {
1649        CHUNK_TYPE_INIT_ACK
1650    }
1651
1652    #[inline]
1653    pub fn flags_raw(&self) -> u8 {
1654        self.flags
1655    }
1656
1657    #[inline]
1658    pub fn set_flags_raw(&mut self, flags: u8) {
1659        self.flags = flags;
1660    }
1661
1662    #[inline]
1663    pub fn unpadded_len(&self) -> usize {
1664        20 + self.options.iter().map(|o| o.len()).sum::<usize>()
1665    }
1666
1667    #[inline]
1668    pub fn len(&self) -> usize {
1669        utils::padded_length::<4>(self.unpadded_len())
1670    }
1671
1672    #[inline]
1673    pub fn init_tag(&self) -> u32 {
1674        self.init_tag
1675    }
1676
1677    #[inline]
1678    pub fn set_init_tag(&mut self, init_tag: u32) {
1679        self.init_tag = init_tag;
1680    }
1681
1682    #[inline]
1683    pub fn a_rwnd(&self) -> u32 {
1684        self.a_rwnd
1685    }
1686
1687    #[inline]
1688    pub fn set_a_rwnd(&mut self, a_rwnd: u32) {
1689        self.a_rwnd = a_rwnd;
1690    }
1691
1692    #[inline]
1693    pub fn ostreams(&self) -> u16 {
1694        self.ostreams
1695    }
1696
1697    #[inline]
1698    pub fn set_ostreams(&mut self, ostreams: u16) {
1699        self.ostreams = ostreams;
1700    }
1701
1702    #[inline]
1703    pub fn istreams(&self) -> u16 {
1704        self.istreams
1705    }
1706
1707    #[inline]
1708    pub fn set_istreams(&mut self, istreams: u16) {
1709        self.istreams = istreams;
1710    }
1711
1712    #[inline]
1713    pub fn init_tsn(&self) -> u32 {
1714        self.init_tsn
1715    }
1716
1717    #[inline]
1718    pub fn set_init_tsn(&mut self, init_tsn: u32) {
1719        self.init_tsn = init_tsn;
1720    }
1721
1722    #[inline]
1723    pub fn options(&self) -> &Vec<InitAckOption> {
1724        &self.options
1725    }
1726
1727    #[inline]
1728    pub fn options_mut(&mut self) -> &mut Vec<InitAckOption> {
1729        &mut self.options
1730    }
1731
1732    pub fn to_bytes_extended<T: PacketWritable>(
1733        &self,
1734        writer: &mut PacketWriter<'_, T>,
1735    ) -> Result<(), SerializationError> {
1736        writer.write_slice(&[CHUNK_TYPE_INIT_ACK, self.flags])?;
1737        writer.write_slice(
1738            &u16::try_from(self.unpadded_len())
1739                .map_err(|_| SerializationError::length_encoding(SctpRef::name()))?
1740                .to_be_bytes(),
1741        )?;
1742        writer.write_slice(&self.init_tag.to_be_bytes())?;
1743        writer.write_slice(&self.a_rwnd.to_be_bytes())?;
1744        writer.write_slice(&self.ostreams.to_be_bytes())?;
1745        writer.write_slice(&self.istreams.to_be_bytes())?;
1746        writer.write_slice(&self.init_tsn.to_be_bytes())?;
1747        for option in &self.options {
1748            option.to_bytes_extended(writer)?;
1749        }
1750
1751        Ok(())
1752    }
1753}
1754
1755#[cfg(feature = "alloc")]
1756impl From<InitAckChunkRef<'_>> for InitAckChunk {
1757    #[inline]
1758    fn from(value: InitAckChunkRef<'_>) -> Self {
1759        Self::from(&value)
1760    }
1761}
1762
1763#[cfg(feature = "alloc")]
1764impl From<&InitAckChunkRef<'_>> for InitAckChunk {
1765    fn from(value: &InitAckChunkRef<'_>) -> Self {
1766        let mut options = Vec::new();
1767        let iter = value.options_iter();
1768        for option in iter {
1769            options.push(option.into());
1770        }
1771
1772        InitAckChunk {
1773            flags: value.flags_raw(),
1774            init_tag: value.init_tag(),
1775            a_rwnd: value.a_rwnd(),
1776            ostreams: value.ostreams(),
1777            istreams: value.istreams(),
1778            init_tsn: value.init_tsn(),
1779            options,
1780        }
1781    }
1782}
1783
1784#[derive(Clone, Copy, Debug)]
1785pub struct InitAckChunkRef<'a> {
1786    data: &'a [u8],
1787}
1788
1789impl<'a> InitAckChunkRef<'a> {
1790    #[inline]
1791    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
1792        Self::validate(bytes)?;
1793        Ok(Self::from_bytes_unchecked(bytes))
1794    }
1795
1796    #[inline]
1797    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
1798        InitAckChunkRef { data: bytes }
1799    }
1800
1801    pub fn validate(bytes: &'a [u8]) -> Result<(), ValidationError> {
1802        match utils::to_array(bytes, 2) {
1803            Some(unpadded_len_arr) => {
1804                let len = u16::from_be_bytes(unpadded_len_arr) as usize;
1805
1806                if bytes.len() < cmp::max(len, 20) {
1807                    return Err(ValidationError {
1808                        layer: SctpRef::name(),
1809                        class: ValidationErrorClass::InsufficientBytes,
1810                        #[cfg(feature = "error_string")]        
1811                        reason: "insufficient bytes in SCTP INIT ACK chunk for header and optional parameters",
1812                    });
1813                }
1814
1815                if len % 4 != 0 {
1816                    return Err(ValidationError {
1817                        layer: SctpRef::name(),
1818                        class: ValidationErrorClass::InvalidValue,
1819                        #[cfg(feature = "error_string")]
1820                        reason: "SCTP INIT ACK chunk length was not a multiple of 4",
1821                    });
1822                }
1823
1824                if len < 20 {
1825                    return Err(ValidationError {
1826                        layer: SctpRef::name(),
1827                        class: ValidationErrorClass::InvalidValue,
1828                        #[cfg(feature = "error_string")]
1829                        reason: "length field of SCTP INIT ACK chunk was too short for header",
1830                    });
1831                }
1832
1833                let mut options = &bytes[20..];
1834                while !options.is_empty() {
1835                    match InitAckOptionRef::validate(options) {
1836                        Err(e) => {
1837                            if let ValidationErrorClass::ExcessBytes(extra) = e.class {
1838                                options = &options[options.len() - extra..];
1839                            } else {
1840                                return Err(e);
1841                            }
1842                        }
1843                        _ => break,
1844                    }
1845                }
1846
1847                if len < bytes.len() {
1848                    Err(ValidationError {
1849                        layer: SctpRef::name(),
1850                        class: ValidationErrorClass::ExcessBytes(bytes.len() - len),
1851                        #[cfg(feature = "error_string")]
1852                        reason: "extra bytes remain at end of SCTP INIT ACK chunk",
1853                    })
1854                } else {
1855                    Ok(())
1856                }
1857            }
1858            _ => Err(ValidationError {
1859                layer: SctpRef::name(),
1860                class: ValidationErrorClass::InsufficientBytes,
1861                #[cfg(feature = "error_string")]
1862                reason: "insufficient bytes in SCTP INIT ACK chunk for header Length field",
1863            }),
1864        }
1865    }
1866
1867    #[inline]
1868    pub fn chunk_type(&self) -> u8 {
1869        self.data[0]
1870    }
1871
1872    #[inline]
1873    pub fn flags_raw(&self) -> u8 {
1874        self.data[1]
1875    }
1876
1877    #[inline]
1878    pub fn unpadded_len(&self) -> u16 {
1879        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
1880    }
1881
1882    #[inline]
1883    pub fn len(&self) -> usize {
1884        utils::padded_length::<4>(self.unpadded_len() as usize)
1885    }
1886
1887    #[inline]
1888    pub fn init_tag(&self) -> u32 {
1889        u32::from_be_bytes(utils::to_array(self.data, 4).unwrap())
1890    }
1891
1892    #[inline]
1893    pub fn a_rwnd(&self) -> u32 {
1894        u32::from_be_bytes(utils::to_array(self.data, 8).unwrap())
1895    }
1896
1897    #[inline]
1898    pub fn ostreams(&self) -> u16 {
1899        u16::from_be_bytes(utils::to_array(self.data, 12).unwrap())
1900    }
1901
1902    #[inline]
1903    pub fn istreams(&self) -> u16 {
1904        u16::from_be_bytes(utils::to_array(self.data, 14).unwrap())
1905    }
1906
1907    #[inline]
1908    pub fn init_tsn(&self) -> u32 {
1909        u32::from_be_bytes(utils::to_array(self.data, 16).unwrap())
1910    }
1911
1912    #[inline]
1913    pub fn options_iter(&self) -> InitAckOptionsIterRef<'a> {
1914        InitAckOptionsIterRef {
1915            bytes: &self.data[20..],
1916        }
1917    }
1918}
1919
1920#[derive(Clone, Copy, Debug)]
1921pub struct InitAckOptionsIterRef<'a> {
1922    bytes: &'a [u8],
1923}
1924
1925impl<'a> Iterator for InitAckOptionsIterRef<'a> {
1926    type Item = InitAckOptionRef<'a>;
1927
1928    fn next(&mut self) -> Option<Self::Item> {
1929        let (opt_type, unpadded_len) = match (
1930            utils::get_array(self.bytes, 0).map(|&a| u16::from_be_bytes(a)),
1931            utils::get_array(self.bytes, 2).map(|&a| u16::from_be_bytes(a)),
1932        ) {
1933            (Some(t), Some(l)) => (t, l),
1934            _ => return None,
1935        };
1936
1937        let min_len = match opt_type {
1938            INIT_ACK_OPT_IPV4_ADDRESS => 8,
1939            INIT_ACK_OPT_IPV6_ADDRESS => 20,
1940            INIT_ACK_OPT_HOSTNAME_ADDR
1941            | INIT_ACK_OPT_STATE_COOKIE
1942            | INIT_ACK_OPT_UNRECOGNIZED_PARAM => 4,
1943            _ => 4,
1944        };
1945
1946        if self.bytes.len() < min_len {
1947            self.bytes = &[]; // Not needed, but this helps further calls to the iterator to short-circuit
1948            return None;
1949        }
1950
1951        let len = cmp::max(min_len, utils::padded_length::<4>(unpadded_len as usize));
1952        match (self.bytes.get(..len), self.bytes.get(len..)) {
1953            (Some(opt_bytes), Some(rem)) => {
1954                self.bytes = rem;
1955                Some(InitAckOptionRef::from_bytes_unchecked(opt_bytes))
1956            }
1957            _ => {
1958                // Just take whatever remaining bytes we can for the payload
1959                let opt_bytes = self.bytes;
1960                self.bytes = &[];
1961                Some(InitAckOptionRef::from_bytes_unchecked(opt_bytes))
1962            }
1963        }
1964    }
1965}
1966
1967#[derive(Clone, Debug)]
1968#[cfg(feature = "alloc")]
1969pub enum InitAckOption {
1970    StateCookie(Vec<u8>),
1971    Ipv4Address(u32),
1972    Ipv6Address(u128),
1973    UnrecognizedParameter(InitOption),
1974    HostnameAddress(Vec<u8>),
1975    Unknown(u16, Vec<u8>),
1976}
1977
1978#[cfg(feature = "alloc")]
1979impl InitAckOption {
1980    #[inline]
1981    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
1982        Self::validate(bytes)?;
1983        Ok(Self::from_bytes_unchecked(bytes))
1984    }
1985
1986    #[inline]
1987    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
1988        Self::from(InitAckOptionRef::from_bytes_unchecked(bytes))
1989    }
1990
1991    #[inline]
1992    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
1993        InitAckOptionRef::validate(bytes)
1994    }
1995
1996    pub fn option_type(&self) -> u16 {
1997        match self {
1998            Self::StateCookie(_) => INIT_ACK_OPT_STATE_COOKIE,
1999            Self::Ipv4Address(_) => INIT_ACK_OPT_IPV4_ADDRESS,
2000            Self::Ipv6Address(_) => INIT_ACK_OPT_IPV6_ADDRESS,
2001            Self::UnrecognizedParameter(_) => INIT_ACK_OPT_UNRECOGNIZED_PARAM,
2002            Self::HostnameAddress(_) => INIT_ACK_OPT_HOSTNAME_ADDR,
2003            Self::Unknown(t, _) => *t,
2004        }
2005    }
2006
2007    pub fn unpadded_len(&self) -> usize {
2008        match self {
2009            Self::StateCookie(s) => 4 + s.len(),
2010            Self::Ipv4Address(_) => 8,
2011            Self::Ipv6Address(_) => 20,
2012            Self::UnrecognizedParameter(p) => 4 + p.len(),
2013            // TODO: ^^ what if the parameter in question is between 65532-65535 bytes long? Unlikely, but could affect other implementations
2014            Self::HostnameAddress(h) => 4 + h.len(),
2015            Self::Unknown(_, v) => 4 + v.len(),
2016        }
2017    }
2018
2019    #[inline]
2020    pub fn len(&self) -> usize {
2021        utils::padded_length::<4>(self.unpadded_len())
2022    }
2023
2024    pub fn to_bytes_extended<T: PacketWritable>(
2025        &self,
2026        writer: &mut PacketWriter<'_, T>,
2027    ) -> Result<(), SerializationError> {
2028        let unpadded_len = u16::try_from(self.unpadded_len())
2029            .map_err(|_| SerializationError::length_encoding(SctpRef::name()))?
2030            .to_be_bytes();
2031
2032        match self {
2033            InitAckOption::StateCookie(c) => {
2034                writer.write_slice(&INIT_ACK_OPT_STATE_COOKIE.to_be_bytes())?;
2035                writer.write_slice(&unpadded_len)?;
2036                writer.write_slice(c)?;
2037                for _ in self.unpadded_len()..self.len() {
2038                    writer.write_slice(&[0])?;
2039                }
2040            }
2041            InitAckOption::Ipv4Address(ipv4) => {
2042                writer.write_slice(&INIT_ACK_OPT_IPV4_ADDRESS.to_be_bytes())?;
2043                writer.write_slice(&unpadded_len)?;
2044                writer.write_slice(&ipv4.to_be_bytes())?;
2045            }
2046            InitAckOption::Ipv6Address(ipv6) => {
2047                writer.write_slice(&INIT_ACK_OPT_IPV6_ADDRESS.to_be_bytes())?;
2048                writer.write_slice(&unpadded_len)?;
2049                writer.write_slice(&ipv6.to_be_bytes())?;
2050            }
2051            InitAckOption::UnrecognizedParameter(param) => {
2052                writer.write_slice(&INIT_ACK_OPT_UNRECOGNIZED_PARAM.to_be_bytes())?;
2053                writer.write_slice(&unpadded_len)?;
2054                param.to_bytes_extended(writer)?;
2055                // No need for padding--parameter is type-checked and guaranteed to be padded
2056            }
2057            InitAckOption::HostnameAddress(host) => {
2058                writer.write_slice(&INIT_ACK_OPT_HOSTNAME_ADDR.to_be_bytes())?;
2059                writer.write_slice(&unpadded_len)?;
2060                writer.write_slice(&host)?;
2061                for _ in self.unpadded_len()..self.len() {
2062                    writer.write_slice(&[0])?;
2063                }
2064            }
2065            InitAckOption::Unknown(t, v) => {
2066                writer.write_slice(&t.to_be_bytes())?;
2067                writer.write_slice(&unpadded_len)?;
2068                writer.write_slice(v)?;
2069                for _ in self.unpadded_len()..self.len() {
2070                    writer.write_slice(&[0])?;
2071                }
2072            }
2073        }
2074
2075        Ok(())
2076    }
2077}
2078
2079#[cfg(feature = "alloc")]
2080impl From<InitAckOptionRef<'_>> for InitAckOption {
2081    #[inline]
2082    fn from(value: InitAckOptionRef<'_>) -> Self {
2083        Self::from(&value)
2084    }
2085}
2086
2087#[cfg(feature = "alloc")]
2088impl From<&InitAckOptionRef<'_>> for InitAckOption {
2089    fn from(value: &InitAckOptionRef<'_>) -> Self {
2090        match value.payload() {
2091            InitAckOptionPayloadRef::StateCookie(cookie) => {
2092                InitAckOption::StateCookie(Vec::from(cookie))
2093            }
2094            InitAckOptionPayloadRef::Ipv4Address(ipv4) => InitAckOption::Ipv4Address(ipv4),
2095            InitAckOptionPayloadRef::Ipv6Address(ipv6) => InitAckOption::Ipv6Address(ipv6),
2096            InitAckOptionPayloadRef::UnrecognizedParameter(param) => {
2097                InitAckOption::UnrecognizedParameter(param.into())
2098            }
2099            InitAckOptionPayloadRef::HostnameAddress(host) => {
2100                InitAckOption::HostnameAddress(Vec::from(host))
2101            }
2102            InitAckOptionPayloadRef::Unknown(t, v) => InitAckOption::Unknown(t, Vec::from(v)),
2103        }
2104    }
2105}
2106
2107#[derive(Clone, Copy, Debug)]
2108pub struct InitAckOptionRef<'a> {
2109    data: &'a [u8],
2110}
2111
2112impl<'a> InitAckOptionRef<'a> {
2113    #[inline]
2114    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
2115        Self::validate(bytes)?;
2116        Ok(Self::from_bytes_unchecked(bytes))
2117    }
2118
2119    #[inline]
2120    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
2121        InitAckOptionRef { data: bytes }
2122    }
2123
2124    pub fn validate(bytes: &'a [u8]) -> Result<(), ValidationError> {
2125        let header = (utils::to_array(bytes, 0), utils::to_array(bytes, 2));
2126        match header {
2127            (Some(opt_type_arr), Some(unpadded_len_arr)) => {
2128                let opt_type = u16::from_be_bytes(opt_type_arr);
2129                let unpadded_len = u16::from_be_bytes(unpadded_len_arr);
2130                let len = utils::padded_length::<4>(unpadded_len as usize);
2131
2132                if bytes.len() < cmp::max(len, 4) {
2133                    return Err(ValidationError {
2134                        layer: SctpRef::name(),
2135                        class: ValidationErrorClass::InsufficientBytes,
2136                        #[cfg(feature = "error_string")]
2137                        reason:
2138                            "insufficient bytes in SCTP INIT ACK option for payload + padding bytes",
2139                    });
2140                }
2141
2142                let expected_unpadded_len = match opt_type {
2143                    INIT_ACK_OPT_IPV4_ADDRESS => Some(8),
2144                    INIT_ACK_OPT_IPV6_ADDRESS => Some(20),
2145                    _ => None,
2146                };
2147
2148                if let Some(e_len) = expected_unpadded_len {
2149                    if unpadded_len != e_len {
2150                        return Err(ValidationError {
2151                            layer: SctpRef::name(),
2152                            class: ValidationErrorClass::InvalidValue,
2153                            #[cfg(feature = "error_string")]            
2154                            reason: "SCTP INIT ACK option Length field didn't match expected length based on Option Type",
2155                        });
2156                    }
2157                } else if unpadded_len < 4 {
2158                    return Err(ValidationError {
2159                        layer: SctpRef::name(),
2160                        class: ValidationErrorClass::InvalidValue,
2161                        #[cfg(feature = "error_string")]
2162                        reason: "SCTP INIT ACK option Length field too short to cover header",
2163                    });
2164                }
2165
2166                if opt_type == INIT_ACK_OPT_UNRECOGNIZED_PARAM {
2167                    // Verify that payload is actually a well-formed INIT Option
2168                    match InitOptionRef::validate(&bytes[4..len]) {
2169                        Ok(_) => (),
2170                        Err(_) => return Err(ValidationError {
2171                            layer: SctpRef::name(),
2172                            class: ValidationErrorClass::InvalidValue,
2173                            #[cfg(feature = "error_string")]            
2174                            reason: "SCTP INIT ACK Unrecognized Parameter Option had malformed INIT parameter in its payload",
2175                        })
2176                    };
2177                }
2178
2179                if len < bytes.len() {
2180                    Err(ValidationError {
2181                        layer: SctpRef::name(),
2182                        class: ValidationErrorClass::ExcessBytes(bytes.len() - len),
2183                        #[cfg(feature = "error_string")]
2184                        reason: "extra bytes remain at end of SCTP INIT ACK Option",
2185                    })
2186                } else {
2187                    Ok(())
2188                }
2189            }
2190            _ => Err(ValidationError {
2191                layer: SctpRef::name(),
2192                class: ValidationErrorClass::InsufficientBytes,
2193                #[cfg(feature = "error_string")]
2194                reason: "insufficient bytes in SCTP INIT ACK Option for header",
2195            }),
2196        }
2197    }
2198
2199    #[inline]
2200    pub fn opt_type(&self) -> u16 {
2201        u16::from_be_bytes(utils::to_array(self.data, 0).unwrap())
2202    }
2203
2204    #[inline]
2205    pub fn unpadded_len(&self) -> u16 {
2206        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
2207    }
2208
2209    #[inline]
2210    pub fn len(&self) -> usize {
2211        utils::padded_length::<4>(self.unpadded_len() as usize)
2212    }
2213
2214    pub fn payload(&self) -> InitAckOptionPayloadRef<'a> {
2215        match self.opt_type() {
2216            INIT_ACK_OPT_IPV4_ADDRESS => InitAckOptionPayloadRef::Ipv4Address(u32::from_be_bytes(
2217                utils::to_array(self.data, 4).unwrap(),
2218            )),
2219            INIT_ACK_OPT_IPV6_ADDRESS => InitAckOptionPayloadRef::Ipv6Address(u128::from_be_bytes(
2220                utils::to_array::<16>(self.data, 4).unwrap(),
2221            )),
2222            INIT_ACK_OPT_HOSTNAME_ADDR => InitAckOptionPayloadRef::HostnameAddress(
2223                &self.data[4..self.unpadded_len() as usize],
2224            ),
2225            INIT_ACK_OPT_STATE_COOKIE => InitAckOptionPayloadRef::StateCookie(
2226                &self.data[4..4 + self.unpadded_len() as usize],
2227            ),
2228            INIT_ACK_OPT_UNRECOGNIZED_PARAM => InitAckOptionPayloadRef::UnrecognizedParameter(
2229                InitOptionRef::from_bytes_unchecked(&self.data[4..self.unpadded_len() as usize]),
2230            ),
2231            _ => InitAckOptionPayloadRef::Unknown(
2232                self.opt_type(),
2233                &self.data[4..self.unpadded_len() as usize],
2234            ),
2235        }
2236    }
2237}
2238
2239pub enum InitAckOptionPayloadRef<'a> {
2240    StateCookie(&'a [u8]),
2241    Ipv4Address(u32),
2242    Ipv6Address(u128),
2243    UnrecognizedParameter(InitOptionRef<'a>),
2244    HostnameAddress(&'a [u8]),
2245    Unknown(u16, &'a [u8]),
2246}
2247
2248#[derive(Clone, Debug)]
2249#[cfg(feature = "alloc")]
2250pub struct SackChunk {
2251    flags: u8,
2252    cum_tsn_ack: u32,
2253    a_rwnd: u32,
2254    gap_ack_blocks: Vec<(u16, u16)>,
2255    duplicate_tsns: Vec<u32>,
2256}
2257
2258#[cfg(feature = "alloc")]
2259impl SackChunk {
2260    #[inline]
2261    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
2262        Self::validate(bytes)?;
2263        Ok(Self::from_bytes_unchecked(bytes))
2264    }
2265
2266    #[inline]
2267    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
2268        Self::from(SackChunkRef::from_bytes_unchecked(bytes))
2269    }
2270
2271    #[inline]
2272    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
2273        SackChunkRef::validate(bytes)
2274    }
2275
2276    #[inline]
2277    pub fn chunk_type(&self) -> u8 {
2278        CHUNK_TYPE_SACK
2279    }
2280
2281    #[inline]
2282    pub fn flags_raw(&self) -> u8 {
2283        self.flags
2284    }
2285
2286    #[inline]
2287    pub fn set_flags_raw(&mut self, flags: u8) {
2288        self.flags = flags;
2289    }
2290
2291    #[inline]
2292    pub fn unpadded_len(&self) -> usize {
2293        16 + (self.gap_ack_blocks.len() * 4) + (self.duplicate_tsns.len() * 4)
2294    }
2295
2296    #[inline]
2297    pub fn len(&self) -> usize {
2298        utils::padded_length::<4>(self.unpadded_len())
2299    }
2300
2301    #[inline]
2302    pub fn ack(&self) -> u32 {
2303        self.cum_tsn_ack
2304    }
2305
2306    #[inline]
2307    pub fn set_ack(&mut self, ack: u32) {
2308        self.cum_tsn_ack = ack;
2309    }
2310
2311    #[inline]
2312    pub fn a_rwnd(&self) -> u32 {
2313        self.a_rwnd
2314    }
2315
2316    #[inline]
2317    pub fn set_a_rwnd(&mut self, a_rwnd: u32) {
2318        self.a_rwnd = a_rwnd;
2319    }
2320
2321    #[inline]
2322    pub fn gap_ack_blocks(&self) -> &Vec<(u16, u16)> {
2323        &self.gap_ack_blocks
2324    }
2325
2326    #[inline]
2327    pub fn gap_ack_blocks_mut(&mut self) -> &mut Vec<(u16, u16)> {
2328        &mut self.gap_ack_blocks
2329    }
2330
2331    #[inline]
2332    pub fn duplicate_tsns(&self) -> &Vec<u32> {
2333        &self.duplicate_tsns
2334    }
2335
2336    #[inline]
2337    pub fn duplicate_tsns_mut(&mut self) -> &mut Vec<u32> {
2338        &mut self.duplicate_tsns
2339    }
2340
2341    pub fn to_bytes_extended<T: PacketWritable>(
2342        &self,
2343        writer: &mut PacketWriter<'_, T>,
2344    ) -> Result<(), SerializationError> {
2345        writer.write_slice(&[CHUNK_TYPE_SACK])?;
2346        writer.write_slice(&[self.flags])?;
2347        writer.write_slice(
2348            &u16::try_from(self.unpadded_len())
2349                .map_err(|_| SerializationError::length_encoding(SctpRef::name()))?
2350                .to_be_bytes(),
2351        )?;
2352        writer.write_slice(&self.cum_tsn_ack.to_be_bytes())?;
2353        writer.write_slice(&self.a_rwnd.to_be_bytes())?;
2354        writer.write_slice(
2355            &u16::try_from(self.gap_ack_blocks.len())
2356                .map_err(|_| SerializationError::length_encoding(SctpRef::name()))?
2357                .to_be_bytes(),
2358        )?;
2359        writer.write_slice(
2360            &u16::try_from(self.duplicate_tsns.len())
2361                .map_err(|_| SerializationError::length_encoding(SctpRef::name()))?
2362                .to_be_bytes(),
2363        )?;
2364        for (gap_ack_start, gap_ack_end) in &self.gap_ack_blocks {
2365            writer.write_slice(&gap_ack_start.to_be_bytes())?;
2366            writer.write_slice(&gap_ack_end.to_be_bytes())?;
2367        }
2368
2369        for dup_tsn in &self.duplicate_tsns {
2370            writer.write_slice(&dup_tsn.to_be_bytes())?;
2371        }
2372        // All parameters are multiples of 4, so no padding at end
2373
2374        Ok(())
2375    }
2376}
2377
2378#[cfg(feature = "alloc")]
2379impl From<SackChunkRef<'_>> for SackChunk {
2380    #[inline]
2381    fn from(value: SackChunkRef<'_>) -> Self {
2382        Self::from(&value)
2383    }
2384}
2385
2386#[cfg(feature = "alloc")]
2387impl From<&SackChunkRef<'_>> for SackChunk {
2388    fn from(value: &SackChunkRef<'_>) -> Self {
2389        let mut gap_ack_blocks = Vec::new();
2390        for gap_ack in value.gap_ack_blocks_iter() {
2391            gap_ack_blocks.push(gap_ack);
2392        }
2393
2394        let mut duplicate_tsns = Vec::new();
2395        for dup_tsn in value.duplicate_tsn_iter() {
2396            duplicate_tsns.push(dup_tsn);
2397        }
2398
2399        SackChunk {
2400            flags: value.flags_raw(),
2401            cum_tsn_ack: value.ack(),
2402            a_rwnd: value.a_rwnd(),
2403            gap_ack_blocks,
2404            duplicate_tsns,
2405        }
2406    }
2407}
2408
2409#[derive(Clone, Copy, Debug)]
2410pub struct SackChunkRef<'a> {
2411    data: &'a [u8],
2412}
2413
2414impl<'a> SackChunkRef<'a> {
2415    #[inline]
2416    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
2417        Self::validate(bytes)?;
2418        Ok(Self::from_bytes_unchecked(bytes))
2419    }
2420
2421    #[inline]
2422    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
2423        SackChunkRef { data: bytes }
2424    }
2425
2426    pub fn validate(bytes: &'a [u8]) -> Result<(), ValidationError> {
2427        match utils::to_array(bytes, 2) {
2428            Some(unpadded_len_arr) => {
2429                let len = u16::from_be_bytes(unpadded_len_arr) as usize;
2430
2431                if bytes.len() < cmp::max(len, 16) {
2432                    return Err(ValidationError {
2433                        layer: SctpRef::name(),
2434                        class: ValidationErrorClass::InsufficientBytes,
2435                        #[cfg(feature = "error_string")]        
2436                        reason: "insufficient bytes in SCTP SACK chunk for header and optional parameters",
2437                    });
2438                }
2439
2440                if len % 4 != 0 {
2441                    return Err(ValidationError {
2442                        layer: SctpRef::name(),
2443                        class: ValidationErrorClass::InvalidValue,
2444                        #[cfg(feature = "error_string")]
2445                        reason: "SCTP SACK chunk length must be a multiple of 4",
2446                    });
2447                }
2448
2449                if len < 16 {
2450                    return Err(ValidationError {
2451                        layer: SctpRef::name(),
2452                        class: ValidationErrorClass::InvalidValue,
2453                        #[cfg(feature = "error_string")]
2454                        reason: "length field of SCTP SACK chunk was too short for header",
2455                    });
2456                }
2457
2458                let (gap_ack_cnt, dup_tsn_cnt) = match (utils::to_array(bytes, 12), utils::to_array(bytes, 14)) {
2459                    (Some(gap_ack_cnt_arr), Some(dup_tsn_cnt_arr)) => (u16::from_be_bytes(gap_ack_cnt_arr) as usize, u16::from_be_bytes(dup_tsn_cnt_arr) as usize),
2460                    _ => return Err(ValidationError {
2461                        layer: SctpRef::name(),
2462                        class: ValidationErrorClass::InsufficientBytes,
2463                        #[cfg(feature = "error_string")]        
2464                        reason: "insufficient bytes in SCTP SACK chunk for Number of Duplicate TSNs field"
2465                    })
2466                };
2467
2468                if 16 + (gap_ack_cnt * 4) + (dup_tsn_cnt * 4) != len {
2469                    return Err(ValidationError {
2470                        layer: SctpRef::name(),
2471                        class: ValidationErrorClass::InvalidValue,
2472                        #[cfg(feature = "error_string")]        
2473                        reason: "SCTP SACK chunk Length field did not match the total length of header + Gap Ack Blocks + Duplicate TSNs"
2474                    });
2475                }
2476
2477                if len < bytes.len() {
2478                    Err(ValidationError {
2479                        layer: SctpRef::name(),
2480                        class: ValidationErrorClass::ExcessBytes(bytes.len() - len),
2481                        #[cfg(feature = "error_string")]
2482                        reason: "extra bytes remain at end of SCTP SACK chunk",
2483                    })
2484                } else {
2485                    Ok(())
2486                }
2487            }
2488            _ => Err(ValidationError {
2489                layer: SctpRef::name(),
2490                class: ValidationErrorClass::InsufficientBytes,
2491                #[cfg(feature = "error_string")]
2492                reason: "insufficient bytes in SCTP SACK chunk for header Length field",
2493            }),
2494        }
2495    }
2496
2497    #[inline]
2498    pub fn chunk_type(&self) -> u8 {
2499        self.data[0]
2500    }
2501
2502    #[inline]
2503    pub fn flags_raw(&self) -> u8 {
2504        self.data[1]
2505    }
2506
2507    #[inline]
2508    pub fn unpadded_len(&self) -> u16 {
2509        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
2510    }
2511
2512    #[inline]
2513    pub fn len(&self) -> usize {
2514        utils::padded_length::<4>(self.unpadded_len() as usize)
2515    }
2516
2517    #[inline]
2518    pub fn ack(&self) -> u32 {
2519        u32::from_be_bytes(utils::to_array(self.data, 4).unwrap())
2520    }
2521
2522    #[inline]
2523    pub fn a_rwnd(&self) -> u32 {
2524        u32::from_be_bytes(utils::to_array(self.data, 8).unwrap())
2525    }
2526
2527    #[inline]
2528    pub fn gap_ack_block_cnt(&self) -> u16 {
2529        u16::from_be_bytes(utils::to_array(self.data, 12).unwrap())
2530    }
2531
2532    #[inline]
2533    pub fn dup_tsn_cnt(&self) -> u16 {
2534        u16::from_be_bytes(utils::to_array(self.data, 14).unwrap())
2535    }
2536
2537    #[inline]
2538    pub fn gap_ack_blocks_iter(&self) -> GapAckBlockIterRef<'a> {
2539        GapAckBlockIterRef {
2540            bytes: &self.data[16..],
2541            block_idx: 0,
2542            block_total: self.gap_ack_block_cnt() as usize,
2543        }
2544    }
2545
2546    #[inline]
2547    pub fn duplicate_tsn_iter(&self) -> DuplicateTsnIterRef {
2548        DuplicateTsnIterRef {
2549            bytes: &self.data[16 + (4 * self.gap_ack_block_cnt() as usize)..],
2550            tsn_idx: 0,
2551            tsn_total: self.dup_tsn_cnt() as usize,
2552        }
2553    }
2554}
2555
2556#[derive(Clone, Copy, Debug)]
2557pub struct GapAckBlockIterRef<'a> {
2558    bytes: &'a [u8],
2559    block_idx: usize,
2560    block_total: usize,
2561}
2562
2563impl<'b> Iterator for GapAckBlockIterRef<'b> {
2564    type Item = (u16, u16);
2565
2566    fn next(&mut self) -> Option<Self::Item> {
2567        if self.block_idx == self.block_total {
2568            return None;
2569        }
2570
2571        let start = u16::from_be_bytes(utils::to_array(self.bytes, 0).unwrap());
2572        let end = u16::from_be_bytes(utils::to_array(self.bytes, 2).unwrap());
2573        self.bytes = &self.bytes[4..];
2574        self.block_idx += 1;
2575
2576        Some((start, end))
2577    }
2578}
2579
2580#[derive(Clone, Copy, Debug)]
2581pub struct DuplicateTsnIterRef<'a> {
2582    bytes: &'a [u8],
2583    tsn_idx: usize,
2584    tsn_total: usize,
2585}
2586
2587impl<'b> Iterator for DuplicateTsnIterRef<'b> {
2588    type Item = u32;
2589
2590    fn next(&mut self) -> Option<Self::Item> {
2591        if self.tsn_idx == self.tsn_total {
2592            return None;
2593        }
2594
2595        let dup_tsn = u32::from_be_bytes(utils::to_array(self.bytes, 0).unwrap());
2596        self.bytes = &self.bytes[4..];
2597        self.tsn_idx += 1;
2598
2599        Some(dup_tsn)
2600    }
2601}
2602
2603#[derive(Clone, Debug)]
2604#[cfg(feature = "alloc")]
2605pub struct HeartbeatChunk {
2606    flags: u8,
2607    heartbeat: Vec<u8>,
2608}
2609
2610#[cfg(feature = "alloc")]
2611impl HeartbeatChunk {
2612    #[inline]
2613    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
2614        Self::validate(bytes)?;
2615        Ok(Self::from_bytes_unchecked(bytes))
2616    }
2617
2618    #[inline]
2619    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
2620        Self::from(HeartbeatChunkRef::from_bytes_unchecked(bytes))
2621    }
2622
2623    #[inline]
2624    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
2625        HeartbeatChunkRef::validate(bytes)
2626    }
2627
2628    #[inline]
2629    pub fn chunk_type(&self) -> u8 {
2630        CHUNK_TYPE_HEARTBEAT
2631    }
2632
2633    #[inline]
2634    pub fn flags(&self) -> u8 {
2635        self.flags
2636    }
2637
2638    #[inline]
2639    pub fn unpadded_len(&self) -> usize {
2640        8 + self.heartbeat.len()
2641    }
2642
2643    #[inline]
2644    pub fn len(&self) -> usize {
2645        utils::padded_length::<4>(self.unpadded_len())
2646    }
2647
2648    #[inline]
2649    pub fn heartbeat(&self) -> &Vec<u8> {
2650        &self.heartbeat
2651    }
2652
2653    #[inline]
2654    pub fn heartbeat_mut(&mut self) -> &mut Vec<u8> {
2655        &mut self.heartbeat
2656    }
2657
2658    pub fn to_bytes_extended<T: PacketWritable>(
2659        &self,
2660        writer: &mut PacketWriter<'_, T>,
2661    ) -> Result<(), SerializationError> {
2662        writer.write_slice(&[CHUNK_TYPE_HEARTBEAT, self.flags])?;
2663        writer.write_slice(
2664            &u16::try_from(self.unpadded_len())
2665                .map_err(|_| SerializationError::length_encoding(SctpRef::name()))?
2666                .to_be_bytes(),
2667        )?;
2668        writer.write_slice(&1u16.to_be_bytes())?; // HEARTBEAT_OPT_HEARTBEAT_INFO (the only option available for HEARTBEAT chunks)
2669        writer.write_slice(
2670            &u16::try_from(self.heartbeat.len())
2671                .map_err(|_| SerializationError::length_encoding(SctpRef::name()))?
2672                .to_be_bytes(),
2673        )?;
2674        writer.write_slice(&self.heartbeat)?;
2675        for _ in self.unpadded_len()..self.len() {
2676            writer.write_slice(&[0])?;
2677        }
2678
2679        Ok(())
2680    }
2681}
2682
2683#[cfg(feature = "alloc")]
2684impl From<HeartbeatChunkRef<'_>> for HeartbeatChunk {
2685    #[inline]
2686    fn from(value: HeartbeatChunkRef<'_>) -> Self {
2687        Self::from(&value)
2688    }
2689}
2690
2691#[cfg(feature = "alloc")]
2692impl From<&HeartbeatChunkRef<'_>> for HeartbeatChunk {
2693    #[inline]
2694    fn from(value: &HeartbeatChunkRef<'_>) -> Self {
2695        HeartbeatChunk {
2696            flags: value.flags_raw(),
2697            heartbeat: Vec::from(value.heartbeat_info().heartbeat()),
2698        }
2699    }
2700}
2701
2702#[derive(Clone, Copy, Debug)]
2703pub struct HeartbeatChunkRef<'a> {
2704    data: &'a [u8],
2705}
2706
2707impl<'a> HeartbeatChunkRef<'a> {
2708    #[inline]
2709    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
2710        Self::validate(bytes)?;
2711        Ok(Self::from_bytes_unchecked(bytes))
2712    }
2713
2714    #[inline]
2715    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
2716        HeartbeatChunkRef { data: bytes }
2717    }
2718
2719    pub fn validate(bytes: &'a [u8]) -> Result<(), ValidationError> {
2720        match utils::to_array(bytes, 2) {
2721            Some(unpadded_len_arr) => {
2722                let unpadded_len = u16::from_be_bytes(unpadded_len_arr) as usize;
2723                let len = utils::padded_length::<4>(unpadded_len);
2724
2725                if bytes.len() < cmp::max(len, 8) {
2726                    return Err(ValidationError {
2727                        layer: SctpRef::name(),
2728                        class: ValidationErrorClass::InsufficientBytes,
2729                        #[cfg(feature = "error_string")]        
2730                        reason: "insufficient bytes in SCTP HEARTBEAT chunk for header + Heartbeat Info option",
2731                    });
2732                }
2733
2734                #[allow(unused_variables)]
2735                if let Err(e) = HeartbeatInfoRef::validate(&bytes[4..len]) {
2736                    return Err(ValidationError {
2737                        layer: SctpRef::name(),
2738                        class: ValidationErrorClass::InvalidValue,
2739                        #[cfg(feature = "error_string")]
2740                        reason: e.reason,
2741                    });
2742                }
2743
2744                for b in bytes.iter().take(len).skip(unpadded_len) {
2745                    if *b != 0 {
2746                        return Err(ValidationError {
2747                            layer: SctpRef::name(),
2748                            class: ValidationErrorClass::InvalidValue,
2749                            #[cfg(feature = "error_string")]
2750                            reason: "invalid nonzero padding values at end of SCTP HEARTBEAT chunk",
2751                        });
2752                    }
2753                }
2754
2755                if len < bytes.len() {
2756                    Err(ValidationError {
2757                        layer: SctpRef::name(),
2758                        class: ValidationErrorClass::ExcessBytes(bytes.len() - len),
2759                        #[cfg(feature = "error_string")]
2760                        reason: "extra bytes remain at end of SCTP HEARTBEAT chunk",
2761                    })
2762                } else {
2763                    Ok(())
2764                }
2765            }
2766            _ => Err(ValidationError {
2767                layer: SctpRef::name(),
2768                class: ValidationErrorClass::InsufficientBytes,
2769                #[cfg(feature = "error_string")]
2770                reason: "insufficient bytes in SCTP HEARTBEAT chunk for header",
2771            }),
2772        }
2773    }
2774
2775    #[inline]
2776    pub fn chunk_type(&self) -> u8 {
2777        self.data[0]
2778    }
2779
2780    #[inline]
2781    pub fn flags_raw(&self) -> u8 {
2782        self.data[1]
2783    }
2784
2785    #[inline]
2786    pub fn unpadded_len(&self) -> u16 {
2787        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
2788    }
2789
2790    #[inline]
2791    pub fn len(&self) -> usize {
2792        utils::padded_length::<4>(self.unpadded_len() as usize)
2793    }
2794
2795    #[inline]
2796    pub fn heartbeat_info(&self) -> HeartbeatInfoRef<'a> {
2797        HeartbeatInfoRef {
2798            data: self.data.get(4..).unwrap(),
2799        }
2800    }
2801}
2802
2803#[derive(Clone, Copy, Debug)]
2804pub struct HeartbeatInfoRef<'a> {
2805    data: &'a [u8],
2806}
2807
2808impl<'a> HeartbeatInfoRef<'a> {
2809    #[inline]
2810    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
2811        Self::validate(bytes)?;
2812        Ok(Self::from_bytes_unchecked(bytes))
2813    }
2814
2815    #[inline]
2816    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
2817        HeartbeatInfoRef { data: bytes }
2818    }
2819
2820    pub fn validate(bytes: &'a [u8]) -> Result<(), ValidationError> {
2821        match utils::to_array(bytes, 2) {
2822            Some(unpadded_len_arr) => {
2823                let unpadded_len = u16::from_be_bytes(unpadded_len_arr);
2824                let len = utils::padded_length::<4>(unpadded_len as usize);
2825
2826                if len > bytes.len() {
2827                    return Err(ValidationError {
2828                        layer: SctpRef::name(),
2829                        class: ValidationErrorClass::InsufficientBytes,
2830                        #[cfg(feature = "error_string")]        
2831                        reason: "insufficient bytes in SCTP HEARTBEAT chunk Heartbeat Info option for Heartbeat field + padding bytes",
2832                    });
2833                }
2834
2835                if len < bytes.len() {
2836                    Err(ValidationError {
2837                        layer: SctpRef::name(),
2838                        class: ValidationErrorClass::ExcessBytes(bytes.len() - len),
2839                        #[cfg(feature = "error_string")]        
2840                        reason: "extra bytes remain at end of SCTP HEARTBEAT chunk Heartbeat Info option",
2841                    })
2842                } else {
2843                    Ok(())
2844                }
2845            }
2846            _ => Err(ValidationError {
2847                layer: SctpRef::name(),
2848                class: ValidationErrorClass::InsufficientBytes,
2849                #[cfg(feature = "error_string")]
2850                reason:
2851                    "insufficient bytes in SCTP HEARTBEAT chunk Heartbeat Info option for header",
2852            }),
2853        }
2854    }
2855
2856    #[inline]
2857    pub fn opt_type(&self) -> u16 {
2858        u16::from_be_bytes(utils::to_array(self.data, 0).unwrap())
2859    }
2860
2861    #[inline]
2862    pub fn unpadded_len(&self) -> u16 {
2863        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
2864    }
2865
2866    #[inline]
2867    pub fn len(&self) -> usize {
2868        utils::padded_length::<4>(self.unpadded_len() as usize)
2869    }
2870
2871    #[inline]
2872    pub fn heartbeat(&self) -> &'a [u8] {
2873        &self.data[4..self.unpadded_len() as usize]
2874    }
2875}
2876
2877#[derive(Clone, Debug)]
2878#[cfg(feature = "alloc")]
2879pub struct HeartbeatAckChunk {
2880    flags: u8,
2881    heartbeat: Vec<u8>,
2882}
2883
2884#[cfg(feature = "alloc")]
2885impl HeartbeatAckChunk {
2886    #[inline]
2887    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
2888        Self::validate(bytes)?;
2889        Ok(Self::from_bytes_unchecked(bytes))
2890    }
2891
2892    #[inline]
2893    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
2894        Self::from(HeartbeatAckChunkRef::from_bytes_unchecked(bytes))
2895    }
2896
2897    #[inline]
2898    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
2899        HeartbeatAckChunkRef::validate(bytes)
2900    }
2901
2902    #[inline]
2903    pub fn chunk_type(&self) -> u8 {
2904        CHUNK_TYPE_HEARTBEAT_ACK
2905    }
2906
2907    #[inline]
2908    pub fn flags(&self) -> u8 {
2909        self.flags
2910    }
2911
2912    #[inline]
2913    pub fn unpadded_len(&self) -> usize {
2914        8 + self.heartbeat.len()
2915    }
2916
2917    #[inline]
2918    pub fn len(&self) -> usize {
2919        utils::padded_length::<4>(self.unpadded_len())
2920    }
2921
2922    #[inline]
2923    pub fn heartbeat(&self) -> &Vec<u8> {
2924        &self.heartbeat
2925    }
2926
2927    #[inline]
2928    pub fn heartbeat_mut(&mut self) -> &mut Vec<u8> {
2929        &mut self.heartbeat
2930    }
2931
2932    pub fn to_bytes_extended<T: PacketWritable>(
2933        &self,
2934        writer: &mut PacketWriter<'_, T>,
2935    ) -> Result<(), SerializationError> {
2936        writer.write_slice(&[CHUNK_TYPE_HEARTBEAT_ACK, self.flags])?;
2937        writer.write_slice(
2938            &u16::try_from(self.unpadded_len())
2939                .map_err(|_| SerializationError::length_encoding(SctpRef::name()))?
2940                .to_be_bytes(),
2941        )?;
2942        writer.write_slice(&1u16.to_be_bytes())?; // HEARTBEAT_ACK_OPT_HEARTBEAT_INFO - the only option available, so we don't define it
2943        writer.write_slice(
2944            &u16::try_from(self.heartbeat.len())
2945                .map_err(|_| SerializationError::length_encoding(SctpRef::name()))?
2946                .to_be_bytes(),
2947        )?;
2948        writer.write_slice(&self.heartbeat)?;
2949        for _ in self.unpadded_len()..self.len() {
2950            writer.write_slice(&[0])?;
2951        }
2952
2953        Ok(())
2954    }
2955}
2956
2957#[cfg(feature = "alloc")]
2958impl From<HeartbeatAckChunkRef<'_>> for HeartbeatAckChunk {
2959    #[inline]
2960    fn from(value: HeartbeatAckChunkRef<'_>) -> Self {
2961        Self::from(&value)
2962    }
2963}
2964
2965#[cfg(feature = "alloc")]
2966impl From<&HeartbeatAckChunkRef<'_>> for HeartbeatAckChunk {
2967    #[inline]
2968    fn from(value: &HeartbeatAckChunkRef<'_>) -> Self {
2969        HeartbeatAckChunk {
2970            flags: value.flags_raw(),
2971            heartbeat: Vec::from(value.heartbeat_info().heartbeat()),
2972        }
2973    }
2974}
2975
2976#[derive(Clone, Copy, Debug)]
2977pub struct HeartbeatAckChunkRef<'a> {
2978    data: &'a [u8],
2979}
2980
2981impl<'a> HeartbeatAckChunkRef<'a> {
2982    #[inline]
2983    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
2984        Self::validate(bytes)?;
2985        Ok(Self::from_bytes_unchecked(bytes))
2986    }
2987
2988    #[inline]
2989    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
2990        HeartbeatAckChunkRef { data: bytes }
2991    }
2992
2993    pub fn validate(bytes: &'a [u8]) -> Result<(), ValidationError> {
2994        match utils::to_array(bytes, 2) {
2995            Some(unpadded_len_arr) => {
2996                let len = u16::from_be_bytes(unpadded_len_arr) as usize;
2997
2998                if len > bytes.len() {
2999                    return Err(ValidationError {
3000                        layer: SctpRef::name(),
3001                        class: ValidationErrorClass::InsufficientBytes,
3002                        #[cfg(feature = "error_string")]        
3003                        reason: "insufficient bytes in SCTP HEARTBEAT ACK chunk for header + Heartbeat field",
3004                    });
3005                }
3006
3007                if len % 4 != 0 {
3008                    return Err(ValidationError {
3009                        layer: SctpRef::name(),
3010                        class: ValidationErrorClass::InvalidValue,
3011                        #[cfg(feature = "error_string")]
3012                        reason: "SCTP HEARTBEAT ACK chunk length was not a multiple of 4",
3013                    });
3014                }
3015
3016                HeartbeatInfoRef::validate(&bytes[4..len])?;
3017
3018                if len < bytes.len() {
3019                    Err(ValidationError {
3020                        layer: SctpRef::name(),
3021                        class: ValidationErrorClass::ExcessBytes(bytes.len() - len),
3022                        #[cfg(feature = "error_string")]
3023                        reason: "extra bytes remain at end of SCTP HEARTBEAT ACK chunk",
3024                    })
3025                } else {
3026                    Ok(())
3027                }
3028            }
3029            _ => Err(ValidationError {
3030                layer: SctpRef::name(),
3031                class: ValidationErrorClass::InsufficientBytes,
3032                #[cfg(feature = "error_string")]
3033                reason: "insufficient bytes in SCTP HEARTBEAT ACK chunk for header",
3034            }),
3035        }
3036    }
3037
3038    #[inline]
3039    pub fn chunk_type(&self) -> u8 {
3040        self.data[0]
3041    }
3042
3043    #[inline]
3044    pub fn flags_raw(&self) -> u8 {
3045        self.data[1]
3046    }
3047
3048    #[inline]
3049    pub fn unpadded_len(&self) -> u16 {
3050        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
3051    }
3052
3053    #[inline]
3054    pub fn len(&self) -> usize {
3055        utils::padded_length::<4>(self.unpadded_len() as usize)
3056    }
3057
3058    #[inline]
3059    pub fn heartbeat_info(&self) -> HeartbeatInfoRef<'a> {
3060        HeartbeatInfoRef::from_bytes_unchecked(&self.data[4..])
3061    }
3062}
3063
3064///
3065#[derive(Clone, Debug)]
3066#[cfg(feature = "alloc")]
3067pub struct AbortChunk {
3068    flags: AbortFlags,
3069    causes: Vec<ErrorCause>,
3070}
3071
3072#[cfg(feature = "alloc")]
3073impl AbortChunk {
3074    #[inline]
3075    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
3076        Self::validate(bytes)?;
3077        Ok(Self::from_bytes_unchecked(bytes))
3078    }
3079
3080    #[inline]
3081    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
3082        Self::from(AbortChunkRef::from_bytes_unchecked(bytes))
3083    }
3084
3085    #[inline]
3086    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
3087        ErrorChunkRef::validate(bytes)
3088    }
3089
3090    #[inline]
3091    pub fn chunk_type(&self) -> u8 {
3092        CHUNK_TYPE_ABORT
3093    }
3094
3095    #[inline]
3096    pub fn flags(&self) -> AbortFlags {
3097        self.flags
3098    }
3099
3100    #[inline]
3101    pub fn set_flags(&mut self, flags: AbortFlags) {
3102        self.flags = flags;
3103    }
3104
3105    #[inline]
3106    pub fn unpadded_len(&self) -> usize {
3107        4 + self.causes.iter().map(|c| c.len()).sum::<usize>()
3108    }
3109
3110    #[inline]
3111    pub fn len(&self) -> usize {
3112        utils::padded_length::<4>(self.unpadded_len())
3113    }
3114
3115    #[inline]
3116    pub fn causes(&self) -> &Vec<ErrorCause> {
3117        &self.causes
3118    }
3119
3120    #[inline]
3121    pub fn set_causes(&mut self) -> &mut Vec<ErrorCause> {
3122        &mut self.causes
3123    }
3124
3125    #[inline]
3126    pub fn to_bytes_extended<T: PacketWritable>(
3127        &self,
3128        writer: &mut PacketWriter<'_, T>,
3129    ) -> Result<(), SerializationError> {
3130        writer.write_slice(&[CHUNK_TYPE_ABORT])?;
3131        writer.write_slice(&[self.flags.bits()])?;
3132        writer.write_slice(
3133            &u16::try_from(self.unpadded_len())
3134                .map_err(|_| SerializationError::length_encoding(SctpRef::name()))?
3135                .to_be_bytes(),
3136        )?;
3137        for cause in &self.causes {
3138            cause.to_bytes_extended(writer)?;
3139        }
3140
3141        Ok(())
3142    }
3143}
3144
3145#[cfg(feature = "alloc")]
3146impl From<AbortChunkRef<'_>> for AbortChunk {
3147    #[inline]
3148    fn from(value: AbortChunkRef<'_>) -> Self {
3149        Self::from(&value)
3150    }
3151}
3152
3153#[cfg(feature = "alloc")]
3154impl From<&AbortChunkRef<'_>> for AbortChunk {
3155    fn from(value: &AbortChunkRef<'_>) -> Self {
3156        let mut causes = Vec::new();
3157        let iter = value.error_iter();
3158        for error in iter {
3159            causes.push(error.into());
3160        }
3161
3162        AbortChunk {
3163            flags: value.flags(),
3164            causes,
3165        }
3166    }
3167}
3168
3169///
3170#[derive(Clone, Copy, Debug)]
3171pub struct AbortChunkRef<'a> {
3172    data: &'a [u8],
3173}
3174
3175impl<'a> AbortChunkRef<'a> {
3176    #[inline]
3177    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
3178        Self::validate(bytes)?;
3179        Ok(Self::from_bytes_unchecked(bytes))
3180    }
3181
3182    #[inline]
3183    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
3184        AbortChunkRef { data: bytes }
3185    }
3186
3187    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
3188        match (bytes.first(), utils::to_array(bytes, 2)) {
3189            (Some(&chunk_type), Some(len_arr)) => {
3190                let len = u16::from_be_bytes(len_arr) as usize;
3191                if bytes.len() < cmp::max(4, len) {
3192                    return Err(ValidationError {
3193                        layer: SctpRef::name(),
3194                        class: ValidationErrorClass::InsufficientBytes,
3195                        #[cfg(feature = "error_string")]
3196                        reason:
3197                            "insufficient bytes in SCTP ABORT chunk for header + Error Cause fields",
3198                    });
3199                }
3200
3201                if chunk_type != CHUNK_TYPE_ABORT {
3202                    return Err(ValidationError {
3203                        layer: SctpRef::name(),
3204                        class: ValidationErrorClass::InvalidValue,
3205                        #[cfg(feature = "error_string")]
3206                        reason: "invalid Chunk Type field in SCTP ABORT chunk (must be equal to 6)",
3207                    });
3208                }
3209
3210                if bytes.len() > 4 {
3211                    Err(ValidationError {
3212                        layer: SctpRef::name(),
3213                        class: ValidationErrorClass::ExcessBytes(bytes.len() - len),
3214                        #[cfg(feature = "error_string")]
3215                        reason: "extra bytes remain at end of SCTP ABORT chunk",
3216                    })
3217                } else {
3218                    Ok(())
3219                }
3220            }
3221            _ => Err(ValidationError {
3222                layer: SctpRef::name(),
3223                class: ValidationErrorClass::InsufficientBytes,
3224                #[cfg(feature = "error_string")]
3225                reason: "insufficient bytes in SCTP ABORT chunk for header",
3226            }),
3227        }
3228    }
3229
3230    #[inline]
3231    pub fn chunk_type(&self) -> u8 {
3232        self.data[0]
3233    }
3234
3235    #[inline]
3236    pub fn flags(&self) -> AbortFlags {
3237        AbortFlags::from_bits_truncate(self.flags_raw())
3238    }
3239
3240    #[inline]
3241    pub fn flags_raw(&self) -> u8 {
3242        self.data[1]
3243    }
3244
3245    #[inline]
3246    pub fn unpadded_len(&self) -> u16 {
3247        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
3248    }
3249
3250    #[inline]
3251    pub fn len(&self) -> usize {
3252        utils::padded_length::<4>(self.unpadded_len() as usize)
3253    }
3254
3255    #[inline]
3256    pub fn error_iter(&self) -> ErrorCauseIterRef {
3257        ErrorCauseIterRef {
3258            bytes: &self.data[4..self.unpadded_len() as usize],
3259        }
3260    }
3261}
3262
3263#[derive(Clone, Copy, Debug)]
3264pub struct ErrorCauseIterRef<'a> {
3265    bytes: &'a [u8],
3266}
3267
3268impl<'a> Iterator for ErrorCauseIterRef<'a> {
3269    type Item = ErrorCauseRef<'a>;
3270
3271    fn next(&mut self) -> Option<Self::Item> {
3272        let (err_type, unpadded_len) = match (
3273            utils::get_array(self.bytes, 0).map(|&a| u16::from_be_bytes(a)),
3274            utils::get_array(self.bytes, 2).map(|&a| u16::from_be_bytes(a)),
3275        ) {
3276            (Some(t), Some(l)) => (t, l),
3277            _ => return None,
3278        };
3279
3280        let min_len = match err_type {
3281            ERR_CODE_INVALID_STREAM_ID | ERR_CODE_STALE_COOKIE | ERR_CODE_NO_USER_DATA => 8,
3282            ERR_CODE_MISSING_MAND_PARAM => 8, // TODO: change to 10 once '1 or more mandatory params' is enforced
3283            ERR_CODE_OUT_OF_RESOURCE
3284            | ERR_CODE_UNRESOLVABLE_ADDRESS
3285            | ERR_CODE_UNRECOGNIZED_CHUNK
3286            | ERR_CODE_INVALID_MAND_PARAM
3287            | ERR_CODE_UNRECOGNIZED_PARAMS
3288            | ERR_CODE_COOKIE_RCVD_SHUTTING_DOWN
3289            | ERR_CODE_RESTART_ASSOC_NEW_ADDR
3290            | ERR_CODE_USER_INITIATED_ABORT
3291            | ERR_CODE_PROTOCOL_VIOLATION => 4,
3292            _ => 4,
3293        };
3294
3295        if self.bytes.len() < min_len {
3296            self.bytes = &[]; // Not needed, but this helps further calls to the iterator to short-circuit
3297            return None;
3298        }
3299
3300        let len = cmp::max(min_len, utils::padded_length::<4>(unpadded_len as usize));
3301        match (self.bytes.get(..len), self.bytes.get(len..)) {
3302            (Some(err_bytes), Some(rem)) => {
3303                self.bytes = rem;
3304                Some(ErrorCauseRef::from_bytes_unchecked(err_bytes))
3305            }
3306            _ => {
3307                // Just take whatever remaining bytes we can for the payload
3308                let err_bytes = self.bytes;
3309                self.bytes = &[];
3310                Some(ErrorCauseRef::from_bytes_unchecked(err_bytes))
3311            }
3312        }
3313    }
3314}
3315
3316#[derive(Clone, Debug)]
3317#[cfg(feature = "alloc")]
3318pub enum ErrorCause {
3319    InvalidStreamIdentifier(StreamIdentifierError),
3320
3321    MissingMandatoryParameter(MissingParameterError),
3322
3323    StaleCookie(StaleCookieError),
3324
3325    OutOfResource,
3326
3327    UnresolvableAddress(UnresolvableAddrError),
3328
3329    UnrecognizedChunkType(UnrecognizedChunkError),
3330
3331    UnrecognizedParameters(UnrecognizedParamError),
3332
3333    InvalidMandatoryParameter,
3334
3335    NoUserData(NoUserDataError),
3336
3337    CookieDuringShutdown,
3338
3339    AssociationNewAddress(AssociationNewAddrError),
3340
3341    UserInitiatedAbort(UserInitiatedAbortError),
3342
3343    ProtocolViolation(ProtocolViolationError),
3344
3345    /// Some other error code not defined in RFC 4960.
3346    Unknown(GenericParam),
3347}
3348
3349#[cfg(feature = "alloc")]
3350impl ErrorCause {
3351    #[inline]
3352    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
3353        Self::validate(bytes)?;
3354        Ok(Self::from_bytes_unchecked(bytes))
3355    }
3356
3357    #[inline]
3358    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
3359        Self::from(ErrorCauseRef::from_bytes_unchecked(bytes))
3360    }
3361
3362    #[inline]
3363    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
3364        ErrorCauseRef::validate(bytes)
3365    }
3366
3367    pub fn len(&self) -> usize {
3368        match self {
3369            Self::OutOfResource | Self::CookieDuringShutdown | Self::InvalidMandatoryParameter => 4,
3370            Self::InvalidStreamIdentifier(_) => 8,
3371            Self::MissingMandatoryParameter(e) => e.len(),
3372            Self::StaleCookie(_) => 8,
3373            Self::UnresolvableAddress(e) => e.len(),
3374            Self::UnrecognizedChunkType(e) => e.len(),
3375            Self::UnrecognizedParameters(e) => e.len(),
3376            Self::NoUserData(_) => 8,
3377            Self::AssociationNewAddress(e) => e.len(),
3378            Self::UserInitiatedAbort(e) => e.len(),
3379            Self::ProtocolViolation(e) => e.len(),
3380            Self::Unknown(e) => e.len(),
3381        }
3382    }
3383
3384    pub fn to_bytes_extended<T: PacketWritable>(
3385        &self,
3386        writer: &mut PacketWriter<'_, T>,
3387    ) -> Result<(), SerializationError> {
3388        match self {
3389            ErrorCause::InvalidStreamIdentifier(e) => e.to_bytes_extended(writer),
3390            ErrorCause::MissingMandatoryParameter(e) => e.to_bytes_extended(writer),
3391            ErrorCause::StaleCookie(e) => e.to_bytes_extended(writer),
3392            ErrorCause::OutOfResource => {
3393                writer.write_slice(&ERR_CODE_OUT_OF_RESOURCE.to_be_bytes())?;
3394                writer.write_slice(&4u16.to_be_bytes())
3395            }
3396            ErrorCause::UnresolvableAddress(e) => e.to_bytes_extended(writer),
3397            ErrorCause::UnrecognizedChunkType(e) => e.to_bytes_extended(writer),
3398            ErrorCause::InvalidMandatoryParameter => {
3399                writer.write_slice(&ERR_CODE_INVALID_MAND_PARAM.to_be_bytes())?;
3400                writer.write_slice(&4u16.to_be_bytes())
3401            }
3402            ErrorCause::UnrecognizedParameters(e) => e.to_bytes_extended(writer),
3403            ErrorCause::NoUserData(e) => e.to_bytes_extended(writer),
3404            ErrorCause::CookieDuringShutdown => {
3405                writer.write_slice(&ERR_CODE_COOKIE_RCVD_SHUTTING_DOWN.to_be_bytes())?;
3406                writer.write_slice(&4u16.to_be_bytes())
3407            }
3408            ErrorCause::AssociationNewAddress(e) => e.to_bytes_extended(writer),
3409            ErrorCause::UserInitiatedAbort(e) => e.to_bytes_extended(writer),
3410            ErrorCause::ProtocolViolation(e) => e.to_bytes_extended(writer),
3411            ErrorCause::Unknown(e) => e.to_bytes_extended(writer),
3412        }
3413    }
3414}
3415
3416#[cfg(feature = "alloc")]
3417impl From<ErrorCauseRef<'_>> for ErrorCause {
3418    #[inline]
3419    fn from(value: ErrorCauseRef<'_>) -> Self {
3420        ErrorCause::from(&value)
3421    }
3422}
3423
3424#[cfg(feature = "alloc")]
3425impl From<&ErrorCauseRef<'_>> for ErrorCause {
3426    fn from(value: &ErrorCauseRef<'_>) -> Self {
3427        match value {
3428            ErrorCauseRef::InvalidStreamIdentifier(e) => {
3429                ErrorCause::InvalidStreamIdentifier(e.into())
3430            }
3431            ErrorCauseRef::MissingMandatoryParameter(e) => {
3432                ErrorCause::MissingMandatoryParameter(e.into())
3433            }
3434            ErrorCauseRef::StaleCookie(e) => ErrorCause::StaleCookie(e.into()),
3435            ErrorCauseRef::OutOfResource(_) => ErrorCause::OutOfResource,
3436            ErrorCauseRef::UnresolvableAddress(e) => ErrorCause::UnresolvableAddress(e.into()),
3437            ErrorCauseRef::UnrecognizedChunkType(e) => ErrorCause::UnrecognizedChunkType(e.into()),
3438            ErrorCauseRef::InvalidMandatoryParameter(_) => ErrorCause::InvalidMandatoryParameter,
3439            ErrorCauseRef::UnrecognizedParameters(e) => {
3440                ErrorCause::UnrecognizedParameters(e.into())
3441            }
3442            ErrorCauseRef::NoUserData(e) => ErrorCause::NoUserData(e.into()),
3443            ErrorCauseRef::CookieDuringShutdown(_) => ErrorCause::CookieDuringShutdown,
3444            ErrorCauseRef::AssociationNewAddress(e) => ErrorCause::AssociationNewAddress(e.into()),
3445            ErrorCauseRef::UserInitiatedAbort(e) => ErrorCause::UserInitiatedAbort(e.into()),
3446            ErrorCauseRef::ProtocolViolation(e) => ErrorCause::ProtocolViolation(e.into()),
3447            ErrorCauseRef::Unknown(e) => ErrorCause::Unknown(e.into()),
3448        }
3449    }
3450}
3451
3452#[derive(Clone, Copy, Debug)]
3453pub enum ErrorCauseRef<'a> {
3454    InvalidStreamIdentifier(StreamIdentifierErrorRef<'a>),
3455
3456    MissingMandatoryParameter(MissingParameterErrorRef<'a>),
3457
3458    StaleCookie(StaleCookieErrorRef<'a>),
3459
3460    OutOfResource(&'a [u8]),
3461
3462    UnresolvableAddress(UnresolvableAddrErrorRef<'a>),
3463
3464    UnrecognizedChunkType(UnrecognizedChunkErrorRef<'a>),
3465
3466    InvalidMandatoryParameter(&'a [u8]),
3467
3468    UnrecognizedParameters(UnrecognizedParamErrorRef<'a>),
3469
3470    NoUserData(NoUserDataErrorRef<'a>),
3471
3472    CookieDuringShutdown(&'a [u8]),
3473
3474    AssociationNewAddress(AssociationNewAddrErrorRef<'a>),
3475
3476    UserInitiatedAbort(UserInitiatedAbortErrorRef<'a>),
3477
3478    ProtocolViolation(ProtocolViolationErrorRef<'a>),
3479
3480    /// Some other error code not defined in RFC 4960.
3481    Unknown(GenericParamRef<'a>),
3482}
3483
3484impl<'a> ErrorCauseRef<'a> {
3485    #[inline]
3486    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
3487        Self::validate(bytes)?;
3488        Ok(Self::from_bytes_unchecked(bytes))
3489    }
3490
3491    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
3492        let cause_code = u16::from_be_bytes(utils::to_array(bytes, 0).unwrap());
3493        match cause_code {
3494            ERR_CODE_INVALID_STREAM_ID => {
3495                Self::InvalidStreamIdentifier(StreamIdentifierErrorRef::from_bytes_unchecked(bytes))
3496            }
3497            ERR_CODE_MISSING_MAND_PARAM => Self::MissingMandatoryParameter(
3498                MissingParameterErrorRef::from_bytes_unchecked(bytes),
3499            ),
3500            ERR_CODE_STALE_COOKIE => {
3501                Self::StaleCookie(StaleCookieErrorRef::from_bytes_unchecked(bytes))
3502            }
3503            ERR_CODE_OUT_OF_RESOURCE => Self::OutOfResource(bytes),
3504            ERR_CODE_UNRESOLVABLE_ADDRESS => {
3505                Self::UnresolvableAddress(UnresolvableAddrErrorRef::from_bytes_unchecked(bytes))
3506            }
3507            ERR_CODE_UNRECOGNIZED_CHUNK => {
3508                Self::UnrecognizedChunkType(UnrecognizedChunkErrorRef::from_bytes_unchecked(bytes))
3509            }
3510            ERR_CODE_INVALID_MAND_PARAM => Self::InvalidMandatoryParameter(bytes),
3511            ERR_CODE_UNRECOGNIZED_PARAMS => {
3512                Self::UnrecognizedParameters(UnrecognizedParamErrorRef::from_bytes_unchecked(bytes))
3513            }
3514            ERR_CODE_NO_USER_DATA => {
3515                Self::NoUserData(NoUserDataErrorRef::from_bytes_unchecked(bytes))
3516            }
3517            ERR_CODE_COOKIE_RCVD_SHUTTING_DOWN => Self::CookieDuringShutdown(bytes),
3518            ERR_CODE_RESTART_ASSOC_NEW_ADDR => {
3519                Self::AssociationNewAddress(AssociationNewAddrErrorRef::from_bytes_unchecked(bytes))
3520            }
3521            ERR_CODE_USER_INITIATED_ABORT => {
3522                Self::UserInitiatedAbort(UserInitiatedAbortErrorRef::from_bytes_unchecked(bytes))
3523            }
3524            ERR_CODE_PROTOCOL_VIOLATION => {
3525                Self::ProtocolViolation(ProtocolViolationErrorRef::from_bytes_unchecked(bytes))
3526            }
3527            _ => Self::Unknown(GenericParamRef::from_bytes_unchecked(bytes)),
3528        }
3529    }
3530
3531    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
3532        let cause_code = u16::from_be_bytes(utils::to_array(bytes, 0).unwrap());
3533        match cause_code {
3534            ERR_CODE_INVALID_STREAM_ID => StreamIdentifierErrorRef::validate(bytes),
3535            ERR_CODE_MISSING_MAND_PARAM => MissingParameterErrorRef::validate(bytes),
3536            ERR_CODE_STALE_COOKIE => StaleCookieErrorRef::validate(bytes),
3537            ERR_CODE_UNRESOLVABLE_ADDRESS => UnresolvableAddrErrorRef::validate(bytes),
3538            ERR_CODE_UNRECOGNIZED_CHUNK => UnrecognizedChunkErrorRef::validate(bytes),
3539            ERR_CODE_UNRECOGNIZED_PARAMS => UnrecognizedParamErrorRef::validate(bytes),
3540            ERR_CODE_NO_USER_DATA => NoUserDataErrorRef::validate(bytes),
3541            ERR_CODE_RESTART_ASSOC_NEW_ADDR => AssociationNewAddrErrorRef::validate(bytes),
3542            ERR_CODE_USER_INITIATED_ABORT => UserInitiatedAbortErrorRef::validate(bytes),
3543            ERR_CODE_PROTOCOL_VIOLATION => ProtocolViolationErrorRef::validate(bytes),
3544            ERR_CODE_OUT_OF_RESOURCE
3545            | ERR_CODE_INVALID_MAND_PARAM
3546            | ERR_CODE_COOKIE_RCVD_SHUTTING_DOWN => match utils::to_array(bytes, 2) {
3547                Some(len_arr) => {
3548                    let len = u16::from_be_bytes(len_arr) as usize;
3549
3550                    if len != 4 {
3551                        return Err(ValidationError {
3552                            layer: SctpRef::name(),
3553                            class: ValidationErrorClass::InvalidValue,
3554                            #[cfg(feature = "error_string")]
3555                            reason: "invalid length in SCTP Error Cause (must be equal to 4)",
3556                        });
3557                    }
3558
3559                    if bytes.len() > 4 {
3560                        Err(ValidationError {
3561                            layer: SctpRef::name(),
3562                            class: ValidationErrorClass::ExcessBytes(bytes.len() - 4),
3563                            #[cfg(feature = "error_string")]
3564                            reason: "extra bytes remain at end of SCTP 4-byte Error Cause",
3565                        })
3566                    } else {
3567                        Ok(())
3568                    }
3569                }
3570                _ => Err(ValidationError {
3571                    layer: SctpRef::name(),
3572                    class: ValidationErrorClass::InsufficientBytes,
3573                    #[cfg(feature = "error_string")]
3574                    reason: "insufficient bytes in SCTP 4-byte Error Cause for header",
3575                }),
3576            },
3577            _ => match utils::to_array(bytes, 2) {
3578                Some(len_arr) => {
3579                    let unpadded_len = u16::from_be_bytes(len_arr) as usize;
3580                    let len = utils::padded_length::<4>(unpadded_len);
3581
3582                    if bytes.len() < cmp::max(8, len) {
3583                        return Err(ValidationError {
3584                            layer: SctpRef::name(),
3585                            class: ValidationErrorClass::InsufficientBytes,
3586                            #[cfg(feature = "error_string")]            
3587                            reason: "insufficient bytes in SCTP <unknown> Error Cause for header and data field",
3588                        });
3589                    }
3590
3591                    if unpadded_len < 8 {
3592                        return Err(ValidationError {
3593                            layer: SctpRef::name(),
3594                            class: ValidationErrorClass::InvalidValue,
3595                            #[cfg(feature = "error_string")]            
3596                            reason: "invalid length in SCTP <unknown> Error Cause (must be at least 8 bytes)",
3597                        });
3598                    }
3599
3600                    if bytes.len() > len {
3601                        Err(ValidationError {
3602                            layer: SctpRef::name(),
3603                            class: ValidationErrorClass::ExcessBytes(bytes.len() - len),
3604                            #[cfg(feature = "error_string")]
3605                            reason: "extra bytes remain at end of SCTP <unknown> Error Cause",
3606                        })
3607                    } else {
3608                        Ok(())
3609                    }
3610                }
3611                _ => Err(ValidationError {
3612                    layer: SctpRef::name(),
3613                    class: ValidationErrorClass::InsufficientBytes,
3614                    #[cfg(feature = "error_string")]
3615                    reason: "insufficient bytes in SCTP <unknown> Error Cause for header",
3616                }),
3617            },
3618        }
3619    }
3620}
3621
3622#[derive(Clone, Debug)]
3623pub struct StreamIdentifierError {
3624    stream_id: u16,
3625    reserved: u16,
3626}
3627
3628impl StreamIdentifierError {
3629    #[inline]
3630    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
3631        Self::validate(bytes)?;
3632        Ok(Self::from_bytes_unchecked(bytes))
3633    }
3634
3635    #[inline]
3636    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
3637        Self::from(StreamIdentifierErrorRef::from_bytes_unchecked(bytes))
3638    }
3639
3640    #[inline]
3641    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
3642        StreamIdentifierErrorRef::validate(bytes)
3643    }
3644
3645    #[inline]
3646    pub fn cause_code(&self) -> u16 {
3647        ERR_CODE_INVALID_STREAM_ID
3648    }
3649
3650    #[inline]
3651    pub fn len(&self) -> usize {
3652        8
3653    }
3654
3655    #[inline]
3656    pub fn stream_id(&self) -> u16 {
3657        self.stream_id
3658    }
3659
3660    #[inline]
3661    pub fn set_stream_id(&mut self, stream_id: u16) {
3662        self.stream_id = stream_id;
3663    }
3664
3665    #[inline]
3666    pub fn reserved(&self) -> u16 {
3667        self.reserved
3668    }
3669
3670    #[inline]
3671    pub fn set_reserved(&mut self, reserved: u16) {
3672        self.reserved = reserved;
3673    }
3674
3675    pub fn to_bytes_extended<T: PacketWritable>(
3676        &self,
3677        writer: &mut PacketWriter<'_, T>,
3678    ) -> Result<(), SerializationError> {
3679        writer.write_slice(&ERR_CODE_INVALID_STREAM_ID.to_be_bytes())?;
3680        writer.write_slice(&8u16.to_be_bytes())?;
3681        writer.write_slice(&self.stream_id.to_be_bytes())?;
3682        writer.write_slice(&self.reserved.to_be_bytes())
3683    }
3684}
3685
3686impl From<StreamIdentifierErrorRef<'_>> for StreamIdentifierError {
3687    #[inline]
3688    fn from(value: StreamIdentifierErrorRef<'_>) -> Self {
3689        Self::from(&value)
3690    }
3691}
3692
3693impl From<&StreamIdentifierErrorRef<'_>> for StreamIdentifierError {
3694    #[inline]
3695    fn from(value: &StreamIdentifierErrorRef<'_>) -> Self {
3696        StreamIdentifierError {
3697            stream_id: value.stream_id(),
3698            reserved: value.reserved(),
3699        }
3700    }
3701}
3702
3703#[derive(Clone, Copy, Debug)]
3704pub struct StreamIdentifierErrorRef<'a> {
3705    data: &'a [u8],
3706}
3707
3708impl<'a> StreamIdentifierErrorRef<'a> {
3709    #[inline]
3710    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
3711        Self::validate(bytes)?;
3712        Ok(Self::from_bytes_unchecked(bytes))
3713    }
3714
3715    #[inline]
3716    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
3717        StreamIdentifierErrorRef { data: bytes }
3718    }
3719
3720    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
3721        match (utils::to_array(bytes, 0), utils::to_array(bytes, 2)) {
3722            (Some(cause_code_arr), Some(len_arr)) => {
3723                let cause_code = u16::from_be_bytes(cause_code_arr);
3724                let len = u16::from_be_bytes(len_arr) as usize;
3725
3726                if bytes.len() < 8 {
3727                    return Err(ValidationError {
3728                        layer: SctpRef::name(),
3729                        class: ValidationErrorClass::InsufficientBytes,
3730                        #[cfg(feature = "error_string")]        
3731                        reason: "insufficient bytes in SCTP Invalid Stream Identifier option for header + Explanation field",
3732                    });
3733                }
3734
3735                if cause_code != ERR_CODE_INVALID_STREAM_ID {
3736                    return Err(ValidationError {
3737                        layer: SctpRef::name(),
3738                        class: ValidationErrorClass::InvalidValue,
3739                        #[cfg(feature = "error_string")]        
3740                        reason: "invalid cause code in SCTP Invalid Stream Identifier Option (must be equal to 1)",
3741                    });
3742                }
3743
3744                if len != 8 {
3745                    return Err(ValidationError {
3746                        layer: SctpRef::name(),
3747                        class: ValidationErrorClass::InvalidValue,
3748                        #[cfg(feature = "error_string")]        
3749                        reason: "invalid length in SCTP Invalid Stream Identifier Option (must be equal to 8)",
3750                    });
3751                }
3752
3753                if bytes.len() > 8 {
3754                    Err(ValidationError {
3755                        layer: SctpRef::name(),
3756                        class: ValidationErrorClass::ExcessBytes(bytes.len() - 8),
3757                        #[cfg(feature = "error_string")]
3758                        reason:
3759                            "extra bytes remain at end of SCTP Invalid Stream Identifier option",
3760                    })
3761                } else {
3762                    Ok(())
3763                }
3764            }
3765            _ => Err(ValidationError {
3766                layer: SctpRef::name(),
3767                class: ValidationErrorClass::InsufficientBytes,
3768                #[cfg(feature = "error_string")]
3769                reason: "insufficient bytes in SCTP Invalid Stream Identifier option for header",
3770            }),
3771        }
3772    }
3773
3774    #[inline]
3775    pub fn cause_code(&self) -> u16 {
3776        u16::from_be_bytes(utils::to_array(self.data, 0).unwrap())
3777    }
3778
3779    #[inline]
3780    pub fn unpadded_len(&self) -> u16 {
3781        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
3782    }
3783
3784    #[inline]
3785    pub fn len(&self) -> usize {
3786        utils::padded_length::<4>(self.unpadded_len() as usize)
3787    }
3788
3789    #[inline]
3790    pub fn stream_id(&self) -> u16 {
3791        u16::from_be_bytes(utils::to_array(self.data, 4).unwrap())
3792    }
3793
3794    #[inline]
3795    pub fn reserved(&self) -> u16 {
3796        u16::from_be_bytes(utils::to_array(self.data, 4).unwrap())
3797    }
3798}
3799
3800#[derive(Clone, Debug)]
3801#[cfg(feature = "alloc")]
3802pub struct MissingParameterError {
3803    missing_params: Vec<u16>,
3804}
3805
3806#[cfg(feature = "alloc")]
3807impl MissingParameterError {
3808    #[inline]
3809    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
3810        Self::validate(bytes)?;
3811        Ok(Self::from_bytes_unchecked(bytes))
3812    }
3813
3814    #[inline]
3815    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
3816        Self::from(MissingParameterErrorRef::from_bytes_unchecked(bytes))
3817    }
3818
3819    #[inline]
3820    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
3821        MissingParameterErrorRef::validate(bytes)
3822    }
3823
3824    #[inline]
3825    pub fn unpadded_len(&self) -> usize {
3826        8 + (2 * self.missing_params.len())
3827    }
3828
3829    #[inline]
3830    pub fn len(&self) -> usize {
3831        utils::padded_length::<4>(self.unpadded_len())
3832    }
3833
3834    #[inline]
3835    pub fn missing_params(&self) -> &Vec<u16> {
3836        &self.missing_params
3837    }
3838
3839    #[inline]
3840    pub fn missing_params_mut(&mut self) -> &mut Vec<u16> {
3841        &mut self.missing_params
3842    }
3843
3844    pub fn to_bytes_extended<T: PacketWritable>(
3845        &self,
3846        writer: &mut PacketWriter<'_, T>,
3847    ) -> Result<(), SerializationError> {
3848        writer.write_slice(&ERR_CODE_MISSING_MAND_PARAM.to_be_bytes())?;
3849        writer.write_slice(
3850            &u16::try_from(self.unpadded_len())
3851                .map_err(|_| SerializationError::length_encoding(SctpRef::name()))?
3852                .to_be_bytes(),
3853        )?;
3854        writer.write_slice(
3855            &u32::try_from(self.missing_params.len())
3856                .map_err(|_| SerializationError::length_encoding(SctpRef::name()))?
3857                .to_be_bytes(),
3858        )?;
3859        for param in &self.missing_params {
3860            writer.write_slice(&param.to_be_bytes())?;
3861        }
3862        if self.missing_params.len() % 4 != 0 {
3863            writer.write_slice(&[0, 0])?;
3864        }
3865        Ok(())
3866    }
3867}
3868
3869#[cfg(feature = "alloc")]
3870impl From<MissingParameterErrorRef<'_>> for MissingParameterError {
3871    #[inline]
3872    fn from(value: MissingParameterErrorRef<'_>) -> Self {
3873        Self::from(&value)
3874    }
3875}
3876
3877#[cfg(feature = "alloc")]
3878impl From<&MissingParameterErrorRef<'_>> for MissingParameterError {
3879    #[inline]
3880    fn from(value: &MissingParameterErrorRef<'_>) -> Self {
3881        MissingParameterError {
3882            missing_params: Vec::from_iter(value.missing_params_iter()),
3883        }
3884    }
3885}
3886
3887#[derive(Clone, Copy, Debug)]
3888pub struct MissingParameterErrorRef<'a> {
3889    data: &'a [u8],
3890}
3891
3892impl<'a> MissingParameterErrorRef<'a> {
3893    #[inline]
3894    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
3895        Self::validate(bytes)?;
3896        Ok(Self::from_bytes_unchecked(bytes))
3897    }
3898
3899    #[inline]
3900    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
3901        MissingParameterErrorRef { data: bytes }
3902    }
3903
3904    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
3905        match (utils::to_array(bytes, 0), utils::to_array(bytes, 2)) {
3906            (Some(cause_code_arr), Some(len_arr)) => {
3907                let cause_code = u16::from_be_bytes(cause_code_arr);
3908                let unpadded_len = u16::from_be_bytes(len_arr) as usize;
3909                let len = utils::padded_length::<4>(unpadded_len);
3910
3911                if bytes.len() < cmp::max(8, len) {
3912                    return Err(ValidationError {
3913                        layer: SctpRef::name(),
3914                        class: ValidationErrorClass::InsufficientBytes,
3915                        #[cfg(feature = "error_string")]        
3916                        reason: "insufficient bytes in SCTP Missing Mandatory Parameter option for header + Missing Parameter fields",
3917                    });
3918                }
3919
3920                if cause_code != ERR_CODE_MISSING_MAND_PARAM {
3921                    return Err(ValidationError {
3922                        layer: SctpRef::name(),
3923                        class: ValidationErrorClass::InvalidValue,
3924                        #[cfg(feature = "error_string")]        
3925                        reason: "invalid cause code in SCTP Missing Mandatory Parameter option (must be equal to 2)",
3926                    });
3927                }
3928
3929                if unpadded_len < 8 {
3930                    return Err(ValidationError {
3931                        layer: SctpRef::name(),
3932                        class: ValidationErrorClass::InvalidValue,
3933                        #[cfg(feature = "error_string")]        
3934                        reason: "invalid length in SCTP Missing Mandatory Parameter option (must be at least 8 bytes long)",
3935                    });
3936                }
3937
3938                if unpadded_len % 2 != 0 {
3939                    return Err(ValidationError {
3940                        layer: SctpRef::name(),
3941                        class: ValidationErrorClass::InvalidValue,
3942                        #[cfg(feature = "error_string")]        
3943                        reason: "invalid length in SCTP Missing Mandatory Parameter option (must be a multiple of 2)",
3944                    });
3945                }
3946
3947                for b in bytes.iter().take(len).skip(unpadded_len) {
3948                    if *b != 0 {
3949                        return Err(ValidationError {
3950                            layer: SctpRef::name(),
3951                            class: ValidationErrorClass::InvalidValue,
3952                            #[cfg(feature = "error_string")]            
3953                            reason: "invalid nonzero padding values at end of SCTP Missing Mandatory Parameter Option",
3954                        });
3955                    }
3956                }
3957
3958                if bytes.len() > len {
3959                    Err(ValidationError {
3960                        layer: SctpRef::name(),
3961                        class: ValidationErrorClass::ExcessBytes(bytes.len() - len),
3962                        #[cfg(feature = "error_string")]
3963                        reason: "extra bytes remain at end of Missing Mandatory Parameter option",
3964                    })
3965                } else {
3966                    Ok(())
3967                }
3968            }
3969            _ => Err(ValidationError {
3970                layer: SctpRef::name(),
3971                class: ValidationErrorClass::InsufficientBytes,
3972                #[cfg(feature = "error_string")]
3973                reason: "insufficient bytes in SCTP Missing Mandatory Parameter option for header",
3974            }),
3975        }
3976    }
3977
3978    #[inline]
3979    pub fn cause_code(&self) -> u16 {
3980        u16::from_be_bytes(utils::to_array(self.data, 0).unwrap())
3981    }
3982
3983    #[inline]
3984    pub fn unpadded_len(&self) -> u16 {
3985        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
3986    }
3987
3988    #[inline]
3989    pub fn len(&self) -> usize {
3990        utils::padded_length::<4>(self.unpadded_len() as usize)
3991    }
3992
3993    #[inline]
3994    pub fn missing_params_cnt(&self) -> u32 {
3995        u32::from_be_bytes(utils::to_array(self.data, 2).unwrap())
3996    }
3997
3998    #[inline]
3999    pub fn missing_params_iter(&self) -> MissingParameterIterRef<'a> {
4000        MissingParameterIterRef {
4001            data: &self.data[4..cmp::min(
4002                4 + (2 * self.missing_params_cnt() as usize),
4003                self.data.len(),
4004            )],
4005        }
4006    }
4007}
4008
4009#[derive(Clone, Copy, Debug)]
4010pub struct MissingParameterIterRef<'a> {
4011    data: &'a [u8],
4012}
4013
4014impl<'a> Iterator for MissingParameterIterRef<'a> {
4015    type Item = u16;
4016
4017    #[inline]
4018    fn next(&mut self) -> Option<Self::Item> {
4019        match (utils::to_array(self.data, 0), self.data.get(2..)) {
4020            (Some(arr), Some(remaining)) => {
4021                self.data = remaining;
4022                Some(u16::from_be_bytes(arr))
4023            }
4024            _ => None,
4025        }
4026    }
4027}
4028
4029#[derive(Clone, Debug)]
4030#[cfg(feature = "alloc")]
4031pub struct StaleCookieError {
4032    staleness: u32,
4033}
4034
4035#[cfg(feature = "alloc")]
4036impl StaleCookieError {
4037    #[inline]
4038    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
4039        Self::validate(bytes)?;
4040        Ok(Self::from_bytes_unchecked(bytes))
4041    }
4042
4043    #[inline]
4044    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
4045        Self::from(StaleCookieErrorRef::from_bytes_unchecked(bytes))
4046    }
4047
4048    #[inline]
4049    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
4050        StaleCookieErrorRef::validate(bytes)
4051    }
4052
4053    #[inline]
4054    pub fn cause_code(&self) -> u16 {
4055        ERR_CODE_STALE_COOKIE
4056    }
4057
4058    #[inline]
4059    pub fn len(&self) -> usize {
4060        8
4061    }
4062
4063    #[inline]
4064    pub fn staleness(&self) -> u32 {
4065        self.staleness
4066    }
4067
4068    #[inline]
4069    pub fn set_staleness(&mut self, staleness: u32) {
4070        self.staleness = staleness;
4071    }
4072
4073    #[inline]
4074    pub fn to_bytes_extended<T: PacketWritable>(
4075        &self,
4076        writer: &mut PacketWriter<'_, T>,
4077    ) -> Result<(), SerializationError> {
4078        writer.write_slice(&ERR_CODE_STALE_COOKIE.to_be_bytes())?;
4079        writer.write_slice(&8u16.to_be_bytes())?;
4080        writer.write_slice(&self.staleness.to_be_bytes())
4081    }
4082}
4083
4084#[cfg(feature = "alloc")]
4085impl From<StaleCookieErrorRef<'_>> for StaleCookieError {
4086    #[inline]
4087    fn from(value: StaleCookieErrorRef<'_>) -> Self {
4088        Self::from(&value)
4089    }
4090}
4091
4092#[cfg(feature = "alloc")]
4093impl From<&StaleCookieErrorRef<'_>> for StaleCookieError {
4094    #[inline]
4095    fn from(value: &StaleCookieErrorRef<'_>) -> Self {
4096        StaleCookieError {
4097            staleness: value.staleness(),
4098        }
4099    }
4100}
4101
4102#[derive(Clone, Copy, Debug)]
4103pub struct StaleCookieErrorRef<'a> {
4104    data: &'a [u8],
4105}
4106
4107impl<'a> StaleCookieErrorRef<'a> {
4108    #[inline]
4109    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
4110        Self::validate(bytes)?;
4111        Ok(Self::from_bytes_unchecked(bytes))
4112    }
4113
4114    #[inline]
4115    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
4116        StaleCookieErrorRef { data: bytes }
4117    }
4118
4119    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
4120        match (utils::to_array(bytes, 0), utils::to_array(bytes, 2)) {
4121            (Some(cause_code_arr), Some(len_arr)) => {
4122                let cause_code = u16::from_be_bytes(cause_code_arr);
4123                let len = u16::from_be_bytes(len_arr) as usize;
4124
4125                if bytes.len() < 8 {
4126                    return Err(ValidationError {
4127                        layer: SctpRef::name(),
4128                        class: ValidationErrorClass::InsufficientBytes,
4129                        #[cfg(feature = "error_string")]        
4130                        reason: "insufficient bytes in SCTP Stale Cookie option for header + Measure of Staleness field",
4131                    });
4132                }
4133
4134                if cause_code != ERR_CODE_STALE_COOKIE {
4135                    return Err(ValidationError {
4136                        layer: SctpRef::name(),
4137                        class: ValidationErrorClass::InvalidValue,
4138                        #[cfg(feature = "error_string")]
4139                        reason:
4140                            "invalid cause code in SCTP Stale Cookie option (must be equal to 3)",
4141                    });
4142                }
4143
4144                if len != 8 {
4145                    return Err(ValidationError {
4146                        layer: SctpRef::name(),
4147                        class: ValidationErrorClass::InvalidValue,
4148                        #[cfg(feature = "error_string")]
4149                        reason: "invalid length in SCTP Stale Cookie option (must be equal to 8)",
4150                    });
4151                }
4152
4153                if bytes.len() > 8 {
4154                    Err(ValidationError {
4155                        layer: SctpRef::name(),
4156                        class: ValidationErrorClass::ExcessBytes(bytes.len() - 8),
4157                        #[cfg(feature = "error_string")]
4158                        reason: "extra bytes remain at end of SCTP Stale Cookie option",
4159                    })
4160                } else {
4161                    Ok(())
4162                }
4163            }
4164            _ => Err(ValidationError {
4165                layer: SctpRef::name(),
4166                class: ValidationErrorClass::InsufficientBytes,
4167                #[cfg(feature = "error_string")]
4168                reason: "insufficient bytes in SCTP Stale Cookie option for header",
4169            }),
4170        }
4171    }
4172
4173    #[inline]
4174    pub fn cause_code(&self) -> u16 {
4175        u16::from_be_bytes(utils::to_array(self.data, 0).unwrap())
4176    }
4177
4178    #[inline]
4179    pub fn unpadded_len(&self) -> u16 {
4180        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
4181    }
4182
4183    #[inline]
4184    pub fn len(&self) -> usize {
4185        utils::padded_length::<4>(self.unpadded_len() as usize)
4186    }
4187
4188    #[inline]
4189    pub fn staleness(&self) -> u32 {
4190        u32::from_be_bytes(utils::to_array(self.data, 4).unwrap())
4191    }
4192}
4193
4194#[derive(Clone, Debug)]
4195#[cfg(feature = "alloc")]
4196pub struct UnresolvableAddrError {
4197    addr: Vec<u8>,
4198}
4199
4200#[cfg(feature = "alloc")]
4201impl UnresolvableAddrError {
4202    #[inline]
4203    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
4204        Self::validate(bytes)?;
4205        Ok(Self::from_bytes_unchecked(bytes))
4206    }
4207
4208    #[inline]
4209    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
4210        Self::from(UnresolvableAddrErrorRef::from_bytes_unchecked(bytes))
4211    }
4212
4213    #[inline]
4214    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
4215        UnresolvableAddrErrorRef::validate(bytes)
4216    }
4217
4218    #[inline]
4219    pub fn cause_code(&self) -> u16 {
4220        ERR_CODE_UNRESOLVABLE_ADDRESS
4221    }
4222
4223    pub fn unpadded_len(&self) -> usize {
4224        4 + self.addr.len()
4225    }
4226
4227    #[inline]
4228    pub fn len(&self) -> usize {
4229        utils::padded_length::<4>(self.unpadded_len())
4230    }
4231
4232    #[inline]
4233    pub fn addr(&self) -> &Vec<u8> {
4234        &self.addr
4235    }
4236
4237    #[inline]
4238    pub fn addr_mut(&mut self) -> &mut Vec<u8> {
4239        &mut self.addr
4240    }
4241
4242    pub fn to_bytes_extended<T: PacketWritable>(
4243        &self,
4244        writer: &mut PacketWriter<'_, T>,
4245    ) -> Result<(), SerializationError> {
4246        writer.write_slice(&ERR_CODE_UNRESOLVABLE_ADDRESS.to_be_bytes())?;
4247        writer.write_slice(
4248            &u16::try_from(self.unpadded_len())
4249                .map_err(|_| SerializationError::length_encoding(SctpRef::name()))?
4250                .to_be_bytes(),
4251        )?;
4252        writer.write_slice(&self.addr)?;
4253        for _ in self.unpadded_len()..self.len() {
4254            writer.write_slice(&[0])?;
4255        }
4256
4257        Ok(())
4258    }
4259}
4260
4261#[cfg(feature = "alloc")]
4262impl From<UnresolvableAddrErrorRef<'_>> for UnresolvableAddrError {
4263    #[inline]
4264    fn from(value: UnresolvableAddrErrorRef<'_>) -> Self {
4265        Self::from(&value)
4266    }
4267}
4268
4269#[cfg(feature = "alloc")]
4270impl From<&UnresolvableAddrErrorRef<'_>> for UnresolvableAddrError {
4271    #[inline]
4272    fn from(value: &UnresolvableAddrErrorRef<'_>) -> Self {
4273        UnresolvableAddrError {
4274            addr: Vec::from(value.addr()),
4275        }
4276    }
4277}
4278
4279#[derive(Clone, Copy, Debug)]
4280pub struct UnresolvableAddrErrorRef<'a> {
4281    data: &'a [u8],
4282}
4283
4284impl<'a> UnresolvableAddrErrorRef<'a> {
4285    #[inline]
4286    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
4287        Self::validate(bytes)?;
4288        Ok(Self::from_bytes_unchecked(bytes))
4289    }
4290
4291    #[inline]
4292    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
4293        UnresolvableAddrErrorRef { data: bytes }
4294    }
4295
4296    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
4297        match (utils::to_array(bytes, 0), utils::to_array(bytes, 2)) {
4298            (Some(cause_code_arr), Some(len_arr)) => {
4299                let cause_code = u16::from_be_bytes(cause_code_arr);
4300                let unpadded_len = u16::from_be_bytes(len_arr) as usize;
4301                let len = utils::padded_length::<4>(unpadded_len);
4302
4303                if bytes.len() < cmp::max(4, len) {
4304                    return Err(ValidationError {
4305                        layer: SctpRef::name(),
4306                        class: ValidationErrorClass::InsufficientBytes,
4307                        #[cfg(feature = "error_string")]        
4308                        reason: "insufficient bytes in SCTP Unresolvable Address option for header + Unresolvable Address field",
4309                    });
4310                }
4311
4312                if cause_code != ERR_CODE_UNRESOLVABLE_ADDRESS {
4313                    return Err(ValidationError {
4314                        layer: SctpRef::name(),
4315                        class: ValidationErrorClass::InvalidValue,
4316                        #[cfg(feature = "error_string")]        
4317                        reason: "invalid cause code in SCTP Unresolvable Address option (must be equal to 5)",
4318                    });
4319                }
4320
4321                if unpadded_len < 4 {
4322                    return Err(ValidationError {
4323                        layer: SctpRef::name(),
4324                        class: ValidationErrorClass::InvalidValue,
4325                        #[cfg(feature = "error_string")]        
4326                        reason: "invalid length in SCTP Unresolvable Address option (must be at least 4 bytes long)",
4327                    });
4328                }
4329
4330                for b in bytes.iter().take(len).skip(unpadded_len) {
4331                    if *b != 0 {
4332                        return Err(ValidationError {
4333                            layer: SctpRef::name(),
4334                            class: ValidationErrorClass::InvalidValue,
4335                            #[cfg(feature = "error_string")]            
4336                            reason: "invalid nonzero padding values at end of SCTP Unresolvable Address 4ption",
4337                        });
4338                    }
4339                }
4340
4341                if bytes.len() > len {
4342                    Err(ValidationError {
4343                        layer: SctpRef::name(),
4344                        class: ValidationErrorClass::ExcessBytes(bytes.len() - len),
4345                        #[cfg(feature = "error_string")]
4346                        reason: "extra bytes remain at end of SCTP Unresolvable Address option",
4347                    })
4348                } else {
4349                    Ok(())
4350                }
4351            }
4352            _ => Err(ValidationError {
4353                layer: SctpRef::name(),
4354                class: ValidationErrorClass::InsufficientBytes,
4355                #[cfg(feature = "error_string")]
4356                reason: "insufficient bytes in SCTP Unresolvable Address option for header",
4357            }),
4358        }
4359    }
4360
4361    #[inline]
4362    pub fn cause_code(&self) -> u16 {
4363        u16::from_be_bytes(utils::to_array(self.data, 0).unwrap())
4364    }
4365
4366    #[inline]
4367    pub fn unpadded_len(&self) -> u16 {
4368        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
4369    }
4370
4371    #[inline]
4372    pub fn len(&self) -> usize {
4373        utils::padded_length::<4>(self.unpadded_len() as usize)
4374    }
4375
4376    #[inline]
4377    pub fn addr(&self) -> &[u8] {
4378        &self.data[4..self.unpadded_len() as usize]
4379    }
4380}
4381
4382#[derive(Clone, Debug)]
4383#[cfg(feature = "alloc")]
4384pub struct UnrecognizedChunkError {
4385    chunk: Vec<u8>,
4386}
4387
4388#[cfg(feature = "alloc")]
4389impl UnrecognizedChunkError {
4390    #[inline]
4391    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
4392        Self::validate(bytes)?;
4393        Ok(Self::from_bytes_unchecked(bytes))
4394    }
4395
4396    #[inline]
4397    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
4398        Self::from(UnrecognizedChunkErrorRef::from_bytes_unchecked(bytes))
4399    }
4400
4401    #[inline]
4402    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
4403        UnrecognizedChunkErrorRef::validate(bytes)
4404    }
4405
4406    #[inline]
4407    pub fn cause_code(&self) -> u16 {
4408        ERR_CODE_UNRECOGNIZED_CHUNK
4409    }
4410
4411    #[inline]
4412    pub fn unpadded_len(&self) -> usize {
4413        4 + self.chunk.len()
4414    }
4415
4416    #[inline]
4417    pub fn len(&self) -> usize {
4418        utils::padded_length::<4>(self.unpadded_len())
4419    }
4420
4421    #[inline]
4422    pub fn chunk(&self) -> &Vec<u8> {
4423        &self.chunk
4424    }
4425
4426    #[inline]
4427    pub fn chunk_mut(&mut self) -> &mut Vec<u8> {
4428        &mut self.chunk
4429    }
4430
4431    #[inline]
4432    pub fn to_bytes_extended<T: PacketWritable>(
4433        &self,
4434        writer: &mut PacketWriter<'_, T>,
4435    ) -> Result<(), SerializationError> {
4436        writer.write_slice(&ERR_CODE_STALE_COOKIE.to_be_bytes())?;
4437        writer.write_slice(&8u16.to_be_bytes())?;
4438        writer.write_slice(&self.chunk)
4439    }
4440}
4441
4442#[cfg(feature = "alloc")]
4443impl From<UnrecognizedChunkErrorRef<'_>> for UnrecognizedChunkError {
4444    #[inline]
4445    fn from(value: UnrecognizedChunkErrorRef<'_>) -> Self {
4446        Self::from(&value)
4447    }
4448}
4449
4450#[cfg(feature = "alloc")]
4451impl From<&UnrecognizedChunkErrorRef<'_>> for UnrecognizedChunkError {
4452    #[inline]
4453    fn from(value: &UnrecognizedChunkErrorRef<'_>) -> Self {
4454        UnrecognizedChunkError {
4455            chunk: Vec::from(value.chunk()),
4456        }
4457    }
4458}
4459
4460#[derive(Clone, Copy, Debug)]
4461pub struct UnrecognizedChunkErrorRef<'a> {
4462    data: &'a [u8],
4463}
4464
4465impl<'a> UnrecognizedChunkErrorRef<'a> {
4466    #[inline]
4467    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
4468        Self::validate(bytes)?;
4469        Ok(Self::from_bytes_unchecked(bytes))
4470    }
4471
4472    #[inline]
4473    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
4474        UnrecognizedChunkErrorRef { data: bytes }
4475    }
4476
4477    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
4478        match (utils::to_array(bytes, 0), utils::to_array(bytes, 2)) {
4479            (Some(cause_code_arr), Some(len_arr)) => {
4480                let cause_code = u16::from_be_bytes(cause_code_arr);
4481                let len = u16::from_be_bytes(len_arr) as usize;
4482
4483                if bytes.len() < cmp::max(8, len) {
4484                    return Err(ValidationError {
4485                        layer: SctpRef::name(),
4486                        class: ValidationErrorClass::InsufficientBytes,
4487                        #[cfg(feature = "error_string")]        
4488                        reason: "insufficient bytes in SCTP Unrecognized Chunk option for header + Unrecognized Chunk field",
4489                    });
4490                }
4491
4492                if cause_code != ERR_CODE_UNRECOGNIZED_CHUNK {
4493                    return Err(ValidationError {
4494                        layer: SctpRef::name(),
4495                        class: ValidationErrorClass::InvalidValue,
4496                        #[cfg(feature = "error_string")]        
4497                        reason: "invalid cause code in SCTP Unrecognized Chunk option (must be equal to 6)",
4498                    });
4499                }
4500
4501                if bytes.len() > 8 {
4502                    Err(ValidationError {
4503                        layer: SctpRef::name(),
4504                        class: ValidationErrorClass::ExcessBytes(bytes.len() - len),
4505                        #[cfg(feature = "error_string")]
4506                        reason: "extra bytes remain at end of SCTP Unrecognized Chunk option",
4507                    })
4508                } else {
4509                    Ok(())
4510                }
4511            }
4512            _ => Err(ValidationError {
4513                layer: SctpRef::name(),
4514                class: ValidationErrorClass::InsufficientBytes,
4515                #[cfg(feature = "error_string")]
4516                reason: "insufficient bytes in SCTP Unrecognized Chunk option for header",
4517            }),
4518        }
4519    }
4520
4521    #[inline]
4522    pub fn cause_code(&self) -> u16 {
4523        u16::from_be_bytes(utils::to_array(self.data, 0).unwrap())
4524    }
4525
4526    #[inline]
4527    pub fn unpadded_len(&self) -> u16 {
4528        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
4529    }
4530
4531    #[inline]
4532    pub fn len(&self) -> usize {
4533        utils::padded_length::<4>(self.unpadded_len() as usize)
4534    }
4535
4536    #[inline]
4537    pub fn chunk(&self) -> &[u8] {
4538        &self.data[8..self.unpadded_len() as usize]
4539    }
4540}
4541
4542#[derive(Clone, Debug)]
4543#[cfg(feature = "alloc")]
4544pub struct UnrecognizedParamError {
4545    params: Vec<GenericParam>,
4546}
4547
4548#[cfg(feature = "alloc")]
4549impl UnrecognizedParamError {
4550    #[inline]
4551    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
4552        Self::validate(bytes)?;
4553        Ok(Self::from_bytes_unchecked(bytes))
4554    }
4555
4556    #[inline]
4557    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
4558        Self::from(UnrecognizedParamErrorRef::from_bytes_unchecked(bytes))
4559    }
4560
4561    #[inline]
4562    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
4563        UnrecognizedParamErrorRef::validate(bytes)
4564    }
4565
4566    #[inline]
4567    pub fn cause_code(&self) -> u16 {
4568        ERR_CODE_UNRECOGNIZED_PARAMS
4569    }
4570
4571    #[inline]
4572    pub fn unpadded_len(&self) -> usize {
4573        4 + self.params.iter().map(|p| p.len()).sum::<usize>()
4574    }
4575
4576    #[inline]
4577    pub fn len(&self) -> usize {
4578        utils::padded_length::<4>(self.unpadded_len())
4579    }
4580
4581    #[inline]
4582    pub fn params(&self) -> &Vec<GenericParam> {
4583        &self.params
4584    }
4585
4586    #[inline]
4587    pub fn params_mut(&mut self) -> &mut Vec<GenericParam> {
4588        &mut self.params
4589    }
4590
4591    pub fn to_bytes_extended<T: PacketWritable>(
4592        &self,
4593        writer: &mut PacketWriter<'_, T>,
4594    ) -> Result<(), SerializationError> {
4595        writer.write_slice(&ERR_CODE_UNRECOGNIZED_PARAMS.to_be_bytes())?;
4596        writer.write_slice(
4597            &u16::try_from(self.unpadded_len())
4598                .map_err(|_| SerializationError::length_encoding(SctpRef::name()))?
4599                .to_be_bytes(),
4600        )?;
4601        for param in self.params.iter() {
4602            param.to_bytes_extended(writer)?;
4603        }
4604
4605        Ok(())
4606    }
4607}
4608
4609#[cfg(feature = "alloc")]
4610impl From<UnrecognizedParamErrorRef<'_>> for UnrecognizedParamError {
4611    #[inline]
4612    fn from(value: UnrecognizedParamErrorRef<'_>) -> Self {
4613        Self::from(&value)
4614    }
4615}
4616
4617#[cfg(feature = "alloc")]
4618impl From<&UnrecognizedParamErrorRef<'_>> for UnrecognizedParamError {
4619    fn from(value: &UnrecognizedParamErrorRef<'_>) -> Self {
4620        let mut params = Vec::new();
4621        let iter = value.params_iter();
4622        for param in iter {
4623            params.push(param.into());
4624        }
4625
4626        UnrecognizedParamError { params }
4627    }
4628}
4629
4630#[derive(Clone, Copy, Debug)]
4631pub struct UnrecognizedParamErrorRef<'a> {
4632    data: &'a [u8],
4633}
4634
4635impl<'a> UnrecognizedParamErrorRef<'a> {
4636    #[inline]
4637    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
4638        Self::validate(bytes)?;
4639        Ok(Self::from_bytes_unchecked(bytes))
4640    }
4641
4642    #[inline]
4643    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
4644        UnrecognizedParamErrorRef { data: bytes }
4645    }
4646
4647    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
4648        match (utils::to_array(bytes, 0), utils::to_array(bytes, 2)) {
4649            (Some(cause_code_arr), Some(len_arr)) => {
4650                let cause_code = u16::from_be_bytes(cause_code_arr);
4651                let len = u16::from_be_bytes(len_arr) as usize;
4652
4653                if bytes.len() < cmp::max(4, len) {
4654                    return Err(ValidationError {
4655                        layer: SctpRef::name(),
4656                        class: ValidationErrorClass::InsufficientBytes,
4657                        #[cfg(feature = "error_string")]        
4658                        reason: "insufficient bytes in SCTP Unrecognized Parameters Option for header and Unrecognized Chunk field",
4659                    });
4660                }
4661
4662                if cause_code != ERR_CODE_UNRECOGNIZED_PARAMS {
4663                    return Err(ValidationError {
4664                        layer: SctpRef::name(),
4665                        class: ValidationErrorClass::InvalidValue,
4666                        #[cfg(feature = "error_string")]        
4667                        reason: "invalid cause code in SCTP Unrecognized Parameters option (must be equal to 8)",
4668                    });
4669                }
4670
4671                if bytes.len() > len {
4672                    Err(ValidationError {
4673                        layer: SctpRef::name(),
4674                        class: ValidationErrorClass::ExcessBytes(bytes.len() - len),
4675                        #[cfg(feature = "error_string")]
4676                        reason: "extra bytes remain at end of SCTP Unrecognized Parameters option",
4677                    })
4678                } else {
4679                    Ok(())
4680                }
4681            }
4682            _ => Err(ValidationError {
4683                layer: SctpRef::name(),
4684                class: ValidationErrorClass::InsufficientBytes,
4685                #[cfg(feature = "error_string")]
4686                reason: "insufficient bytes in SCTP Unrecognized Parameters option for header",
4687            }),
4688        }
4689    }
4690
4691    #[inline]
4692    pub fn cause_code(&self) -> u16 {
4693        u16::from_be_bytes(utils::to_array(self.data, 0).unwrap())
4694    }
4695
4696    #[inline]
4697    pub fn unpadded_len(&self) -> u16 {
4698        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
4699    }
4700
4701    #[inline]
4702    pub fn len(&self) -> usize {
4703        utils::padded_length::<4>(self.unpadded_len() as usize)
4704    }
4705
4706    #[inline]
4707    pub fn params_iter(&self) -> ParamsIterRef<'a> {
4708        ParamsIterRef { bytes: self.data }
4709    }
4710}
4711
4712#[derive(Clone, Copy, Debug)]
4713pub struct ParamsIterRef<'a> {
4714    bytes: &'a [u8],
4715}
4716
4717impl<'a> Iterator for ParamsIterRef<'a> {
4718    type Item = GenericParamRef<'a>;
4719
4720    fn next(&mut self) -> Option<Self::Item> {
4721        match utils::to_array(self.bytes, 2) {
4722            Some(unpadded_len_arr) => {
4723                let unpadded_len = cmp::max(4, u16::from_be_bytes(unpadded_len_arr));
4724                let len = utils::padded_length::<4>(unpadded_len as usize);
4725                match (self.bytes.get(..len), self.bytes.get(len..)) {
4726                    (Some(param), Some(remaining)) => {
4727                        self.bytes = remaining;
4728                        Some(GenericParamRef::from_bytes_unchecked(param))
4729                    }
4730                    _ => {
4731                        let param = GenericParamRef::from_bytes_unchecked(self.bytes);
4732                        self.bytes = &[];
4733                        Some(param)
4734                    }
4735                }
4736            }
4737            None => None,
4738        }
4739    }
4740}
4741
4742#[derive(Clone, Debug)]
4743pub struct NoUserDataError {
4744    tsn: u32,
4745}
4746
4747impl NoUserDataError {
4748    #[inline]
4749    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
4750        Self::validate(bytes)?;
4751        Ok(Self::from_bytes_unchecked(bytes))
4752    }
4753
4754    #[inline]
4755    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
4756        Self::from(NoUserDataErrorRef::from_bytes_unchecked(bytes))
4757    }
4758
4759    #[inline]
4760    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
4761        NoUserDataErrorRef::validate(bytes)
4762    }
4763
4764    #[inline]
4765    pub fn cause_code(&self) -> u16 {
4766        ERR_CODE_NO_USER_DATA
4767    }
4768
4769    #[inline]
4770    pub fn len(&self) -> usize {
4771        8
4772    }
4773
4774    #[inline]
4775    pub fn tsn(&self) -> u32 {
4776        self.tsn
4777    }
4778
4779    #[inline]
4780    pub fn set_tsn(&mut self, tsn: u32) {
4781        self.tsn = tsn;
4782    }
4783
4784    pub fn to_bytes_extended<T: PacketWritable>(
4785        &self,
4786        writer: &mut PacketWriter<'_, T>,
4787    ) -> Result<(), SerializationError> {
4788        writer.write_slice(&ERR_CODE_NO_USER_DATA.to_be_bytes())?;
4789        writer.write_slice(&8u16.to_be_bytes())?;
4790        writer.write_slice(&self.tsn.to_be_bytes())
4791    }
4792}
4793
4794impl From<NoUserDataErrorRef<'_>> for NoUserDataError {
4795    #[inline]
4796    fn from(value: NoUserDataErrorRef<'_>) -> Self {
4797        Self::from(&value)
4798    }
4799}
4800
4801impl From<&NoUserDataErrorRef<'_>> for NoUserDataError {
4802    #[inline]
4803    fn from(value: &NoUserDataErrorRef<'_>) -> Self {
4804        NoUserDataError { tsn: value.tsn() }
4805    }
4806}
4807
4808#[derive(Clone, Copy, Debug)]
4809pub struct NoUserDataErrorRef<'a> {
4810    data: &'a [u8],
4811}
4812
4813impl<'a> NoUserDataErrorRef<'a> {
4814    #[inline]
4815    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
4816        Self::validate(bytes)?;
4817        Ok(Self::from_bytes_unchecked(bytes))
4818    }
4819
4820    #[inline]
4821    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
4822        NoUserDataErrorRef { data: bytes }
4823    }
4824
4825    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
4826        match (utils::to_array(bytes, 0), utils::to_array(bytes, 2)) {
4827            (Some(cause_code_arr), Some(len_arr)) => {
4828                let cause_code = u16::from_be_bytes(cause_code_arr);
4829                let len = u16::from_be_bytes(len_arr) as usize;
4830
4831                if bytes.len() < 8 {
4832                    return Err(ValidationError {
4833                        layer: SctpRef::name(),
4834                        class: ValidationErrorClass::InsufficientBytes,
4835                        #[cfg(feature = "error_string")]        
4836                        reason: "insufficient bytes in SCTP No User Data option for header and explanation field",
4837                    });
4838                }
4839
4840                if cause_code != ERR_CODE_NO_USER_DATA {
4841                    return Err(ValidationError {
4842                        layer: SctpRef::name(),
4843                        class: ValidationErrorClass::InvalidValue,
4844                        #[cfg(feature = "error_string")]
4845                        reason:
4846                            "invalid cause code in SCTP No User Data option (must be equal to 9)",
4847                    });
4848                }
4849
4850                if len != 8 {
4851                    return Err(ValidationError {
4852                        layer: SctpRef::name(),
4853                        class: ValidationErrorClass::InvalidValue,
4854                        #[cfg(feature = "error_string")]
4855                        reason: "invalid length in SCTP No User Data option (must be equal to 8)",
4856                    });
4857                }
4858
4859                if bytes.len() > 8 {
4860                    Err(ValidationError {
4861                        layer: SctpRef::name(),
4862                        class: ValidationErrorClass::ExcessBytes(bytes.len() - 8),
4863                        #[cfg(feature = "error_string")]
4864                        reason: "extra bytes remain at end of SCTP No User Data option",
4865                    })
4866                } else {
4867                    Ok(())
4868                }
4869            }
4870            _ => Err(ValidationError {
4871                layer: SctpRef::name(),
4872                class: ValidationErrorClass::InsufficientBytes,
4873                #[cfg(feature = "error_string")]
4874                reason: "insufficient bytes in SCTP No User Data option for header",
4875            }),
4876        }
4877    }
4878
4879    #[inline]
4880    pub fn cause_code(&self) -> u16 {
4881        u16::from_be_bytes(utils::to_array(self.data, 0).unwrap())
4882    }
4883
4884    #[inline]
4885    pub fn unpadded_len(&self) -> u16 {
4886        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
4887    }
4888
4889    #[inline]
4890    pub fn len(&self) -> usize {
4891        utils::padded_length::<4>(self.unpadded_len() as usize)
4892    }
4893
4894    #[inline]
4895    pub fn tsn(&self) -> u32 {
4896        u32::from_be_bytes(utils::to_array(self.data, 4).unwrap())
4897    }
4898}
4899
4900#[derive(Clone, Debug)]
4901#[cfg(feature = "alloc")]
4902pub struct AssociationNewAddrError {
4903    tlvs: Vec<GenericParam>,
4904}
4905
4906#[cfg(feature = "alloc")]
4907impl AssociationNewAddrError {
4908    #[inline]
4909    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
4910        Self::validate(bytes)?;
4911        Ok(Self::from_bytes_unchecked(bytes))
4912    }
4913
4914    #[inline]
4915    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
4916        Self::from(AssociationNewAddrErrorRef::from_bytes_unchecked(bytes))
4917    }
4918
4919    #[inline]
4920    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
4921        AssociationNewAddrErrorRef::validate(bytes)
4922    }
4923
4924    #[inline]
4925    pub fn cause_code(&self) -> u16 {
4926        ERR_CODE_RESTART_ASSOC_NEW_ADDR
4927    }
4928
4929    #[inline]
4930    pub fn unpadded_len(&self) -> usize {
4931        4 + self.tlvs.iter().map(|p| p.len()).sum::<usize>()
4932    }
4933
4934    #[inline]
4935    pub fn len(&self) -> usize {
4936        utils::padded_length::<4>(self.unpadded_len())
4937    }
4938
4939    #[inline]
4940    pub fn params(&self) -> &Vec<GenericParam> {
4941        &self.tlvs
4942    }
4943
4944    #[inline]
4945    pub fn params_mut(&mut self) -> &mut Vec<GenericParam> {
4946        &mut self.tlvs
4947    }
4948
4949    pub fn to_bytes_extended<T: PacketWritable>(
4950        &self,
4951        writer: &mut PacketWriter<'_, T>,
4952    ) -> Result<(), SerializationError> {
4953        writer.write_slice(&ERR_CODE_RESTART_ASSOC_NEW_ADDR.to_be_bytes())?;
4954        writer.write_slice(
4955            &u16::try_from(self.unpadded_len())
4956                .map_err(|_| SerializationError::length_encoding(SctpRef::name()))?
4957                .to_be_bytes(),
4958        )?;
4959        for tlv in self.tlvs.iter() {
4960            tlv.to_bytes_extended(writer)?;
4961        }
4962
4963        Ok(())
4964    }
4965}
4966
4967#[cfg(feature = "alloc")]
4968impl From<AssociationNewAddrErrorRef<'_>> for AssociationNewAddrError {
4969    #[inline]
4970    fn from(value: AssociationNewAddrErrorRef<'_>) -> Self {
4971        Self::from(&value)
4972    }
4973}
4974
4975#[cfg(feature = "alloc")]
4976impl From<&AssociationNewAddrErrorRef<'_>> for AssociationNewAddrError {
4977    #[inline]
4978    fn from(value: &AssociationNewAddrErrorRef<'_>) -> Self {
4979        let mut tlvs = Vec::new();
4980        let iter = value.params_iter();
4981        for param in iter {
4982            tlvs.push(param.into());
4983        }
4984
4985        AssociationNewAddrError { tlvs }
4986    }
4987}
4988
4989#[derive(Clone, Copy, Debug)]
4990pub struct AssociationNewAddrErrorRef<'a> {
4991    data: &'a [u8],
4992}
4993
4994impl<'a> AssociationNewAddrErrorRef<'a> {
4995    #[inline]
4996    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
4997        Self::validate(bytes)?;
4998        Ok(Self::from_bytes_unchecked(bytes))
4999    }
5000
5001    #[inline]
5002    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
5003        AssociationNewAddrErrorRef { data: bytes }
5004    }
5005
5006    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
5007        match (utils::to_array(bytes, 0), utils::to_array(bytes, 2)) {
5008            (Some(cause_code_arr), Some(len_arr)) => {
5009                let cause_code = u16::from_be_bytes(cause_code_arr);
5010                let len = u16::from_be_bytes(len_arr) as usize;
5011
5012                if bytes.len() < cmp::max(4, len) {
5013                    return Err(ValidationError {
5014                        layer: SctpRef::name(),
5015                        class: ValidationErrorClass::InsufficientBytes,
5016                        #[cfg(feature = "error_string")]        
5017                        reason: "insufficient bytes in SCTP Restart of Association with New Address option for header + New Address TLVs field",
5018                    })
5019                }
5020
5021                if cause_code != ERR_CODE_RESTART_ASSOC_NEW_ADDR {
5022                    return Err(ValidationError {
5023                        layer: SctpRef::name(),
5024                        class: ValidationErrorClass::InvalidValue,
5025                        #[cfg(feature = "error_string")]        
5026                        reason: "invalid cause code in SCTP Restart of Association with New Address option (must be equal to 11)",
5027                    })
5028                }
5029
5030                if bytes.len() > len {
5031                    Err(ValidationError {
5032                        layer: SctpRef::name(),
5033                        class: ValidationErrorClass::ExcessBytes(bytes.len() - len),
5034                        #[cfg(feature = "error_string")]        
5035                        reason: "extra bytes remain at end of SCTP Restart of Association with New Address option",
5036                    })
5037                } else {
5038                    Ok(())
5039                }
5040            },
5041            _ => Err(ValidationError {
5042                layer: SctpRef::name(),
5043                class: ValidationErrorClass::InsufficientBytes,
5044                #[cfg(feature = "error_string")]
5045                reason: "insufficient bytes in SCTP Restart of Association with New Address option for header"
5046            })
5047        }
5048    }
5049
5050    #[inline]
5051    pub fn cause_code(&self) -> u16 {
5052        u16::from_be_bytes(utils::to_array(self.data, 0).unwrap())
5053    }
5054
5055    #[inline]
5056    pub fn unpadded_len(&self) -> u16 {
5057        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
5058    }
5059
5060    #[inline]
5061    pub fn len(&self) -> usize {
5062        utils::padded_length::<4>(self.unpadded_len() as usize)
5063    }
5064
5065    #[inline]
5066    pub fn params_iter(&self) -> ParamsIterRef<'a> {
5067        ParamsIterRef { bytes: self.data }
5068    }
5069}
5070
5071#[derive(Clone, Debug)]
5072#[cfg(feature = "alloc")]
5073pub struct UserInitiatedAbortError {
5074    reason: Vec<u8>,
5075}
5076
5077#[cfg(feature = "alloc")]
5078impl UserInitiatedAbortError {
5079    #[inline]
5080    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
5081        Self::validate(bytes)?;
5082        Ok(Self::from_bytes_unchecked(bytes))
5083    }
5084
5085    #[inline]
5086    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
5087        Self::from(UserInitiatedAbortErrorRef::from_bytes_unchecked(bytes))
5088    }
5089
5090    #[inline]
5091    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
5092        UserInitiatedAbortErrorRef::validate(bytes)
5093    }
5094
5095    #[inline]
5096    pub fn cause_code(&self) -> u16 {
5097        ERR_CODE_USER_INITIATED_ABORT
5098    }
5099
5100    #[inline]
5101    pub fn unpadded_len(&self) -> usize {
5102        4 + self.reason.len()
5103    }
5104
5105    #[inline]
5106    pub fn len(&self) -> usize {
5107        utils::padded_length::<4>(self.unpadded_len())
5108    }
5109
5110    #[inline]
5111    pub fn reason(&self) -> &Vec<u8> {
5112        &self.reason
5113    }
5114
5115    #[inline]
5116    pub fn reason_mut(&mut self) -> &mut Vec<u8> {
5117        &mut self.reason
5118    }
5119
5120    pub fn to_bytes_extended<T: PacketWritable>(
5121        &self,
5122        writer: &mut PacketWriter<'_, T>,
5123    ) -> Result<(), SerializationError> {
5124        writer.write_slice(&ERR_CODE_USER_INITIATED_ABORT.to_be_bytes())?;
5125        writer.write_slice(
5126            &u16::try_from(self.unpadded_len())
5127                .map_err(|_| SerializationError::length_encoding(SctpRef::name()))?
5128                .to_be_bytes(),
5129        )?;
5130        writer.write_slice(&self.reason)?;
5131        for _ in self.unpadded_len()..self.len() {
5132            writer.write_slice(&[0])?;
5133        }
5134
5135        Ok(())
5136    }
5137}
5138
5139#[cfg(feature = "alloc")]
5140impl From<UserInitiatedAbortErrorRef<'_>> for UserInitiatedAbortError {
5141    #[inline]
5142    fn from(value: UserInitiatedAbortErrorRef<'_>) -> Self {
5143        Self::from(&value)
5144    }
5145}
5146
5147#[cfg(feature = "alloc")]
5148impl From<&UserInitiatedAbortErrorRef<'_>> for UserInitiatedAbortError {
5149    #[inline]
5150    fn from(value: &UserInitiatedAbortErrorRef<'_>) -> Self {
5151        UserInitiatedAbortError {
5152            reason: Vec::from(value.reason()),
5153        }
5154    }
5155}
5156
5157#[derive(Clone, Copy, Debug)]
5158pub struct UserInitiatedAbortErrorRef<'a> {
5159    data: &'a [u8],
5160}
5161
5162impl<'a> UserInitiatedAbortErrorRef<'a> {
5163    #[inline]
5164    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
5165        Self::validate(bytes)?;
5166        Ok(Self::from_bytes_unchecked(bytes))
5167    }
5168
5169    #[inline]
5170    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
5171        UserInitiatedAbortErrorRef { data: bytes }
5172    }
5173
5174    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
5175        match (utils::to_array(bytes, 0), utils::to_array(bytes, 2)) {
5176            (Some(cause_code_arr), Some(len_arr)) => {
5177                let cause_code = u16::from_be_bytes(cause_code_arr);
5178                let len = u16::from_be_bytes(len_arr) as usize;
5179
5180                if bytes.len() < cmp::max(4, len) {
5181                    return Err(ValidationError {
5182                        layer: SctpRef::name(),
5183                        class: ValidationErrorClass::InsufficientBytes,
5184                        #[cfg(feature = "error_string")]        
5185                        reason: "insufficient bytes in SCTP User-Initiated Abort option for header + Reason field",
5186                    });
5187                }
5188
5189                if cause_code != ERR_CODE_USER_INITIATED_ABORT {
5190                    return Err(ValidationError {
5191                        layer: SctpRef::name(),
5192                        class: ValidationErrorClass::InvalidValue,
5193                        #[cfg(feature = "error_string")]        
5194                        reason: "invalid cause code in SCTP User-Initiated Abort option (must be equal to 12)",
5195                    });
5196                }
5197
5198                if bytes.len() > len {
5199                    Err(ValidationError {
5200                        layer: SctpRef::name(),
5201                        class: ValidationErrorClass::ExcessBytes(bytes.len() - len),
5202                        #[cfg(feature = "error_string")]
5203                        reason: "extra bytes remain at end of SCTP User-Initiated Abort option",
5204                    })
5205                } else {
5206                    Ok(())
5207                }
5208            }
5209            _ => Err(ValidationError {
5210                layer: SctpRef::name(),
5211                class: ValidationErrorClass::InsufficientBytes,
5212                #[cfg(feature = "error_string")]
5213                reason: "insufficient bytes in SCTP User-Initiated Abort option for header",
5214            }),
5215        }
5216    }
5217
5218    #[inline]
5219    pub fn cause_code(&self) -> u16 {
5220        u16::from_be_bytes(utils::to_array(self.data, 0).unwrap())
5221    }
5222
5223    #[inline]
5224    pub fn unpadded_len(&self) -> u16 {
5225        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
5226    }
5227
5228    #[inline]
5229    pub fn len(&self) -> usize {
5230        utils::padded_length::<4>(self.unpadded_len() as usize)
5231    }
5232
5233    #[inline]
5234    pub fn reason(&self) -> &[u8] {
5235        &self.data[8..self.unpadded_len() as usize]
5236    }
5237}
5238
5239#[derive(Clone, Debug)]
5240#[cfg(feature = "alloc")]
5241pub struct ProtocolViolationError {
5242    information: Vec<u8>,
5243}
5244
5245#[cfg(feature = "alloc")]
5246impl ProtocolViolationError {
5247    #[inline]
5248    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
5249        Self::validate(bytes)?;
5250        Ok(Self::from_bytes_unchecked(bytes))
5251    }
5252
5253    #[inline]
5254    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
5255        Self::from(ProtocolViolationErrorRef::from_bytes_unchecked(bytes))
5256    }
5257
5258    #[inline]
5259    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
5260        ProtocolViolationErrorRef::validate(bytes)
5261    }
5262
5263    #[inline]
5264    pub fn cause_code(&self) -> u16 {
5265        ERR_CODE_PROTOCOL_VIOLATION
5266    }
5267
5268    #[inline]
5269    pub fn unpadded_len(&self) -> usize {
5270        4 + self.information.len()
5271    }
5272
5273    #[inline]
5274    pub fn len(&self) -> usize {
5275        utils::padded_length::<4>(self.unpadded_len())
5276    }
5277
5278    #[inline]
5279    pub fn information(&self) -> &Vec<u8> {
5280        &self.information
5281    }
5282
5283    #[inline]
5284    pub fn information_mut(&mut self) -> &mut Vec<u8> {
5285        &mut self.information
5286    }
5287
5288    pub fn to_bytes_extended<T: PacketWritable>(
5289        &self,
5290        writer: &mut PacketWriter<'_, T>,
5291    ) -> Result<(), SerializationError> {
5292        writer.write_slice(&ERR_CODE_PROTOCOL_VIOLATION.to_be_bytes())?;
5293        writer.write_slice(
5294            &u16::try_from(self.unpadded_len())
5295                .map_err(|_| SerializationError::length_encoding(SctpRef::name()))?
5296                .to_be_bytes(),
5297        )?;
5298        writer.write_slice(&self.information)?;
5299        for _ in self.unpadded_len()..self.len() {
5300            writer.write_slice(&[0])?;
5301        }
5302
5303        Ok(())
5304    }
5305}
5306
5307#[cfg(feature = "alloc")]
5308impl From<ProtocolViolationErrorRef<'_>> for ProtocolViolationError {
5309    #[inline]
5310    fn from(value: ProtocolViolationErrorRef<'_>) -> Self {
5311        Self::from(&value)
5312    }
5313}
5314
5315#[cfg(feature = "alloc")]
5316impl From<&ProtocolViolationErrorRef<'_>> for ProtocolViolationError {
5317    #[inline]
5318    fn from(value: &ProtocolViolationErrorRef<'_>) -> Self {
5319        ProtocolViolationError {
5320            information: Vec::from(value.information()),
5321        }
5322    }
5323}
5324
5325#[derive(Clone, Copy, Debug)]
5326pub struct ProtocolViolationErrorRef<'a> {
5327    data: &'a [u8],
5328}
5329
5330impl<'a> ProtocolViolationErrorRef<'a> {
5331    #[inline]
5332    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
5333        Self::validate(bytes)?;
5334        Ok(Self::from_bytes_unchecked(bytes))
5335    }
5336
5337    #[inline]
5338    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
5339        ProtocolViolationErrorRef { data: bytes }
5340    }
5341
5342    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
5343        match (utils::to_array(bytes, 0), utils::to_array(bytes, 2)) {
5344            (Some(cause_code_arr), Some(len_arr)) => {
5345                let cause_code = u16::from_be_bytes(cause_code_arr);
5346                let len = u16::from_be_bytes(len_arr) as usize;
5347
5348                if bytes.len() < cmp::max(8, len) {
5349                    return Err(ValidationError {
5350                        layer: SctpRef::name(),
5351                        class: ValidationErrorClass::InsufficientBytes,
5352                        #[cfg(feature = "error_string")]        
5353                        reason: "insufficient bytes in SCTP Protocol Violation option for header + Additional Information field",
5354                    });
5355                }
5356
5357                if cause_code != ERR_CODE_PROTOCOL_VIOLATION {
5358                    return Err(ValidationError {
5359                        layer: SctpRef::name(),
5360                        class: ValidationErrorClass::InvalidValue,
5361                        #[cfg(feature = "error_string")]        
5362                        reason: "invalid cause code in SCTP Protocol Violation option (must be equal to 13)",
5363                    });
5364                }
5365
5366                if bytes.len() > len {
5367                    Err(ValidationError {
5368                        layer: SctpRef::name(),
5369                        class: ValidationErrorClass::ExcessBytes(bytes.len() - len),
5370                        #[cfg(feature = "error_string")]
5371                        reason: "extra bytes remain at end of SCTP Protocol Violation option",
5372                    })
5373                } else {
5374                    Ok(())
5375                }
5376            }
5377            _ => Err(ValidationError {
5378                layer: SctpRef::name(),
5379                class: ValidationErrorClass::InsufficientBytes,
5380                #[cfg(feature = "error_string")]
5381                reason: "insufficient bytes in SCTP Protocol Violation option for header",
5382            }),
5383        }
5384    }
5385
5386    #[inline]
5387    pub fn cause_code(&self) -> u16 {
5388        u16::from_be_bytes(utils::to_array(self.data, 0).unwrap())
5389    }
5390
5391    #[inline]
5392    pub fn unpadded_len(&self) -> u16 {
5393        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
5394    }
5395
5396    #[inline]
5397    pub fn len(&self) -> usize {
5398        utils::padded_length::<4>(self.unpadded_len() as usize)
5399    }
5400
5401    #[inline]
5402    pub fn information(&self) -> &[u8] {
5403        &self.data[8..self.unpadded_len() as usize]
5404    }
5405}
5406
5407/// An optional/variable-length parameter with a type not recognized by the `pkts` library.
5408///
5409/// ## Packet Layout
5410/// ```txt
5411///    .    Octet 0    .    Octet 1    .    Octet 2    .    Octet 3    .
5412///    |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
5413///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5414///  0 |         Parameter Type        |        Parameter Length       |
5415///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5416///  4 Z                        Parameter Value                        Z
5417///    Z                                                               Z
5418/// .. .                              ...                              .
5419///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5420/// ```
5421#[derive(Clone, Debug)]
5422#[cfg(feature = "alloc")]
5423pub struct GenericParam {
5424    param_type: u16,
5425    value: Vec<u8>,
5426}
5427
5428#[cfg(feature = "alloc")]
5429impl GenericParam {
5430    #[inline]
5431    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
5432        Self::validate(bytes)?;
5433        Ok(Self::from_bytes_unchecked(bytes))
5434    }
5435
5436    #[inline]
5437    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
5438        Self::from(GenericParamRef::from_bytes_unchecked(bytes))
5439    }
5440
5441    #[inline]
5442    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
5443        GenericParamRef::validate(bytes)
5444    }
5445
5446    #[inline]
5447    pub fn param_type(&self) -> u16 {
5448        self.param_type
5449    }
5450
5451    #[inline]
5452    pub fn set_param_type(&mut self, param_type: u16) {
5453        self.param_type = param_type;
5454    }
5455
5456    #[inline]
5457    pub fn unpadded_len(&self) -> usize {
5458        4 + self.value.len()
5459    }
5460
5461    #[inline]
5462    pub fn len(&self) -> usize {
5463        utils::padded_length::<4>(self.unpadded_len())
5464    }
5465
5466    #[inline]
5467    pub fn value(&self) -> &Vec<u8> {
5468        &self.value
5469    }
5470
5471    #[inline]
5472    pub fn value_mut(&mut self) -> &mut Vec<u8> {
5473        &mut self.value
5474    }
5475
5476    pub fn to_bytes_extended<T: PacketWritable>(
5477        &self,
5478        writer: &mut PacketWriter<'_, T>,
5479    ) -> Result<(), SerializationError> {
5480        writer.write_slice(&self.param_type.to_be_bytes())?;
5481        writer.write_slice(
5482            &u16::try_from(self.unpadded_len())
5483                .map_err(|_| SerializationError::length_encoding(SctpRef::name()))?
5484                .to_be_bytes(),
5485        )?;
5486        writer.write_slice(&self.value)?;
5487        for _ in self.unpadded_len()..self.len() {
5488            writer.write_slice(&[0])?;
5489        }
5490
5491        Ok(())
5492    }
5493}
5494
5495#[cfg(feature = "alloc")]
5496impl From<GenericParamRef<'_>> for GenericParam {
5497    #[inline]
5498    fn from(value: GenericParamRef<'_>) -> Self {
5499        Self::from(&value)
5500    }
5501}
5502
5503#[cfg(feature = "alloc")]
5504impl From<&GenericParamRef<'_>> for GenericParam {
5505    #[inline]
5506    fn from(value: &GenericParamRef<'_>) -> Self {
5507        GenericParam {
5508            param_type: value.param_type(),
5509            value: Vec::from(value.value()),
5510        }
5511    }
5512}
5513
5514/// An optional/variable-length parameter for an SCTP Control chunk with a type not recognized by
5515/// the `pkts` library.
5516///
5517/// ## Packet Layout
5518/// ```txt
5519///    .    Octet 0    .    Octet 1    .    Octet 2    .    Octet 3    .
5520///    |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
5521///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5522///  0 |         Parameter Type        |        Parameter Length       |
5523///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5524///  4 Z                        Parameter Value                        Z
5525///    Z                                                               Z
5526/// .. .                              ...                              .
5527///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5528/// ```
5529#[derive(Clone, Copy, Debug)]
5530pub struct GenericParamRef<'a> {
5531    data: &'a [u8],
5532}
5533
5534impl<'a> GenericParamRef<'a> {
5535    #[inline]
5536    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
5537        Self::validate(bytes)?;
5538        Ok(Self::from_bytes_unchecked(bytes))
5539    }
5540
5541    #[inline]
5542    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
5543        GenericParamRef { data: bytes }
5544    }
5545
5546    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
5547        match utils::to_array(bytes, 2) {
5548            Some(len_arr) => {
5549                let unpadded_len = u16::from_be_bytes(len_arr) as usize;
5550                let len = utils::padded_length::<4>(unpadded_len);
5551
5552                if bytes.len() < cmp::max(4, len) {
5553                    return Err(ValidationError {
5554                        layer: SctpRef::name(),
5555                        class: ValidationErrorClass::InsufficientBytes,
5556                        #[cfg(feature = "error_string")]
5557                        reason: "insufficient bytes in SCTP Parameter for header + Value field",
5558                    });
5559                }
5560
5561                if unpadded_len < 4 {
5562                    return Err(ValidationError {
5563                        layer: SctpRef::name(),
5564                        class: ValidationErrorClass::InvalidValue,
5565                        #[cfg(feature = "error_string")]
5566                        reason: "invalid length in SCTP Parameter (must be at least 4 bytes long)",
5567                    });
5568                }
5569
5570                for b in bytes.iter().take(len).skip(unpadded_len) {
5571                    if *b != 0 {
5572                        return Err(ValidationError {
5573                            layer: SctpRef::name(),
5574                            class: ValidationErrorClass::InvalidValue,
5575                            #[cfg(feature = "error_string")]
5576                            reason: "invalid nonzero padding values at end of SCTP Parameter",
5577                        });
5578                    }
5579                }
5580
5581                if bytes.len() > len {
5582                    Err(ValidationError {
5583                        layer: SctpRef::name(),
5584                        class: ValidationErrorClass::ExcessBytes(bytes.len() - len),
5585                        #[cfg(feature = "error_string")]
5586                        reason: "extra bytes remain at end of SCTP Parameter",
5587                    })
5588                } else {
5589                    Ok(())
5590                }
5591            }
5592            _ => Err(ValidationError {
5593                layer: SctpRef::name(),
5594                class: ValidationErrorClass::InsufficientBytes,
5595                #[cfg(feature = "error_string")]
5596                reason: "insufficient bytes in SCTP Parameter for header",
5597            }),
5598        }
5599    }
5600
5601    #[inline]
5602    pub fn param_type(&self) -> u16 {
5603        u16::from_be_bytes(utils::to_array(self.data, 0).unwrap())
5604    }
5605
5606    #[inline]
5607    pub fn unpadded_len(&self) -> u16 {
5608        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
5609    }
5610
5611    #[inline]
5612    pub fn len(&self) -> usize {
5613        utils::padded_length::<4>(self.unpadded_len() as usize)
5614    }
5615
5616    #[inline]
5617    pub fn value(&self) -> &[u8] {
5618        &self.data[4..self.unpadded_len() as usize]
5619    }
5620}
5621
5622bitflags! {
5623    #[derive(Clone, Copy, Debug, Default)]
5624    pub struct AbortFlags: u8 {
5625        const T = 0b00000001;
5626    }
5627}
5628
5629#[derive(Clone, Debug)]
5630pub struct ShutdownChunk {
5631    flags: u8,
5632    cum_tsn_ack: u32,
5633}
5634
5635impl ShutdownChunk {
5636    #[inline]
5637    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
5638        Self::validate(bytes)?;
5639        Ok(Self::from_bytes_unchecked(bytes))
5640    }
5641
5642    #[inline]
5643    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
5644        Self::from(ShutdownChunkRef::from_bytes_unchecked(bytes))
5645    }
5646
5647    #[inline]
5648    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
5649        ShutdownChunkRef::validate(bytes)
5650    }
5651
5652    #[inline]
5653    pub fn chunk_type(&self) -> u8 {
5654        CHUNK_TYPE_SHUTDOWN
5655    }
5656
5657    #[inline]
5658    pub fn flags_raw(&self) -> u8 {
5659        self.flags
5660    }
5661
5662    #[inline]
5663    pub fn set_flags_raw(&mut self, flags: u8) {
5664        self.flags = flags;
5665    }
5666
5667    #[inline]
5668    pub fn len(&self) -> usize {
5669        8
5670    }
5671
5672    #[inline]
5673    pub fn cum_tsn_ack(&self) -> u32 {
5674        self.cum_tsn_ack
5675    }
5676
5677    #[inline]
5678    pub fn set_cum_tsn_ack(&mut self, ack: u32) {
5679        self.cum_tsn_ack = ack;
5680    }
5681
5682    pub fn to_bytes_extended<T: PacketWritable>(
5683        &self,
5684        writer: &mut PacketWriter<'_, T>,
5685    ) -> Result<(), SerializationError> {
5686        writer.write_slice(&[CHUNK_TYPE_SHUTDOWN, self.flags])?;
5687        writer.write_slice(&8u16.to_be_bytes())?;
5688        writer.write_slice(&self.cum_tsn_ack.to_be_bytes())
5689    }
5690}
5691
5692impl From<ShutdownChunkRef<'_>> for ShutdownChunk {
5693    #[inline]
5694    fn from(value: ShutdownChunkRef<'_>) -> Self {
5695        Self::from(&value)
5696    }
5697}
5698
5699impl From<&ShutdownChunkRef<'_>> for ShutdownChunk {
5700    #[inline]
5701    fn from(value: &ShutdownChunkRef<'_>) -> Self {
5702        ShutdownChunk {
5703            flags: value.flags(),
5704            cum_tsn_ack: value.cum_tsn_ack(),
5705        }
5706    }
5707}
5708
5709#[derive(Clone, Copy, Debug)]
5710pub struct ShutdownChunkRef<'a> {
5711    data: &'a [u8],
5712}
5713
5714impl<'a> ShutdownChunkRef<'a> {
5715    #[inline]
5716    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
5717        Self::validate(bytes)?;
5718        Ok(Self::from_bytes_unchecked(bytes))
5719    }
5720
5721    #[inline]
5722    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
5723        ShutdownChunkRef { data: bytes }
5724    }
5725
5726    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
5727        match (bytes.first(), utils::to_array(bytes, 2)) {
5728            (Some(&chunk_type), Some(len_arr)) => {
5729                let len = u16::from_be_bytes(len_arr) as usize;
5730
5731                if bytes.len() < 8 {
5732                    return Err(ValidationError {
5733                        layer: SctpRef::name(),
5734                        class: ValidationErrorClass::InsufficientBytes,
5735                        #[cfg(feature = "error_string")]        
5736                        reason: "insufficient bytes in SCTP SHUTDOWN chunk for header + Cumulative TSN Ack field",
5737                    });
5738                }
5739
5740                if chunk_type != CHUNK_TYPE_SHUTDOWN {
5741                    return Err(ValidationError {
5742                        layer: SctpRef::name(),
5743                        class: ValidationErrorClass::InvalidValue,
5744                        #[cfg(feature = "error_string")]
5745                        reason:
5746                            "invalid Chunk Type field in SCTP SHUTDOWN chunk (must be equal to 7)",
5747                    });
5748                }
5749
5750                if len != 8 {
5751                    return Err(ValidationError {
5752                        layer: SctpRef::name(),
5753                        class: ValidationErrorClass::InvalidValue,
5754                        #[cfg(feature = "error_string")]
5755                        reason: "invalid length in SCTP SHUTDOWN chunk (must be equal to 8)",
5756                    });
5757                }
5758
5759                if bytes.len() > 8 {
5760                    Err(ValidationError {
5761                        layer: SctpRef::name(),
5762                        class: ValidationErrorClass::ExcessBytes(bytes.len() - 8),
5763                        #[cfg(feature = "error_string")]
5764                        reason: "extra bytes remain at end of SCTP SHUTDOWN chunk",
5765                    })
5766                } else {
5767                    Ok(())
5768                }
5769            }
5770            _ => Err(ValidationError {
5771                layer: SctpRef::name(),
5772                class: ValidationErrorClass::InsufficientBytes,
5773                #[cfg(feature = "error_string")]
5774                reason: "insufficient bytes in SCTP SHUTDOWN chunk for header",
5775            }),
5776        }
5777    }
5778
5779    #[inline]
5780    pub fn chunk_type(&self) -> u8 {
5781        self.data[0]
5782    }
5783
5784    #[inline]
5785    pub fn flags(&self) -> u8 {
5786        self.data[1]
5787    }
5788
5789    #[inline]
5790    pub fn unpadded_len(&self) -> u16 {
5791        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
5792    }
5793
5794    #[inline]
5795    pub fn len(&self) -> usize {
5796        utils::padded_length::<4>(self.unpadded_len() as usize)
5797    }
5798
5799    #[inline]
5800    pub fn cum_tsn_ack(&self) -> u32 {
5801        u32::from_be_bytes(utils::to_array(self.data, 4).unwrap())
5802    }
5803}
5804
5805#[derive(Clone, Debug)]
5806pub struct ShutdownAckChunk {
5807    flags: u8,
5808}
5809
5810impl ShutdownAckChunk {
5811    #[inline]
5812    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
5813        Self::validate(bytes)?;
5814        Ok(Self::from_bytes_unchecked(bytes))
5815    }
5816
5817    #[inline]
5818    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
5819        Self::from(ShutdownAckChunkRef::from_bytes_unchecked(bytes))
5820    }
5821
5822    #[inline]
5823    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
5824        ShutdownAckChunkRef::validate(bytes)
5825    }
5826
5827    #[inline]
5828    pub fn chunk_type(&self) -> u8 {
5829        CHUNK_TYPE_SHUTDOWN_ACK
5830    }
5831
5832    #[inline]
5833    pub fn flags_raw(&self) -> u8 {
5834        self.flags
5835    }
5836
5837    #[inline]
5838    pub fn set_flags_raw(&mut self, flags: u8) {
5839        self.flags = flags;
5840    }
5841
5842    #[inline]
5843    pub fn len(&self) -> usize {
5844        4
5845    }
5846
5847    pub fn to_bytes_extended<T: PacketWritable>(
5848        &self,
5849        writer: &mut PacketWriter<'_, T>,
5850    ) -> Result<(), SerializationError> {
5851        writer.write_slice(&[CHUNK_TYPE_SHUTDOWN_ACK, self.flags])?;
5852        writer.write_slice(&4u16.to_be_bytes())
5853    }
5854}
5855
5856impl From<ShutdownAckChunkRef<'_>> for ShutdownAckChunk {
5857    #[inline]
5858    fn from(value: ShutdownAckChunkRef<'_>) -> Self {
5859        Self::from(&value)
5860    }
5861}
5862
5863impl From<&ShutdownAckChunkRef<'_>> for ShutdownAckChunk {
5864    #[inline]
5865    fn from(value: &ShutdownAckChunkRef<'_>) -> Self {
5866        ShutdownAckChunk {
5867            flags: value.flags(),
5868        }
5869    }
5870}
5871
5872#[derive(Clone, Copy, Debug)]
5873pub struct ShutdownAckChunkRef<'a> {
5874    data: &'a [u8],
5875}
5876
5877impl<'a> ShutdownAckChunkRef<'a> {
5878    #[inline]
5879    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
5880        Self::validate(bytes)?;
5881        Ok(Self::from_bytes_unchecked(bytes))
5882    }
5883
5884    #[inline]
5885    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
5886        ShutdownAckChunkRef { data: bytes }
5887    }
5888
5889    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
5890        match (bytes.first(), utils::to_array(bytes, 2)) {
5891            (Some(&chunk_type), Some(len_arr)) => {
5892                let len = u16::from_be_bytes(len_arr) as usize;
5893                if chunk_type != CHUNK_TYPE_SHUTDOWN_ACK {
5894                    return Err(ValidationError {
5895                        layer: SctpRef::name(),
5896                        class: ValidationErrorClass::InvalidValue,
5897                        #[cfg(feature = "error_string")]        
5898                        reason: "invalid Chunk Type field in SCTP SHUTDOWN ACK chunk (must be equal to 8)",
5899                    });
5900                }
5901
5902                if len != 4 {
5903                    return Err(ValidationError {
5904                        layer: SctpRef::name(),
5905                        class: ValidationErrorClass::InvalidValue,
5906                        #[cfg(feature = "error_string")]
5907                        reason: "invalid length in SCTP SHUTDOWN ACK chunk (must be equal to 4)",
5908                    });
5909                }
5910
5911                if bytes.len() > 4 {
5912                    Err(ValidationError {
5913                        layer: SctpRef::name(),
5914                        class: ValidationErrorClass::ExcessBytes(bytes.len() - 4),
5915                        #[cfg(feature = "error_string")]
5916                        reason: "extra bytes remain at end of SCTP SHUTDOWN ACK chunk",
5917                    })
5918                } else {
5919                    Ok(())
5920                }
5921            }
5922            _ => Err(ValidationError {
5923                layer: SctpRef::name(),
5924                class: ValidationErrorClass::InsufficientBytes,
5925                #[cfg(feature = "error_string")]
5926                reason: "insufficient bytes in SCTP SHUTDOWN ACK chunk for header",
5927            }),
5928        }
5929    }
5930
5931    #[inline]
5932    pub fn chunk_type(&self) -> u8 {
5933        self.data[0]
5934    }
5935
5936    #[inline]
5937    pub fn flags(&self) -> u8 {
5938        self.data[1]
5939    }
5940
5941    #[inline]
5942    pub fn unpadded_len(&self) -> u16 {
5943        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
5944    }
5945
5946    #[inline]
5947    pub fn len(&self) -> usize {
5948        utils::padded_length::<4>(self.unpadded_len() as usize)
5949    }
5950}
5951
5952#[derive(Clone, Debug)]
5953#[cfg(feature = "alloc")]
5954pub struct ErrorChunk {
5955    flags: u8,
5956    causes: Vec<ErrorCause>,
5957}
5958
5959#[cfg(feature = "alloc")]
5960impl ErrorChunk {
5961    #[inline]
5962    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
5963        Self::validate(bytes)?;
5964        Ok(Self::from_bytes_unchecked(bytes))
5965    }
5966
5967    #[inline]
5968    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
5969        Self::from(ErrorChunkRef::from_bytes_unchecked(bytes))
5970    }
5971
5972    #[inline]
5973    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
5974        ErrorChunkRef::validate(bytes)
5975    }
5976
5977    #[inline]
5978    pub fn chunk_type(&self) -> u8 {
5979        CHUNK_TYPE_ERROR
5980    }
5981
5982    #[inline]
5983    pub fn flags_raw(&self) -> u8 {
5984        self.flags
5985    }
5986
5987    #[inline]
5988    pub fn set_flags_raw(&mut self, flags: u8) {
5989        self.flags = flags;
5990    }
5991
5992    #[inline]
5993    pub fn unpadded_len(&self) -> usize {
5994        4 + self.causes.iter().map(|c| c.len()).sum::<usize>()
5995    }
5996
5997    #[inline]
5998    pub fn len(&self) -> usize {
5999        self.unpadded_len()
6000    }
6001
6002    #[inline]
6003    pub fn causes(&self) -> &Vec<ErrorCause> {
6004        &self.causes
6005    }
6006
6007    #[inline]
6008    pub fn set_causes(&mut self) -> &mut Vec<ErrorCause> {
6009        &mut self.causes
6010    }
6011
6012    pub fn to_bytes_extended<T: PacketWritable>(
6013        &self,
6014        writer: &mut PacketWriter<'_, T>,
6015    ) -> Result<(), SerializationError> {
6016        writer.write_slice(&[CHUNK_TYPE_ERROR, self.flags])?;
6017        writer.write_slice(
6018            &u16::try_from(self.unpadded_len())
6019                .map_err(|_| SerializationError::length_encoding(SctpRef::name()))?
6020                .to_be_bytes(),
6021        )?;
6022        for cause in &self.causes {
6023            cause.to_bytes_extended(writer)?
6024        }
6025
6026        Ok(())
6027    }
6028}
6029
6030#[cfg(feature = "alloc")]
6031impl From<ErrorChunkRef<'_>> for ErrorChunk {
6032    #[inline]
6033    fn from(value: ErrorChunkRef<'_>) -> Self {
6034        Self::from(&value)
6035    }
6036}
6037
6038#[cfg(feature = "alloc")]
6039impl From<&ErrorChunkRef<'_>> for ErrorChunk {
6040    fn from(value: &ErrorChunkRef<'_>) -> Self {
6041        let mut causes = Vec::new();
6042        let iter = value.error_iter();
6043        for error in iter {
6044            causes.push(error.into());
6045        }
6046
6047        ErrorChunk {
6048            flags: value.flags_raw(),
6049            causes,
6050        }
6051    }
6052}
6053
6054#[derive(Clone, Copy, Debug)]
6055pub struct ErrorChunkRef<'a> {
6056    data: &'a [u8],
6057}
6058
6059impl<'a> ErrorChunkRef<'a> {
6060    #[inline]
6061    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
6062        Self::validate(bytes)?;
6063        Ok(Self::from_bytes_unchecked(bytes))
6064    }
6065
6066    #[inline]
6067    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
6068        ErrorChunkRef { data: bytes }
6069    }
6070
6071    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
6072        match (bytes.first(), utils::to_array(bytes, 2)) {
6073            (Some(&chunk_type), Some(len_arr)) => {
6074                let len = u16::from_be_bytes(len_arr) as usize;
6075                if bytes.len() < cmp::max(4, len) {
6076                    return Err(ValidationError {
6077                        layer: SctpRef::name(),
6078                        class: ValidationErrorClass::InsufficientBytes,
6079                        #[cfg(feature = "error_string")]
6080                        reason:
6081                            "insufficient bytes in SCTP ERROR chunk for header + Error Causes field",
6082                    });
6083                }
6084
6085                if chunk_type != CHUNK_TYPE_ERROR {
6086                    return Err(ValidationError {
6087                        layer: SctpRef::name(),
6088                        class: ValidationErrorClass::InvalidValue,
6089                        #[cfg(feature = "error_string")]
6090                        reason: "invalid Chunk Type field in SCTP ERROR chunk (must be equal to 9)",
6091                    });
6092                }
6093
6094                if bytes.len() > len {
6095                    Err(ValidationError {
6096                        layer: SctpRef::name(),
6097                        class: ValidationErrorClass::ExcessBytes(bytes.len() - len),
6098                        #[cfg(feature = "error_string")]
6099                        reason: "extra bytes remain at end of SCTP ERROR chunk",
6100                    })
6101                } else {
6102                    Ok(())
6103                }
6104            }
6105            _ => Err(ValidationError {
6106                layer: SctpRef::name(),
6107                class: ValidationErrorClass::InsufficientBytes,
6108                #[cfg(feature = "error_string")]
6109                reason: "insufficient bytes in SCTP ERROR chunk for header",
6110            }),
6111        }
6112    }
6113
6114    #[inline]
6115    pub fn chunk_type(&self) -> u8 {
6116        self.data[0]
6117    }
6118
6119    #[inline]
6120    pub fn flags_raw(&self) -> u8 {
6121        self.data[0]
6122    }
6123
6124    #[inline]
6125    pub fn unpadded_len(&self) -> u16 {
6126        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
6127    }
6128
6129    #[inline]
6130    pub fn len(&self) -> usize {
6131        utils::padded_length::<4>(self.unpadded_len() as usize)
6132    }
6133
6134    #[inline]
6135    pub fn error_iter(&self) -> ErrorCauseIterRef {
6136        ErrorCauseIterRef {
6137            bytes: &self.data[4..self.unpadded_len() as usize],
6138        }
6139    }
6140}
6141
6142#[derive(Clone, Debug)]
6143#[cfg(feature = "alloc")]
6144pub struct CookieEchoChunk {
6145    flags: u8,
6146    cookie: Vec<u8>,
6147}
6148
6149#[cfg(feature = "alloc")]
6150impl CookieEchoChunk {
6151    #[inline]
6152    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
6153        Self::validate(bytes)?;
6154        Ok(Self::from_bytes_unchecked(bytes))
6155    }
6156
6157    #[inline]
6158    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
6159        Self::from(CookieEchoChunkRef::from_bytes_unchecked(bytes))
6160    }
6161
6162    #[inline]
6163    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
6164        CookieEchoChunkRef::validate(bytes)
6165    }
6166
6167    #[inline]
6168    pub fn chunk_type(&self) -> u8 {
6169        CHUNK_TYPE_COOKIE_ECHO
6170    }
6171
6172    #[inline]
6173    pub fn flags_raw(&self) -> u8 {
6174        self.flags
6175    }
6176
6177    #[inline]
6178    pub fn set_flags_raw(&mut self, flags: u8) {
6179        self.flags = flags;
6180    }
6181
6182    #[inline]
6183    pub fn unpadded_len(&self) -> usize {
6184        4 + self.cookie.len()
6185    }
6186
6187    #[inline]
6188    pub fn len(&self) -> usize {
6189        utils::padded_length::<4>(self.unpadded_len())
6190    }
6191
6192    #[inline]
6193    pub fn cookie(&self) -> &Vec<u8> {
6194        &self.cookie
6195    }
6196
6197    #[inline]
6198    pub fn cookie_mut(&mut self) -> &mut Vec<u8> {
6199        &mut self.cookie
6200    }
6201
6202    pub fn to_bytes_extended<T: PacketWritable>(
6203        &self,
6204        writer: &mut PacketWriter<'_, T>,
6205    ) -> Result<(), SerializationError> {
6206        writer.write_slice(&[CHUNK_TYPE_COOKIE_ECHO, self.flags])?;
6207        writer.write_slice(
6208            &u16::try_from(self.unpadded_len())
6209                .map_err(|_| SerializationError::length_encoding(SctpRef::name()))?
6210                .to_be_bytes(),
6211        )?;
6212        writer.write_slice(&self.cookie)?;
6213        for _ in self.unpadded_len()..self.len() {
6214            writer.write_slice(&[0])?;
6215        }
6216
6217        Ok(())
6218    }
6219}
6220
6221#[cfg(feature = "alloc")]
6222impl From<CookieEchoChunkRef<'_>> for CookieEchoChunk {
6223    #[inline]
6224    fn from(value: CookieEchoChunkRef<'_>) -> Self {
6225        Self::from(&value)
6226    }
6227}
6228
6229#[cfg(feature = "alloc")]
6230impl From<&CookieEchoChunkRef<'_>> for CookieEchoChunk {
6231    #[inline]
6232    fn from(value: &CookieEchoChunkRef<'_>) -> Self {
6233        CookieEchoChunk {
6234            flags: value.flags_raw(),
6235            cookie: Vec::from(value.cookie()),
6236        }
6237    }
6238}
6239
6240#[derive(Clone, Copy, Debug)]
6241pub struct CookieEchoChunkRef<'a> {
6242    data: &'a [u8],
6243}
6244
6245impl<'a> CookieEchoChunkRef<'a> {
6246    #[inline]
6247    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
6248        Self::validate(bytes)?;
6249        Ok(Self::from_bytes_unchecked(bytes))
6250    }
6251
6252    #[inline]
6253    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
6254        CookieEchoChunkRef { data: bytes }
6255    }
6256
6257    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
6258        match (bytes.first(), utils::to_array(bytes, 2)) {
6259            (Some(&chunk_type), Some(len_arr)) => {
6260                let unpadded_len = u16::from_be_bytes(len_arr) as usize;
6261                let len = utils::padded_length::<4>(unpadded_len);
6262
6263                if bytes.len() < cmp::max(4, len) {
6264                    return Err(ValidationError {
6265                        layer: SctpRef::name(),
6266                        class: ValidationErrorClass::InsufficientBytes,
6267                        #[cfg(feature = "error_string")]
6268                        reason:
6269                            "insufficient bytes in SCTP COOKIE ECHO chunk for header + Cookie field",
6270                    });
6271                }
6272
6273                if unpadded_len < 4 {
6274                    return Err(ValidationError {
6275                        layer: SctpRef::name(),
6276                        class: ValidationErrorClass::InvalidValue,
6277                        #[cfg(feature = "error_string")]
6278                        reason: "invalid length in SCTP COOKIE ECHO chunk (must be at least 4 octets long)",
6279                    });
6280                }
6281
6282                if chunk_type != CHUNK_TYPE_COOKIE_ECHO {
6283                    return Err(ValidationError {
6284                        layer: SctpRef::name(),
6285                        class: ValidationErrorClass::InvalidValue,
6286                        #[cfg(feature = "error_string")]
6287                        reason: "invalid Chunk Type field in SCTP COOKIE ECHO chunk (must be equal to 10)",
6288                    });
6289                }
6290
6291                for b in bytes.iter().take(len).skip(unpadded_len) {
6292                    if *b != 0 {
6293                        return Err(ValidationError {
6294                            layer: SctpRef::name(),
6295                            class: ValidationErrorClass::InvalidValue,
6296                            #[cfg(feature = "error_string")]
6297                            reason:
6298                                "invalid nonzero padding values at end of SCTP COOKIE ECHO chunk",
6299                        });
6300                    }
6301                }
6302
6303                if bytes.len() > len {
6304                    Err(ValidationError {
6305                        layer: SctpRef::name(),
6306                        class: ValidationErrorClass::ExcessBytes(bytes.len() - len),
6307                        #[cfg(feature = "error_string")]
6308                        reason: "extra bytes remain at end of SCTP COOKIE ECHO hunk",
6309                    })
6310                } else {
6311                    Ok(())
6312                }
6313            }
6314            _ => Err(ValidationError {
6315                layer: SctpRef::name(),
6316                class: ValidationErrorClass::InsufficientBytes,
6317                #[cfg(feature = "error_string")]
6318                reason: "insufficient bytes in SCTP COOKIE ECHO chunk for header",
6319            }),
6320        }
6321    }
6322
6323    #[inline]
6324    pub fn chunk_type(&self) -> u8 {
6325        self.data[0]
6326    }
6327
6328    #[inline]
6329    pub fn flags_raw(&self) -> u8 {
6330        self.data[1]
6331    }
6332
6333    #[inline]
6334    pub fn unpadded_len(&self) -> u16 {
6335        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
6336    }
6337
6338    #[inline]
6339    pub fn len(&self) -> usize {
6340        utils::padded_length::<4>(self.unpadded_len() as usize)
6341    }
6342
6343    #[inline]
6344    pub fn cookie(&self) -> &[u8] {
6345        &self.data[4..self.unpadded_len() as usize]
6346    }
6347}
6348
6349#[derive(Clone, Debug)]
6350#[cfg(feature = "alloc")]
6351pub struct CookieAckChunk {
6352    flags: u8,
6353}
6354
6355#[cfg(feature = "alloc")]
6356impl CookieAckChunk {
6357    #[inline]
6358    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
6359        Self::validate(bytes)?;
6360        Ok(Self::from_bytes_unchecked(bytes))
6361    }
6362
6363    #[inline]
6364    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
6365        Self::from(CookieAckChunkRef::from_bytes_unchecked(bytes))
6366    }
6367
6368    #[inline]
6369    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
6370        CookieAckChunkRef::validate(bytes)
6371    }
6372
6373    #[inline]
6374    pub fn chunk_type(&self) -> u8 {
6375        CHUNK_TYPE_COOKIE_ACK
6376    }
6377
6378    #[inline]
6379    pub fn flags_raw(&self) -> u8 {
6380        self.flags
6381    }
6382
6383    #[inline]
6384    pub fn set_flags_raw(&mut self, flags: u8) {
6385        self.flags = flags;
6386    }
6387
6388    #[inline]
6389    pub fn len(&self) -> usize {
6390        4
6391    }
6392
6393    #[inline]
6394    pub fn to_bytes_extended<T: PacketWritable>(
6395        &self,
6396        writer: &mut PacketWriter<'_, T>,
6397    ) -> Result<(), SerializationError> {
6398        writer.write_slice(&[CHUNK_TYPE_COOKIE_ACK, self.flags])?;
6399        writer.write_slice(&4u16.to_be_bytes())
6400    }
6401}
6402
6403#[cfg(feature = "alloc")]
6404impl From<CookieAckChunkRef<'_>> for CookieAckChunk {
6405    #[inline]
6406    fn from(value: CookieAckChunkRef<'_>) -> Self {
6407        Self::from(&value)
6408    }
6409}
6410
6411#[cfg(feature = "alloc")]
6412impl From<&CookieAckChunkRef<'_>> for CookieAckChunk {
6413    #[inline]
6414    fn from(value: &CookieAckChunkRef<'_>) -> Self {
6415        CookieAckChunk {
6416            flags: value.flags(),
6417        }
6418    }
6419}
6420
6421#[derive(Clone, Copy, Debug)]
6422pub struct CookieAckChunkRef<'a> {
6423    data: &'a [u8],
6424}
6425
6426impl<'a> CookieAckChunkRef<'a> {
6427    #[inline]
6428    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
6429        Self::validate(bytes)?;
6430        Ok(Self::from_bytes_unchecked(bytes))
6431    }
6432
6433    #[inline]
6434    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
6435        CookieAckChunkRef { data: bytes }
6436    }
6437
6438    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
6439        match (bytes.first(), utils::to_array(bytes, 2)) {
6440            (Some(&chunk_type), Some(len_arr)) => {
6441                let len = u16::from_be_bytes(len_arr) as usize;
6442                if chunk_type != CHUNK_TYPE_COOKIE_ACK {
6443                    return Err(ValidationError {
6444                        layer: SctpRef::name(),
6445                        class: ValidationErrorClass::InvalidValue,
6446                        #[cfg(feature = "error_string")]
6447                        reason:
6448                            "invalid Chunk Type field in SCTP COOKIE ACK chunk (must be equal to 11)",
6449                    });
6450                }
6451
6452                if len != 4 {
6453                    return Err(ValidationError {
6454                        layer: SctpRef::name(),
6455                        class: ValidationErrorClass::InvalidValue,
6456                        #[cfg(feature = "error_string")]
6457                        reason: "invalid length in SCTP COOKIE_ACK chunk (must be equal to 4)",
6458                    });
6459                }
6460
6461                if bytes.len() > 4 {
6462                    Err(ValidationError {
6463                        layer: SctpRef::name(),
6464                        class: ValidationErrorClass::ExcessBytes(bytes.len() - 4),
6465                        #[cfg(feature = "error_string")]
6466                        reason: "extra bytes remain at end of SCTP COOKIE ACK chunk",
6467                    })
6468                } else {
6469                    Ok(())
6470                }
6471            }
6472            _ => Err(ValidationError {
6473                layer: SctpRef::name(),
6474                class: ValidationErrorClass::InsufficientBytes,
6475                #[cfg(feature = "error_string")]
6476                reason: "insufficient bytes in SCTP COOKIE ACK chunk for header",
6477            }),
6478        }
6479    }
6480
6481    #[inline]
6482    pub fn chunk_type(&self) -> u8 {
6483        self.data[0]
6484    }
6485
6486    #[inline]
6487    pub fn flags(&self) -> u8 {
6488        self.data[1]
6489    }
6490
6491    #[inline]
6492    pub fn unpadded_len(&self) -> u16 {
6493        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
6494    }
6495
6496    #[inline]
6497    pub fn len(&self) -> usize {
6498        utils::padded_length::<4>(self.unpadded_len() as usize)
6499    }
6500}
6501
6502#[derive(Clone, Debug)]
6503#[cfg(feature = "alloc")]
6504pub struct ShutdownCompleteChunk {
6505    flags: ShutdownCompleteFlags,
6506}
6507
6508#[cfg(feature = "alloc")]
6509impl ShutdownCompleteChunk {
6510    #[inline]
6511    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
6512        Self::validate(bytes)?;
6513        Ok(Self::from_bytes_unchecked(bytes))
6514    }
6515
6516    #[inline]
6517    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
6518        Self::from(ShutdownCompleteChunkRef::from_bytes_unchecked(bytes))
6519    }
6520
6521    #[inline]
6522    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
6523        ShutdownCompleteChunkRef::validate(bytes)
6524    }
6525
6526    #[inline]
6527    pub fn chunk_type(&self) -> u8 {
6528        CHUNK_TYPE_SHUTDOWN_COMPLETE
6529    }
6530
6531    #[inline]
6532    pub fn flags(&self) -> ShutdownCompleteFlags {
6533        self.flags
6534    }
6535
6536    #[inline]
6537    pub fn set_flags(&mut self, flags: ShutdownCompleteFlags) {
6538        self.flags = flags;
6539    }
6540
6541    #[inline]
6542    pub fn len(&self) -> usize {
6543        4
6544    }
6545
6546    #[inline]
6547    pub fn to_bytes_extended<T: PacketWritable>(
6548        &self,
6549        writer: &mut PacketWriter<'_, T>,
6550    ) -> Result<(), SerializationError> {
6551        writer.write_slice(&[CHUNK_TYPE_SHUTDOWN_COMPLETE, self.flags.bits()])?;
6552        writer.write_slice(&4u16.to_be_bytes())
6553    }
6554}
6555
6556#[cfg(feature = "alloc")]
6557impl From<ShutdownCompleteChunkRef<'_>> for ShutdownCompleteChunk {
6558    #[inline]
6559    fn from(value: ShutdownCompleteChunkRef<'_>) -> Self {
6560        Self::from(&value)
6561    }
6562}
6563
6564#[cfg(feature = "alloc")]
6565impl From<&ShutdownCompleteChunkRef<'_>> for ShutdownCompleteChunk {
6566    #[inline]
6567    fn from(value: &ShutdownCompleteChunkRef<'_>) -> Self {
6568        ShutdownCompleteChunk {
6569            flags: value.flags(),
6570        }
6571    }
6572}
6573
6574#[derive(Clone, Copy, Debug)]
6575pub struct ShutdownCompleteChunkRef<'a> {
6576    data: &'a [u8],
6577}
6578
6579impl<'a> ShutdownCompleteChunkRef<'a> {
6580    #[inline]
6581    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
6582        Self::validate(bytes)?;
6583        Ok(Self::from_bytes_unchecked(bytes))
6584    }
6585
6586    #[inline]
6587    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
6588        ShutdownCompleteChunkRef { data: bytes }
6589    }
6590
6591    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
6592        match (bytes.first(), utils::to_array(bytes, 2)) {
6593            (Some(&chunk_type), Some(len_arr)) => {
6594                let len = u16::from_be_bytes(len_arr) as usize;
6595                if chunk_type != CHUNK_TYPE_SHUTDOWN_COMPLETE {
6596                    return Err(ValidationError {
6597                        layer: SctpRef::name(),
6598                        class: ValidationErrorClass::InvalidValue,
6599                        #[cfg(feature = "error_string")]
6600                        reason: "invalid Chunk Type field in SCTP SHUTDOWN COMPLETE chunk (must be equal to 14)",
6601                    });
6602                }
6603
6604                if len != 4 {
6605                    return Err(ValidationError {
6606                        layer: SctpRef::name(),
6607                        class: ValidationErrorClass::InvalidValue,
6608                        #[cfg(feature = "error_string")]
6609                        reason:
6610                            "invalid length in SCTP SHUTDOWN COMPLETE chunk (must be equal to 4)",
6611                    });
6612                }
6613
6614                if bytes.len() > 4 {
6615                    Err(ValidationError {
6616                        layer: SctpRef::name(),
6617                        class: ValidationErrorClass::ExcessBytes(bytes.len() - 4),
6618                        #[cfg(feature = "error_string")]
6619                        reason: "extra bytes remain at end of SCTP SHUTDOWN COMPLETE chunk",
6620                    })
6621                } else {
6622                    Ok(())
6623                }
6624            }
6625            _ => Err(ValidationError {
6626                layer: SctpRef::name(),
6627                class: ValidationErrorClass::InsufficientBytes,
6628                #[cfg(feature = "error_string")]
6629                reason: "insufficient bytes in SCTP SHUTDOWN COMPLETE chunk for header",
6630            }),
6631        }
6632    }
6633
6634    #[inline]
6635    pub fn chunk_type(&self) -> u8 {
6636        self.data[0]
6637    }
6638
6639    #[inline]
6640    pub fn flags(&self) -> ShutdownCompleteFlags {
6641        ShutdownCompleteFlags::from_bits_truncate(self.data[1])
6642    }
6643
6644    #[inline]
6645    pub fn unpadded_len(&self) -> u16 {
6646        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
6647    }
6648
6649    #[inline]
6650    pub fn len(&self) -> usize {
6651        utils::padded_length::<4>(self.unpadded_len() as usize)
6652    }
6653}
6654
6655bitflags! {
6656    #[derive(Clone, Copy, Debug, Default)]
6657    pub struct ShutdownCompleteFlags: u8 {
6658        const T = 0b00000001;
6659    }
6660}
6661
6662/// A chunk containing a Chunk Type value that does not match any chunk type defined in RFC 4960.
6663///
6664/// ## Packet Format
6665/// ```txt
6666///    .    Octet 0    .    Octet 1    .    Octet 2    .    Octet 3    .
6667///    |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
6668///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6669///  0 |   Chunk Type  |  Chunk Flags  |          Chunk Length         |
6670///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6671///  4 Z                          Chunk Value                          Z
6672///    Z                                                               Z
6673/// .. .                              ...                              .
6674///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6675/// ```
6676#[derive(Clone, Debug)]
6677#[cfg(feature = "alloc")]
6678pub struct UnknownChunk {
6679    chunk_type: u8,
6680    flags: u8,
6681    value: Vec<u8>,
6682}
6683
6684#[cfg(feature = "alloc")]
6685impl UnknownChunk {
6686    #[inline]
6687    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
6688        Self::validate(bytes)?;
6689        Ok(Self::from_bytes_unchecked(bytes))
6690    }
6691
6692    #[inline]
6693    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
6694        Self::from(UnknownChunkRef::from_bytes_unchecked(bytes))
6695    }
6696
6697    #[inline]
6698    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
6699        UnknownChunkRef::validate(bytes)
6700    }
6701
6702    #[inline]
6703    pub fn chunk_type(&self) -> u8 {
6704        self.chunk_type
6705    }
6706
6707    #[inline]
6708    pub fn flags_raw(&self) -> u8 {
6709        self.flags
6710    }
6711
6712    #[inline]
6713    pub fn set_flags_raw(&mut self, flags: u8) {
6714        self.flags = flags;
6715    }
6716
6717    #[inline]
6718    pub fn unpadded_len(&self) -> usize {
6719        self.value.len() + 4
6720    }
6721
6722    #[inline]
6723    pub fn len(&self) -> usize {
6724        utils::padded_length::<4>(self.unpadded_len())
6725    }
6726
6727    #[inline]
6728    pub fn value(&self) -> &Vec<u8> {
6729        &self.value
6730    }
6731
6732    #[inline]
6733    pub fn value_mut(&mut self) -> &mut Vec<u8> {
6734        &mut self.value
6735    }
6736
6737    pub fn to_bytes_extended<T: PacketWritable>(
6738        &self,
6739        writer: &mut PacketWriter<'_, T>,
6740    ) -> Result<(), SerializationError> {
6741        writer.write_slice(&[self.chunk_type, self.flags])?;
6742        writer.write_slice(
6743            &u16::try_from(self.unpadded_len())
6744                .map_err(|_| SerializationError::length_encoding(SctpRef::name()))?
6745                .to_be_bytes(),
6746        )?;
6747        writer.write_slice(&self.value)?;
6748
6749        for _ in self.unpadded_len()..self.len() {
6750            writer.write_slice(&[0])?;
6751        }
6752
6753        Ok(())
6754    }
6755}
6756
6757#[cfg(feature = "alloc")]
6758impl From<UnknownChunkRef<'_>> for UnknownChunk {
6759    #[inline]
6760    fn from(value: UnknownChunkRef<'_>) -> Self {
6761        Self::from(&value)
6762    }
6763}
6764
6765#[cfg(feature = "alloc")]
6766impl From<&UnknownChunkRef<'_>> for UnknownChunk {
6767    #[inline]
6768    fn from(value: &UnknownChunkRef<'_>) -> Self {
6769        UnknownChunk {
6770            chunk_type: value.chunk_type(),
6771            flags: value.flags_raw(),
6772            value: Vec::from(value.value()),
6773        }
6774    }
6775}
6776
6777/// A chunk containing a Chunk Type value that does not match any chunk type defined in RFC 4960.
6778///
6779/// ## Packet Format
6780/// ```txt
6781///    .    Octet 0    .    Octet 1    .    Octet 2    .    Octet 3    .
6782///    |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
6783///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6784///  0 |   Chunk Type  |  Chunk Flags  |          Chunk Length         |
6785///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6786///  4 Z                          Chunk Value                          Z
6787///    Z                                                               Z
6788/// .. .                              ...                              .
6789///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6790/// ```
6791#[derive(Clone, Copy, Debug)]
6792pub struct UnknownChunkRef<'a> {
6793    data: &'a [u8],
6794}
6795
6796impl<'a> UnknownChunkRef<'a> {
6797    #[inline]
6798    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
6799        Self::validate(bytes)?;
6800        Ok(Self::from_bytes_unchecked(bytes))
6801    }
6802
6803    #[inline]
6804    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
6805        UnknownChunkRef { data: bytes }
6806    }
6807
6808    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
6809        match utils::to_array(bytes, 2) {
6810            Some(len_arr) => {
6811                let unpadded_len = u16::from_be_bytes(len_arr) as usize;
6812                let len = utils::padded_length::<4>(unpadded_len);
6813
6814                if bytes.len() < cmp::max(4, len) {
6815                    return Err(ValidationError {
6816                        layer: SctpRef::name(),
6817                        class: ValidationErrorClass::InsufficientBytes,
6818                        #[cfg(feature = "error_string")]
6819                        reason: "insufficient bytes in SCTP <unknown> chunk for header/Value field",
6820                    });
6821                }
6822
6823                if unpadded_len < 4 {
6824                    return Err(ValidationError {
6825                        layer: SctpRef::name(),
6826                        class: ValidationErrorClass::InvalidValue,
6827                        #[cfg(feature = "error_string")]
6828                        reason:
6829                            "invalid length in SCTP <unknown> chunk (must be at least 4 bytes long)",
6830                    });
6831                }
6832
6833                for b in bytes.iter().take(len).skip(unpadded_len) {
6834                    if *b != 0 {
6835                        return Err(ValidationError {
6836                            layer: SctpRef::name(),
6837                            class: ValidationErrorClass::InvalidValue,
6838                            #[cfg(feature = "error_string")]
6839                            reason: "invalid nonzero padding values at end of SCTP <unknown> chunk",
6840                        });
6841                    }
6842                }
6843
6844                if bytes.len() > len {
6845                    Err(ValidationError {
6846                        layer: SctpRef::name(),
6847                        class: ValidationErrorClass::ExcessBytes(bytes.len() - len),
6848                        #[cfg(feature = "error_string")]
6849                        reason: "extra bytes remain at end of SCTP <unknown> chunk",
6850                    })
6851                } else {
6852                    Ok(())
6853                }
6854            }
6855            _ => Err(ValidationError {
6856                layer: SctpRef::name(),
6857                class: ValidationErrorClass::InsufficientBytes,
6858                #[cfg(feature = "error_string")]
6859                reason: "insufficient bytes in SCTP <unknown> chunk for header",
6860            }),
6861        }
6862    }
6863
6864    #[inline]
6865    pub fn chunk_type(&self) -> u8 {
6866        self.data[0]
6867    }
6868
6869    #[inline]
6870    pub fn flags_raw(&self) -> u8 {
6871        self.data[1]
6872    }
6873
6874    #[inline]
6875    pub fn unpadded_len(&self) -> u16 {
6876        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
6877    }
6878
6879    #[inline]
6880    pub fn len(&self) -> usize {
6881        utils::padded_length::<4>(self.unpadded_len() as usize)
6882    }
6883
6884    #[inline]
6885    pub fn value(&self) -> &[u8] {
6886        &self.data[4..self.unpadded_len() as usize]
6887    }
6888}
6889
6890/// An SCTP DATA chunk.
6891///
6892/// ## Packet Layout
6893/// ```txt
6894///    .    Octet 0    .    Octet 1    .    Octet 2    .    Octet 3    .
6895///    |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
6896///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6897///  0 |    Type (0)   | Reserved|U|B|E|             Length            |
6898///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6899///  4 |               Transmission Sequence Number (TSN)              |
6900///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6901///  8 |           Stream ID           |  Stream Sequence Number (SSN) |
6902///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6903/// 12 |                  Payload Protocol Identifier                  |
6904///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6905/// 16 Z                           User Data                           Z
6906///    Z                                                               Z
6907/// .. .                              ...                              .
6908///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6909/// ```
6910#[derive(Clone, Debug, Layer, StatelessLayer)]
6911#[metadata_type(SctpDataChunkMetadata)]
6912#[ref_type(SctpDataChunkRef)]
6913#[cfg(feature = "alloc")]
6914pub struct SctpDataChunk {
6915    flags: DataChunkFlags,
6916    tsn: u32,
6917    stream_id: u16,
6918    stream_seq: u16,
6919    proto_id: u32,
6920    payload: Option<Box<dyn LayerObject>>,
6921}
6922
6923#[cfg(feature = "alloc")]
6924impl SctpDataChunk {
6925    /// Converts the given bytes into a [`struct@SctpDataChunk`] instance, returning an error if the bytes are
6926    /// not well-formed.
6927    #[inline]
6928    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidationError> {
6929        Self::validate(bytes)?;
6930        Ok(Self::from_bytes_unchecked(bytes))
6931    }
6932
6933    /// Converts the given bytes into a [`struct@SctpDataChunk`] instance without validating the bytes.
6934    ///
6935    /// # Panics
6936    ///
6937    /// The following method may panic if the bytes being passed in do not represent a well-formed
6938    /// DATA chunk (i.e. if a call to [`struct@SctpDataChunk::validate()`] would return an error).
6939    #[inline]
6940    pub fn from_bytes_unchecked(bytes: &[u8]) -> Self {
6941        Self::from(SctpDataChunkRef::from_bytes_unchecked(bytes))
6942    }
6943
6944    /// Validates the given bytes against the expected structure and syntactic values of a
6945    /// DATA chunk. If the bytes represent a well-formed DATA chunk, this method will return
6946    /// `Ok()`; otherwise, it will return a [`ValidationError`] indicating what part of the
6947    /// chunk was invalid.
6948    #[inline]
6949    pub fn validate(bytes: &[u8]) -> Result<(), ValidationError> {
6950        SctpDataChunkRef::validate(bytes)
6951    }
6952
6953    /// The Type field of the DATA chunk.
6954    #[inline]
6955    pub fn chunk_type(&self) -> u8 {
6956        CHUNK_TYPE_DATA
6957    }
6958
6959    /// The flags of the DATA chunk.
6960    #[inline]
6961    pub fn flags(&self) -> DataChunkFlags {
6962        self.flags
6963    }
6964
6965    /// Sets the flags of the DATA chunk.
6966    #[inline]
6967    pub fn set_flags(&mut self, flags: DataChunkFlags) {
6968        self.flags = flags;
6969    }
6970
6971    /// The length (without padding) of the DATA chunk.
6972    #[inline]
6973    pub fn unpadded_len(&self) -> usize {
6974        // TODO: chunk min length is 17. Enforce at to_bytes()
6975        16 + match &self.payload {
6976            Some(p) => p.len(),
6977            None => 0,
6978        }
6979    }
6980
6981    /// The length (including padding) of the DATA chunk.
6982    #[inline]
6983    pub fn len(&self) -> usize {
6984        utils::padded_length::<4>(self.unpadded_len())
6985    }
6986
6987    /// The Transmission Sequence Number (TSN) of the DATA chunk.
6988    #[inline]
6989    pub fn tsn(&self) -> u32 {
6990        self.tsn
6991    }
6992
6993    /// Sets the Transmission Sequence Number (TSN) of the DATA chunk.
6994    #[inline]
6995    pub fn set_tsn(&mut self, tsn: u32) {
6996        self.tsn = tsn;
6997    }
6998
6999    /// The Stream Identifier of the DATA chunk.
7000    #[inline]
7001    pub fn stream_id(&self) -> u16 {
7002        self.stream_id
7003    }
7004
7005    /// Sets the Stream Identifier of the DATA chunk.
7006    #[inline]
7007    pub fn set_stream_id(&mut self, stream_id: u16) {
7008        self.stream_id = stream_id;
7009    }
7010
7011    /// The Stream Sequence Number (SSN) of the DATA chunk.
7012    #[inline]
7013    pub fn stream_seq(&self) -> u16 {
7014        self.stream_seq
7015    }
7016
7017    /// Sets the Stream Sequence Number (SSN) of the DATA chunk.
7018    #[inline]
7019    pub fn set_stream_seq(&mut self, stream_seq: u16) {
7020        self.stream_seq = stream_seq;
7021    }
7022
7023    /// The Payload Protocol Identifier (PPID) of the DATA chunk.
7024    #[inline]
7025    pub fn proto_id(&self) -> u32 {
7026        self.proto_id
7027    }
7028
7029    /// Sets the Payload Protocol Identifier (PPID) of the DATA chunk.
7030    #[inline]
7031    pub fn set_proto_id(&mut self, proto_id: u32) {
7032        self.proto_id = proto_id;
7033    }
7034}
7035
7036#[cfg(feature = "alloc")]
7037impl LayerLength for SctpDataChunk {
7038    #[inline]
7039    fn len(&self) -> usize {
7040        16 + match &self.payload {
7041            Some(p) => utils::padded_length::<4>(p.len()),
7042            None => 0,
7043        }
7044    }
7045}
7046
7047#[allow(unused_variables)]
7048#[cfg(feature = "alloc")]
7049impl LayerObject for SctpDataChunk {
7050    fn can_add_payload_default(&self, payload: &dyn LayerObject) -> bool {
7051        true // SCTP supports arbitrary payloads
7052    }
7053
7054    #[inline]
7055    fn add_payload_unchecked(&mut self, payload: Box<dyn LayerObject>) {
7056        self.payload = Some(payload);
7057    }
7058
7059    #[inline]
7060    fn payloads(&self) -> &[Box<dyn LayerObject>] {
7061        match &self.payload {
7062            Some(p) => slice::from_ref(p),
7063            None => &[],
7064        }
7065    }
7066
7067    fn payloads_mut(&mut self) -> &mut [Box<dyn LayerObject>] {
7068        match &mut self.payload {
7069            Some(p) => slice::from_mut(p),
7070            None => &mut [],
7071        }
7072    }
7073
7074    fn remove_payload_at(&mut self, index: usize) -> Option<Box<dyn LayerObject>> {
7075        if index == 0 {
7076            let mut ret = None;
7077            mem::swap(&mut ret, &mut self.payload);
7078            ret
7079        } else {
7080            None
7081        }
7082    }
7083}
7084
7085#[cfg(feature = "alloc")]
7086impl ToBytes for SctpDataChunk {
7087    fn to_bytes_checksummed(
7088        &self,
7089        writer: &mut PacketWriter<'_, Vec<u8>>,
7090        _prev: Option<(LayerId, usize)>,
7091    ) -> Result<(), SerializationError> {
7092        let start = writer.len();
7093        writer.update_layer::<SctpDataChunk>();
7094        writer.write_slice(&[0, self.flags.bits()])?; // DATA Type = 0
7095        writer.write_slice(
7096            &u16::try_from(self.unpadded_len())
7097                .map_err(|_| SerializationError::length_encoding(SctpDataChunk::name()))?
7098                .to_be_bytes(),
7099        )?;
7100        writer.write_slice(&self.tsn.to_be_bytes())?;
7101        writer.write_slice(&self.stream_id.to_be_bytes())?;
7102        writer.write_slice(&self.stream_seq.to_be_bytes())?;
7103        writer.write_slice(&self.proto_id.to_be_bytes())?;
7104        if let Some(p) = &self.payload {
7105            p.to_bytes_checksummed(writer, Some((SctpDataChunk::layer_id(), start)))?;
7106        }
7107
7108        for _ in self.unpadded_len() as usize..self.len() {
7109            writer.write_slice(&[0])?;
7110        }
7111
7112        Ok(())
7113    }
7114}
7115
7116#[doc(hidden)]
7117#[cfg(feature = "alloc")]
7118impl FromBytesCurrent for SctpDataChunk {
7119    fn from_bytes_current_layer_unchecked(bytes: &[u8]) -> Self {
7120        let data = SctpDataChunkRef::from_bytes_unchecked(bytes);
7121        SctpDataChunk {
7122            flags: data.flags(),
7123            tsn: data.tsn(),
7124            stream_id: data.stream_id(),
7125            stream_seq: data.stream_seq(),
7126            proto_id: data.proto_id(),
7127            payload: None,
7128        }
7129    }
7130
7131    #[inline]
7132    fn payload_from_bytes_unchecked_default(&mut self, bytes: &[u8]) {
7133        let data = SctpDataChunkRef::from_bytes_unchecked(bytes);
7134        self.payload = Some(Box::new(Raw::from_bytes_unchecked(data.user_data())));
7135    }
7136}
7137
7138/// An SCTP DATA chunk.
7139///
7140/// ## Packet Layout
7141/// ```txt
7142///    .    Octet 0    .    Octet 1    .    Octet 2    .    Octet 3    .
7143///    |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
7144///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
7145///  0 |    Type (0)   |  Res  |I|U|B|E|             Length            |
7146///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
7147///  4 |               Transmission Sequence Number (TSN)              |
7148///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
7149///  8 |           Stream ID           |  Stream Sequence Number (SSN) |
7150///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
7151/// 12 |                  Payload Protocol Identifier                  |
7152///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
7153/// 16 Z                           User Data                           Z
7154///    Z                                                               Z
7155/// .. .                              ...                              .
7156///    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
7157/// ```
7158#[derive(Clone, Copy, Debug, LayerRef, StatelessLayer)]
7159#[owned_type(SctpDataChunk)]
7160#[metadata_type(SctpDataChunkMetadata)]
7161pub struct SctpDataChunkRef<'a> {
7162    #[data_field]
7163    data: &'a [u8],
7164}
7165
7166impl<'a> SctpDataChunkRef<'a> {
7167    /// Converts the given bytes into a [`struct@SctpDataChunkRef`] instance, returning an error if they are
7168    /// not well-formed.
7169    #[inline]
7170    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, ValidationError> {
7171        Self::validate(bytes)?;
7172        Ok(Self::from_bytes_unchecked(bytes))
7173    }
7174
7175    /// Converts the given bytes into a [`struct@SctpDataChunkRef`] instance without validating the bytes.
7176    ///
7177    /// # Panics
7178    ///
7179    /// The following method may panic or cause a panic at some future method invocation on the
7180    /// instance if the bytes being passed in do not represent a well-formed DATA chunk (i.e. if a
7181    /// call to [`validate()`](Validate::validate()) would return an error).
7182    #[inline]
7183    pub fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
7184        SctpDataChunkRef { data: bytes }
7185    }
7186
7187    /// The Type field of the DATA chunk.
7188    #[inline]
7189    pub fn chunk_type(&self) -> u8 {
7190        self.data[0]
7191    }
7192
7193    /// The flags of the DATA chunk.
7194    #[inline]
7195    pub fn flags(&self) -> DataChunkFlags {
7196        DataChunkFlags::from_bits_truncate(self.data[1])
7197    }
7198
7199    /// The length (without padding) of the DATA chunk.
7200    #[inline]
7201    pub fn chunk_len(&self) -> u16 {
7202        u16::from_be_bytes(utils::to_array(self.data, 2).unwrap())
7203    }
7204
7205    /// The length (including padding) of the DATA chunk.
7206    #[inline]
7207    pub fn chunk_len_padded(&self) -> usize {
7208        utils::padded_length::<4>(self.chunk_len() as usize)
7209    }
7210
7211    /// The Transmission Sequence Number (TSN) of the DATA chunk.
7212    #[inline]
7213    pub fn tsn(&self) -> u32 {
7214        u32::from_be_bytes(utils::to_array(self.data, 4).unwrap())
7215    }
7216
7217    /// Sets the Stream Identifier of the DATA chunk.
7218    #[inline]
7219    pub fn stream_id(&self) -> u16 {
7220        u16::from_be_bytes(utils::to_array(self.data, 8).unwrap())
7221    }
7222
7223    /// The Stream Sequence Number (SSN) of the DATA chunk.
7224    #[inline]
7225    pub fn stream_seq(&self) -> u16 {
7226        u16::from_be_bytes(utils::to_array(self.data, 10).unwrap())
7227    }
7228
7229    /// The Payload Protocol Identifier (PPID) of the DATA chunk.
7230    #[inline]
7231    pub fn proto_id(&self) -> u32 {
7232        u32::from_be_bytes(utils::to_array(self.data, 12).unwrap())
7233    }
7234
7235    /// The User Data payload of the DATA chunk.
7236    #[inline]
7237    pub fn user_data(&self) -> &[u8] {
7238        self.data.get(16..self.chunk_len() as usize).unwrap()
7239    }
7240
7241    /// The padding at the end of the DATA chunk.
7242    #[inline]
7243    pub fn padding(&self) -> &[u8] {
7244        &self.data[self.chunk_len() as usize..self.chunk_len_padded()]
7245    }
7246}
7247
7248impl LayerOffset for SctpDataChunkRef<'_> {
7249    #[inline]
7250    fn payload_byte_index_default(bytes: &[u8], _layer_type: LayerId) -> Option<usize> {
7251        if bytes.len() > 16 {
7252            Some(16)
7253        } else {
7254            None
7255        }
7256    }
7257}
7258
7259impl Validate for SctpDataChunkRef<'_> {
7260    fn validate_current_layer(curr_layer: &[u8]) -> Result<(), ValidationError> {
7261        let len = match utils::to_array(curr_layer, 2) {
7262            None => {
7263                return Err(ValidationError {
7264                    layer: Self::name(),
7265                    class: ValidationErrorClass::InsufficientBytes,
7266                    #[cfg(feature = "error_string")]
7267                    reason: "SCTP DATA chunk must have a minimum of 16 bytes for its header",
7268                })
7269            }
7270            Some(arr) => u16::from_be_bytes(arr) as usize,
7271        };
7272
7273        let payload_type = curr_layer[0]; // This won't panic because we've already retrieved bytes at index 2
7274        if payload_type != 0 {
7275            return Err(ValidationError {
7276                layer: Self::name(),
7277                class: ValidationErrorClass::InvalidValue,
7278                #[cfg(feature = "error_string")]
7279                reason: "invalid Chunk Type field in SCTP DATA chunk (must be equal to 0)",
7280            });
7281        }
7282
7283        if len < 17 {
7284            return Err(ValidationError {
7285                layer: Self::name(),
7286                class: ValidationErrorClass::InvalidValue,
7287                #[cfg(feature = "error_string")]
7288                reason: "packet length field had invalid value (insufficient length to cover packet header and at least one byte of data) for SCTP DATA chunk",
7289            });
7290        }
7291
7292        Ok(())
7293    }
7294
7295    #[inline]
7296    fn validate_payload_default(curr_layer: &[u8]) -> Result<(), ValidationError> {
7297        let data = SctpDataChunkRef::from_bytes_unchecked(curr_layer);
7298        let padded_len = data.chunk_len_padded();
7299        if padded_len > curr_layer.len() {
7300            return Err(ValidationError {
7301                layer: Self::name(),
7302                class: ValidationErrorClass::InsufficientBytes,
7303                #[cfg(feature = "error_string")]
7304                reason: "insufficient bytes for User Data portion of SCTP DATA chunk",
7305            });
7306        }
7307
7308        let len = data.chunk_len() as usize;
7309
7310        // The payload is considered valid by default, since we count it as a [`Raw`] packet type.
7311
7312        for b in curr_layer.iter().take(padded_len).skip(len) {
7313            if *b != 0 {
7314                return Err(ValidationError {
7315                    layer: Self::name(),
7316                    class: ValidationErrorClass::UnusualPadding,
7317                    #[cfg(feature = "error_string")]
7318                    reason: "padding at end of SCTP DATA chunk had a non-zero value",
7319                });
7320            }
7321        }
7322
7323        if padded_len < curr_layer.len() {
7324            Err(ValidationError {
7325                layer: Self::name(),
7326                class: ValidationErrorClass::ExcessBytes(curr_layer.len() - padded_len),
7327                #[cfg(feature = "error_string")]
7328                reason: "SCTP DATA chunk had additional trailing bytes at the end of its data",
7329            })
7330        } else {
7331            Ok(())
7332        }
7333    }
7334}
7335
7336bitflags! {
7337    /// The flags of a DATA chunk.
7338    #[derive(Clone, Copy, Debug, Default)]
7339    pub struct DataChunkFlags: u8 {
7340        const R1 = 0b10000000;
7341        const R2 = 0b01000000;
7342        const R3 = 0b00100000;
7343        const R4 = 0b00010000;
7344        const IMMEDIATE = 0b00001000;
7345        const UNORDERED = 0b00000100;
7346        const BEGIN_FRAGMENT = 0b00000010;
7347        const END_FRAGMENT = 0b00000001;
7348    }
7349}
7350
7351impl From<u8> for DataChunkFlags {
7352    fn from(value: u8) -> Self {
7353        DataChunkFlags::from_bits_truncate(value)
7354    }
7355}