Added a proxy launcher script.
[cnetworkmanager.git] / cnetworkmanager
blobbe26c4b5a953678cd3d4eb6c7e05c41de631708d
1 #! /usr/bin/python
2 # cnetworkmanager: Command Line Interface for NetworkManager
3 # by: http://en.opensuse.org/User:Mvidner
4 # license: http://www.gnu.org/licenses/gpl-2.0.html or later
6 VERSION = "0.8.1"
7 print "cnetworkmanager %s - Command Line Interface for NetworkManager" % VERSION
9 norpm = False
10 import sys
11 import os
12 import string
13 import re
14 import time
15 import uuid
16 import math
17 import hashlib
18 import pbkdf2
19 from binascii import hexlify
20 import ConfigParser # knm config
21 from optparse import OptionParser
22 try:
23 import dbus
24 import dbus.service
25 import _dbus_bindings
26 except:
27 print "Install python-1-dbus.rpm or or python-dbus.rpm or python-dbus.deb"
28 norpm = True
29 import xml.dom.minidom
30 try:
31 import gobject
32 except:
33 # todo - only if loop wanted
34 print "Install python-gobject2.rpm or pygobject2.rpm or python-gobject.deb"
35 norpm = True
36 # python-gnome.rpm has gconf for nm-applet...
37 if norpm:
38 sys.exit(1)
40 from dbus.mainloop.glib import DBusGMainLoop
41 DBusGMainLoop(set_as_default=True)
43 LOOP = False
45 bus = dbus.SystemBus()
47 # FOOC = connection (service) string
48 # FOOI = interface string
49 # fooo = object
50 # fooi = interface
51 # foopi = property interface
52 NMC = 'org.freedesktop.NetworkManager'
53 NMI = NMC
54 PI = 'org.freedesktop.DBus.Properties'
55 SSC = "org.freedesktop.NetworkManagerSystemSettings"
56 USC = "org.freedesktop.NetworkManagerUserSettings"
57 NMIC = "org.freedesktop.NetworkManagerInfo"
59 def introspect(obj):
60 ii = dbus.Interface(obj, 'org.freedesktop.DBus.Introspectable')
61 print ii.Introspect()
63 class cNM:
64 # TODO: pull them from introspection.xml
65 NM_STATE = ["UNKNOWN", "ASLEEP", "CONNECTING", "CONNECTED", "DISCONNECTED",]
67 def __init__(self, opath):
68 self.opath = opath
69 self.nmo = bus.get_object(NMC, self.opath)
70 self.nmi = dbus.Interface(self.nmo, NMI)
71 self.nmpi = dbus.Interface(self.nmo, PI)
73 def Api(self):
74 return "common"
76 def Dump0(self):
77 "Dumps its own info (not owned objects)."
78 pass
80 def Dump(self):
81 self.Dump0()
82 if options.dev:
83 for device in self.Devices():
84 device.Dump()
86 if options.actcon:
87 print "Active Connections"
88 aconns = self.ActiveConnections()
89 for aconn in aconns:
90 aconn.Dump()
92 def ListNets(self):
93 print "Wifi Networks:"
94 for dev in self.Devices():
95 dev.ListNets()
97 def reply_handler(self, opath):
98 print "Connected:", opath
100 def err_handler(self, *args):
101 print "ERR:", args
103 def silent_handler(self, *args):
104 pass
105 print "BOO!:", args
107 def quitter_handler(self, *args):
108 # exit the loop that runs only because of us
109 print "padla"
110 sys.exit(0)
113 def make_nm(opath):
114 "Detects NM version and chooses appropriate class"
116 nmo = bus.get_object(NMC, opath)
117 nmi = dbus.Interface(nmo, NMI)
118 try:
119 dummy = nmi.getDevices()
120 return cNM_06(opath)
121 except dbus.exceptions.DBusException:
122 return cNM_07(opath)
124 class cNM_06(cNM):
125 def Api(self):
126 return "06"
128 def SetWifiEnabled(self, v):
129 # TODO: async call, catch the state signal and exit
130 # weird: synchronous call works, but times out
131 # asynchronous call does not work
132 self.nmi.setWirelessEnabled(v,
133 reply_handler=self.quitter_handler,
134 error_handler=self.quitter_handler)
135 global LOOP
136 LOOP = True
138 def SetOnline(self, v):
139 if v:
140 self.nmi.wake(True,
141 reply_handler=self.quitter_handler,
142 error_handler=self.quitter_handler)
143 else:
144 self.nmi.sleep(True,
145 reply_handler=self.quitter_handler,
146 error_handler=self.quitter_handler)
147 global LOOP
148 LOOP = True
150 def Dump0(self):
151 print "State:", self.NM_STATE[self.nmi.state()]
152 we = self.nmi.getWirelessEnabled()
153 if isinstance(we, tuple):
154 print "Wifi enabled:", bool(we[0])
155 print "Wifi HW enabled:", bool(we[1])
156 else:
157 print "Wifi enabled:", bool(we)
159 try:
160 dup = self.nmi.getDialup()
161 print "Dialup:", dup
162 except dbus.exceptions.DBusException, e:
163 #if e.get_dbus_name() == "org.freedesktop.NetworkManager.NoDialup":
164 # pass
165 #else:
166 print e
168 def Devices(self):
169 opaths = self.nmi.getDevices()
170 return map(cDevice_06, opaths)
172 def ActiveConnections(self):
173 return [] # at most one active connection, FIXME find it
175 def reply_handler(self):
176 print "Connection requested"
178 def err_handler(self, *args):
179 print "ERR:", args
181 def ActivateConnection(self, conn, device, ap):
182 # passing *_handler makes the call asynchronous
183 self.nmi.setActiveDevice(device.opath, ssid_str(conn.Ssid()),
184 reply_handler=self.reply_handler,
185 error_handler=self.err_handler,
188 class cNM_07(cNM):
189 def Api(self):
190 return "07"
192 def SetWifiEnabled(self, v):
193 self.nmpi.Set(NMI, "WirelessEnabled", v)
195 def SetOnline(self, v):
196 self.nmi.Sleep(not v)
198 def Dump0(self):
199 print "State:", self.NM_STATE[self.nmpi.Get(NMI, "State")]
200 print "Wifi enabled:", self.nmpi.Get(NMI, "WirelessEnabled")
201 print "Wifi HW enabled:", self.nmpi.Get(NMI, "WirelessHardwareEnabled")
203 def Devices(self):
204 opaths = self.nmi.GetDevices()
205 return map(cDevice_07, opaths)
207 def ActiveConnections(self):
208 aconns = self.nmpi.Get(NMI, "ActiveConnections")
209 return map(cActiveConnection, aconns)
211 def ActivateConnection(self, conn, device, ap):
212 # passing *_handler makes the call asynchronous
213 self.nmi.ActivateConnection(USC,
214 conn.__dbus_object_path__,
215 device.opath,
216 ap.opath,
217 reply_handler=self.reply_handler,
218 error_handler=self.err_handler,
222 class cActiveConnection:
223 def __init__(self, opath):
224 self.opath = opath
226 def Dump(self):
227 print self.opath
228 co = bus.get_object(NMC, self.opath)
229 copi = dbus.Interface(co, PI)
230 for P in ["ServiceName", "Connection", "SpecificObject",]:
231 print " %s: %s" % (P, copi.Get(NMI, P))
232 devs = copi.Get(NMI, "Devices")
233 print " Devices:"
234 for dev in devs:
235 print " ", dev
237 def bitmask_str(map, value):
238 ret = []
239 for mask in sorted(map.keys()):
240 if value & mask: ret.append(map[mask])
241 return ",".join(ret)
244 class cDevice:
245 def __init__(self, opath):
246 self.opath = opath
247 self.devo = bus.get_object(NMC, self.opath)
248 self.devi = dbus.Interface(self.devo, NMI + ".Device")
249 self.devpi = dbus.Interface(self.devo, PI)
250 self.dt = None
251 self.DeviceType0()
253 DEVICE_TYPE = ["UNKNOWN", "802_3_ETHERNET", "802_11_WIRELESS",
254 "GSM", "CDMA",] #OLPC: 3 is MESH
256 def DeviceType(self):
257 return self.DEVICE_TYPE[self.DeviceType0()]
259 def ip_str(self, i32):
260 ret = []
261 ret.append("%d" % (i32 % 256))
262 i32 /= 256
263 ret.append("%d" % (i32 % 256))
264 i32 /= 256
265 ret.append("%d" % (i32 % 256))
266 i32 /= 256
267 ret.append("%d" % (i32 % 256))
268 i32 /= 256
269 return ".".join(ret)
271 def DumpIp4Config(self, opath):
272 print " Ip4Config:", opath
273 o = bus.get_object(NMC, opath)
274 pi = dbus.Interface(o, PI)
275 try:
276 for P in ["Address", "Netmask", "Broadcast", "Gateway",]: # beta2?
277 print " %s: %s" % (P, self.ip_str(pi.Get(NMI, P)))
278 except:
279 print " Addresses:"
280 addrs = pi.Get(NMI, "Addresses")
281 for addr in addrs:
282 print " %s/%s via %s" % tuple(map(self.ip_str, addr))
283 nss = pi.Get(NMI, "Nameservers")
284 print " Nameservers:", " ".join(map(self.ip_str, nss))
285 doms = pi.Get(NMI, "Domains")
286 print " Domains:", " ".join(doms)
288 NM_DEVICE_CAP = {1: "NM_SUPPORTED", 2: "CARRIER_DETECT", 4: "SCANNING", }
291 def Dump(self):
292 print "Device:", self.opath
295 IW_MODE = ["AUTO", "ADHOC", "INFRA", "MASTER",
296 "REPEAT", "SECOND", "MONITOR",]
298 def APs(self):
299 return []
301 def ListNets(self):
302 for ap in self.APs():
303 ap.ListNets()
305 # mixin
306 class cDeviceEth:
307 pass
309 class cDevice_06(cDevice):
310 def DeviceType0(self):
311 if self.dt is None:
312 self.dt = self.devi.getProperties()[2]
313 if self.dt == 1:
314 self.__class__ = cDeviceEth_06
315 elif self.dt == 2:
316 self.__class__ = cDeviceWifi_06
317 return self.dt
319 NM_ACT_STAGE = [
320 "UNKNOWN", "DEVICE_PREPARE", "DEVICE_CONFIG", "NEED_USER_KEY",
321 "IP_CONFIG_START", "IP_CONFIG_GET", "IP_CONFIG_COMMIT",
322 "ACTIVATED", "FAILED", "CANCELLED", ]
324 def Dump(self):
325 cDevice.Dump(self)
326 print " Driver:", self.devi.getDriver()
327 props = self.devi.getProperties() # osusb ussss sssii biuus as
328 print " Self:", props[0] # o
329 print " Interface:", props[1] # s
330 print " Type:", self.DEVICE_TYPE[props[2]] # u
331 print " UDI:", props[3] # s
332 print " Active:", bool(props[4]) # b
333 print " Activation Stage:", self.NM_ACT_STAGE[props[5]] # u
334 print " IP:", props[6] # s
335 print " Mask:", props[7] # s
336 print " Bcast:", props[8] # s
337 print " HwAddress:", props[9] # s
338 print " GW:", props[10] # s
339 print " NS1:", props[11] # s
340 print " NS2:", props[12] # s
341 self.DumpMore()
343 def DumpMore(self):
344 print " (unknown device type, not dumping more)"
346 class cDeviceEth_06(cDevice_06, cDeviceEth):
347 def DumpMore(self):
348 props = self.devi.getProperties() # osusb ussss sssii biuus as
349 print " Link Active:", bool(props[15]) # b
350 print " Speed:", props[16] # i
351 print " Generic Capabilities:", bitmask_str(self.NM_DEVICE_CAP, props[17]) # u
353 class cDeviceWifi_06(cDevice_06):
354 NM_802_11_CAP = {
355 0x00000001: "PROTO_NONE",
356 0x00000002: "PROTO_WEP",
357 0x00000004: "PROTO_WPA",
358 0x00000008: "PROTO_WPA2",
359 0x00000010: "RESERVED1",
360 0x00000020: "RESERVED2",
361 0x00000040: "KEY_MGMT_PSK",
362 0x00000080: "KEY_MGMT_802_1X",
363 0x00000100: "RESERVED3",
364 0x00000200: "RESERVED4",
365 0x00000400: "RESERVED5",
366 0x00000800: "RESERVED6",
367 0x00001000: "CIPHER_WEP40",
368 0x00002000: "CIPHER_WEP104",
369 0x00004000: "CIPHER_TKIP",
370 0x00008000: "CIPHER_CCMP",
373 def APs(self):
374 self.wdevi = dbus.Interface(self.devo, NMI + ".Device.Wireless")
375 aps = self.devi.getProperties()[20]
376 return map(cAP_06, aps)
378 def DumpMore(self):
379 props = self.devi.getProperties() # osusb ussss sssii biuus as
380 print " Mode:", self.IW_MODE[props[13]] # i
381 print " Strength:", props[14] # i
382 print " Link Active:", bool(props[15]) # b
383 print " Speed:", props[16] # i
384 print " Generic Capabilities:", bitmask_str(self.NM_DEVICE_CAP, props[17]) # u
385 print " Capabilities:", bitmask_str(self.NM_802_11_CAP, props[18]) # u
386 print " Current net:", props[19] # s
387 nets = props[20] # as
388 print " Seen nets:", " ".join(nets)
389 if options.ap:
390 print " Access Points"
391 for ap in self.APs():
392 ap.Dump()
394 class cDevice_07(cDevice):
395 def DeviceType0(self):
396 if self.dt is None:
397 self.dt = self.devpi.Get(NMI, "DeviceType")
398 if self.dt == 1:
399 self.__class__ = cDeviceEth_07
400 elif self.dt == 2:
401 self.__class__ = cDeviceWifi_07
402 return self.dt
404 NM_DEVICE_STATE = [
405 "UNKNOWN", "UNMANAGED", "UNAVAILABLE", "DISCONNECTED", "PREPARE",
406 "CONFIG", "NEED_AUTH", "IP_CONFIG", "ACTIVATED", "FAILED",]
408 def Dump(self):
409 cDevice.Dump(self)
411 # "Ip4Config", only for NM_DEVICE_STATE_ACTIVATED
412 for P in ["Udi", "Interface", "Driver",]:
413 print " %s: %s" % (P, self.devpi.Get(NMI, P))
414 addr = self.devpi.Get(NMI, "Ip4Address")
415 print " Ip4Address:", self.ip_str(addr)
416 caps = self.devpi.Get(NMI, "Capabilities")
417 print " Capabilities:", bitmask_str(self.NM_DEVICE_CAP, caps)
418 state = self.NM_DEVICE_STATE[self.devpi.Get(NMI, "State")]
419 print " Dev State:", state
420 if state == "ACTIVATED":
421 self.DumpIp4Config(self.devpi.Get(NMI, "Ip4Config"))
423 dt = self.DeviceType()
424 print " Dev Type:", dt
425 self.DumpMore()
427 class cDeviceEth_07(cDevice_07, cDeviceEth):
428 def DumpMore(self):
429 for P in ["HwAddress", "Speed", "Carrier"]:
430 print " %s: %s" % (P, self.devpi.Get(NMI, P))
432 class cDeviceWifi_07(cDevice_07):
433 NM_802_11_DEVICE_CAP = {1:"CIPHER_WEP40", 2:"CIPHER_WEP104",
434 4:"CIPHER_TKIP", 8:"CIPHER_CCMP",
435 16:"WPA", 32:"RSN",}
437 def APs(self):
438 self.wdevi = dbus.Interface(self.devo, NMI + ".Device.Wireless")
439 aps = self.wdevi.GetAccessPoints()
440 return map(cAP_07, aps)
442 def DumpMore(self):
443 print " Dev Mode:", self.IW_MODE[self.devpi.Get(NMI, "Mode")]
444 wcaps = self.devpi.Get(NMI, "WirelessCapabilities")
445 print " Wifi Capabilities:", bitmask_str(self.NM_802_11_DEVICE_CAP, wcaps)
446 for P in ["HwAddress", "Bitrate", "ActiveAccessPoint"]:
447 print " %s: %s" % (P, self.devpi.Get(NMI, P))
448 if options.ap:
449 print " Access Points"
450 for ap in self.APs():
451 ap.Dump()
453 """An AP found around us"""
454 class cAP:
455 def __init__(self, opath):
456 self.opath = opath
457 self.apo = bus.get_object(NMC, self.opath)
458 self.appi = dbus.Interface(self.apo, PI)
459 # for _06
460 self.devi = dbus.Interface(self.apo, NMI + ".Devices")
462 NM_802_11_AP_FLAGS = {1: "PRIVACY",}
464 NM_802_11_AP_SEC = {
465 1: "PAIR_WEP40", 2: "PAIR_WEP104", 4: "PAIR_TKIP", 8: "PAIR_CCMP",
466 16: "GROUP_WEP40", 32: "GROUP_WEP104", 64: "GROUP_TKIP",
467 128: "GROUP_CCMP", 256: "KEY_MGMT_PSK", 512: "KEY_MGMT_802_1X",}
469 def ListNets(self, marker = " "):
470 # TODO *mark current
471 mbr = self.Mbr() / 1024 # 07 1000, 06 1024?
472 priv_s = self.PrivS()
473 print "%s%3d: %s (%dMb%s)" % (marker, self.Strength(), self.Ssid(), mbr, priv_s)
475 class cAP_06(cAP):
476 def Mbr(self, props=None):
477 if props is None:
478 props = self.devi.getProperties()
479 return props[5]
482 def PrivS(self):
483 props = self.devi.getProperties()
484 caps_s = bitmask_str(cDeviceWifi_06.NM_802_11_CAP, props[7]) + ","
485 priv_s = ""
486 if caps_s.find("PROTO_WEP,") != -1:
487 priv_s += " WEP"
488 if caps_s.find("PROTO_WPA,") != -1:
489 priv_s += " WPA"
490 if caps_s.find("PROTO_WPA2,") != -1:
491 priv_s += " WPA2"
492 if caps_s.find("KEY_MGMT_802_1X,") != -1:
493 priv_s += " Enterprise"
494 return priv_s
496 def Strength(self, props=None):
497 if props is None:
498 props = self.devi.getProperties()
499 return props[3]
501 def Ssid(self, props=None):
502 if props is None:
503 props = self.devi.getProperties()
504 return props[1]
507 def Dump(self):
508 props = self.devi.getProperties() # ossid iiib
509 print " Self:", props[0]
510 print " Ssid:", self.Ssid(props)
511 print " HwAddress:", props[2]
512 print " Strength:", self.Strength(props)
513 print " Frequency:", props[4]
514 print " MaxBitrate:", self.Mbr(props)
515 print " AP Mode:", cDevice.IW_MODE[props[6]]
516 print " Capabilities:", bitmask_str(cDeviceWifi_06.NM_802_11_CAP, props[7])
517 print " Broadcast:", props[8]
519 def ssid_str(array):
520 s = ""
521 for b in array:
522 s = s + ("%c" % b)
523 return s
525 def opath_validchar(c):
526 # _ is also escaped even though it is valid
527 return \
528 string.ascii_letters.find(c) != -1 or \
529 string.digits.find(c) != -1
531 def opath_escape(s):
532 r = ""
533 for c in s:
534 # TODO find a more elegant way
535 if not opath_validchar(c):
536 # "-" -> "_2d_"
537 c = "_%2x_" % ord(c)
538 r = r + c
539 return r
541 def opath_unescape(s):
542 # "2d" -> "-"
543 unhex = lambda xx: chr(eval("0x"+xx))
544 # all "_2d_" -> "-"
545 return re.sub("_.._", lambda p: unhex(p.group()[1:3]), s)
547 class cAP_07(cAP):
548 def Mbr(self):
549 return self.appi.Get(NMI, "MaxBitrate")
551 def PrivS(self):
552 priv = self.appi.Get(NMI, "Flags") != 0
553 wpa = self.appi.Get(NMI, "WpaFlags") != 0
554 wpa2 = self.appi.Get(NMI, "RsnFlags") != 0
555 priv_s = ""
556 if priv:
557 if not wpa and not wpa2:
558 priv_s = priv_s + " WEP"
559 if wpa:
560 priv_s = priv_s + " WPA"
561 if wpa2:
562 priv_s = priv_s + " WPA2"
563 return priv_s
565 def Strength(self):
566 return int(self.appi.Get(NMI, "Strength"))
568 def Ssid(self):
569 return ssid_str(self.appi.Get(NMI, "Ssid"))
571 def Dump(self):
572 print " AP:", self.opath
573 print " Ssid:", self.Ssid()
574 for P in ["Frequency", "HwAddress", "MaxBitrate",]:
575 print " %s: %s" % (P, self.appi.Get(NMI, P))
576 print " Strength:", self.Strength()
577 print " AP Mode:", cDevice.IW_MODE[self.appi.Get(NMI, "Mode")]
578 print " AP Flags:", bitmask_str(self.NM_802_11_AP_FLAGS,
579 self.appi.Get(NMI, "Flags"))
580 print " AP WPA Flags:", bitmask_str(self.NM_802_11_AP_SEC,
581 self.appi.Get(NMI, "WpaFlags"))
582 print " AP RSN Flags:", bitmask_str(self.NM_802_11_AP_SEC,
583 self.appi.Get(NMI, "RsnFlags"))
585 # this is the client side of the applet; see also UserSettings
586 class cApplet:
587 def __init__(self, svc, opath):
588 self.svc = svc
589 self.opath = opath
590 self.so = bus.get_object(self.svc, self.opath)
591 self.si = dbus.Interface(self.so, 'org.freedesktop.NetworkManagerSettings')
593 def isSystem(self):
594 return self.svc == SSC;
596 def Dump(self):
597 for conn in self.Connections():
598 conn.Dump()
599 if self.isSystem():
600 self.DumpSystem()
602 def DumpSystem(self):
603 sspi = dbus.Interface(self.so, PI)
604 print "Unmanaged Devices"
605 umds = sspi.Get(NMI, "UnmanagedDevices")
606 for umd in umds:
607 print " ", umd
608 # dump_settings_conn(svc, conn) umd?
611 def myConnection(self, opath):
612 return cConnection(self.svc, opath)
614 def Connections(self):
615 opaths = self.si.ListConnections()
616 return map(self.myConnection, opaths)
618 NETWORK_TYPE_ALLOWED = 1
619 class cApplet_06(cApplet):
620 def __init__(self, svc, opath):
621 self.svc = svc
622 self.opath = opath
623 self.io = bus.get_object(self.svc, self.opath)
624 self.ii = dbus.Interface(self.io, 'org.freedesktop.NetworkManagerInfo')
626 def isSystem(self):
627 return False;
629 def myConnection(self, opath):
630 return cConnection_06(self, opath)
632 # TODO also VPN conns
633 def Connections(self):
634 names = self.ii.getNetworks(NETWORK_TYPE_ALLOWED)
635 return map(self.myConnection, names)
637 class cConnection:
638 def __init__(self, svc, opath):
639 self.svc = svc
640 self.opath = opath
641 self.co = bus.get_object(self.svc, self.opath)
642 self.ci = dbus.Interface(self.co, 'org.freedesktop.NetworkManagerSettings.Connection')
644 def Dump(self):
645 print "Conn:", self.opath
646 settings = self.Settings()
647 settings.Dump()
649 si = dbus.Interface(self.co, 'org.freedesktop.NetworkManagerSettings.Connection.Secrets')
650 security = settings.Security()
651 if security != "":
652 print " SECRETS:", security
653 # TODO merge them
654 secrets = cSettings(si.GetSecrets(security,[],False))
655 secrets.Dump()
657 def Settings(self):
658 return cSettings(self.ci.GetSettings())
660 def dump_time(unixtime):
661 return time.asctime(time.localtime(unixtime))
663 class cConnection_06:
664 def __init__(self, applet, id):
665 self.id = id
666 self.applet = applet
668 def Dump(self):
669 print "Conn:", self.id
671 np = self.applet.ii.getNetworkProperties(self.id, NETWORK_TYPE_ALLOWED)
672 ssid = np[0]
673 print " ssid:", ssid
674 print " time:", dump_time(np[1])
675 print " trusted:", bool(np[2])
676 print " bssids:", ", ".join(np[3])
677 enctype = np[4]
678 print " we_cipher:", enctype
679 if enctype != 1:
680 print " secret:", np[5]
681 if enctype == 16:
682 print " wep_auth_algorithm:", np[6]
683 elif enctype == 0:
684 print " wpa_psk_key_mgt:", np[6]
685 print " wpa_psk_wpa_version:", np[7]
687 return # nm-applet will not tell kfn anyway
688 devp = "/org/freedesktop/NetworkManager/Devices/ath0" #FIXME
689 netp = devp + "/Networks/" + opath_escape(self.id)
690 attempt = 1
691 newkey = False
692 kfn = self.applet.ii.getKeyForNetwork(devp, netp, ssid, attempt, newkey)
693 print " kfn:", kfn
696 # 06
697 NM_AUTH_TYPE_WPA_PSK_AUTO = 0x00000000
698 NM_AUTH_TYPE_NONE = 0x00000001
699 NM_AUTH_TYPE_WEP40 = 0x00000002
700 NM_AUTH_TYPE_WPA_PSK_TKIP = 0x00000004
701 NM_AUTH_TYPE_WPA_PSK_CCMP = 0x00000008
702 NM_AUTH_TYPE_WEP104 = 0x00000010
703 NM_AUTH_TYPE_WPA_EAP = 0x00000020
704 NM_AUTH_TYPE_LEAP = 0x00000040
706 IW_AUTH_ALG_OPEN_SYSTEM = 0x00000001
707 IW_AUTH_ALG_SHARED_KEY = 0x00000002
708 IW_AUTH_ALG_LEAP = 0x00000004
710 class cSettings:
711 def __init__(self, conmap):
712 #print "INIT", conmap
713 self.conmap = conmap
715 def Type(self):
716 return self.conmap["connection"]["type"]
718 def ID(self):
719 return self.conmap["connection"]["id"]
721 def Ssid(self):
722 s = self.conmap["802-11-wireless"]["ssid"]
723 #print s
724 return s
726 def Timestamp(self):
727 try:
728 return self.conmap["connection"]["timestamp"]
729 except KeyError:
730 return 0
732 def Trusted(self):
733 # false by default
734 return False
736 def SeenBssids(self):
737 try:
738 return self.conmap["802-11-wireless"]["seen-bssids"]
739 except KeyError:
740 return []
742 # for 06
743 def WeCipher(self):
744 k = self.Key()
745 if len(k) == 26:
746 return NM_AUTH_TYPE_WEP104
747 elif len(k) == 64:
748 return NM_AUTH_TYPE_WPA_PSK_AUTO
749 elif len(k) == 0:
750 return NM_AUTH_TYPE_NONE
751 print "Defaulting cipher type to none"
752 return NM_AUTH_TYPE_NONE
754 def Key(self):
755 try:
756 return self.conmap["802-11-wireless-security"]["psk"]
757 except KeyError:
758 pass
759 try:
760 return self.conmap["802-11-wireless-security"]["wep-key0"]
761 except KeyError:
762 pass
763 # no key
764 return ""
766 def WepAuthAlgorithm(self):
767 print "FIXME Defaulting WEP auth alg to open"
768 return IW_AUTH_ALG_OPEN_SYSTEM
770 def PskKeyMgt(self):
771 print "FIXME Defaulting PSK key mgmt to 2"
772 return 2
774 def PskWpaVersion(self):
775 print "FIXME Defaulting WPA version to 2"
776 return 2
778 def Security(self):
779 try:
780 return self.conmap[self.Type()]["security"]
781 except KeyError:
782 return ""
784 def isNet(self, net_name):
785 return self.ID() == net_name or self.Ssid() == net_name
787 # FIXME check spec/NM what to censor
788 secrets = dict.fromkeys(["wep-key0", "psk"])
790 def ConMap(self):
791 "For GetSettings: censor secrets."
793 cm = dict()
794 for n1, v1 in self.conmap.iteritems():
795 cm[n1] = dict()
796 for n2, v2 in v1.iteritems():
797 cv2 = v2
798 if self.secrets.has_key(n2):
799 cv2 = ""
800 cm[n1][n2] = cv2
801 return cm
803 def SecMap(self):
804 "For GetSecrets: only secrets."
805 s = self.Security()
806 r = {
807 s: self.conmap[s]
809 print "SECMAP", r
810 return r
812 def Dump(self):
813 for n1, v1 in self.conmap.iteritems():
814 print " ",n1
815 for n2, v2 in v1.iteritems():
816 print " %s: %s" % (n2, v2)
818 def mkconmap_wifi(ssid):
819 return {
820 'connection': {
821 'id': '_cnm_handcrafted_',
822 'uuid': str(uuid.uuid1()), # new in oS 11.1
823 'type': '802-11-wireless',
825 '802-11-wireless': {
826 'ssid': dbus.ByteArray(ssid),
827 'mode': 'infrastructure',
828 'security': '802-11-wireless-security',
830 '802-11-wireless-security': {
831 'key-mgmt': 'none',
835 def elongate(s, tlen):
836 "repeat string s to target length tlen"
837 if s == "":
838 return ""
839 copies_needed = int(math.ceil(tlen / float(len(s))))
840 return (s * copies_needed)[:tlen]
842 # http://www.mail-archive.com/networkmanager-list@gnome.org/msg07935.html
843 def wep_passphrase_to_hash(p):
844 return hashlib.md5(elongate(p, 64)).hexdigest()
846 def mkconmap_wep_pass(ssid, key):
847 cm = mkconmap_wifi(ssid)
848 cm["802-11-wireless-security"]["key-mgmt"] = "none"
849 cm["802-11-wireless-security"]["wep-tx-keyidx"] = 0
850 cm["802-11-wireless-security"]["wep-key0"] = wep_passphrase_to_hash(key)
851 return cm
853 def mkconmap_wep(ssid, key):
854 cm = mkconmap_wifi(ssid)
855 cm["802-11-wireless-security"]["key-mgmt"] = "none"
856 cm["802-11-wireless-security"]["wep-tx-keyidx"] = 0
857 cm["802-11-wireless-security"]["wep-key0"] = key
858 return cm
860 def mkconmap_psk(ssid, key):
861 cm = mkconmap_wifi(ssid)
862 cm["802-11-wireless-security"]["key-mgmt"] = "wpa-psk"
863 cm["802-11-wireless-security"]["wep-tx-keyidx"] = 0
864 cm["802-11-wireless-security"]["psk"] = key
865 return cm
868 # server analog of cApplet
869 class UserSettings(dbus.service.Object):
870 # conmaps is a list
871 def __init__(self, opath, conmaps):
872 dbus.service.Object.__init__(self, bus, opath)
873 #print "CONMAPS:", conmaps
874 self.conns = map(self.newCon, conmaps)
876 def addCon(self, conmap):
877 c = self.newCon(conmap)
878 self.conns.append(c)
879 return c
881 counter = 1
882 def newCon(self, conmap):
883 cpath = "/MyConnection/%d" % self.counter
884 self.counter = self.counter + 1
885 c = Connection(cpath, conmap)
886 self.NewConnection(cpath) # announce it
887 return c
889 @dbus.service.method(dbus_interface='org.freedesktop.NetworkManagerSettings',
890 in_signature='', out_signature='ao')
891 def ListConnections(self):
892 return [c.__dbus_object_path__ for c in self.conns]
894 #this is for EMITTING a signal, not receiving it
895 @dbus.service.signal(dbus_interface='org.freedesktop.NetworkManagerSettings',
896 signature='o')
897 def NewConnection(self, opath):
898 pass
899 #print "signalling newconn:", opath
901 def GetByNet(self, net_name):
902 "Returns connection, or None"
903 for c in self.conns:
904 if c.isNet(net_name):
905 return c
906 return None
909 class UserSettings_06(UserSettings):
910 # conmaps is a list
911 def __init__(self, opath, conmaps):
912 dbus.service.Object.__init__(self, bus, opath)
913 #print "CONMAPS:", conmaps
914 self.conns = map(self.newCon, conmaps)
916 counter = 1
917 def newCon(self, conmap):
918 cpath = "/MyConnection/%d" % self.counter
919 self.counter = self.counter + 1
920 c = Connection_06(cpath, conmap)
921 #self.NewConnection(cpath) # announce it
922 return c
924 @dbus.service.method(dbus_interface="org.freedesktop.NetworkManagerInfo",
925 in_signature="i", out_signature='as')
926 def getNetworks(self, i):
927 # FIXME bytearray to str WHERE?
928 #n = [ssid_str(c.Ssid()) for c in self.conns]
929 n = [c.ID() for c in self.conns]
930 print "getNetworks:", n
931 return n
933 @dbus.service.method(dbus_interface="org.freedesktop.NetworkManagerInfo",
934 in_signature="", out_signature='ao') # out??
935 def getVPNConnections(self):
936 return [] # FIXME
938 @dbus.service.method(dbus_interface="org.freedesktop.NetworkManagerInfo",
939 in_signature="si")
940 #out_signature='sibasi') #varies
941 def getNetworkProperties(self, net, type):
942 print "GNP", net
943 # type is 1, NETWORK_TYPE_ALLOWED
944 c = self.GetByNet(net)
945 if c != None:
946 return c.getNetworkProperties()
947 print "Oops, could not getNetworkProperties for " + net
950 @dbus.service.method(dbus_interface="org.freedesktop.NetworkManagerInfo",
951 in_signature="oosib")
952 #out_signature="isi") varies
953 def getKeyForNetwork(self, dev, net, ssid, attempt, newkey):
954 print "GKFN", dev, net, ssid, attempt, bool(newkey)
955 if newkey:
956 m = "Cannot ask for key"
957 print m
958 raise dbus.exceptions.DBusException(m)
960 snet = opath_unescape(net[net.rfind("/")+1 : ]) # only stuff after /
961 c = self.GetByNet(snet)
962 if c != None:
963 return c.getKeyForNetwork()
964 print "Oops, could not getKeyForNetwork " + net
966 @dbus.service.method(dbus_interface="org.freedesktop.NetworkManagerInfo",
967 out_signature='')
968 #in_signature="sbs isi", varies
969 def updateNetworkInfo(self, ssid, automatic, bssid, *security):
970 print "Connected successfully"
971 return
972 print "UNI"
973 print " ssid:", ssid
974 print " automatic:", bool(automatic)
975 print " bssid:", bssid
976 print " security:", security
979 def GetByNet(self, net_name):
980 "Returns connection, or None"
981 for c in self.conns:
982 if c.isNet(net_name):
983 return c
984 return None
987 # server analog of cConnection
988 class Connection(dbus.service.Object):
989 def __init__(self, opath, conmap):
990 dbus.service.Object.__init__(self, bus, opath)
991 self.settings = cSettings(conmap)
993 @dbus.service.method(dbus_interface='org.freedesktop.NetworkManagerSettings.Connection',
994 in_signature='', out_signature='a{sa{sv}}')
995 def GetSettings(self):
996 #print "Getting settings:", self. __dbus_object_path__
997 # return self.settings.ConMap()
998 # grr, censoring secrets makes NM complain!?
999 return self.settings.conmap
1001 @dbus.service.method(dbus_interface='org.freedesktop.NetworkManagerSettings.Connection.Secrets',
1002 in_signature='sasb', out_signature='a{sa{sv}}')
1003 def GetSecrets(self, tag, hints, ask):
1004 # FIXME respect args
1005 print "Getting secrets:", self.__dbus_object_path__
1006 return self.settings.SecMap()
1008 @dbus.service.method(dbus_interface='org.freedesktop.NetworkManagerSettings.Connection',
1009 in_signature='', out_signature='s')
1010 def ID(self):
1011 return self.settings.ID()
1013 def Ssid(self):
1014 return self.settings.Ssid()
1016 def isNet(self, net_name):
1017 return self.settings.isNet(net_name)
1019 class Connection_06(Connection):
1020 def __init__(self, opath, conmap):
1021 dbus.service.Object.__init__(self, bus, opath)
1022 #print "C6", conmap
1023 self.settings = cSettings(conmap)
1025 # dbus.service.method
1026 def getNetworkProperties(self):
1027 # essid, timestamp, ?, bssids, we_cipher, ?, ...
1028 # we_cipher=16: i wep_auth_algorithm
1029 # we_cipher=0: i wpa_psk_key_mgt, i wpa_psk_wpa_version
1030 ssid = ssid_str(self.settings.Ssid())
1031 time = self.settings.Timestamp() # last sucessfully connected? seen?
1032 trusted = self.settings.Trusted()
1033 bssids = dbus.Array(self.settings.SeenBssids(), signature="s")
1034 r = [ssid, time, trusted, bssids]
1035 security = self.getKeyForNetwork("fake key")
1036 r.extend(security)
1037 return tuple(r)
1039 # dbus.service.method
1040 def getKeyForNetwork(self, fake="no"):
1041 if fake == "no":
1042 key = self.settings.Key()
1043 else:
1044 key = ""
1046 # security
1047 cip = self.settings.WeCipher()
1048 if cip == NM_AUTH_TYPE_NONE:
1049 security = tuple([cip])
1050 elif cip == NM_AUTH_TYPE_WEP40 or cip == NM_AUTH_TYPE_WEP104:
1051 wep_auth_algorithm = self.settings.WepAuthAlgorithm()
1052 security = (cip, key, wep_auth_algorithm)
1053 elif cip == NM_AUTH_TYPE_WPA_PSK_AUTO or cip == NM_AUTH_TYPE_TKIP or \
1054 cip == NM_AUTH_TYPE_CCMP:
1055 wpa_psk_key_mgt = self.settings.PskKeyMgt()
1056 wpa_psk_wpa_version = self.settings.PskWpaVersion()
1057 security = (cip, key, wpa_psk_key_mgt, wpa_psk_wpa_version)
1058 elif cip == NM_AUTH_TYPE_WPA_EAP:
1059 security = tuple([cip]) # TODO more...
1060 elif cip == NM_AUTH_TYPE_LEAP:
1061 security = tuple([cip]) # TODO more...
1062 return security
1065 class ConfigParserKNM:
1066 "Parse ~/.kde/share/config/knetworkmanagerrc"
1068 def __init__(self):
1069 p = ConfigParser.RawConfigParser()
1070 ok = p.read(os.getenv("HOME") + "/.kde/share/config/knetworkmanagerrc")
1072 self.conmaps_d = {}
1073 for s in p.sections():
1074 path = s.split("_")
1075 #print path
1076 if path[0] in ["ConnectionSetting", "ConnectionSecrets"]:
1077 cid = path[1]
1078 self.conmaps_d.setdefault(cid, {})
1079 part = path[2]
1081 values = {}
1082 for (n, v) in p.items(s):
1083 # WTF, Value_ is transfrmed to value_
1084 if n[:6] == "value_":
1085 n = n[6:]
1086 v = self.ParseValue(v)
1087 values[n] = v
1088 if len(values) != 0: # empty 802-1x confuses NM!?
1089 self.conmaps_d[cid].setdefault(part, {})
1090 self.conmaps_d[cid][part].update(**values)
1091 #print "PARSED", cid, part, values
1093 def ConMaps(self):
1094 return self.conmaps_d.values()
1096 def ParseValue(self, v):
1097 v = eval('"%s"' % v) # unescape backslashes
1098 dom = xml.dom.minidom.parseString(v)
1099 return self.ParseNode(dom.documentElement)
1101 def ParseNode(self, n):
1102 t = n.localName
1103 if t != "list":
1104 v = self.NodeText(n)
1106 if t == "string":
1107 return v
1108 elif t == "byte":
1109 return dbus.Byte(int(v))
1110 elif t == "bool":
1111 return v == "true"
1112 elif t == "int32" or t == "uint32":
1113 return int(v)
1114 elif t == "list":
1115 v = []
1116 c = n.firstChild
1117 while c != None:
1118 if c.localName != None: # whitespace
1119 v.append(self.ParseNode(c))
1120 c = c.nextSibling
1121 return v
1123 def NodeText(self, n):
1124 if n.hasChildNodes():
1125 return n.firstChild.wholeText
1126 else:
1127 return ""
1129 def abbr_signal_handler(*args, **kwargs):
1130 ifc = kwargs["interface"]
1131 sig = kwargs["member"]
1132 opath = kwargs["path"]
1133 line = "SIG %s: %s.%s%s" % (abbrev(opath,"/"), abbrev(ifc,"."), sig, args)
1134 print line
1136 class Monitor:
1137 def __init__(self):
1138 self.amap = {}
1139 bus.add_signal_receiver(self.abbr_signal_handler,
1140 path_keyword="path",
1141 interface_keyword="interface",
1142 member_keyword="member")
1144 def abbr_signal_handler(self, *args, **kwargs):
1145 ifc = kwargs["interface"]
1146 sig = kwargs["member"]
1147 opath = kwargs["path"]
1148 line = "SIG %s: %s.%s%s" % (self.abbrev(opath,"/"),
1149 self.abbrev(ifc,"."),
1150 sig, args)
1151 print line
1153 def abbrev(self, s, sep):
1154 words = s.split(sep)
1155 words = map (self.a1, words)
1156 result = sep.join(words)
1157 if not self.amap.has_key(s):
1158 print "ABBR %s is %s" % (result, s)
1159 self.amap[s] = result
1160 else:
1161 if self.amap[s] != result:
1162 print "ABBR COLLISION %s was %s now %s" % (s, self.amap[s], result)
1163 return result
1165 def a1(self, s):
1166 try:
1167 return s[0]
1168 except:
1169 return ""
1171 # main
1173 op = OptionParser(version="%prog " + VERSION)
1174 op.add_option("-d", "--dev",
1175 action="store_true", default=False,
1176 help="list devices")
1177 op.add_option("-c", "--actcon",
1178 action="store_true", default=False,
1179 help="list active connections")
1180 op.add_option("-u", "--usrcon",
1181 action="store_true", default=False,
1182 help="list user connection settings (can CRASH nm-applet)")
1183 op.add_option("-s", "--syscon",
1184 action="store_true", default=False,
1185 help="list system connection settings")
1186 op.add_option("-a", "--ap",
1187 action="store_true", default=False,
1188 help="list found access points")
1189 op.add_option("-n", "--nets",
1190 action="store_true", default=False,
1191 help="list found wireless networks")
1192 # TODO http://docs.python.org/lib/optparse-adding-new-types.html
1193 op.add_option("-w", "--wifi",
1194 choices=["0","1","off","on","no","yes","false","true"],
1195 metavar="BOOL",
1196 help="enable or disable wireless")
1197 op.add_option("-o", "--online",
1198 choices=["0","1","off","on","no","yes","false","true"],
1199 metavar="BOOL",
1200 help="enable or disable network at all")
1202 op.add_option("-C", "--connect",
1203 help="connect to a wireless network NET (using knetworkmanagerrc or the key options below)",
1204 metavar="NET")
1205 op.add_option("--unprotected",
1206 action="store_true", default=False,
1207 help="network does not require a key")
1208 op.add_option("--wep-hex",
1209 metavar="KEY",
1210 help="use this WEP key of 26 hex digits")
1211 op.add_option("--wep-pass",
1212 metavar="KEY",
1213 help="use this WEP passphrase")
1214 op.add_option("--wpa-psk-hex",
1215 metavar="KEY",
1216 help="use this WPA key of 64 hex digits")
1217 op.add_option("--wpa-pass",
1218 metavar="KEY",
1219 help="use this WPA passphrase")
1220 op.add_option("-m", "--monitor",
1221 action="store_true", default=False,
1222 help="loop to show dbus signals")
1225 (options, args) = op.parse_args()
1227 if options.ap:
1228 options.dev = True
1229 if options.monitor:
1230 LOOP = True
1233 nmp = '/org/freedesktop/NetworkManager'
1234 try:
1235 nm = make_nm(nmp)
1236 except dbus.exceptions.DBusException, e:
1237 print e
1238 print "NetworkManager is not running"
1239 sys.exit(1)
1240 if options.dev or options.actcon:
1241 nm.Dump()
1243 true_choices = ["1", "on", "yes", "true"]
1244 if options.wifi != None:
1245 nm.SetWifiEnabled(options.wifi in true_choices)
1246 if options.online != None:
1247 nm.SetOnline(options.online in true_choices)
1249 if options.nets:
1250 nm.ListNets()
1252 if options.syscon:
1253 print "SYSTEM Connections"
1254 if nm.Api() == "06":
1255 print "Cannot do that with NM 0.6"
1256 else:
1257 ss = cApplet(SSC, '/org/freedesktop/NetworkManagerSettings')
1258 ss.Dump()
1260 if options.usrcon:
1261 print "USER Connections"
1262 try:
1263 if nm.Api() == "06":
1264 us = cApplet_06(NMIC, "/org/freedesktop/NetworkManagerInfo")
1265 else:
1266 us = cApplet(USC, '/org/freedesktop/NetworkManagerSettings')
1267 us.Dump()
1268 except dbus.exceptions.DBusException, e:
1269 print e
1270 #if e.get_dbus_name() == "org.freedesktop.DBus.Error.ServiceUnknown":
1271 print "Applet is not running"
1273 nmo = bus.get_object(NMC, nmp)
1274 nmi = dbus.Interface(nmo, NMI)
1276 def service_pid(name):
1277 DBS = 'org.freedesktop.DBus'
1278 DBI = DBS
1279 dbo = bus.get_object(DBS, '/')
1280 dbi = dbus.Interface(dbo, DBI)
1281 owner = dbi.GetNameOwner(name)
1282 pid = dbi.GetConnectionUnixProcessID(owner)
1283 return pid
1285 # TODO UserSettings_06
1286 if options.connect != None:
1287 if nm.Api() == "06":
1288 name = NMIC
1289 else:
1290 name = USC
1291 brn = bus.request_name(name, _dbus_bindings.NAME_FLAG_DO_NOT_QUEUE)
1292 if brn == _dbus_bindings.REQUEST_NAME_REPLY_EXISTS:
1293 print "Could not provide settings service, another applet is running (pid %s)" % service_pid(name)
1294 sys.exit(1)
1295 cfg = ConfigParserKNM()
1296 if nm.Api() == "06":
1297 us = UserSettings_06("/org/freedesktop/NetworkManagerInfo",
1298 cfg.ConMaps())
1299 else:
1300 us = UserSettings("/org/freedesktop/NetworkManagerSettings",
1301 cfg.ConMaps())
1303 def Connect(wanted_net): # any. or take arg. net is config name or ssid name
1304 # ... in general, look for string in all config data. ssid for wifi, whatever for dialup
1305 # TODO also respect autoconnect
1307 # ActivateConn wants setting device ap; can find device from ap? ap is "specific" for wifi devices
1308 #print "Connection wanted to", wanted_net
1309 found_con = found_ap = found_dev = None
1310 for dev in nm.Devices():
1311 for ap in dev.APs():
1312 if wanted_net == ap.Ssid():
1313 found_ap = ap
1314 found_dev = dev
1315 break # FIXME both loops
1316 found_con = us.GetByNet(wanted_net)
1317 if found_ap == None:
1318 print "No AP found with SSID", wanted_net
1319 return False
1320 if found_con == None:
1321 print "No settings for net %s, assuming no key is needed" % wanted_net
1322 c = mkconmap_wifi(wanted_net)
1323 found_con = us.addCon(c)
1324 nm.ActivateConnection(found_con, found_dev, found_ap) # TODO async
1325 # TODO run loop, exit it when we have serviced the required calls
1326 return True
1328 if options.connect != None:
1329 if options.unprotected:
1330 c = mkconmap_wifi(options.connect)
1331 us.addCon(c)
1332 if options.wep_hex != None:
1333 c = mkconmap_wep(options.connect, options.wep_hex)
1334 us.addCon(c)
1335 if options.wep_pass != None:
1336 c = mkconmap_wep_pass(options.connect, options.wep_pass)
1337 us.addCon(c)
1338 if options.wpa_psk_hex != None:
1339 c = mkconmap_psk(options.connect, options.wpa_psk_hex)
1340 us.addCon(c)
1341 if options.wpa_pass != None:
1342 wpa_psk_hex = hexlify(pbkdf2.pbkdf2(options.wpa_pass, options.connect, 4096, 32))
1343 print "pbkdf2", wpa_psk_hex
1344 c = mkconmap_psk(options.connect, wpa_psk_hex)
1345 us.addCon(c)
1346 if Connect(options.connect):
1347 LOOP = True
1349 if options.monitor:
1350 m = Monitor()
1352 def loop():
1353 loop = gobject.MainLoop()
1354 try:
1355 loop.run()
1356 except:
1357 print "Loop exited"
1359 if LOOP:
1360 loop()