fix matching between src/dest and local/remote addresses
[bwmon.git] / bwmon / proc.py
blob218d4e671818ca8c11ef3d65e29b1e93a4df5571
1 import os
2 import re
3 import hashlib
5 def get_connections(conn_type='tcp'):
6 """
7 returns the connections from /proc/net/tcp indexed by their id (first
8 column).
9 """
10 f = open('/proc/net/%s' % conn_type, 'r')
11 connections = {}
13 #documentation for /proc/net/tcp in
14 #http://lkml.indiana.edu/hypermail/linux/kernel/0409.1/2166.html
16 for line in f.readlines():
17 line = line.strip()
19 # header line
20 if line.startswith('s'):
21 continue
23 parts = filter(lambda x: x, line.split(' '))
24 index = parts[0].strip()[:-1]
25 local_addr = ip_repr(parts[1])
26 rem_addr = ip_repr(parts[2])
27 inode = int(parts[9])
29 connections[index] = {
30 'local': local_addr,
31 'remote': rem_addr,
32 'inode': inode
35 return connections
38 def ip_repr(ip):
39 """
40 returns the dotted-decimal representation of an IP addresse when given
41 the formated used in /proc/net/tcp
43 >>> ip_repr('C8BCED82:1A0B')
44 '130.237.188.200:6667'
45 """
47 if ':' in ip:
48 ip, port = ip.split(':')
49 else:
50 port = None
52 s = '.'.join([ repr(int(ip[x-2:x], 16)) for x in range(8, 0, -2) ])
53 if port:
54 s += ':%d' % int(port, 16)
56 return s
59 def get_fd_map():
60 """ returns a dictionary mapping filedescriptors to process information"""
62 proc = '/proc/'
63 fd = 'fd'
64 pid_dir = r'\d+'
65 socket_regex = r'socket:\[(\d+)\]'
66 cmdline = 'cmdline'
67 m = {}
69 for pid in os.listdir(proc):
71 # process directories
72 d = os.path.join(proc, pid)
73 if not os.path.isdir(d):
74 continue
76 if not re.match(pid_dir, pid):
77 continue
79 fd_dir = os.path.join(d, fd)
80 for x in os.listdir(fd_dir):
81 path = os.path.join(fd_dir, x)
82 try:
83 f_desc = os.readlink(path)
84 except OSError:
85 continue
87 # search for socket file-descriptors
88 match = re.match(socket_regex, f_desc)
89 if match:
90 inode = int(match.group(1))
91 else:
92 continue
94 cmd_file = open(os.path.join(d, cmdline), 'r')
95 cmd = cmd_file.read()
97 m[inode] = {'inode': inode, 'cmd': cmd, 'pid': int(pid)}
99 return m
102 def parse_ip_conntrack():
104 connections = {}
106 f = open('/proc/net/ip_conntrack', 'r')
107 for line in f.readlines():
109 values = {}
111 parts = filter(lambda x: x, line.split(' '))
112 for p in parts:
113 if not '=' in p:
114 continue
115 key, value = p.split('=')
117 # lines often contain src and dest reversed (for returning traffic)
118 # we are just interested in one-way traffic
119 if key in values:
120 continue
122 values[key] = value
124 src = '%s:%s' % (values['src'], values['sport'])
125 dst = '%s:%s' % (values['dst'], values['dport'])
126 key = ip_hash(src, dst)
127 connections[key] = values
129 return connections
131 def ip_hash(src_ip, dest_ip):
132 return '%s-%s' % (src_ip, dest_ip)