1313from xml .etree import ElementTree
1414from xml .etree .ElementTree import Element
1515
16- def __parse_meta_connection_tag (meta : Element ) -> dict :
17- """
18- From a meta tag, extract the connection information.
19-
20- Args:
21- - meta: ElementTree.Element with the meta tag.
22-
23- Returns:
24- dictionary with the connection information.
25- """
26- result = {'src' : '' , 'dest' : '' , 'protocol' : '' , 'packets' : '0' , 'bytes' : '0' }
27- layer3 = meta .find ('layer3' )
28- result ['src' ] = layer3 .find ('src' ).text
29- result ['dest' ] = layer3 .find ('dst' ).text
30- layer4 = meta .find ('layer4' )
31- result ['protocol' ] = layer4 .get ('protoname' )
32- # start port and end port might not be present for some protocols, like ICMP.
33- if layer4 .find ('sport' ) is not None :
34- result ['start_port' ] = layer4 .find ('sport' ).text
35- if layer4 .find ('dport' ) is not None :
36- result ['end_port' ] = layer4 .find ('dport' ).text
37- counters = meta .find ('counters' )
38- if counters is not None :
39- result ['packets' ] = counters .find ('packets' ).text
40- result ['bytes' ] = counters .find ('bytes' ).text
41- return result
42-
4316
4417def __parse_connection_info (flow : Element ) -> dict :
4518 """
@@ -54,35 +27,40 @@ def __parse_connection_info(flow: Element) -> dict:
5427 result = {}
5528 # expand meta tags
5629 for child in flow .findall ('meta' ):
57- # parse the meta tag using __parse_meta_connection_tag function
58- if child .get ('direction' ) == 'original' or child .get ('direction' ) == 'reply' :
59- connection_info = __parse_meta_connection_tag (child )
60- if child .get ('direction' ) == 'original' :
61- result ['source' ] = connection_info ['src' ]
62- result ['destination' ] = connection_info ['dest' ]
63- result ['protocol' ] = connection_info ['protocol' ]
64- if 'start_port' in connection_info :
65- result ['source_port' ] = connection_info ['start_port' ]
66- if 'end_port' in connection_info :
67- result ['destination_port' ] = connection_info ['end_port' ]
30+ if child .get ('direction' ) == 'original' :
31+ layer3 = child .find ('layer3' )
32+ result ['source' ] = layer3 .find ('src' ).text
33+ result ['destination' ] = layer3 .find ('dst' ).text
34+ layer4 = child .find ('layer4' )
35+ result ['protocol' ] = layer4 .get ('protoname' )
36+ if layer4 .find ('sport' ) is not None :
37+ result ['source_port' ] = layer4 .find ('sport' ).text
38+ if layer4 .find ('dport' ) is not None :
39+ result ['destination_port' ] = layer4 .find ('dport' ).text
40+ counters = child .find ('counters' )
41+ if counters is not None :
6842 result ['source_stats' ] = {
69- 'packets' : connection_info [ 'packets' ] ,
70- 'bytes' : connection_info [ 'bytes' ]
43+ 'packets' : int ( counters . find ( 'packets' ). text ) ,
44+ 'bytes' : int ( counters . find ( 'bytes' ). text )
7145 }
72- else :
46+ if child .get ('direction' ) == 'reply' :
47+ counters = child .find ('counters' )
48+ if counters is not None :
7349 result ['destination_stats' ] = {
74- 'packets' : connection_info [ 'packets' ] ,
75- 'bytes' : connection_info [ 'bytes' ]
50+ 'packets' : int ( counters . find ( 'packets' ). text ) ,
51+ 'bytes' : int ( counters . find ( 'bytes' ). text )
7652 }
77- # not easily parsable, just add the values
78- else :
53+ if child .get ('direction' ) == 'independent' :
7954 result ['id' ] = child .find ('id' ).text
8055 if child .find ('timeout' ) is not None :
8156 result ['timeout' ] = child .find ('timeout' ).text
8257 if child .find ('unreplied' ) is not None :
8358 result ['unreplied' ] = True
8459 if child .find ('state' ) is not None :
8560 result ['state' ] = child .find ('state' ).text
61+ result ['labels' ] = []
62+ for label in child .findall ('labels/label' ):
63+ result ['labels' ].append (label .text )
8664
8765 return result
8866
@@ -94,13 +72,10 @@ def list_connections():
9472 Returns:
9573 dict of applications and their connections.
9674 """
97- result = subprocess .run (["conntrack" , "-L" , "-o" , "xml" ], capture_output = True , text = True )
75+ result = subprocess .run (["conntrack" , "-L" , "-o" , "labels, xml" ], capture_output = True , text = True )
9876 root = ElementTree .fromstring (result .stdout )
9977 result = []
10078 for flow in root .findall ('flow' ):
101- # download
102- # upload
103- # wan
10479 result .append (__parse_connection_info (flow ))
10580
10681 return result
0 commit comments