Skip to content

Commit 82781f1

Browse files
authored
Ignore unknown parameters (#14)
1 parent 4bfd178 commit 82781f1

File tree

5 files changed

+149
-36
lines changed

5 files changed

+149
-36
lines changed

src/error.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ pub enum Error {
5757
#[error("raw is too small for error cause")]
5858
ErrErrorCauseTooSmall,
5959

60-
#[error("unhandled ParamType")]
61-
ErrParamTypeUnhandled,
60+
#[error("unhandled ParamType: {typ}")]
61+
ErrParamTypeUnhandled { typ: u16 },
6262

6363
#[error("unexpected ParamType")]
6464
ErrParamTypeUnexpected,

src/param/mod.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ pub(crate) mod param_requested_hmac_algorithm;
1212
pub(crate) mod param_state_cookie;
1313
pub(crate) mod param_supported_extensions;
1414
pub(crate) mod param_type;
15+
pub(crate) mod param_uknown;
1516

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

32+
use self::param_uknown::ParamUnknown;
33+
3134
pub(crate) trait Param: fmt::Display + fmt::Debug {
3235
fn header(&self) -> ParamHeader;
3336
fn unmarshal(raw: &Bytes) -> Result<Self>
@@ -57,7 +60,8 @@ pub(crate) fn build_param(raw_param: &Bytes) -> Result<Box<dyn Param + Send + Sy
5760
return Err(Error::ErrParamHeaderTooShort);
5861
}
5962
let reader = &mut raw_param.slice(..2);
60-
let t: ParamType = reader.get_u16().into();
63+
let raw_type = reader.get_u16();
64+
let t: ParamType = raw_type.into();
6165
match t {
6266
ParamType::ForwardTsnSupp => Ok(Box::new(ParamForwardTsnSupported::unmarshal(raw_param)?)),
6367
ParamType::SupportedExt => Ok(Box::new(ParamSupportedExtensions::unmarshal(raw_param)?)),
@@ -68,6 +72,16 @@ pub(crate) fn build_param(raw_param: &Bytes) -> Result<Box<dyn Param + Send + Sy
6872
ParamType::HeartbeatInfo => Ok(Box::new(ParamHeartbeatInfo::unmarshal(raw_param)?)),
6973
ParamType::OutSsnResetReq => Ok(Box::new(ParamOutgoingResetRequest::unmarshal(raw_param)?)),
7074
ParamType::ReconfigResp => Ok(Box::new(ParamReconfigResponse::unmarshal(raw_param)?)),
71-
_ => Err(Error::ErrParamTypeUnhandled),
75+
_ => {
76+
// According to RFC https://datatracker.ietf.org/doc/html/rfc4960#section-3.2.1
77+
let stop_processing = ((raw_type >> 15) & 0x01) == 0;
78+
if stop_processing {
79+
Err(Error::ErrParamTypeUnhandled { typ: raw_type })
80+
} else {
81+
// We still might need to report this param as unrecognized.
82+
// This depends on the context though.
83+
Ok(Box::new(ParamUnknown::unmarshal(raw_param)?))
84+
}
85+
}
7286
}
7387
}

src/param/param_header.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::{param_type::*, *};
22

33
use bytes::BufMut;
44

5-
#[derive(Default, Debug, Clone, PartialEq)]
5+
#[derive(Debug, Clone, PartialEq)]
66
pub(crate) struct ParamHeader {
77
pub(crate) typ: ParamType,
88
pub(crate) value_length: u16,
@@ -43,7 +43,7 @@ impl Param for ParamHeader {
4343
}
4444

4545
fn marshal_to(&self, writer: &mut BytesMut) -> Result<usize> {
46-
writer.put_u16(self.typ as u16);
46+
writer.put_u16(self.typ.into());
4747
writer.put_u16(self.value_length + PARAM_HEADER_LENGTH as u16);
4848
Ok(writer.len())
4949
}

src/param/param_type.rs

+64-30
Original file line numberDiff line numberDiff line change
@@ -3,62 +3,62 @@ use std::fmt;
33
/// paramType represents a SCTP INIT/INITACK parameter
44
#[derive(Debug, Copy, Clone, PartialEq)]
55
#[repr(C)]
6-
#[derive(Default)]
76
pub(crate) enum ParamType {
8-
HeartbeatInfo = 1,
7+
HeartbeatInfo,
98
/// Heartbeat Info [RFCRFC4960]
10-
Ipv4Addr = 5,
9+
Ipv4Addr,
1110
/// IPv4 IP [RFCRFC4960]
12-
Ipv6Addr = 6,
11+
Ipv6Addr,
1312
/// IPv6 IP [RFCRFC4960]
14-
StateCookie = 7,
13+
StateCookie,
1514
/// State Cookie [RFCRFC4960]
16-
UnrecognizedParam = 8,
15+
UnrecognizedParam,
1716
/// Unrecognized Parameters [RFCRFC4960]
18-
CookiePreservative = 9,
17+
CookiePreservative,
1918
/// Cookie Preservative [RFCRFC4960]
20-
HostNameAddr = 11,
19+
HostNameAddr,
2120
/// Host Name IP [RFCRFC4960]
22-
SupportedAddrTypes = 12,
21+
SupportedAddrTypes,
2322
/// Supported IP Types [RFCRFC4960]
24-
OutSsnResetReq = 13,
23+
OutSsnResetReq,
2524
/// Outgoing SSN Reset Request Parameter [RFCRFC6525]
26-
IncSsnResetReq = 14,
25+
IncSsnResetReq,
2726
/// Incoming SSN Reset Request Parameter [RFCRFC6525]
28-
SsnTsnResetReq = 15,
27+
SsnTsnResetReq,
2928
/// SSN/TSN Reset Request Parameter [RFCRFC6525]
30-
ReconfigResp = 16,
29+
ReconfigResp,
3130
/// Re-configuration Response Parameter [RFCRFC6525]
32-
AddOutStreamsReq = 17,
31+
AddOutStreamsReq,
3332
/// Add Outgoing Streams Request Parameter [RFCRFC6525]
34-
AddIncStreamsReq = 18,
33+
AddIncStreamsReq,
3534
/// Add Incoming Streams Request Parameter [RFCRFC6525]
36-
Random = 32770,
35+
Random,
3736
/// Random (0x8002) [RFCRFC4805]
38-
ChunkList = 32771,
37+
ChunkList,
3938
/// Chunk List (0x8003) [RFCRFC4895]
40-
ReqHmacAlgo = 32772,
39+
ReqHmacAlgo,
4140
/// Requested HMAC Algorithm Parameter (0x8004) [RFCRFC4895]
42-
Padding = 32773,
41+
Padding,
4342
/// Padding (0x8005)
44-
SupportedExt = 32776,
43+
SupportedExt,
4544
/// Supported Extensions (0x8008) [RFCRFC5061]
46-
ForwardTsnSupp = 49152,
45+
ForwardTsnSupp,
4746
/// Forward TSN supported (0xC000) [RFCRFC3758]
48-
AddIpAddr = 49153,
47+
AddIpAddr,
4948
/// Add IP IP (0xC001) [RFCRFC5061]
50-
DelIpaddr = 49154,
49+
DelIpaddr,
5150
/// Delete IP IP (0xC002) [RFCRFC5061]
52-
ErrClauseInd = 49155,
51+
ErrClauseInd,
5352
/// Error Cause Indication (0xC003) [RFCRFC5061]
54-
SetPriAddr = 49156,
53+
SetPriAddr,
5554
/// Set Primary IP (0xC004) [RFCRFC5061]
56-
SuccessInd = 49157,
55+
SuccessInd,
5756
/// Success Indication (0xC005) [RFCRFC5061]
58-
AdaptLayerInd = 49158,
57+
AdaptLayerInd,
5958
/// Adaptation Layer Indication (0xC006) [RFCRFC5061]
60-
#[default]
61-
Unknown,
59+
Unknown {
60+
param_type: u16,
61+
},
6262
}
6363

6464
impl fmt::Display for ParamType {
@@ -124,7 +124,41 @@ impl From<u16> for ParamType {
124124
49155 => ParamType::ErrClauseInd,
125125
49156 => ParamType::SetPriAddr,
126126
49157 => ParamType::SuccessInd,
127-
_ => ParamType::Unknown,
127+
_ => ParamType::Unknown { param_type: v },
128+
}
129+
}
130+
}
131+
132+
impl From<ParamType> for u16 {
133+
fn from(v: ParamType) -> u16 {
134+
match v {
135+
ParamType::HeartbeatInfo => 1,
136+
ParamType::Ipv4Addr => 5,
137+
ParamType::Ipv6Addr => 6,
138+
ParamType::StateCookie => 7,
139+
ParamType::UnrecognizedParam => 8,
140+
ParamType::CookiePreservative => 9,
141+
ParamType::HostNameAddr => 11,
142+
ParamType::SupportedAddrTypes => 12,
143+
ParamType::OutSsnResetReq => 13,
144+
ParamType::IncSsnResetReq => 14,
145+
ParamType::SsnTsnResetReq => 15,
146+
ParamType::ReconfigResp => 16,
147+
ParamType::AddOutStreamsReq => 17,
148+
ParamType::AddIncStreamsReq => 18,
149+
ParamType::Random => 32770,
150+
ParamType::ChunkList => 32771,
151+
ParamType::ReqHmacAlgo => 32772,
152+
ParamType::Padding => 32773,
153+
ParamType::SupportedExt => 32776,
154+
ParamType::ForwardTsnSupp => 49152,
155+
ParamType::AddIpAddr => 49153,
156+
ParamType::DelIpaddr => 49154,
157+
ParamType::ErrClauseInd => 49155,
158+
ParamType::SetPriAddr => 49156,
159+
ParamType::SuccessInd => 49157,
160+
ParamType::AdaptLayerInd => 49158,
161+
ParamType::Unknown { param_type, .. } => param_type,
128162
}
129163
}
130164
}

src/param/param_uknown.rs

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
use std::any::Any;
2+
use std::fmt::{Debug, Display, Formatter};
3+
4+
use bytes::{Bytes, BytesMut};
5+
6+
use crate::param::param_header::{ParamHeader, PARAM_HEADER_LENGTH};
7+
use crate::param::param_type::ParamType;
8+
use crate::param::Param;
9+
10+
/// This type is meant to represent ANY parameter for un/remarshaling purposes, where we do not have a more specific type for it.
11+
/// This means we do not really understand the semantics of the param but can represent it.
12+
///
13+
/// This is useful for usage in e.g.`ParamUnrecognized` where we want to report some unrecognized params back to the sender.
14+
#[derive(Clone, Debug, PartialEq, Eq)]
15+
pub struct ParamUnknown {
16+
typ: u16,
17+
value: Bytes,
18+
}
19+
20+
impl Display for ParamUnknown {
21+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
22+
write!(f, "ParamUnknown( {} {:?} )", self.header(), self.value)
23+
}
24+
}
25+
26+
impl Param for ParamUnknown {
27+
fn header(&self) -> ParamHeader {
28+
ParamHeader {
29+
typ: ParamType::Unknown {
30+
param_type: self.typ,
31+
},
32+
value_length: self.value.len() as u16,
33+
}
34+
}
35+
36+
fn as_any(&self) -> &(dyn Any + Send + Sync) {
37+
self
38+
}
39+
40+
fn unmarshal(raw: &Bytes) -> crate::error::Result<Self>
41+
where
42+
Self: Sized,
43+
{
44+
let header = ParamHeader::unmarshal(raw)?;
45+
let value = raw.slice(PARAM_HEADER_LENGTH..PARAM_HEADER_LENGTH + header.value_length());
46+
Ok(Self {
47+
typ: header.typ.into(),
48+
value,
49+
})
50+
}
51+
52+
fn marshal_to(&self, buf: &mut BytesMut) -> crate::error::Result<usize> {
53+
self.header().marshal_to(buf)?;
54+
buf.extend(self.value.clone());
55+
Ok(buf.len())
56+
}
57+
58+
fn value_length(&self) -> usize {
59+
self.value.len()
60+
}
61+
62+
fn clone_to(&self) -> Box<dyn Param + Send + Sync> {
63+
Box::new(self.clone())
64+
}
65+
}

0 commit comments

Comments
 (0)