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