@@ -14,6 +14,7 @@ use Nom;
14
14
use nom:: Err as NomErr ;
15
15
use nom:: IResult ;
16
16
use nom:: bytes:: complete:: take;
17
+ use nom:: combinator:: map_res;
17
18
use nom:: error:: { Error as NomError , ErrorKind } ;
18
19
use nom:: multi:: count;
19
20
use nom:: number:: complete:: { be_u8, be_u16} ;
@@ -49,6 +50,26 @@ pub struct IPFixParser {
49
50
pub options_templates : BTreeMap < TemplateId , OptionsTemplate > ,
50
51
}
51
52
53
+ // Custom parse set function to take only length provided by header.
54
+ fn parse_sets < ' a > (
55
+ i : & ' a [ u8 ] ,
56
+ parser : & mut IPFixParser ,
57
+ length : u16 ,
58
+ ) -> IResult < & ' a [ u8 ] , Vec < FlowSet > > {
59
+ let length = length. checked_sub ( 16 ) . unwrap_or ( length) ;
60
+ let ( i, taken) = take ( length) ( i) ?;
61
+ let mut sets = vec ! [ ] ;
62
+ let mut remaining = taken;
63
+
64
+ while !remaining. is_empty ( ) {
65
+ let ( i, set) = FlowSet :: parse ( remaining, parser) ?;
66
+ sets. push ( set) ;
67
+ remaining = i;
68
+ }
69
+
70
+ Ok ( ( i, sets) )
71
+ }
72
+
52
73
#[ derive( Nom , Debug , PartialEq , Clone , Serialize ) ]
53
74
#[ nom( ExtraArgs ( parser: & mut IPFixParser ) ) ]
54
75
pub struct IPFix {
@@ -94,7 +115,12 @@ pub struct Header {
94
115
#[ nom( ExtraArgs ( parser: & mut IPFixParser ) ) ]
95
116
pub struct FlowSet {
96
117
pub header : FlowSetHeader ,
97
- #[ nom( Parse = "{ |i| parse_set_body(i, parser, header.length, header.header_id) }" ) ]
118
+ #[ nom(
119
+ PreExec = "let length = header.length.saturating_sub(4);" ,
120
+ Parse = "map_res(take(length),
121
+ |i| FlowSetBody::parse(i, parser, header.header_id)
122
+ .map(|(_, flow_set)| flow_set))"
123
+ ) ]
98
124
pub body : FlowSetBody ,
99
125
}
100
126
@@ -112,7 +138,7 @@ pub struct FlowSetHeader {
112
138
}
113
139
114
140
#[ derive( Debug , PartialEq , Clone , Serialize , Nom ) ]
115
- #[ nom( ExtraArgs ( parser: & mut IPFixParser , id: u16 , length : u16 ) ) ]
141
+ #[ nom( ExtraArgs ( parser: & mut IPFixParser , id: u16 ) ) ]
116
142
pub struct FlowSetBody {
117
143
#[ nom(
118
144
Cond = "id < SET_MIN_RANGE && id != OPTIONS_TEMPLATE_ID" ,
@@ -126,8 +152,7 @@ pub struct FlowSetBody {
126
152
pub template : Option < Template > ,
127
153
#[ nom(
128
154
Cond = "id == OPTIONS_TEMPLATE_ID" ,
129
- PreExec = "let set_length = length.checked_sub(4).unwrap_or(length);" ,
130
- Parse = "{ |i| OptionsTemplate::parse(i, set_length) }" ,
155
+ Parse = "{ |i| OptionsTemplate::parse(i) }" ,
131
156
Verify = "usize::from(options_template.field_count) == options_template.fields.len()" ,
132
157
Verify = "options_template.get_fields().any(|f| f.field_length > 0)" ,
133
158
// Save our templates
@@ -151,6 +176,8 @@ pub struct FlowSetBody {
151
176
) ]
152
177
#[ serde( skip_serializing_if = "Option::is_none" ) ]
153
178
pub options_data : Option < OptionsData > ,
179
+ #[ serde( skip_serializing) ]
180
+ pub padding : Vec < u8 > ,
154
181
}
155
182
156
183
#[ derive( Debug , PartialEq , Clone , Serialize , Nom ) ]
@@ -176,46 +203,25 @@ pub struct OptionsData {
176
203
}
177
204
178
205
#[ derive( Debug , Default , PartialEq , Eq , Clone , Serialize , Nom ) ]
179
- #[ nom( ExtraArgs ( set_length: u16 ) ) ]
180
206
pub struct OptionsTemplate {
181
207
pub template_id : u16 ,
182
208
pub field_count : u16 ,
183
209
pub scope_field_count : u16 ,
184
210
#[ nom(
185
211
PreExec = "let combined_count = usize::from(scope_field_count.saturating_add(
186
212
field_count.checked_sub(scope_field_count).unwrap_or(field_count)));" ,
187
- Parse = "count(TemplateField::parse, combined_count)" ,
188
- PostExec = "let options_remaining
189
- = set_length.checked_sub(field_count.saturating_mul(4)).unwrap_or(set_length) > 0;"
213
+ Parse = "count(TemplateField::parse, combined_count)"
190
214
) ]
191
215
pub fields : Vec < TemplateField > ,
192
- #[ nom( Cond = "options_remaining && !i.is_empty()" ) ]
193
- #[ serde( skip_serializing) ]
194
- padding : Option < u16 > ,
195
216
}
196
217
197
218
#[ derive( Debug , PartialEq , Eq , Clone , Serialize , Nom , Default ) ]
198
219
pub struct Template {
199
220
pub template_id : u16 ,
200
221
pub field_count : u16 ,
201
- #[ nom( Parse = "{ |i| parse_template_fields(i, field_count) } " ) ]
202
222
pub fields : Vec < TemplateField > ,
203
223
}
204
224
205
- fn parse_template_fields ( i : & [ u8 ] , count : u16 ) -> IResult < & [ u8 ] , Vec < TemplateField > > {
206
- let mut result = vec ! [ ] ;
207
-
208
- let mut remaining = i;
209
-
210
- for _ in 0 ..count {
211
- let ( i, field) = TemplateField :: parse ( remaining) ?;
212
- result. push ( field) ;
213
- remaining = i;
214
- }
215
-
216
- Ok ( ( remaining, result) )
217
- }
218
-
219
225
#[ derive( Debug , PartialEq , Eq , Clone , Serialize , Nom ) ]
220
226
pub struct TemplateField {
221
227
pub field_type_number : u16 ,
@@ -252,40 +258,6 @@ impl CommonTemplate for OptionsTemplate {
252
258
}
253
259
}
254
260
255
- // Custom parse set function to take only length provided by header.
256
- fn parse_sets < ' a > (
257
- i : & ' a [ u8 ] ,
258
- parser : & mut IPFixParser ,
259
- length : u16 ,
260
- ) -> IResult < & ' a [ u8 ] , Vec < FlowSet > > {
261
- let length = length. checked_sub ( 16 ) . unwrap_or ( length) ;
262
- let ( _, taken) = take ( length) ( i) ?;
263
- let mut sets = vec ! [ ] ;
264
- let mut remaining = taken;
265
-
266
- while !remaining. is_empty ( ) {
267
- let ( i, set) = FlowSet :: parse ( remaining, parser) ?;
268
- sets. push ( set) ;
269
- remaining = i;
270
- }
271
-
272
- Ok ( ( remaining, sets) )
273
- }
274
-
275
- // Custom parse set body function to take only length provided by set header.
276
- fn parse_set_body < ' a > (
277
- i : & ' a [ u8 ] ,
278
- parser : & mut IPFixParser ,
279
- length : u16 ,
280
- id : u16 ,
281
- ) -> IResult < & ' a [ u8 ] , FlowSetBody > {
282
- // length - 4 to account for the set header
283
- let length = length. checked_sub ( 4 ) . unwrap_or ( length) ;
284
- let ( remaining, taken) = take ( length) ( i) ?;
285
- let ( _, set_body) = FlowSetBody :: parse ( taken, parser, id, length) ?;
286
- Ok ( ( remaining, set_body) )
287
- }
288
-
289
261
/// Takes a byte stream and a cached template.
290
262
/// Fields get matched to static types.
291
263
/// Returns BTree of IPFix Types & Fields or IResult Error.
@@ -297,38 +269,38 @@ fn parse_fields<T: CommonTemplate + std::fmt::Debug>(
297
269
return Err ( NomErr :: Error ( NomError :: new ( i, ErrorKind :: Fail ) ) ) ;
298
270
}
299
271
272
+ let mut total_taken = 0 ;
273
+
300
274
// If no fields there are no fields to parse, return an error.
301
275
let mut fields = vec ! [ ] ;
302
276
let mut remaining = i;
303
277
for ( c, field) in template. get_fields ( ) . iter ( ) . enumerate ( ) {
304
278
// Iter through template fields and push them to a vec. If we encouter any zero length fields we return an error.
305
279
let mut data_field = BTreeMap :: new ( ) ;
306
280
let ( i, field_value) = parse_field ( remaining, field) ?;
281
+ let taken = remaining. len ( ) . saturating_sub ( i. len ( ) ) ;
282
+ total_taken += taken;
307
283
remaining = i;
308
284
data_field. insert ( c, ( field. field_type , field_value) ) ;
309
285
fields. push ( data_field) ;
310
286
}
311
287
312
- if !remaining. is_empty ( )
313
- && i. len ( )
314
- >= template
315
- . get_fields ( )
316
- . iter ( )
317
- . map ( |m| m. field_length as usize )
318
- . sum :: < usize > ( )
319
- {
320
- let ( _, more) = parse_fields ( remaining, template) ?;
288
+ let remaining = if !remaining. is_empty ( ) && remaining. len ( ) >= total_taken {
289
+ let ( remaining, more) = parse_fields ( remaining, template) ?;
321
290
fields. extend ( more) ;
322
- }
291
+ remaining
292
+ } else {
293
+ remaining
294
+ } ;
323
295
324
- Ok ( ( & [ ] , fields) )
296
+ Ok ( ( remaining , fields) )
325
297
}
326
298
327
299
// If 65335, read 1 byte.
328
300
// If that byte is < 255 that is the length.
329
301
// If that byte is == 255 then read 2 bytes. That is the length.
330
302
// Otherwise, return the field length.
331
- fn calculate_variable_field_length < ' a > (
303
+ fn calculate_field_length < ' a > (
332
304
i : & ' a [ u8 ] ,
333
305
template_field : & TemplateField ,
334
306
) -> IResult < & ' a [ u8 ] , u16 > {
@@ -349,7 +321,7 @@ fn parse_field<'a>(
349
321
i : & ' a [ u8 ] ,
350
322
template_field : & TemplateField ,
351
323
) -> IResult < & ' a [ u8 ] , FieldValue > {
352
- let ( i, length) = calculate_variable_field_length ( i, template_field) ?;
324
+ let ( i, length) = calculate_field_length ( i, template_field) ?;
353
325
if template_field. enterprise_number . is_some ( ) {
354
326
let ( i, data) = take ( length) ( i) ?;
355
327
Ok ( ( i, FieldValue :: Vec ( data. to_vec ( ) ) ) )
@@ -401,9 +373,6 @@ impl IPFix {
401
373
result_flowset. extend_from_slice ( & enterprise. to_be_bytes ( ) ) ;
402
374
}
403
375
}
404
- if let Some ( padding) = & options_template. padding {
405
- result_flowset. extend_from_slice ( & padding. to_be_bytes ( ) ) ;
406
- }
407
376
}
408
377
409
378
if let Some ( data) = & flow. body . data {
@@ -412,6 +381,8 @@ impl IPFix {
412
381
result_flowset. extend_from_slice ( & v. to_be_bytes ( ) ) ;
413
382
}
414
383
}
384
+
385
+ result_flowset. extend_from_slice ( & flow. body . padding ) ;
415
386
}
416
387
417
388
if let Some ( data) = & flow. body . options_data {
0 commit comments