08285466c69bf1740fb6268d53375cbfcfaffa36
[bwmon.git] / bwmon / proc.py
blob08285466c69bf1740fb6268d53375cbfcfaffa36
1 # -*- coding: utf-8 -*-
3 from __future__ import absolute_import
5 import os
6 import re
7 import hashlib
9 def get_connections(conn_type='tcp'):
10 """Get connections from /proc/net/
12 Read the currently-running connections from the
13 /proc/ filesystem.
15 @param conn_type: The connection type ('tcp' or 'udp')
16 """
17 f = open('/proc/net/%s' % conn_type, 'r')
18 connections = {}
20 #documentation for /proc/net/tcp in
21 #http://lkml.indiana.edu/hypermail/linux/kernel/0409.1/2166.html
23 for line in f.readlines():
24 line = line.strip()
26 # header line
27 if line.startswith('s'):
28 continue
30 parts = filter(lambda x: x, line.split(' '))
31 index = parts[0].strip()[:-1]
32 local_addr = ip_repr(parts[1])
33 rem_addr = ip_repr(parts[2])
34 inode = int(parts[9])
36 connections[index] = {
37 'local': local_addr,
38 'remote': rem_addr,
39 'inode': inode
42 return connections
45 def ip_repr(ip):
46 """Get the dotted-decimal representation of an IP
48 @param ip: The IP as formatted in /proc/net/tcp
49 @return: the dotted-decimal representation of an IP
51 >>> ip_repr('C8BCED82:1A0B')
52 '130.237.188.200:6667'
53 """
55 if ':' in ip:
56 ip, port = ip.split(':')
57 else:
58 port = None
60 s = '.'.join([ repr(int(ip[x-2:x], 16)) for x in range(8, 0, -2) ])
61 if port:
62 s += ':%d' % int(port, 16)
64 return s
67 def get_fd_map():
68 """Get a filedescriptor-to-process mapping
70 @return: A dictionary mapping file descriptors to process infos
71 """
73 proc = '/proc/'
74 fd = 'fd'
75 pid_dir = r'\d+'
76 socket_regex = r'socket:\[(\d+)\]'
77 cmdline = 'cmdline'
78 m = {}
80 for pid in os.listdir(proc):
82 # process directories
83 d = os.path.join(proc, pid)
84 if not os.path.isdir(d):
85 continue
87 if not re.match(pid_dir, pid):
88 continue
90 fd_dir = os.path.join(d, fd)
91 for x in os.listdir(fd_dir):
92 path = os.path.join(fd_dir, x)
93 try:
94 f_desc = os.readlink(path)
95 except OSError:
96 continue
98 # search for socket file-descriptors
99 match = re.match(socket_regex, f_desc)
100 if match:
101 inode = int(match.group(1))
102 else:
103 continue
105 cmd_file = open(os.path.join(d, cmdline), 'rb')
106 cmd = cmd_file.read()
108 # Command line arguments are splitted by '\0'
109 cmd = cmd.replace('\0', ' ')
111 m[inode] = {'inode': inode, 'cmd': cmd, 'pid': int(pid)}
113 return m
116 def parse_ip_conntrack():
117 """Get a parsed representation of /proc/net/ip_conntrack
119 @return: A dictionary of connections
121 connections = {}
123 # http://www.faqs.org/docs/iptables/theconntrackentries.html
124 for line in open('/proc/net/ip_conntrack'):
125 parts = line.split()
127 # We only care about TCP and UDP connections
128 if parts[0] not in ('udp', 'tcp'):
129 continue
131 entry = {}
132 for (k, v) in [x.split('=', 1) for x in parts if '=' in x]:
133 # key-value pairs occur twice per line; if first key occurs
134 # again, we finish the first entry and start the next one
135 if k in entry:
136 key = get_key(entry)
137 connections[key] = entry
138 entry = {}
140 entry[k] = v
142 key = get_key(entry)
143 connections[key] = entry
145 return connections
148 def get_key(values):
149 """Build a hashed key out of a ip_conntrack connection
151 This takes the source IP, source port and destination
152 IP and destination port and returns a unique key.
154 @param values: An entry from the ip_conntrack table
155 @return: The hashed key for this connection pair
157 src = '%s:%s' % (values['src'], values['sport'])
158 dst = '%s:%s' % (values['dst'], values['dport'])
159 return ip_hash(src, dst)
162 def ip_hash(src_ip, dest_ip):
163 """Hash an IP pair
165 @param src_ip: The IP address of the source
166 @param dest_ip: The IP address of the destination
167 @return: A string that combines both parameters
169 return '%s-%s' % (src_ip, dest_ip)