The trunk can use the main server again (for the time being).
[switzerland.git] / switzerland / common / local_ip.py
blob41818364839df9db396dfec95e57bf4b0580c3bd
1 from subprocess import *
2 import socket
3 import sys
4 import platform
5 if platform.system() == 'Windows':
6 import _winreg as winreg
8 def get_interface():
9 os_type = platform.system()
10 if os_type == "Linux":
11 interface = get_linux_interface()
12 elif os_type == 'Darwin':
13 interface = get_darwin_interface()
14 elif os_type == 'Windows':
15 interface = get_windows_interface()
16 elif os_type[-3:] == "BSD":
17 interface = get_bsd_interface()
18 else:
19 raise OSError, "Don't know how to identify the network interface used to reach the Internet. Try specifying one with -i <interface>"
20 if not interface:
21 print 'sorry, couldn''t detect your network interface (is it up?)\n'
22 print 'please use -i to specify an interface\n'
23 sys.exit(1)
24 return interface
27 def get_local_ip(interface=None):
28 """
29 Figure out the local IP address, by hook or by crook. Optional
30 command line hints about the local IP should be passed in here; sometimes
31 we might need them.
32 """
34 os_type = platform.system()
35 if os_type == "Linux":
36 if not interface: interface = get_linux_interface()
37 if interface != None:
38 ip=get_linux_local_ip(interface)
39 return ip
40 elif os_type == 'Darwin':
41 if not interface: interface = get_darwin_interface()
42 interface = get_darwin_interface()
43 if interface != None:
44 ip=get_darwin_local_ip(interface)
45 return ip
46 elif os_type == 'Windows':
47 return get_windows_local_ip()
48 elif os_type[-3:] == "BSD":
49 if not interface: interface = get_bsd_interface()
50 if interface != None:
51 ip=get_darwin_local_ip(interface)
52 return ip
53 else:
54 print "Alice cannot id your local IP address. Check that you have \
55 network access; if you do, try adding your LAN IP manually with -l"
56 sys.exit(0)
58 print "Alice could not id your network interface. Check that you have \
59 network access; if you do, try adding the local interface manually with -i"
60 sys.exit(0)
63 # XXX Audit for local privilege escalation here
65 def get_linux_interface():
66 "Guess which interface we are using, on linux"
68 cmd = Popen(["/sbin/route", "-n"], stdout=PIPE, stderr=PIPE)
69 ret = cmd.wait()
71 if ret != 0:
72 cmd = Popen(["route", "-n"], stdout=PIPE, stderr=PIPE)
73 ret = cmd.wait()
75 if ret !=0:
76 return -1
78 for line in cmd.stdout.readlines():
79 words = line.split()
80 try:
81 # This is the default route
82 if words[0] == "0.0.0.0":
83 return words[-1]
84 except IndexError:
85 pass
87 return None
89 def get_darwin_interface():
90 "Guess which interface we are using, on darwin"
92 cmd = Popen(["/sbin/route", "-n", "get", "default"], stdout=PIPE, stderr=PIPE)
93 ret = cmd.wait()
95 if ret != 0:
96 cmd = Popen(["route", "-n", "get", "default"], stdout=PIPE, stderr=PIPE)
97 ret = cmd.wait()
99 if ret !=0:
100 return -1
102 for line in cmd.stdout.readlines():
103 words = line.split()
104 try:
105 # This is the default route
106 if words[0] == "interface:":
107 return words[-1]
108 except IndexError:
109 pass
111 return None
113 def get_windows_connection_names():
114 """ return a map from pretty connection name -> interface device guid """
115 magic = 'SYSTEM\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}'
116 k = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, magic)
117 (nsk, blah, blah) = winreg.QueryInfoKey(k)
118 connections = {}
119 for i in xrange(0,nsk):
120 dev = winreg.EnumKey(k,i)
121 if len(dev) == 38 and dev[0]=='{': # guid
122 try:
123 sk = winreg.OpenKey(k, dev+'\Connection')
124 name = winreg.QueryValueEx(sk, 'Name')
125 connections[name[0]] = dev
126 except:
127 pass
129 return connections
131 def get_windows_interface():
132 """ get device name of default interface """
133 # 1. get ip address of default route
134 ip = get_windows_local_ip()
135 if ip == -1:
136 return None
138 # 2. get network device keys from registry
139 devices = get_windows_connection_names().values()
141 # 3. scan registry to figure out which has ip
142 for dev in devices:
143 try:
144 kn = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\"+dev
145 k = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, kn)
146 enable_dhcp = winreg.QueryValueEx(k, 'EnableDHCP')[0]
147 if enable_dhcp:
148 dhcp_ip = winreg.QueryValueEx(k, 'DhcpIPAddress')[0]
149 if dhcp_ip == ip:
150 return "\\Device\\NPF_"+dev
151 else:
152 static_ip = winreg.QueryValueEx(k, 'IPAddress')[0][0]
153 if static_ip == ip:
154 return "\\Device\\NPF_"+dev
155 except:
156 pass
158 return None
160 def get_darwin_local_ip(interface):
161 cmd = Popen(["/sbin/ifconfig", interface], stdout=PIPE, stderr=PIPE)
162 ret = cmd.wait()
163 if ret !=0:
164 print cmd.stderr.read()
165 return -1
166 words = cmd.stdout.read().split()
167 num_words = len(words)
168 for i in range(num_words):
169 if words[i] == "inet" and i+1 < num_words:
170 return words[i+1]
171 return -1
173 # what do you know, Darwin gets its code from BSD :)
175 get_bsd_interface = get_darwin_interface
176 get_bsd_local_ip = get_darwin_local_ip
178 def get_linux_local_ip(interface):
179 cmd = Popen(["/sbin/ifconfig", interface], stdout=PIPE, stderr=PIPE)
180 ret = cmd.wait()
181 if ret !=0:
182 print cmd.stderr.read()
183 return -1
184 words = cmd.stdout.read().split()
185 for word in words:
186 if word[:5] == "addr:":
187 return word[5:]
189 def get_windows_local_ip():
190 cmd = Popen(['route', 'print', '0.0.0.0'], stdout=PIPE, stderr=PIPE)
191 ret = cmd.wait()
192 if ret != 0:
193 print cmd.stderr.read()
194 return -1
195 lines = cmd.stdout.read().split("\r\n")
196 found_header = False
197 for line in lines:
198 try:
199 words = line.split()
200 if len(words) > 3 and words[0] == '0.0.0.0':
201 return words[3]
202 except:
203 pass
205 return -1
207 if __name__ == "__main__":
208 print "Local IP is", get_local_ip()