@@ -156,6 +156,33 @@ impl BgpNotificationMessage {
156156/// Parse BGP OPEN message.
157157///
158158/// The parsing of BGP OPEN message also includes decoding the BGP capabilities.
159+ ///
160+ /// RFC 4271: https://datatracker.ietf.org/doc/html/rfc4271
161+ /// ```text
162+ /// 0 1 2 3
163+ /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
164+ /// +-+-+-+-+-+-+-+-+
165+ /// | Version |
166+ /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
167+ /// | My Autonomous System |
168+ /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
169+ /// | Hold Time |
170+ /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
171+ /// | BGP Identifier |
172+ /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
173+ /// | Opt Parm Len |
174+ /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
175+ /// | |
176+ /// | Optional Parameters (variable) |
177+ /// | |
178+ /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
179+ ///
180+ /// 0 1
181+ /// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
182+ /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-...
183+ /// | Parm. Type | Parm. Length | Parameter Value (variable)
184+ /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-...
185+ /// ```
159186pub fn parse_bgp_open_message ( input : & mut Bytes ) -> Result < BgpOpenMessage , ParserError > {
160187 input. has_n_remaining ( 10 ) ?;
161188 let version = input. get_u8 ( ) ;
@@ -172,8 +199,14 @@ pub fn parse_bgp_open_message(input: &mut Bytes) -> Result<BgpOpenMessage, Parse
172199 while input. remaining ( ) >= 2 {
173200 let mut param_type = input. get_u8 ( ) ;
174201 if first {
202+ if opt_params_len == 0 && param_type == 255 {
203+ return Err ( ParserError :: ParseError (
204+ "RFC 9072 violation: Non-Extended Optional Parameters Length must not be 0 when using extended format" . to_string ( )
205+ ) ) ;
206+ }
175207 // first parameter, check if it is extended length message
176- if opt_params_len == 255 && param_type == 255 {
208+ if opt_params_len != 0 && param_type == 255 {
209+ // RFC 9072: https://datatracker.ietf.org/doc/rfc9072/
177210 //
178211 // 0 1 2 3
179212 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
@@ -191,7 +224,7 @@ pub fn parse_bgp_open_message(input: &mut Bytes) -> Result<BgpOpenMessage, Parse
191224 // | |
192225 // | Optional Parameters (variable) |
193226 // | |
194- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
227+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
195228 //
196229 // Figure 1: Extended Encoding OPEN Format
197230 extended_length = true ;
@@ -218,6 +251,7 @@ pub fn parse_bgp_open_message(input: &mut Bytes) -> Result<BgpOpenMessage, Parse
218251 true => input. read_u16 ( ) ?,
219252 false => input. read_u8 ( ) ? as u16 ,
220253 } ;
254+
221255 // https://tools.ietf.org/html/rfc3392
222256 // https://www.iana.org/assignments/bgp-parameters/bgp-parameters.xhtml#bgp-parameters-11
223257
@@ -232,10 +266,7 @@ pub fn parse_bgp_open_message(input: &mut Bytes) -> Result<BgpOpenMessage, Parse
232266 // capability codes:
233267 // https://www.iana.org/assignments/capability-codes/capability-codes.xhtml#capability-codes-2
234268 let code = param_data. read_u8 ( ) ?;
235- let len = match extended_length {
236- true => param_data. read_u16 ( ) ?,
237- false => param_data. read_u8 ( ) ? as u16 ,
238- } ;
269+ let len = param_data. read_u8 ( ) ? as u16 ; // Capability length is ALWAYS 1 byte per RFC 5492
239270
240271 let capability_data = param_data. read_n_bytes ( len as usize ) ?;
241272 let capability_type = BgpCapabilityType :: from ( code) ;
0 commit comments