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
7 print "cnetworkmanager %s - Command Line Interface for NetworkManager" % VERSION
11 # find other modules in our prefix, if specified
12 if len(sys
.argv
) > 2 and sys
.argv
[1] == "--prefix":
14 sys
.argv
[1:] = sys
.argv
[3:]
15 sys
.path
.append(prefix
+ "/share/cnetworkmanager");
25 from binascii
import hexlify
26 import ConfigParser
# knm config
27 from optparse
import OptionParser
33 print "Install python-1-dbus.rpm or or python-dbus.rpm or python-dbus.deb"
35 import xml
.dom
.minidom
39 # todo - only if loop wanted
40 print "Install python-gobject2.rpm or pygobject2.rpm or python-gobject.deb"
42 # python-gnome.rpm has gconf for nm-applet...
46 from dbus
.mainloop
.glib
import DBusGMainLoop
47 DBusGMainLoop(set_as_default
=True)
51 bus
= dbus
.SystemBus()
53 # FOOC = connection (service) string
54 # FOOI = interface string
57 # foopi = property interface
58 NMC
= 'org.freedesktop.NetworkManager'
60 PI
= 'org.freedesktop.DBus.Properties'
61 SSC
= "org.freedesktop.NetworkManagerSystemSettings"
62 USC
= "org.freedesktop.NetworkManagerUserSettings"
63 NMIC
= "org.freedesktop.NetworkManagerInfo"
66 ii
= dbus
.Interface(obj
, 'org.freedesktop.DBus.Introspectable')
70 # TODO: pull them from introspection.xml
71 NM_STATE
= ["UNKNOWN", "ASLEEP", "CONNECTING", "CONNECTED", "DISCONNECTED",]
73 def __init__(self
, opath
):
75 self
.nmo
= bus
.get_object(NMC
, self
.opath
)
76 self
.nmi
= dbus
.Interface(self
.nmo
, NMI
)
77 self
.nmpi
= dbus
.Interface(self
.nmo
, PI
)
83 "Dumps its own info (not owned objects)."
89 for device
in self
.Devices():
93 print "Active Connections"
94 aconns
= self
.ActiveConnections()
99 print "Wifi Networks:"
100 for dev
in self
.Devices():
103 def err_handler(self
, *args
):
106 def silent_handler(self
, *args
):
110 def quitter_handler(self
, *args
):
111 # exit the loop that runs only because of us
115 def WatchState(self
):
116 bus
.add_signal_receiver(self
.state_changed_handler
,
117 dbus_interface
="org.freedesktop.NetworkManager",
118 signal_name
="StateChanged")
120 def state_changed_handler(self
, *args
):
122 ss
= self
.NM_STATE
[s
]
123 print time
.strftime("(%X)"),
128 "Detects NM version and chooses appropriate class"
130 nmo
= bus
.get_object(NMC
, opath
)
131 nmi
= dbus
.Interface(nmo
, NMI
)
133 dummy
= nmi
.getDevices()
135 except dbus
.exceptions
.DBusException
, e
:
136 if e
.get_dbus_name() == 'org.freedesktop.DBus.Error.AccessDenied':
144 def SetWifiEnabled(self
, v
):
145 # TODO: async call, catch the state signal and exit
146 # weird: synchronous call works, but times out
147 # asynchronous call does not work
148 self
.nmi
.setWirelessEnabled(v
,
149 reply_handler
=self
.quitter_handler
,
150 error_handler
=self
.quitter_handler
)
154 def SetOnline(self
, v
):
157 reply_handler
=self
.quitter_handler
,
158 error_handler
=self
.quitter_handler
)
161 reply_handler
=self
.quitter_handler
,
162 error_handler
=self
.quitter_handler
)
167 print "State:", self
.NM_STATE
[self
.nmi
.state()]
168 we
= self
.nmi
.getWirelessEnabled()
169 if isinstance(we
, tuple):
170 print "Wifi enabled:", bool(we
[0])
171 print "Wifi HW enabled:", bool(we
[1])
173 print "Wifi enabled:", bool(we
)
176 dup
= self
.nmi
.getDialup()
178 except dbus
.exceptions
.DBusException
, e
:
179 #if e.get_dbus_name() == "org.freedesktop.NetworkManager.NoDialup":
185 opaths
= self
.nmi
.getDevices()
186 return map(cDevice_06
, opaths
)
188 def ActiveConnections(self
):
189 return [] # at most one active connection, FIXME find it
191 def ActivateConnection(self
, conn
, device
, ap
):
192 # passing *_handler makes the call asynchronous
193 self
.nmi
.setActiveDevice(device
.opath
, ssid_str(conn
.Ssid()),
194 reply_handler
=self
.silent_handler
,
195 error_handler
=self
.err_handler
,
202 def SetWifiEnabled(self
, v
):
203 self
.nmpi
.Set(NMI
, "WirelessEnabled", v
)
205 def SetOnline(self
, v
):
206 self
.nmi
.Sleep(not v
)
209 print "State:", self
.NM_STATE
[self
.nmpi
.Get(NMI
, "State")]
210 print "Wifi enabled:", self
.nmpi
.Get(NMI
, "WirelessEnabled")
211 print "Wifi HW enabled:", self
.nmpi
.Get(NMI
, "WirelessHardwareEnabled")
214 opaths
= self
.nmi
.GetDevices()
215 return map(cDevice_07
, opaths
)
217 def ActiveConnections(self
):
218 aconns
= self
.nmpi
.Get(NMI
, "ActiveConnections")
219 return map(cActiveConnection
, aconns
)
221 def ActivateConnection(self
, conn
, device
, ap
):
222 # passing *_handler makes the call asynchronous
223 self
.nmi
.ActivateConnection(USC
,
224 conn
.__dbus
_object
_path
__,
227 reply_handler
=self
.silent_handler
,
228 error_handler
=self
.err_handler
,
232 class cActiveConnection
:
233 def __init__(self
, opath
):
238 co
= bus
.get_object(NMC
, self
.opath
)
239 copi
= dbus
.Interface(co
, PI
)
240 for P
in ["ServiceName", "Connection", "SpecificObject",]:
241 print " %s: %s" % (P
, copi
.Get(NMI
, P
))
242 devs
= copi
.Get(NMI
, "Devices")
247 def bitmask_str(map, value
):
249 for mask
in sorted(map.keys()):
250 if value
& mask
: ret
.append(map[mask
])
255 def __init__(self
, opath
):
257 self
.devo
= bus
.get_object(NMC
, self
.opath
)
258 self
.devi
= dbus
.Interface(self
.devo
, NMI
+ ".Device")
259 self
.devpi
= dbus
.Interface(self
.devo
, PI
)
263 DEVICE_TYPE
= ["UNKNOWN", "802_3_ETHERNET", "802_11_WIRELESS",
264 "GSM", "CDMA",] #OLPC: 3 is MESH
266 def DeviceType(self
):
267 return self
.DEVICE_TYPE
[self
.DeviceType0()]
269 def ip_str(self
, i32
):
271 ret
.append("%d" % (i32
% 256))
273 ret
.append("%d" % (i32
% 256))
275 ret
.append("%d" % (i32
% 256))
277 ret
.append("%d" % (i32
% 256))
281 def DumpIp4Config(self
, opath
):
282 print " Ip4Config:", opath
283 o
= bus
.get_object(NMC
, opath
)
284 pi
= dbus
.Interface(o
, PI
)
286 for P
in ["Address", "Netmask", "Broadcast", "Gateway",]: # beta2?
287 print " %s: %s" % (P
, self
.ip_str(pi
.Get(NMI
, P
)))
290 addrs
= pi
.Get(NMI
, "Addresses")
292 print " %s/%s via %s" % tuple(map(self
.ip_str
, addr
))
293 nss
= pi
.Get(NMI
, "Nameservers")
294 print " Nameservers:", " ".join(map(self
.ip_str
, nss
))
295 doms
= pi
.Get(NMI
, "Domains")
296 print " Domains:", " ".join(doms
)
298 NM_DEVICE_CAP
= {1: "NM_SUPPORTED", 2: "CARRIER_DETECT", 4: "SCANNING", }
302 print "Device:", self
.opath
305 IW_MODE
= ["AUTO", "ADHOC", "INFRA", "MASTER",
306 "REPEAT", "SECOND", "MONITOR",]
312 for ap
in self
.APs():
319 class cDevice_06(cDevice
):
320 def DeviceType0(self
):
322 self
.dt
= self
.devi
.getProperties()[2]
324 self
.__class
__ = cDeviceEth_06
326 self
.__class
__ = cDeviceWifi_06
330 "UNKNOWN", "DEVICE_PREPARE", "DEVICE_CONFIG", "NEED_USER_KEY",
331 "IP_CONFIG_START", "IP_CONFIG_GET", "IP_CONFIG_COMMIT",
332 "ACTIVATED", "FAILED", "CANCELLED", ]
336 print " Driver:", self
.devi
.getDriver()
337 props
= self
.devi
.getProperties() # osusb ussss sssii biuus as
338 print " Self:", props
[0] # o
339 print " Interface:", props
[1] # s
340 print " Type:", self
.DEVICE_TYPE
[props
[2]] # u
341 print " UDI:", props
[3] # s
342 print " Active:", bool(props
[4]) # b
343 print " Activation Stage:", self
.NM_ACT_STAGE
[props
[5]] # u
344 print " IP:", props
[6] # s
345 print " Mask:", props
[7] # s
346 print " Bcast:", props
[8] # s
347 print " HwAddress:", props
[9] # s
348 print " GW:", props
[10] # s
349 print " NS1:", props
[11] # s
350 print " NS2:", props
[12] # s
354 print " (unknown device type, not dumping more)"
356 class cDeviceEth_06(cDevice_06
, cDeviceEth
):
358 props
= self
.devi
.getProperties() # osusb ussss sssii biuus as
359 print " Link Active:", bool(props
[15]) # b
360 print " Speed:", props
[16] # i
361 print " Generic Capabilities:", bitmask_str(self
.NM_DEVICE_CAP
, props
[17]) # u
363 class cDeviceWifi_06(cDevice_06
):
365 0x00000001: "PROTO_NONE",
366 0x00000002: "PROTO_WEP",
367 0x00000004: "PROTO_WPA",
368 0x00000008: "PROTO_WPA2",
369 0x00000010: "RESERVED1",
370 0x00000020: "RESERVED2",
371 0x00000040: "KEY_MGMT_PSK",
372 0x00000080: "KEY_MGMT_802_1X",
373 0x00000100: "RESERVED3",
374 0x00000200: "RESERVED4",
375 0x00000400: "RESERVED5",
376 0x00000800: "RESERVED6",
377 0x00001000: "CIPHER_WEP40",
378 0x00002000: "CIPHER_WEP104",
379 0x00004000: "CIPHER_TKIP",
380 0x00008000: "CIPHER_CCMP",
384 self
.wdevi
= dbus
.Interface(self
.devo
, NMI
+ ".Device.Wireless")
385 aps
= self
.devi
.getProperties()[20]
386 return map(cAP_06
, aps
)
389 props
= self
.devi
.getProperties() # osusb ussss sssii biuus as
390 print " Mode:", self
.IW_MODE
[props
[13]] # i
391 print " Strength:", props
[14] # i
392 print " Link Active:", bool(props
[15]) # b
393 print " Speed:", props
[16] # i
394 print " Generic Capabilities:", bitmask_str(self
.NM_DEVICE_CAP
, props
[17]) # u
395 print " Capabilities:", bitmask_str(self
.NM_802_11_CAP
, props
[18]) # u
396 print " Current net:", props
[19] # s
397 nets
= props
[20] # as
398 print " Seen nets:", " ".join(nets
)
400 print " Access Points"
401 for ap
in self
.APs():
404 class cDevice_07(cDevice
):
405 def DeviceType0(self
):
407 self
.dt
= self
.devpi
.Get(NMI
, "DeviceType")
409 self
.__class
__ = cDeviceEth_07
411 self
.__class
__ = cDeviceWifi_07
413 self
.__class
__ = cDeviceGSM_07
417 "UNKNOWN", "UNMANAGED", "UNAVAILABLE", "DISCONNECTED", "PREPARE",
418 "CONFIG", "NEED_AUTH", "IP_CONFIG", "ACTIVATED", "FAILED",]
423 # "Ip4Config", only for NM_DEVICE_STATE_ACTIVATED
424 for P
in ["Udi", "Interface", "Driver",]:
425 print " %s: %s" % (P
, self
.devpi
.Get(NMI
, P
))
426 addr
= self
.devpi
.Get(NMI
, "Ip4Address")
427 print " Ip4Address:", self
.ip_str(addr
)
428 caps
= self
.devpi
.Get(NMI
, "Capabilities")
429 print " Capabilities:", bitmask_str(self
.NM_DEVICE_CAP
, caps
)
430 state
= self
.NM_DEVICE_STATE
[self
.devpi
.Get(NMI
, "State")]
431 print " Dev State:", state
432 if state
== "ACTIVATED":
433 self
.DumpIp4Config(self
.devpi
.Get(NMI
, "Ip4Config"))
435 dt
= self
.DeviceType()
436 print " Dev Type:", dt
439 class cDeviceEth_07(cDevice_07
, cDeviceEth
):
441 for P
in ["HwAddress", "Speed", "Carrier"]:
442 print " %s: %s" % (P
, self
.devpi
.Get(NMI
, P
))
444 class cDeviceGSM_07(cDevice_07
):
447 print " %s: %s" % (P
, self
.devpi
.Get(NMI
, P
))
449 class cDeviceWifi_07(cDevice_07
):
450 NM_802_11_DEVICE_CAP
= {1:"CIPHER_WEP40", 2:"CIPHER_WEP104",
451 4:"CIPHER_TKIP", 8:"CIPHER_CCMP",
455 self
.wdevi
= dbus
.Interface(self
.devo
, NMI
+ ".Device.Wireless")
456 aps
= self
.wdevi
.GetAccessPoints()
457 return map(cAP_07
, aps
)
460 print " Dev Mode:", self
.IW_MODE
[self
.devpi
.Get(NMI
, "Mode")]
461 wcaps
= self
.devpi
.Get(NMI
, "WirelessCapabilities")
462 print " Wifi Capabilities:", bitmask_str(self
.NM_802_11_DEVICE_CAP
, wcaps
)
463 for P
in ["HwAddress", "Bitrate", "ActiveAccessPoint"]:
464 print " %s: %s" % (P
, self
.devpi
.Get(NMI
, P
))
466 print " Access Points"
467 for ap
in self
.APs():
470 """An AP found around us"""
472 def __init__(self
, opath
):
474 self
.apo
= bus
.get_object(NMC
, self
.opath
)
475 self
.appi
= dbus
.Interface(self
.apo
, PI
)
477 self
.devi
= dbus
.Interface(self
.apo
, NMI
+ ".Devices")
479 NM_802_11_AP_FLAGS
= {1: "PRIVACY",}
482 1: "PAIR_WEP40", 2: "PAIR_WEP104", 4: "PAIR_TKIP", 8: "PAIR_CCMP",
483 16: "GROUP_WEP40", 32: "GROUP_WEP104", 64: "GROUP_TKIP",
484 128: "GROUP_CCMP", 256: "KEY_MGMT_PSK", 512: "KEY_MGMT_802_1X",}
486 def ListNets(self
, marker
= " "):
488 mbr
= self
.Mbr() / 1024 # 07 1000, 06 1024?
489 priv_s
= self
.PrivS()
490 print "%s%3d: %s (%dMb%s)" % (marker
, self
.Strength(), self
.Ssid(), mbr
, priv_s
)
493 def Mbr(self
, props
=None):
495 props
= self
.devi
.getProperties()
500 props
= self
.devi
.getProperties()
501 caps_s
= bitmask_str(cDeviceWifi_06
.NM_802_11_CAP
, props
[7]) + ","
503 if caps_s
.find("PROTO_WEP,") != -1:
505 if caps_s
.find("PROTO_WPA,") != -1:
507 if caps_s
.find("PROTO_WPA2,") != -1:
509 if caps_s
.find("KEY_MGMT_802_1X,") != -1:
510 priv_s
+= " Enterprise"
513 def Strength(self
, props
=None):
515 props
= self
.devi
.getProperties()
518 def Ssid(self
, props
=None):
520 props
= self
.devi
.getProperties()
525 props
= self
.devi
.getProperties() # ossid iiib
526 print " Self:", props
[0]
527 print " Ssid:", self
.Ssid(props
)
528 print " HwAddress:", props
[2]
529 print " Strength:", self
.Strength(props
)
530 print " Frequency:", props
[4]
531 print " MaxBitrate:", self
.Mbr(props
)
532 print " AP Mode:", cDevice
.IW_MODE
[props
[6]]
533 print " Capabilities:", bitmask_str(cDeviceWifi_06
.NM_802_11_CAP
, props
[7])
534 print " Broadcast:", props
[8]
542 def opath_validchar(c
):
543 # _ is also escaped even though it is valid
545 string
.ascii_letters
.find(c
) != -1 or \
546 string
.digits
.find(c
) != -1
551 # TODO find a more elegant way
552 if not opath_validchar(c
):
558 def opath_unescape(s
):
560 unhex
= lambda xx
: chr(eval("0x"+xx
))
562 return re
.sub("_.._", lambda p
: unhex(p
.group()[1:3]), s
)
566 return self
.appi
.Get(NMI
, "MaxBitrate")
569 priv
= self
.appi
.Get(NMI
, "Flags") != 0
570 wpa
= self
.appi
.Get(NMI
, "WpaFlags") != 0
571 wpa2
= self
.appi
.Get(NMI
, "RsnFlags") != 0
574 if not wpa
and not wpa2
:
575 priv_s
= priv_s
+ " WEP"
577 priv_s
= priv_s
+ " WPA"
579 priv_s
= priv_s
+ " WPA2"
583 return int(self
.appi
.Get(NMI
, "Strength"))
586 return ssid_str(self
.appi
.Get(NMI
, "Ssid"))
589 print " AP:", self
.opath
590 print " Ssid:", self
.Ssid()
591 for P
in ["Frequency", "HwAddress", "MaxBitrate",]:
592 print " %s: %s" % (P
, self
.appi
.Get(NMI
, P
))
593 print " Strength:", self
.Strength()
594 print " AP Mode:", cDevice
.IW_MODE
[self
.appi
.Get(NMI
, "Mode")]
595 print " AP Flags:", bitmask_str(self
.NM_802_11_AP_FLAGS
,
596 self
.appi
.Get(NMI
, "Flags"))
597 print " AP WPA Flags:", bitmask_str(self
.NM_802_11_AP_SEC
,
598 self
.appi
.Get(NMI
, "WpaFlags"))
599 print " AP RSN Flags:", bitmask_str(self
.NM_802_11_AP_SEC
,
600 self
.appi
.Get(NMI
, "RsnFlags"))
602 # this is the client side of the applet; see also UserSettings
604 def __init__(self
, svc
, opath
):
607 self
.so
= bus
.get_object(self
.svc
, self
.opath
)
608 self
.si
= dbus
.Interface(self
.so
, 'org.freedesktop.NetworkManagerSettings')
611 return self
.svc
== SSC
;
614 for conn
in self
.Connections():
619 def DumpSystem(self
):
620 sspi
= dbus
.Interface(self
.so
, PI
)
621 print "Unmanaged Devices"
622 umds
= sspi
.Get(NMI
, "UnmanagedDevices")
625 # dump_settings_conn(svc, conn) umd?
628 def myConnection(self
, opath
):
629 return cConnection(self
.svc
, opath
)
631 def Connections(self
):
632 opaths
= self
.si
.ListConnections()
633 return map(self
.myConnection
, opaths
)
635 NETWORK_TYPE_ALLOWED
= 1
636 class cApplet_06(cApplet
):
637 def __init__(self
, svc
, opath
):
640 self
.io
= bus
.get_object(self
.svc
, self
.opath
)
641 self
.ii
= dbus
.Interface(self
.io
, 'org.freedesktop.NetworkManagerInfo')
646 def myConnection(self
, opath
):
647 return cConnection_06(self
, opath
)
649 # TODO also VPN conns
650 def Connections(self
):
651 names
= self
.ii
.getNetworks(NETWORK_TYPE_ALLOWED
)
652 return map(self
.myConnection
, names
)
655 def __init__(self
, svc
, opath
):
658 self
.co
= bus
.get_object(self
.svc
, self
.opath
)
659 self
.ci
= dbus
.Interface(self
.co
, 'org.freedesktop.NetworkManagerSettings.Connection')
662 print "Conn:", self
.opath
663 settings
= self
.Settings()
666 si
= dbus
.Interface(self
.co
, 'org.freedesktop.NetworkManagerSettings.Connection.Secrets')
667 security
= settings
.Security()
669 print " SECRETS:", security
672 secrets
= cSettings(si
.GetSecrets(security
,[],False))
674 except dbus
.exceptions
.DBusException
, e
:
675 if e
.get_dbus_name() == "org.freedesktop.DBus.Error.AccessDenied":
676 print " Access denied"
679 print " FIXME figure out 802-1x secrets"
682 return cSettings(self
.ci
.GetSettings())
684 def dump_time(unixtime
):
685 return time
.asctime(time
.localtime(unixtime
))
687 class cConnection_06
:
688 def __init__(self
, applet
, id):
693 print "Conn:", self
.id
695 np
= self
.applet
.ii
.getNetworkProperties(self
.id, NETWORK_TYPE_ALLOWED
)
698 print " time:", dump_time(np
[1])
699 print " trusted:", bool(np
[2])
700 print " bssids:", ", ".join(np
[3])
702 print " we_cipher:", enctype
704 print " secret:", np
[5]
706 print " wep_auth_algorithm:", np
[6]
708 print " wpa_psk_key_mgt:", np
[6]
709 print " wpa_psk_wpa_version:", np
[7]
711 return # nm-applet will not tell kfn anyway
712 devp
= "/org/freedesktop/NetworkManager/Devices/ath0" #FIXME
713 netp
= devp
+ "/Networks/" + opath_escape(self
.id)
716 kfn
= self
.applet
.ii
.getKeyForNetwork(devp
, netp
, ssid
, attempt
, newkey
)
721 NM_AUTH_TYPE_WPA_PSK_AUTO
= 0x00000000
722 NM_AUTH_TYPE_NONE
= 0x00000001
723 NM_AUTH_TYPE_WEP40
= 0x00000002
724 NM_AUTH_TYPE_WPA_PSK_TKIP
= 0x00000004
725 NM_AUTH_TYPE_WPA_PSK_CCMP
= 0x00000008
726 NM_AUTH_TYPE_WEP104
= 0x00000010
727 NM_AUTH_TYPE_WPA_EAP
= 0x00000020
728 NM_AUTH_TYPE_LEAP
= 0x00000040
730 IW_AUTH_ALG_OPEN_SYSTEM
= 0x00000001
731 IW_AUTH_ALG_SHARED_KEY
= 0x00000002
732 IW_AUTH_ALG_LEAP
= 0x00000004
735 def __init__(self
, conmap
):
736 #print "INIT", conmap
740 return self
.conmap
["connection"]["type"]
743 return self
.conmap
["connection"]["id"]
747 return self
.conmap
["802-11-wireless"]["ssid"]
750 # probably 802-3-ethernet
755 return self
.conmap
["connection"]["timestamp"]
763 def SeenBssids(self
):
765 return self
.conmap
["802-11-wireless"]["seen-bssids"]
773 return NM_AUTH_TYPE_WEP104
775 return NM_AUTH_TYPE_WPA_PSK_AUTO
777 return NM_AUTH_TYPE_NONE
778 print "Defaulting cipher type to none"
779 return NM_AUTH_TYPE_NONE
783 return self
.conmap
["802-11-wireless-security"]["psk"]
787 return self
.conmap
["802-11-wireless-security"]["wep-key0"]
793 def WepAuthAlgorithm(self
):
794 print "FIXME Defaulting WEP auth alg to open"
795 return IW_AUTH_ALG_OPEN_SYSTEM
798 print "FIXME Defaulting PSK key mgmt to 2"
801 def PskWpaVersion(self
):
802 print "FIXME Defaulting WPA version to 2"
807 return self
.conmap
[self
.Type()]["security"]
811 def isNet(self
, net_name
):
812 return self
.ID() == net_name
or self
.Ssid() == net_name
814 # FIXME check spec/NM what to censor
815 secrets
= dict.fromkeys(["wep-key0", "psk"])
818 "For GetSettings: censor secrets."
821 for n1
, v1
in self
.conmap
.iteritems():
823 for n2
, v2
in v1
.iteritems():
825 if self
.secrets
.has_key(n2
):
831 "For GetSecrets: only secrets."
840 for n1
, v1
in self
.conmap
.iteritems():
842 for n2
, v2
in v1
.iteritems():
843 print " %s: %s" % (n2
, v2
)
845 def mkconmap_wifi(ssid
):
848 'id': '_cnm_handcrafted_',
849 'uuid': str(uuid
.uuid1()), # new in oS 11.1
850 'type': '802-11-wireless',
853 'ssid': dbus
.ByteArray(ssid
),
854 'mode': 'infrastructure',
858 def elongate(s
, tlen
):
859 "repeat string s to target length tlen"
862 copies_needed
= int(math
.ceil(tlen
/ float(len(s
))))
863 return (s
* copies_needed
)[:tlen
]
865 # http://www.mail-archive.com/networkmanager-list@gnome.org/msg07935.html
866 def wep_passphrase_to_hash(p
):
867 return hashlib
.md5(elongate(p
, 64)).hexdigest()
869 def mkconmap_wep_pass(ssid
, key
):
870 cm
= mkconmap_wifi(ssid
)
871 cm
["802-11-wireless"]["security"] = "802-11-wireless-security"
872 cm
["802-11-wireless-security"] = {}
873 cm
["802-11-wireless-security"]["key-mgmt"] = "none"
874 cm
["802-11-wireless-security"]["wep-tx-keyidx"] = 0
875 cm
["802-11-wireless-security"]["wep-key0"] = wep_passphrase_to_hash(key
)
878 def mkconmap_wep(ssid
, key
):
879 cm
= mkconmap_wifi(ssid
)
880 cm
["802-11-wireless"]["security"] = "802-11-wireless-security"
881 cm
["802-11-wireless-security"] = {}
882 cm
["802-11-wireless-security"]["key-mgmt"] = "none"
883 cm
["802-11-wireless-security"]["wep-tx-keyidx"] = 0
884 cm
["802-11-wireless-security"]["wep-key0"] = key
887 def mkconmap_psk(ssid
, key
):
888 cm
= mkconmap_wifi(ssid
)
889 cm
["802-11-wireless"]["security"] = "802-11-wireless-security"
890 cm
["802-11-wireless-security"] = {}
891 cm
["802-11-wireless-security"]["key-mgmt"] = "wpa-psk"
892 cm
["802-11-wireless-security"]["psk"] = key
893 cm
["802-11-wireless-security"]["group"] = ["tkip", "ccmp"]
894 cm
["802-11-wireless-security"]["pairwise"] = ["tkip", "ccmp"]
898 # server analog of cApplet
899 class UserSettings(dbus
.service
.Object
):
901 def __init__(self
, opath
, conmaps
):
902 dbus
.service
.Object
.__init
__(self
, bus
, opath
)
903 #print "CONMAPS:", conmaps
904 self
.conns
= map(self
.newCon
, conmaps
)
906 def addCon(self
, conmap
):
907 c
= self
.newCon(conmap
)
912 def newCon(self
, conmap
):
913 cpath
= "/MyConnection/%d" % self
.counter
914 self
.counter
= self
.counter
+ 1
915 c
= Connection(cpath
, conmap
)
916 self
.NewConnection(cpath
) # announce it
919 @dbus.service
.method(dbus_interface
='org.freedesktop.NetworkManagerSettings',
920 in_signature
='', out_signature
='ao')
921 def ListConnections(self
):
922 return [c
.__dbus
_object
_path
__ for c
in self
.conns
]
924 #this is for EMITTING a signal, not receiving it
925 @dbus.service
.signal(dbus_interface
='org.freedesktop.NetworkManagerSettings',
927 def NewConnection(self
, opath
):
929 #print "signalling newconn:", opath
931 def GetByNet(self
, net_name
):
932 "Returns connection, or None"
934 if c
.isNet(net_name
):
939 class UserSettings_06(UserSettings
):
941 def __init__(self
, opath
, conmaps
):
942 dbus
.service
.Object
.__init
__(self
, bus
, opath
)
943 #print "CONMAPS:", conmaps
944 self
.conns
= map(self
.newCon
, conmaps
)
947 def newCon(self
, conmap
):
948 cpath
= "/MyConnection/%d" % self
.counter
949 self
.counter
= self
.counter
+ 1
950 c
= Connection_06(cpath
, conmap
)
951 #self.NewConnection(cpath) # announce it
954 @dbus.service
.method(dbus_interface
="org.freedesktop.NetworkManagerInfo",
955 in_signature
="i", out_signature
='as')
956 def getNetworks(self
, i
):
957 # FIXME bytearray to str WHERE?
958 #n = [ssid_str(c.Ssid()) for c in self.conns]
959 n
= [c
.ID() for c
in self
.conns
]
960 print "getNetworks:", n
963 @dbus.service
.method(dbus_interface
="org.freedesktop.NetworkManagerInfo",
964 in_signature
="", out_signature
='ao') # out??
965 def getVPNConnections(self
):
968 @dbus.service
.method(dbus_interface
="org.freedesktop.NetworkManagerInfo",
970 #out_signature='sibasi') #varies
971 def getNetworkProperties(self
, net
, type):
973 # type is 1, NETWORK_TYPE_ALLOWED
974 c
= self
.GetByNet(net
)
976 return c
.getNetworkProperties()
977 print "Oops, could not getNetworkProperties for " + net
980 @dbus.service
.method(dbus_interface
="org.freedesktop.NetworkManagerInfo",
981 in_signature
="oosib")
982 #out_signature="isi") varies
983 def getKeyForNetwork(self
, dev
, net
, ssid
, attempt
, newkey
):
984 print "GKFN", dev
, net
, ssid
, attempt
, bool(newkey
)
986 m
= "Cannot ask for key"
988 raise dbus
.exceptions
.DBusException(m
)
990 snet
= opath_unescape(net
[net
.rfind("/")+1 : ]) # only stuff after /
991 c
= self
.GetByNet(snet
)
993 return c
.getKeyForNetwork()
994 print "Oops, could not getKeyForNetwork " + net
996 @dbus.service
.method(dbus_interface
="org.freedesktop.NetworkManagerInfo",
998 #in_signature="sbs isi", varies
999 def updateNetworkInfo(self
, ssid
, automatic
, bssid
, *security
):
1000 print "Connected successfully"
1003 print " ssid:", ssid
1004 print " automatic:", bool(automatic
)
1005 print " bssid:", bssid
1006 print " security:", security
1009 def GetByNet(self
, net_name
):
1010 "Returns connection, or None"
1011 for c
in self
.conns
:
1012 if c
.isNet(net_name
):
1017 # server analog of cConnection
1018 class Connection(dbus
.service
.Object
):
1019 def __init__(self
, opath
, conmap
):
1020 dbus
.service
.Object
.__init
__(self
, bus
, opath
)
1021 self
.settings
= cSettings(conmap
)
1023 @dbus.service
.method(dbus_interface
='org.freedesktop.NetworkManagerSettings.Connection',
1024 sender_keyword
='sender',
1025 in_signature
='', out_signature
='a{sa{sv}}')
1026 def GetSettings(self
, sender
):
1027 #print "Getting settings:", self. __dbus_object_path__
1028 # return self.settings.ConMap()
1029 # grr, censoring secrets makes NM complain!?
1030 # bnc#479566#c3: Until I figure out how to make it work with
1031 # censored secrets, only pass the settings to the same user.
1032 sender_uid
= bus
.get_unix_user(sender
)
1033 if sender_uid
!= 0 and sender_uid
!= os
.geteuid():
1034 e
= "User %u is not permitted to read the settings" % sender_uid
1036 raise dbus
.exceptions
.DBusException(e
) # could do NM_SETTINGS_ERROR_* instead
1037 return self
.settings
.conmap
1039 @dbus.service
.method(dbus_interface
='org.freedesktop.NetworkManagerSettings.Connection.Secrets',
1040 in_signature
='sasb', out_signature
='a{sa{sv}}')
1041 def GetSecrets(self
, tag
, hints
, ask
):
1042 # FIXME respect args
1043 print "Getting secrets:", self
.__dbus
_object
_path
__
1044 return self
.settings
.SecMap()
1046 @dbus.service
.method(dbus_interface
='org.freedesktop.NetworkManagerSettings.Connection',
1047 in_signature
='', out_signature
='s')
1049 return self
.settings
.ID()
1052 return self
.settings
.Ssid()
1054 def isNet(self
, net_name
):
1055 return self
.settings
.isNet(net_name
)
1057 class Connection_06(Connection
):
1058 def __init__(self
, opath
, conmap
):
1059 dbus
.service
.Object
.__init
__(self
, bus
, opath
)
1061 self
.settings
= cSettings(conmap
)
1063 # dbus.service.method
1064 def getNetworkProperties(self
):
1065 # essid, timestamp, ?, bssids, we_cipher, ?, ...
1066 # we_cipher=16: i wep_auth_algorithm
1067 # we_cipher=0: i wpa_psk_key_mgt, i wpa_psk_wpa_version
1068 ssid
= ssid_str(self
.settings
.Ssid())
1069 time
= self
.settings
.Timestamp() # last sucessfully connected? seen?
1070 trusted
= self
.settings
.Trusted()
1071 bssids
= dbus
.Array(self
.settings
.SeenBssids(), signature
="s")
1072 r
= [ssid
, time
, trusted
, bssids
]
1073 security
= self
.getKeyForNetwork("fake key")
1077 # dbus.service.method
1078 def getKeyForNetwork(self
, fake
="no"):
1080 key
= self
.settings
.Key()
1085 cip
= self
.settings
.WeCipher()
1086 if cip
== NM_AUTH_TYPE_NONE
:
1087 security
= tuple([cip
])
1088 elif cip
== NM_AUTH_TYPE_WEP40
or cip
== NM_AUTH_TYPE_WEP104
:
1089 wep_auth_algorithm
= self
.settings
.WepAuthAlgorithm()
1090 security
= (cip
, key
, wep_auth_algorithm
)
1091 elif cip
== NM_AUTH_TYPE_WPA_PSK_AUTO
or cip
== NM_AUTH_TYPE_TKIP
or \
1092 cip
== NM_AUTH_TYPE_CCMP
:
1093 wpa_psk_key_mgt
= self
.settings
.PskKeyMgt()
1094 wpa_psk_wpa_version
= self
.settings
.PskWpaVersion()
1095 security
= (cip
, key
, wpa_psk_key_mgt
, wpa_psk_wpa_version
)
1096 elif cip
== NM_AUTH_TYPE_WPA_EAP
:
1097 security
= tuple([cip
]) # TODO more...
1098 elif cip
== NM_AUTH_TYPE_LEAP
:
1099 security
= tuple([cip
]) # TODO more...
1103 class ConfigParserKNM
:
1104 "Parse ~/.kde/share/config/knetworkmanagerrc"
1107 p
= ConfigParser
.RawConfigParser()
1108 ok
= p
.read(os
.getenv("HOME") + "/.kde/share/config/knetworkmanagerrc")
1111 for s
in p
.sections():
1114 if path
[0] in ["ConnectionSetting", "ConnectionSecrets"]:
1116 self
.conmaps_d
.setdefault(cid
, {})
1120 for (n
, v
) in p
.items(s
):
1121 # WTF, Value_ is transformed to value_
1122 if n
[:6] == "value_":
1124 v
= self
.ParseValue(v
)
1125 #print "# %s:%s" % (n, v)
1126 # do not overwrite ConnectionSecrets
1127 # with empty ConnectionSettings field
1129 vv
= self
.conmaps_d
[cid
][part
][n
]
1134 if len(values
) != 0: # empty 802-1x confuses NM!?
1135 self
.conmaps_d
[cid
].setdefault(part
, {})
1136 self
.conmaps_d
[cid
][part
].update(**values
)
1137 #print "PARSED", cid, part, values
1140 return self
.conmaps_d
.values()
1142 def ParseValue(self
, v
):
1143 v
= eval('"%s"' % v
) # unescape backslashes
1144 dom
= xml
.dom
.minidom
.parseString(v
)
1145 return self
.ParseNode(dom
.documentElement
)
1147 def ParseNode(self
, n
):
1150 v
= self
.NodeText(n
)
1155 return dbus
.Byte(int(v
))
1158 elif t
== "int32" or t
== "uint32":
1164 if c
.localName
!= None: # whitespace
1165 v
.append(self
.ParseNode(c
))
1169 def NodeText(self
, n
):
1170 if n
.hasChildNodes():
1171 return n
.firstChild
.wholeText
1179 bus
.add_signal_receiver(self
.abbr_h
,
1180 path_keyword
="path",
1181 interface_keyword
="interface",
1182 member_keyword
="member")
1184 def ignore(self
, dbus_interface
, signal_name
):
1185 self
.watch(self
.null_h
, dbus_interface
, signal_name
)
1187 def null_h(self
, *args
, **kwargs
):
1190 def watch(self
, handler
, dbus_interface
, signal_name
):
1191 self
.specific
[dbus_interface
+"."+ signal_name
] = True
1192 bus
.add_signal_receiver(handler
,
1193 dbus_interface
=dbus_interface
,
1194 signal_name
=signal_name
,
1195 path_keyword
="path")
1197 def abbr_h(self
, *args
, **kwargs
):
1198 ifc
= kwargs
["interface"]
1199 sig
= kwargs
["member"]
1200 if self
.specific
.has_key(ifc
+"."+ sig
):
1203 opath
= kwargs
["path"]
1204 line
= "SIG %s: %s.%s%s" % (self
.abbrev(opath
,"/"),
1205 self
.abbrev(ifc
,"."),
1209 def abbrev(self
, s
, sep
):
1210 words
= s
.split(sep
)
1211 words
= map (self
.a1
, words
)
1212 result
= sep
.join(words
)
1213 if self
.amap
.has_key(result
):
1214 if self
.amap
[result
] != s
:
1215 print "ABBR COLLISION %s was %s now %s" % (result
, self
.amap
[result
], s
)
1217 print "ABBR %s is %s" % (result
, s
)
1218 self
.amap
[result
] = s
1225 # first char, delete lowercase and _ from the rest
1226 return s
[0] + s
[1:].translate(string
.maketrans("", ""),
1227 string
.lowercase
+ "_")
1229 class Monitor(MonitorBase
):
1231 MonitorBase
.__init
__(self
)
1235 dbus_interface
="org.freedesktop.NetworkManager.Device.Wireless",
1236 signal_name
="PropertiesChanged")
1239 dbus_interface
="org.freedesktop.NetworkManager.AccessPoint",
1240 signal_name
="PropertiesChanged")
1242 self
.ignore("org.freedesktop.Hal.Device", "PropertyModified")
1243 self
.ignore("fi.epitest.hostap.WPASupplicant.Interface", "ScanResultsAvailable")
1244 self
.ignore("com.redhat.PrinterSpooler", "QueueChanged")
1245 self
.ignore("org.freedesktop.NetworkManager", "StateChange") # deprecated
1246 self
.watch(self
.nm_sc_h
, "org.freedesktop.NetworkManager", "StateChanged")
1247 self
.watch(self
.wpas_isc_h
, "fi.epitest.hostap.WPASupplicant.Interface", "StateChange")
1248 self
.watch(self
.nmd_sc_h
, "org.freedesktop.NetworkManager.Device", "StateChanged")
1249 self
.watch(self
.bus_noc_h
, "org.freedesktop.DBus", "NameOwnerChanged")
1251 def bus_noc_h(self
, *args
, **kwargs
):
1252 (name
, old
, new
) = args
1257 print "\tBUS NOC\t%s %s" % (name
, new
)
1259 def wpas_isc_h(self
, *args
, **kwargs
):
1260 opath
= kwargs
["path"]
1262 print "\tWPAS %s\t(%s, was %s)" % (new
, opath
, old
.lower())
1264 def nmd_sc_h(self
, *args
, **kwargs
):
1265 opath
= kwargs
["path"]
1266 (new
, old
, reason
) = args
1267 news
= cDevice_07
.NM_DEVICE_STATE
[new
]
1268 olds
= cDevice_07
.NM_DEVICE_STATE
[old
]
1271 reasons
= "reason %d" % reason
1272 print "\tDevice State %s\t(%s, was %s%s)" % (news
, opath
, olds
.lower(), reasons
)
1274 def nm_sc_h(self
, *args
, **kwargs
):
1276 ss
= cNM
.NM_STATE
[s
]
1277 print "\tNM State:", ss
1279 def propc_h(self
, *args
, **kwargs
):
1280 opath
= kwargs
["path"]
1282 for k
, v
in props
.iteritems():
1285 line
= "\tPROP\t%s\t%s\t(%s)" % (k
, v
, opath
)
1293 op
= OptionParser(version
="%prog " + VERSION
)
1294 op
.add_option("-d", "--dev",
1295 action
="store_true", default
=False,
1296 help="list devices")
1297 op
.add_option("-c", "--actcon",
1298 action
="store_true", default
=False,
1299 help="list active connections")
1300 op
.add_option("-u", "--usrcon",
1301 action
="store_true", default
=False,
1302 help="list user connection settings (can CRASH nm-applet)")
1303 op
.add_option("-s", "--syscon",
1304 action
="store_true", default
=False,
1305 help="list system connection settings")
1306 op
.add_option("-a", "--ap",
1307 action
="store_true", default
=False,
1308 help="list found access points")
1309 op
.add_option("-n", "--nets",
1310 action
="store_true", default
=False,
1311 help="list found wireless networks")
1312 # TODO http://docs.python.org/lib/optparse-adding-new-types.html
1313 op
.add_option("-w", "--wifi",
1314 choices
=["0","1","off","on","no","yes","false","true"],
1316 help="enable or disable wireless")
1317 op
.add_option("-o", "--online",
1318 choices
=["0","1","off","on","no","yes","false","true"],
1320 help="enable or disable network at all")
1322 op
.add_option("--activate-connection",
1323 help="raw API: activate the KIND(user/system) connection CON on device DEV using AP",
1324 metavar
="[KIND],CON,DEV,[AP]")
1325 op
.add_option("-C", "--connect",
1326 help="connect to a wireless network NET (using knetworkmanagerrc or the key options below)",
1328 op
.add_option("--unprotected",
1329 action
="store_true", default
=False,
1330 help="network does not require a key")
1331 op
.add_option("--wep-hex",
1333 help="use this WEP key of 26 hex digits")
1334 op
.add_option("--wep-pass",
1336 help="use this WEP passphrase")
1337 op
.add_option("--wpa-psk-hex",
1339 help="use this WPA key of 64 hex digits")
1340 op
.add_option("--wpa-pass",
1342 help="use this WPA passphrase")
1343 op
.add_option("-m", "--monitor",
1344 action
="store_true", default
=False,
1345 help="loop to show dbus signals")
1348 (options
, args
) = op
.parse_args()
1356 nmp
= '/org/freedesktop/NetworkManager'
1359 except dbus
.exceptions
.DBusException
, e
:
1360 print "NetworkManager is not running or running as an other user"
1362 if options
.dev
or options
.actcon
:
1365 true_choices
= ["1", "on", "yes", "true"]
1366 if options
.wifi
!= None:
1367 nm
.SetWifiEnabled(options
.wifi
in true_choices
)
1368 if options
.online
!= None:
1369 nm
.SetOnline(options
.online
in true_choices
)
1375 print "SYSTEM Connections"
1376 if nm
.Api() == "06":
1377 print "Cannot do that with NM 0.6"
1380 ss
= cApplet(SSC
, '/org/freedesktop/NetworkManagerSettings')
1384 print "USER Connections"
1386 if nm
.Api() == "06":
1387 us
= cApplet_06(NMIC
, "/org/freedesktop/NetworkManagerInfo")
1389 us
= cApplet(USC
, '/org/freedesktop/NetworkManagerSettings')
1391 except dbus
.exceptions
.DBusException
, e
:
1393 #if e.get_dbus_name() == "org.freedesktop.DBus.Error.ServiceUnknown":
1394 print "Applet is not running"
1397 nmo
= bus
.get_object(NMC
, nmp
)
1398 nmi
= dbus
.Interface(nmo
, NMI
)
1400 def service_pid(name
):
1401 DBS
= 'org.freedesktop.DBus'
1403 dbo
= bus
.get_object(DBS
, '/')
1404 dbi
= dbus
.Interface(dbo
, DBI
)
1405 owner
= dbi
.GetNameOwner(name
)
1406 pid
= dbi
.GetConnectionUnixProcessID(owner
)
1409 # TODO UserSettings_06
1410 if options
.connect
!= None:
1411 if nm
.Api() == "06":
1415 brn
= bus
.request_name(name
, _dbus_bindings
.NAME_FLAG_DO_NOT_QUEUE
)
1416 if brn
== _dbus_bindings
.REQUEST_NAME_REPLY_EXISTS
:
1417 print "Could not provide settings service, another applet is running (pid %s)" % service_pid(name
)
1419 cfg
= ConfigParserKNM()
1420 if nm
.Api() == "06":
1421 us
= UserSettings_06("/org/freedesktop/NetworkManagerInfo",
1424 us
= UserSettings("/org/freedesktop/NetworkManagerSettings",
1427 def Connect(wanted_net
): # any. or take arg. net is config name or ssid name
1428 # ... in general, look for string in all config data. ssid for wifi, whatever for dialup
1429 # TODO also respect autoconnect
1431 # ActivateConn wants setting device ap; can find device from ap? ap is "specific" for wifi devices
1432 #print "Connection wanted to", wanted_net
1433 found_con
= found_ap
= found_dev
= None
1434 for dev
in nm
.Devices():
1435 for ap
in dev
.APs():
1436 if wanted_net
== ap
.Ssid():
1439 break # FIXME both loops
1440 found_con
= us
.GetByNet(wanted_net
)
1441 if found_ap
== None:
1442 print "No AP found with SSID", wanted_net
1444 if found_con
== None:
1445 print "No settings for net %s, assuming no key is needed" % wanted_net
1446 c
= mkconmap_wifi(wanted_net
)
1447 found_con
= us
.addCon(c
)
1448 nm
.ActivateConnection(found_con
, found_dev
, found_ap
) # TODO async
1449 # TODO run loop, exit it when we have serviced the required calls
1452 if options
.connect
!= None:
1453 if options
.unprotected
:
1454 c
= mkconmap_wifi(options
.connect
)
1456 if options
.wep_hex
!= None:
1457 c
= mkconmap_wep(options
.connect
, options
.wep_hex
)
1459 if options
.wep_pass
!= None:
1460 c
= mkconmap_wep_pass(options
.connect
, options
.wep_pass
)
1462 if options
.wpa_psk_hex
!= None:
1463 c
= mkconmap_psk(options
.connect
, options
.wpa_psk_hex
)
1465 if options
.wpa_pass
!= None:
1466 wpa_psk_hex
= hexlify(pbkdf2
.pbkdf2(options
.wpa_pass
, options
.connect
, 4096, 32))
1467 print "pbkdf2", wpa_psk_hex
1468 c
= mkconmap_psk(options
.connect
, wpa_psk_hex
)
1471 if Connect(options
.connect
):
1476 if options
.activate_connection
!= None:
1477 (svc
, conpath
, devpath
, appath
) = options
.activate_connection
.split(',')
1478 if svc
== "" or svc
== "user":
1480 elif svc
== "system":
1488 nm
.nmi
.ActivateConnection(svc
, conpath
, devpath
, appath
,
1489 reply_handler
=nm
.silent_handler
,
1490 error_handler
=nm
.err_handler
,
1498 loop
= gobject
.MainLoop()