Skip to content

Commit

Permalink
Ignore unknown parameters (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
algesten authored Aug 7, 2024
1 parent 4bfd178 commit 82781f1
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 36 deletions.
4 changes: 2 additions & 2 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ pub enum Error {
#[error("raw is too small for error cause")]
ErrErrorCauseTooSmall,

#[error("unhandled ParamType")]
ErrParamTypeUnhandled,
#[error("unhandled ParamType: {typ}")]
ErrParamTypeUnhandled { typ: u16 },

#[error("unexpected ParamType")]
ErrParamTypeUnexpected,
Expand Down
18 changes: 16 additions & 2 deletions src/param/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub(crate) mod param_requested_hmac_algorithm;
pub(crate) mod param_state_cookie;
pub(crate) mod param_supported_extensions;
pub(crate) mod param_type;
pub(crate) mod param_uknown;

use crate::error::{Error, Result};
use crate::param::{
Expand All @@ -28,6 +29,8 @@ use param_type::*;
use bytes::{Buf, Bytes, BytesMut};
use std::{any::Any, fmt};

use self::param_uknown::ParamUnknown;

pub(crate) trait Param: fmt::Display + fmt::Debug {
fn header(&self) -> ParamHeader;
fn unmarshal(raw: &Bytes) -> Result<Self>
Expand Down Expand Up @@ -57,7 +60,8 @@ pub(crate) fn build_param(raw_param: &Bytes) -> Result<Box<dyn Param + Send + Sy
return Err(Error::ErrParamHeaderTooShort);
}
let reader = &mut raw_param.slice(..2);
let t: ParamType = reader.get_u16().into();
let raw_type = reader.get_u16();
let t: ParamType = raw_type.into();
match t {
ParamType::ForwardTsnSupp => Ok(Box::new(ParamForwardTsnSupported::unmarshal(raw_param)?)),
ParamType::SupportedExt => Ok(Box::new(ParamSupportedExtensions::unmarshal(raw_param)?)),
Expand All @@ -68,6 +72,16 @@ pub(crate) fn build_param(raw_param: &Bytes) -> Result<Box<dyn Param + Send + Sy
ParamType::HeartbeatInfo => Ok(Box::new(ParamHeartbeatInfo::unmarshal(raw_param)?)),
ParamType::OutSsnResetReq => Ok(Box::new(ParamOutgoingResetRequest::unmarshal(raw_param)?)),
ParamType::ReconfigResp => Ok(Box::new(ParamReconfigResponse::unmarshal(raw_param)?)),
_ => Err(Error::ErrParamTypeUnhandled),
_ => {
// According to RFC https://datatracker.ietf.org/doc/html/rfc4960#section-3.2.1
let stop_processing = ((raw_type >> 15) & 0x01) == 0;
if stop_processing {
Err(Error::ErrParamTypeUnhandled { typ: raw_type })
} else {
// We still might need to report this param as unrecognized.
// This depends on the context though.
Ok(Box::new(ParamUnknown::unmarshal(raw_param)?))
}
}
}
}
4 changes: 2 additions & 2 deletions src/param/param_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::{param_type::*, *};

use bytes::BufMut;

#[derive(Default, Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct ParamHeader {
pub(crate) typ: ParamType,
pub(crate) value_length: u16,
Expand Down Expand Up @@ -43,7 +43,7 @@ impl Param for ParamHeader {
}

fn marshal_to(&self, writer: &mut BytesMut) -> Result<usize> {
writer.put_u16(self.typ as u16);
writer.put_u16(self.typ.into());
writer.put_u16(self.value_length + PARAM_HEADER_LENGTH as u16);
Ok(writer.len())
}
Expand Down
94 changes: 64 additions & 30 deletions src/param/param_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,62 +3,62 @@ use std::fmt;
/// paramType represents a SCTP INIT/INITACK parameter
#[derive(Debug, Copy, Clone, PartialEq)]
#[repr(C)]
#[derive(Default)]
pub(crate) enum ParamType {
HeartbeatInfo = 1,
HeartbeatInfo,
/// Heartbeat Info [RFCRFC4960]
Ipv4Addr = 5,
Ipv4Addr,
/// IPv4 IP [RFCRFC4960]
Ipv6Addr = 6,
Ipv6Addr,
/// IPv6 IP [RFCRFC4960]
StateCookie = 7,
StateCookie,
/// State Cookie [RFCRFC4960]
UnrecognizedParam = 8,
UnrecognizedParam,
/// Unrecognized Parameters [RFCRFC4960]
CookiePreservative = 9,
CookiePreservative,
/// Cookie Preservative [RFCRFC4960]
HostNameAddr = 11,
HostNameAddr,
/// Host Name IP [RFCRFC4960]
SupportedAddrTypes = 12,
SupportedAddrTypes,
/// Supported IP Types [RFCRFC4960]
OutSsnResetReq = 13,
OutSsnResetReq,
/// Outgoing SSN Reset Request Parameter [RFCRFC6525]
IncSsnResetReq = 14,
IncSsnResetReq,
/// Incoming SSN Reset Request Parameter [RFCRFC6525]
SsnTsnResetReq = 15,
SsnTsnResetReq,
/// SSN/TSN Reset Request Parameter [RFCRFC6525]
ReconfigResp = 16,
ReconfigResp,
/// Re-configuration Response Parameter [RFCRFC6525]
AddOutStreamsReq = 17,
AddOutStreamsReq,
/// Add Outgoing Streams Request Parameter [RFCRFC6525]
AddIncStreamsReq = 18,
AddIncStreamsReq,
/// Add Incoming Streams Request Parameter [RFCRFC6525]
Random = 32770,
Random,
/// Random (0x8002) [RFCRFC4805]
ChunkList = 32771,
ChunkList,
/// Chunk List (0x8003) [RFCRFC4895]
ReqHmacAlgo = 32772,
ReqHmacAlgo,
/// Requested HMAC Algorithm Parameter (0x8004) [RFCRFC4895]
Padding = 32773,
Padding,
/// Padding (0x8005)
SupportedExt = 32776,
SupportedExt,
/// Supported Extensions (0x8008) [RFCRFC5061]
ForwardTsnSupp = 49152,
ForwardTsnSupp,
/// Forward TSN supported (0xC000) [RFCRFC3758]
AddIpAddr = 49153,
AddIpAddr,
/// Add IP IP (0xC001) [RFCRFC5061]
DelIpaddr = 49154,
DelIpaddr,
/// Delete IP IP (0xC002) [RFCRFC5061]
ErrClauseInd = 49155,
ErrClauseInd,
/// Error Cause Indication (0xC003) [RFCRFC5061]
SetPriAddr = 49156,
SetPriAddr,
/// Set Primary IP (0xC004) [RFCRFC5061]
SuccessInd = 49157,
SuccessInd,
/// Success Indication (0xC005) [RFCRFC5061]
AdaptLayerInd = 49158,
AdaptLayerInd,
/// Adaptation Layer Indication (0xC006) [RFCRFC5061]
#[default]
Unknown,
Unknown {
param_type: u16,
},
}

impl fmt::Display for ParamType {
Expand Down Expand Up @@ -124,7 +124,41 @@ impl From<u16> for ParamType {
49155 => ParamType::ErrClauseInd,
49156 => ParamType::SetPriAddr,
49157 => ParamType::SuccessInd,
_ => ParamType::Unknown,
_ => ParamType::Unknown { param_type: v },
}
}
}

impl From<ParamType> for u16 {
fn from(v: ParamType) -> u16 {
match v {
ParamType::HeartbeatInfo => 1,
ParamType::Ipv4Addr => 5,
ParamType::Ipv6Addr => 6,
ParamType::StateCookie => 7,
ParamType::UnrecognizedParam => 8,
ParamType::CookiePreservative => 9,
ParamType::HostNameAddr => 11,
ParamType::SupportedAddrTypes => 12,
ParamType::OutSsnResetReq => 13,
ParamType::IncSsnResetReq => 14,
ParamType::SsnTsnResetReq => 15,
ParamType::ReconfigResp => 16,
ParamType::AddOutStreamsReq => 17,
ParamType::AddIncStreamsReq => 18,
ParamType::Random => 32770,
ParamType::ChunkList => 32771,
ParamType::ReqHmacAlgo => 32772,
ParamType::Padding => 32773,
ParamType::SupportedExt => 32776,
ParamType::ForwardTsnSupp => 49152,
ParamType::AddIpAddr => 49153,
ParamType::DelIpaddr => 49154,
ParamType::ErrClauseInd => 49155,
ParamType::SetPriAddr => 49156,
ParamType::SuccessInd => 49157,
ParamType::AdaptLayerInd => 49158,
ParamType::Unknown { param_type, .. } => param_type,
}
}
}
65 changes: 65 additions & 0 deletions src/param/param_uknown.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use std::any::Any;
use std::fmt::{Debug, Display, Formatter};

use bytes::{Bytes, BytesMut};

use crate::param::param_header::{ParamHeader, PARAM_HEADER_LENGTH};
use crate::param::param_type::ParamType;
use crate::param::Param;

/// This type is meant to represent ANY parameter for un/remarshaling purposes, where we do not have a more specific type for it.
/// This means we do not really understand the semantics of the param but can represent it.
///
/// This is useful for usage in e.g.`ParamUnrecognized` where we want to report some unrecognized params back to the sender.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ParamUnknown {
typ: u16,
value: Bytes,
}

impl Display for ParamUnknown {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "ParamUnknown( {} {:?} )", self.header(), self.value)
}
}

impl Param for ParamUnknown {
fn header(&self) -> ParamHeader {
ParamHeader {
typ: ParamType::Unknown {
param_type: self.typ,
},
value_length: self.value.len() as u16,
}
}

fn as_any(&self) -> &(dyn Any + Send + Sync) {
self
}

fn unmarshal(raw: &Bytes) -> crate::error::Result<Self>
where
Self: Sized,
{
let header = ParamHeader::unmarshal(raw)?;
let value = raw.slice(PARAM_HEADER_LENGTH..PARAM_HEADER_LENGTH + header.value_length());
Ok(Self {
typ: header.typ.into(),
value,
})
}

fn marshal_to(&self, buf: &mut BytesMut) -> crate::error::Result<usize> {
self.header().marshal_to(buf)?;
buf.extend(self.value.clone());
Ok(buf.len())
}

fn value_length(&self) -> usize {
self.value.len()
}

fn clone_to(&self) -> Box<dyn Param + Send + Sync> {
Box::new(self.clone())
}
}

0 comments on commit 82781f1

Please # to comment.