77 "io"
88 "io/ioutil"
99 "path/filepath"
10+ "regexp"
1011 "strconv"
1112 "sync"
1213 "time"
@@ -251,12 +252,7 @@ func removeInplace(s, sep []byte) []byte {
251252}
252253
253254func decodeStreamedFlow (scanner * bufio.Scanner ) (flow , error ) {
254- var (
255- // Use ints for parsing unused fields since their allocations
256- // are almost for free
257- unused [2 ]int
258- f flow
259- )
255+ var f flow
260256
261257 // Examples:
262258 // " [UPDATE] udp 17 29 src=192.168.2.100 dst=192.168.2.1 sport=57767 dport=53 src=192.168.2.1 dst=192.168.2.100 sport=53 dport=57767"
@@ -271,44 +267,82 @@ func decodeStreamedFlow(scanner *bufio.Scanner) (flow, error) {
271267 }
272268
273269 line = bytes .TrimLeft (line , " " )
270+ var regExpBegin string
271+ var regExpEnd string = `src=([^\s]+).*\sdst=([^\s]+).*\ssport=([^\s]+).*\sdport=([^\s]+).*\ssrc=([^\s]+).*\sdst=([^\s]+).*\ssport=([^\s]+).*\sdport=([^\s]+).*\sid=([^\s]+)`
272+
273+ // Destroy events don't have a timeout or state field
274274 if bytes .HasPrefix (line , destroyTypeB ) {
275- // Destroy events don't have a timeout or state field
276- _ , err = fmt .Sscanf (string (line ), "%s %s %d src=%s dst=%s sport=%d dport=%d src=%s dst=%s sport=%d dport=%d id=%d" ,
277- & f .Type ,
278- & f .Original .Layer4 .Proto ,
279- & unused [0 ],
280- & f .Original .Layer3 .SrcIP ,
281- & f .Original .Layer3 .DstIP ,
282- & f .Original .Layer4 .SrcPort ,
283- & f .Original .Layer4 .DstPort ,
284- & f .Reply .Layer3 .SrcIP ,
285- & f .Reply .Layer3 .DstIP ,
286- & f .Reply .Layer4 .SrcPort ,
287- & f .Reply .Layer4 .DstPort ,
288- & f .Independent .ID ,
289- )
275+ regExpBegin = `(\[[[:alpha:]]*\])\s+([[:alpha:]]*)\s+\d+\s+`
276+ var lineMatch = regexp .MustCompile (regExpBegin + regExpEnd )
277+ matches := lineMatch .FindSubmatch (line )
278+ if len (matches ) != 12 {
279+ return flow {}, fmt .Errorf ("Error parsing streamed flow %q: matches count: %v " , line , len (matches ))
280+ }
281+
282+ f .Type = string (matches [1 ])
283+ f .Original .Layer4 .Proto = string (matches [2 ])
284+ f .Original .Layer3 .SrcIP = string (matches [3 ])
285+ f .Original .Layer3 .DstIP = string (matches [4 ])
286+ f .Original .Layer4 .SrcPort , err = strconv .Atoi (string (matches [5 ]))
287+ if err != nil {
288+ return flow {}, fmt .Errorf ("Error parsing streamed flow %q: %v " , line , err )
289+ }
290+ f .Original .Layer4 .DstPort , err = strconv .Atoi (string (matches [6 ]))
291+ if err != nil {
292+ return flow {}, fmt .Errorf ("Error parsing streamed flow %q: %v " , line , err )
293+ }
294+ f .Reply .Layer3 .SrcIP = string (matches [7 ])
295+ f .Reply .Layer3 .DstIP = string (matches [8 ])
296+ f .Reply .Layer4 .SrcPort , err = strconv .Atoi (string (matches [9 ]))
297+ if err != nil {
298+ return flow {}, fmt .Errorf ("Error parsing streamed flow %q: %v " , line , err )
299+ }
300+ f .Reply .Layer4 .DstPort , err = strconv .Atoi (string (matches [10 ]))
301+ if err != nil {
302+ return flow {}, fmt .Errorf ("Error parsing streamed flow %q: %v " , line , err )
303+ }
304+ f .Independent .ID , err = strconv .ParseInt (string (matches [11 ]), 10 , 64 )
305+ if err != nil {
306+ return flow {}, fmt .Errorf ("Error parsing streamed flow %q: %v " , line , err )
307+ }
308+
290309 } else {
291- _ , err = fmt .Sscanf (string (line ), "%s %s %d %d %s src=%s dst=%s sport=%d dport=%d src=%s dst=%s sport=%d dport=%d id=%d" ,
292- & f .Type ,
293- & f .Original .Layer4 .Proto ,
294- & unused [0 ],
295- & unused [1 ],
296- & f .Independent .State ,
297- & f .Original .Layer3 .SrcIP ,
298- & f .Original .Layer3 .DstIP ,
299- & f .Original .Layer4 .SrcPort ,
300- & f .Original .Layer4 .DstPort ,
301- & f .Reply .Layer3 .SrcIP ,
302- & f .Reply .Layer3 .DstIP ,
303- & f .Reply .Layer4 .SrcPort ,
304- & f .Reply .Layer4 .DstPort ,
305- & f .Independent .ID ,
306- )
307- }
310+ regExpBegin = `(\[[[:alpha:]]*\])\s+([[:alpha:]]*)\s+\d+\s+\d+\s+([[:alpha:]_]*)\s+`
311+ var lineMatch = regexp .MustCompile (regExpBegin + regExpEnd )
312+ matches := lineMatch .FindSubmatch (line )
313+ if len (matches ) != 13 {
314+ return flow {}, fmt .Errorf ("Error parsing streamed flow %q: matches count: %v " , line , len (matches ))
315+ }
308316
309- if err != nil {
310- return flow {}, fmt .Errorf ("Error parsing streamed flow %q: %v " , line , err )
317+ f .Type = string (matches [1 ])
318+ f .Original .Layer4 .Proto = string (matches [2 ])
319+ f .Independent .State = string (matches [3 ])
320+ f .Original .Layer3 .SrcIP = string (matches [4 ])
321+ f .Original .Layer3 .DstIP = string (matches [5 ])
322+ f .Original .Layer4 .SrcPort , err = strconv .Atoi (string (matches [6 ]))
323+ if err != nil {
324+ return flow {}, fmt .Errorf ("Error parsing streamed flow %q: %v " , line , err )
325+ }
326+ f .Original .Layer4 .DstPort , err = strconv .Atoi (string (matches [7 ]))
327+ if err != nil {
328+ return flow {}, fmt .Errorf ("Error parsing streamed flow %q: %v " , line , err )
329+ }
330+ f .Reply .Layer3 .SrcIP = string (matches [8 ])
331+ f .Reply .Layer3 .DstIP = string (matches [9 ])
332+ f .Reply .Layer4 .SrcPort , err = strconv .Atoi (string (matches [10 ]))
333+ if err != nil {
334+ return flow {}, fmt .Errorf ("Error parsing streamed flow %q: %v " , line , err )
335+ }
336+ f .Reply .Layer4 .DstPort , err = strconv .Atoi (string (matches [11 ]))
337+ if err != nil {
338+ return flow {}, fmt .Errorf ("Error parsing streamed flow %q: %v " , line , err )
339+ }
340+ f .Independent .ID , err = strconv .ParseInt (string (matches [12 ]), 10 , 64 )
341+ if err != nil {
342+ return flow {}, fmt .Errorf ("Error parsing streamed flow %q: %v " , line , err )
343+ }
311344 }
345+
312346 f .Reply .Layer4 .Proto = f .Original .Layer4 .Proto
313347 return f , nil
314348}
@@ -346,12 +380,7 @@ func (c *conntrackWalker) existingConnections() ([]flow, error) {
346380}
347381
348382func decodeDumpedFlow (scanner * bufio.Scanner ) (flow , error ) {
349- var (
350- // Use ints for parsing unused fields since allocations
351- // are almost for free
352- unused [4 ]int
353- f flow
354- )
383+ var f flow
355384
356385 // Example:
357386 // " tcp 6 431997 ESTABLISHED src=10.32.0.1 dst=10.32.0.1 sport=50274 dport=4040 src=10.32.0.1 dst=10.32.0.1 sport=4040 dport=50274 [ASSURED] mark=0 use=1 id=407401088c"
@@ -361,24 +390,37 @@ func decodeDumpedFlow(scanner *bufio.Scanner) (flow, error) {
361390 return flow {}, err
362391 }
363392
364- _ , err = fmt .Sscanf (string (line ), "%s %d %d %s src=%s dst=%s sport=%d dport=%d src=%s dst=%s sport=%d dport=%d mark=%d use=%d id=%d" ,
365- & f .Original .Layer4 .Proto ,
366- & unused [0 ],
367- & unused [1 ],
368- & f .Independent .State ,
369- & f .Original .Layer3 .SrcIP ,
370- & f .Original .Layer3 .DstIP ,
371- & f .Original .Layer4 .SrcPort ,
372- & f .Original .Layer4 .DstPort ,
373- & f .Reply .Layer3 .SrcIP ,
374- & f .Reply .Layer3 .DstIP ,
375- & f .Reply .Layer4 .SrcPort ,
376- & f .Reply .Layer4 .DstPort ,
377- & unused [2 ],
378- & unused [3 ],
379- & f .Independent .ID ,
380- )
393+ var regExpEnd string = `src=([^\s]+).*\sdst=([^\s]+).*\ssport=([^\s]+).*\sdport=([^\s]+).*\ssrc=([^\s]+).*\sdst=([^\s]+).*\ssport=([^\s]+).*\sdport=([^\s]+).*\sid=([^\s]+)`
394+ var regExpBegin string = `([[:alpha:]]*)\s+\d+\s+\d+\s+([[:alpha:]_]*)\s+`
395+ var lineMatch = regexp .MustCompile (regExpBegin + regExpEnd )
396+ matches := lineMatch .FindSubmatch (line )
397+ if len (matches ) != 12 {
398+ return flow {}, fmt .Errorf ("Error parsing dumped flow %q: matches count: %v " , line , len (matches ))
399+ }
381400
401+ f .Original .Layer4 .Proto = string (matches [1 ])
402+ f .Independent .State = string (matches [2 ])
403+ f .Original .Layer3 .SrcIP = string (matches [3 ])
404+ f .Original .Layer3 .DstIP = string (matches [4 ])
405+ f .Original .Layer4 .SrcPort , err = strconv .Atoi (string (matches [5 ]))
406+ if err != nil {
407+ return flow {}, fmt .Errorf ("Error parsing dumped flow %q: %v " , line , err )
408+ }
409+ f .Original .Layer4 .DstPort , err = strconv .Atoi (string (matches [6 ]))
410+ if err != nil {
411+ return flow {}, fmt .Errorf ("Error parsing dumped flow %q: %v " , line , err )
412+ }
413+ f .Reply .Layer3 .SrcIP = string (matches [7 ])
414+ f .Reply .Layer3 .DstIP = string (matches [8 ])
415+ f .Reply .Layer4 .SrcPort , err = strconv .Atoi (string (matches [9 ]))
416+ if err != nil {
417+ return flow {}, fmt .Errorf ("Error parsing dumped flow %q: %v " , line , err )
418+ }
419+ f .Reply .Layer4 .DstPort , err = strconv .Atoi (string (matches [10 ]))
420+ if err != nil {
421+ return flow {}, fmt .Errorf ("Error parsing dumped flow %q: %v " , line , err )
422+ }
423+ f .Independent .ID , err = strconv .ParseInt (string (matches [11 ]), 10 , 64 )
382424 if err != nil {
383425 return flow {}, fmt .Errorf ("Error parsing dumped flow %q: %v " , line , err )
384426 }
0 commit comments