@@ -13,6 +13,7 @@ use crate::{NetflowByteParserVariable, NetflowPacketResult, ParsedNetflow};
13
13
14
14
use nom:: bytes:: complete:: take;
15
15
use nom:: error:: { Error as NomError , ErrorKind } ;
16
+ use nom:: multi:: count;
16
17
use nom:: number:: complete:: { be_u128, be_u32} ;
17
18
use nom:: Err as NomErr ;
18
19
use nom:: IResult ;
@@ -118,12 +119,12 @@ pub struct OptionsTemplate {
118
119
pub template_id : u16 ,
119
120
pub field_count : u16 ,
120
121
pub scope_field_count : u16 ,
121
- #[ nom( Count = "scope_field_count" ) ]
122
- pub scope_field_specifiers : Vec < OptionsTemplateField > ,
123
122
#[ nom(
124
- Count = "(field_count.checked_sub(scope_field_count).unwrap_or(field_count)) as usize"
123
+ PreExec = "let combined_count = scope_field_count as usize +
124
+ field_count.checked_sub(scope_field_count).unwrap_or(field_count) as usize;" ,
125
+ Parse = "count(|i| TemplateField::parse(i, true), combined_count as usize)"
125
126
) ]
126
- pub field_specifiers : Vec < OptionsTemplateField > ,
127
+ pub fields : Vec < TemplateField > ,
127
128
#[ nom( Cond = "!i.is_empty()" ) ]
128
129
#[ serde( skip_serializing) ]
129
130
padding : Option < u16 > ,
@@ -133,23 +134,28 @@ pub struct OptionsTemplate {
133
134
pub struct Template {
134
135
pub template_id : u16 ,
135
136
pub field_count : u16 ,
136
- #[ nom( Count = "field_count" ) ]
137
+ #[ nom( Parse = "count(|i| TemplateField::parse(i, false), field_count as usize) " ) ]
137
138
pub fields : Vec < TemplateField > ,
138
139
}
139
140
140
141
#[ derive( Debug , PartialEq , Eq , Clone , Serialize , Nom ) ]
141
- pub struct OptionsTemplateField {
142
+ #[ nom( ExtraArgs ( options_template: bool ) ) ]
143
+ pub struct TemplateField {
142
144
pub field_type_number : u16 ,
143
145
#[ nom( Value ( IPFixField :: from( field_type_number) ) ) ]
144
146
pub field_type : IPFixField ,
145
- field_length : u16 ,
147
+ pub field_length : u16 ,
146
148
#[ nom(
147
- Cond = "field_type_number > 32767" ,
148
- PostExec = "let field_type_number = field_type_number.overflowing_sub(32768).0;" ,
149
- PostExec = "let field_type = set_entperprise_field(field_type, enterprise_number);"
149
+ Cond = "options_template && field_type_number > 32767" ,
150
+ PostExec = "let field_type_number = if options_template {
151
+ field_type_number.overflowing_sub(32768).0
152
+ } else { field_type_number };" ,
153
+ PostExec = "let field_type = if options_template {
154
+ set_entperprise_field(field_type, enterprise_number)
155
+ } else { field_type };"
150
156
) ]
151
157
#[ serde( skip_serializing_if = "Option::is_none" ) ]
152
- enterprise_number : Option < u32 > ,
158
+ pub enterprise_number : Option < u32 > ,
153
159
}
154
160
155
161
fn set_entperprise_field ( field_type : IPFixField , enterprise_number : Option < u32 > ) -> IPFixField {
@@ -159,14 +165,6 @@ fn set_entperprise_field(field_type: IPFixField, enterprise_number: Option<u32>)
159
165
}
160
166
}
161
167
162
- #[ derive( Debug , PartialEq , Eq , Clone , Serialize , PartialOrd , Ord , Nom ) ]
163
- pub struct TemplateField {
164
- pub field_type_number : u16 ,
165
- #[ nom( Value ( IPFixField :: from( field_type_number) ) ) ]
166
- pub field_type : IPFixField ,
167
- pub field_length : u16 ,
168
- }
169
-
170
168
/// Parses options template
171
169
fn parse_options_template ( i : & [ u8 ] , length : u16 ) -> IResult < & [ u8 ] , OptionsTemplate > {
172
170
let ( remaining, taken) = take ( length. checked_sub ( 4 ) . unwrap_or ( length) ) ( i) ?;
@@ -177,37 +175,26 @@ fn parse_options_template(i: &[u8], length: u16) -> IResult<&[u8], OptionsTempla
177
175
// Hacky way when using Template as generic T to cast to a common field type.
178
176
// We use OptionsTemplateField as it is the same as type Template Field but
179
177
// with enterprise_field. In TemplateField tpe enterprise_field is just None.
180
- trait CommonTemplateFields {
181
- fn get_fields ( & self ) -> Vec < OptionsTemplateField > ;
178
+ trait CommonTemplate {
179
+ fn get_fields ( & self ) -> & Vec < TemplateField > ;
182
180
}
183
181
184
- impl CommonTemplateFields for Template {
185
- fn get_fields ( & self ) -> Vec < OptionsTemplateField > {
186
- self . fields
187
- . iter ( )
188
- . map ( |f| OptionsTemplateField {
189
- field_length : f. field_length ,
190
- field_type : f. field_type ,
191
- field_type_number : f. field_type_number ,
192
- enterprise_number : None ,
193
- } )
194
- . collect ( )
182
+ impl CommonTemplate for Template {
183
+ fn get_fields ( & self ) -> & Vec < TemplateField > {
184
+ & self . fields
195
185
}
196
186
}
197
187
198
- impl CommonTemplateFields for OptionsTemplate {
199
- fn get_fields ( & self ) -> Vec < OptionsTemplateField > {
200
- let mut temp = vec ! [ ] ;
201
- temp. append ( & mut self . scope_field_specifiers . clone ( ) ) ;
202
- temp. append ( & mut self . field_specifiers . clone ( ) ) ;
203
- temp
188
+ impl CommonTemplate for OptionsTemplate {
189
+ fn get_fields ( & self ) -> & Vec < TemplateField > {
190
+ & self . fields
204
191
}
205
192
}
206
193
207
194
/// Takes a byte stream and a cached template.
208
195
/// Fields get matched to static types.
209
196
/// Returns BTree of IPFix Types & Fields or IResult Error.
210
- fn parse_fields < ' a , T : CommonTemplateFields > (
197
+ fn parse_fields < ' a , T : CommonTemplate > (
211
198
i : & ' a [ u8 ] ,
212
199
template : Option < & T > ,
213
200
) -> IResult < & ' a [ u8 ] , Vec < BTreeMap < IPFixField , FieldValue > > > {
0 commit comments