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