@@ -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 ;
@@ -100,17 +101,15 @@ pub struct Set {
100
101
#[ derive( Debug , PartialEq , Clone , Serialize , Nom ) ]
101
102
#[ nom( ExtraArgs ( parser: & mut IPFixParser , set_id: u16 ) ) ]
102
103
pub struct Data {
103
- #[ nom(
104
- Parse = "{ |i| parse_fields::<Template>(i, parser.templates.get(&set_id).cloned()) }"
105
- ) ]
104
+ #[ nom( Parse = "{ |i| parse_fields::<Template>(i, parser.templates.get(&set_id)) }" ) ]
106
105
pub data_fields : Vec < BTreeMap < IPFixField , FieldValue > > ,
107
106
}
108
107
109
108
#[ derive( Debug , PartialEq , Clone , Serialize , Nom ) ]
110
109
#[ nom( ExtraArgs ( parser: & mut IPFixParser , set_id: u16 ) ) ]
111
110
pub struct OptionsData {
112
111
#[ nom(
113
- Parse = "{ |i| parse_fields::<OptionsTemplate>(i, parser.options_templates.get(&set_id).cloned() ) }"
112
+ Parse = "{ |i| parse_fields::<OptionsTemplate>(i, parser.options_templates.get(&set_id)) }"
114
113
) ]
115
114
pub data_fields : Vec < BTreeMap < IPFixField , FieldValue > > ,
116
115
}
@@ -120,12 +119,12 @@ pub struct OptionsTemplate {
120
119
pub template_id : u16 ,
121
120
pub field_count : u16 ,
122
121
pub scope_field_count : u16 ,
123
- #[ nom( Count = "scope_field_count" ) ]
124
- pub scope_field_specifiers : Vec < OptionsTemplateField > ,
125
122
#[ nom(
126
- 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)"
127
126
) ]
128
- pub field_specifiers : Vec < OptionsTemplateField > ,
127
+ pub fields : Vec < TemplateField > ,
129
128
#[ nom( Cond = "!i.is_empty()" ) ]
130
129
#[ serde( skip_serializing) ]
131
130
padding : Option < u16 > ,
@@ -135,23 +134,28 @@ pub struct OptionsTemplate {
135
134
pub struct Template {
136
135
pub template_id : u16 ,
137
136
pub field_count : u16 ,
138
- #[ nom( Count = "field_count" ) ]
137
+ #[ nom( Parse = "count(|i| TemplateField::parse(i, false), field_count as usize) " ) ]
139
138
pub fields : Vec < TemplateField > ,
140
139
}
141
140
142
141
#[ derive( Debug , PartialEq , Eq , Clone , Serialize , Nom ) ]
143
- pub struct OptionsTemplateField {
142
+ #[ nom( ExtraArgs ( options_template: bool ) ) ]
143
+ pub struct TemplateField {
144
144
pub field_type_number : u16 ,
145
145
#[ nom( Value ( IPFixField :: from( field_type_number) ) ) ]
146
146
pub field_type : IPFixField ,
147
- field_length : u16 ,
147
+ pub field_length : u16 ,
148
148
#[ nom(
149
- Cond = "field_type_number > 32767" ,
150
- PostExec = "let field_type_number = field_type_number.overflowing_sub(32768).0;" ,
151
- 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 };"
152
156
) ]
153
157
#[ serde( skip_serializing_if = "Option::is_none" ) ]
154
- enterprise_number : Option < u32 > ,
158
+ pub enterprise_number : Option < u32 > ,
155
159
}
156
160
157
161
fn set_entperprise_field ( field_type : IPFixField , enterprise_number : Option < u32 > ) -> IPFixField {
@@ -161,14 +165,6 @@ fn set_entperprise_field(field_type: IPFixField, enterprise_number: Option<u32>)
161
165
}
162
166
}
163
167
164
- #[ derive( Debug , PartialEq , Eq , Clone , Serialize , PartialOrd , Ord , Nom ) ]
165
- pub struct TemplateField {
166
- pub field_type_number : u16 ,
167
- #[ nom( Value ( IPFixField :: from( field_type_number) ) ) ]
168
- pub field_type : IPFixField ,
169
- pub field_length : u16 ,
170
- }
171
-
172
168
/// Parses options template
173
169
fn parse_options_template ( i : & [ u8 ] , length : u16 ) -> IResult < & [ u8 ] , OptionsTemplate > {
174
170
let ( remaining, taken) = take ( length. checked_sub ( 4 ) . unwrap_or ( length) ) ( i) ?;
@@ -179,57 +175,47 @@ fn parse_options_template(i: &[u8], length: u16) -> IResult<&[u8], OptionsTempla
179
175
// Hacky way when using Template as generic T to cast to a common field type.
180
176
// We use OptionsTemplateField as it is the same as type Template Field but
181
177
// with enterprise_field. In TemplateField tpe enterprise_field is just None.
182
- trait CommonTemplateFields {
183
- fn get_fields ( & self ) -> Vec < OptionsTemplateField > ;
178
+ trait CommonTemplate {
179
+ fn get_fields ( & self ) -> & Vec < TemplateField > ;
184
180
}
185
181
186
- impl CommonTemplateFields for Template {
187
- fn get_fields ( & self ) -> Vec < OptionsTemplateField > {
188
- self . fields
189
- . iter ( )
190
- . map ( |f| OptionsTemplateField {
191
- field_length : f. field_length ,
192
- field_type : f. field_type ,
193
- field_type_number : f. field_type_number ,
194
- enterprise_number : None ,
195
- } )
196
- . collect ( )
182
+ impl CommonTemplate for Template {
183
+ fn get_fields ( & self ) -> & Vec < TemplateField > {
184
+ & self . fields
197
185
}
198
186
}
199
187
200
- impl CommonTemplateFields for OptionsTemplate {
201
- fn get_fields ( & self ) -> Vec < OptionsTemplateField > {
202
- let mut temp = vec ! [ ] ;
203
- temp. append ( & mut self . scope_field_specifiers . clone ( ) ) ;
204
- temp. append ( & mut self . field_specifiers . clone ( ) ) ;
205
- temp
188
+ impl CommonTemplate for OptionsTemplate {
189
+ fn get_fields ( & self ) -> & Vec < TemplateField > {
190
+ & self . fields
206
191
}
207
192
}
208
193
209
194
/// Takes a byte stream and a cached template.
210
195
/// Fields get matched to static types.
211
196
/// Returns BTree of IPFix Types & Fields or IResult Error.
212
- fn parse_fields < T : CommonTemplateFields > (
213
- i : & [ u8 ] ,
214
- template : Option < T > ,
215
- ) -> IResult < & [ u8 ] , Vec < BTreeMap < IPFixField , FieldValue > > > {
197
+ fn parse_fields < ' a , T : CommonTemplate > (
198
+ i : & ' a [ u8 ] ,
199
+ template : Option < & T > ,
200
+ ) -> IResult < & ' a [ u8 ] , Vec < BTreeMap < IPFixField , FieldValue > > > {
216
201
let template = match template {
217
202
Some ( t) => t,
218
203
None => {
219
204
// dbg!("Could not fetch any v10 templates!");
220
205
return Err ( NomErr :: Error ( NomError :: new ( i, ErrorKind :: Fail ) ) ) ;
221
206
}
222
207
} ;
208
+ let template_fields = template. get_fields ( ) ;
223
209
// If no fields there are no fields to parse
224
- if template . get_fields ( ) . is_empty ( ) {
210
+ if template_fields . is_empty ( ) {
225
211
// dbg!("Template without fields!");
226
212
return Err ( NomErr :: Error ( NomError :: new ( i, ErrorKind :: Fail ) ) ) ;
227
213
} ;
228
214
let mut fields = vec ! [ ] ;
229
215
let mut remaining = i;
230
216
while !remaining. is_empty ( ) {
231
217
let mut data_field = BTreeMap :: new ( ) ;
232
- for template_field in template . get_fields ( ) . iter ( ) {
218
+ for template_field in template_fields . iter ( ) {
233
219
let field_type: FieldDataType = template_field. field_type . into ( ) ;
234
220
// Enterprise Number
235
221
if template_field. enterprise_number . is_some ( ) {
@@ -349,7 +335,7 @@ impl NetflowByteParserVariable for IPFixParser {
349
335
. checked_sub ( remaining. len ( ) )
350
336
. unwrap_or ( total_left) ;
351
337
total_left -= parsed;
352
- sets. push ( v10_set. clone ( ) ) ;
338
+ sets. push ( v10_set) ;
353
339
}
354
340
355
341
let v10_parsed = IPFix {
0 commit comments