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
12 import ConfigParser
# knm config
13 from optparse
import OptionParser
19 print "Install python-1-dbus.rpm"
21 import xml
.dom
.minidom
25 # todo - only if loop wanted
26 print "Install python-gobject2.rpm"
28 # python-gnome.rpm has gconf for nm-applet...
32 from dbus
.mainloop
.glib
import DBusGMainLoop
33 DBusGMainLoop(set_as_default
=True)
37 bus
= dbus
.SystemBus()
39 # FOOC = connection (service) string
40 # FOOI = interface string
43 # foopi = property interface
44 NMC
= 'org.freedesktop.NetworkManager'
46 PI
= 'org.freedesktop.DBus.Properties'
47 SSC
= "org.freedesktop.NetworkManagerSystemSettings"
48 USC
= "org.freedesktop.NetworkManagerUserSettings"
51 ii
= dbus
.Interface(obj
, 'org.freedesktop.DBus.Introspectable')
55 # TODO: pull them from introspection.xml
56 NM_STATE
= ["UNKNOWN", "ASLEEP", "CONNECTING", "CONNECTED", "DISCONNECTED",]
58 def __init__(self
, opath
):
60 self
.nmo
= bus
.get_object(NMC
, self
.opath
)
61 self
.nmi
= dbus
.Interface(self
.nmo
, NMI
)
62 self
.nmpi
= dbus
.Interface(self
.nmo
, PI
)
64 def SetWifiEnabled(self
, v
):
65 self
.nmpi
.Set(NMI
, "WirelessEnabled", v
)
67 def SetOnline(self
, v
):
71 print "State:", self
.NM_STATE
[self
.nmpi
.Get(NMI
, "State")]
72 print "Wifi enabled:", self
.nmpi
.Get(NMI
, "WirelessEnabled")
73 print "Wifi HW enabled:", self
.nmpi
.Get(NMI
, "WirelessHardwareEnabled")
74 # self.nmpi.Set(NMI, "WirelessEnabled", True)
75 # self.nmi.Sleep(True)
78 print "State:", self
.NM_STATE
[self
.nmi
.state()]
81 "Dumps its own info (not owned objects)."
84 dummy
= self
.nmi
.getDevices()
92 for device
in self
.Devices():
96 print "Active Connections"
97 aconns
= self
.ActiveConnections()
103 opaths
= self
.nmi
.getDevices() # 0.6
105 opaths
= self
.nmi
.GetDevices()
106 return map(cDevice
, opaths
)
109 print "Wifi Networks:"
110 for dev
in self
.Devices():
113 def ActiveConnections(self
):
115 aconns
= self
.nmi
.GetActiveConnections() # 0.6
117 aconns
= self
.nmpi
.Get(NMI
, "ActiveConnections")
118 return map(cActiveConnection
, aconns
)
120 def reply_handler(self
, opath
):
121 print "Connected:", opath
123 def err_handler(self
, *args
):
126 def ActivateConnection(self
, conn
, device
, ap
):
127 self
.nmi
.ActivateConnection(USC
,
128 conn
.__dbus
_object
_path
__,
131 reply_handler
=self
.reply_handler
,
132 error_handler
=self
.err_handler
,
135 class cActiveConnection
:
136 def __init__(self
, opath
):
141 co
= bus
.get_object(NMC
, self
.opath
)
142 copi
= dbus
.Interface(co
, PI
)
143 for P
in ["ServiceName", "Connection", "SharedServiceName", "SharedConnection", "SpecificObject",]:
144 print " %s: %s" % (P
, copi
.Get(NMI
, P
))
145 devs
= copi
.Get(NMI
, "Devices")
150 def bitmask_str(map, value
):
152 for mask
, s
in map.iteritems():
153 if value
& mask
: ret
.append(s
)
158 def __init__(self
, opath
):
160 self
.devo
= bus
.get_object(NMC
, self
.opath
)
161 self
.devi
= dbus
.Interface(self
.devo
, NMI
+ ".Device")
162 self
.devpi
= dbus
.Interface(self
.devo
, PI
)
164 DEVICE_TYPE
= ["UNKNOWN", "802_3_ETHERNET", "802_11_WIRELESS",
167 def DeviceType(self
):
168 return self
.DEVICE_TYPE
[self
.devpi
.Get(NMI
, "DeviceType")]
171 return self
.DeviceType() == "802_11_WIRELESS"
176 self
.wdevi
= dbus
.Interface(self
.devo
, NMI
+ ".Device.Wireless")
177 aps
= self
.wdevi
.GetAccessPoints()
180 def ip_str(self
, i32
):
182 ret
.append("%d" % (i32
% 256))
184 ret
.append("%d" % (i32
% 256))
186 ret
.append("%d" % (i32
% 256))
188 ret
.append("%d" % (i32
% 256))
192 def DumpIp4Config(self
, opath
):
193 print " Ip4Config:", opath
194 o
= bus
.get_object(NMC
, opath
)
195 pi
= dbus
.Interface(o
, PI
)
197 for P
in ["Address", "Netmask", "Broadcast", "Gateway",]: # beta2?
198 print " %s: %s" % (P
, self
.ip_str(pi
.Get(NMI
, P
)))
201 addrs
= pi
.Get(NMI
, "Addresses")
203 print " %s/%s via %s" % tuple(map(self
.ip_str
, addr
))
204 hn
= pi
.Get(NMI
, "Hostname")
205 print " Hostname:", hn
206 nss
= pi
.Get(NMI
, "Nameservers")
207 print " Nameservers:", " ".join(map(self
.ip_str
, nss
))
208 doms
= pi
.Get(NMI
, "Domains")
209 print " Domains:", " ".join(doms
)
210 nisd
= pi
.Get(NMI
, "NisDomain")
211 print " NisDomain:", nisd
212 niss
= pi
.Get(NMI
, "NisServers")
213 print " NisServers:", " ".join(map(self
.ip_str
, niss
))
215 NM_DEVICE_CAP
= {1: "NM_SUPPORTED", 2: "CARRIER_DETECT",}
218 "UNKNOWN", "UNMANAGED", "UNAVAILABLE", "DISCONNECTED", "PREPARE",
219 "CONFIG", "NEED_AUTH", "IP_CONFIG", "ACTIVATED", "FAILED",]
222 # "Ip4Config", only for NM_DEVICE_STATE_ACTIVATED
223 for P
in ["Udi", "Interface", "Driver",]:
224 print " %s: %s" % (P
, self
.devpi
.Get(NMI
, P
))
225 addr
= self
.devpi
.Get(NMI
, "Ip4Address")
226 print " Ip4Address:", self
.ip_str(addr
)
227 caps
= self
.devpi
.Get(NMI
, "Capabilities")
228 print " Capabilities:", bitmask_str(self
.NM_DEVICE_CAP
, caps
)
229 state
= self
.NM_DEVICE_STATE
[self
.devpi
.Get(NMI
, "State")]
230 print " Dev State:", state
231 if state
== "ACTIVATED":
232 self
.DumpIp4Config(self
.devpi
.Get(NMI
, "Ip4Config"))
234 dt
= self
.DeviceType()
235 print " Dev Type:", dt
236 if dt
== "802_3_ETHERNET":
238 elif dt
== "802_11_WIRELESS":
242 print " Driver:", self
.devi
.getDriver()
243 props
= self
.devi
.getProperties()
244 print " Self:", props
[0]
245 print " Interface:", props
[1]
246 print " Type:", self
.DEVICE_TYPE
[props
[2]]
247 print " UDI:", props
[3]
248 print " ?4:", props
[4]
249 print " ?5:", props
[5]
250 print " IP:", props
[6]
251 print " Mask:", props
[7]
252 print " Bcast:", props
[8]
253 print " MAC:", props
[9]
254 print " GW:", props
[10]
255 print " NS1:", props
[11]
256 print " NS2:", props
[12]
257 print " ?13:", props
[13]
258 print " Strength:", props
[14]
259 print " ?15:", props
[15]
260 print " ?16:", props
[16]
261 print " ?17:", props
[17]
262 print " ?18:", props
[18]
263 print " Current net:", props
[19]
264 print " Seen nets:", " ".join(props
[20])
267 print "Device:", self
.opath
269 a
= self
.devi
.getDriver()
271 except dbus
.exceptions
.DBusException
:
275 for P
in ["HwAddress", "Speed", "Carrier"]:
276 print " %s: %s" % (P
, self
.devpi
.Get(NMI
, P
))
279 IW_MODE
= ["AUTO", "ADHOC", "INFRA", "MASTER",
280 "REPEAT", "SECOND", "MONITOR",]
282 NM_802_11_DEVICE_CAP
= {1:"CIPHER_WEP40", 2:"CIPHER_WEP104",
283 4:"CIPHER_TKIP", 8:"CIPHER_CCMP",
287 print " Dev Mode:", self
.IW_MODE
[self
.devpi
.Get(NMI
, "Mode")]
288 wcaps
= self
.devpi
.Get(NMI
, "WirelessCapabilities")
289 print " Wifi Capabilities:", bitmask_str(self
.NM_802_11_DEVICE_CAP
, wcaps
)
290 for P
in ["HwAddress", "Bitrate", "ActiveAccessPoint"]:
291 print " %s: %s" % (P
, self
.devpi
.Get(NMI
, P
))
293 print " Access Points"
294 for ap
in self
.APs():
302 for ap
in self
.APs():
305 """An AP found around us"""
307 def __init__(self
, opath
):
309 self
.apo
= bus
.get_object(NMC
, self
.opath
)
310 self
.appi
= dbus
.Interface(self
.apo
, PI
)
312 def ssid_str(noself
, array
):
319 return self
.ssid_str(self
.appi
.Get(NMI
, "Ssid"))
322 return int(self
.appi
.Get(NMI
, "Strength"))
324 NM_802_11_AP_FLAGS
= {1: "PRIVACY",}
327 1: "PAIR_WEP40", 2: "PAIR_WEP104", 4: "PAIR_TKIP", 8: "PAIR_CCMP",
328 16: "GROUP_WEP40", 32: "GROUP_WEP104", 64: "GROUP_TKIP",
329 128: "GROUP_CCMP", 256: "KEY_MGMT_PSK", 512: "KEY_MGMT_802_1X",}
332 print " AP:", self
.opath
333 print " Ssid:", self
.Ssid()
334 for P
in ["Frequency", "HwAddress", "MaxBitrate",]:
335 print " %s: %s" % (P
, self
.appi
.Get(NMI
, P
))
336 print " Strength:", self
.Strength()
337 print " AP Mode:", cDevice
.IW_MODE
[self
.appi
.Get(NMI
, "Mode")]
338 print " AP Flags:", bitmask_str(self
.NM_802_11_AP_FLAGS
,
339 self
.appi
.Get(NMI
, "Flags"))
340 print " AP WPA Flags:", bitmask_str(self
.NM_802_11_AP_SEC
,
341 self
.appi
.Get(NMI
, "WpaFlags"))
342 print " AP RSN Flags:", bitmask_str(self
.NM_802_11_AP_SEC
,
343 self
.appi
.Get(NMI
, "RsnFlags"))
346 mbr
= self
.appi
.Get(NMI
, "MaxBitrate") / 1000
347 priv
= self
.appi
.Get(NMI
, "Flags") != 0
348 wpa
= self
.appi
.Get(NMI
, "WpaFlags") != 0
349 wpa2
= self
.appi
.Get(NMI
, "RsnFlags") != 0
352 if not wpa
and not wpa2
:
353 priv_s
= priv_s
+ " WEP"
355 priv_s
= priv_s
+ " WPA"
357 priv_s
= priv_s
+ " WPA2"
358 print "%3d: %s (%dMb%s)" % (self
.Strength(), self
.Ssid(), mbr
, priv_s
)
360 # Settings is overloaded
362 def __init__(self
, svc
, opath
):
365 self
.so
= bus
.get_object(self
.svc
, self
.opath
)
366 self
.si
= dbus
.Interface(self
.so
, 'org.freedesktop.NetworkManagerSettings')
369 return self
.svc
== SSC
;
372 for conn
in self
.Connections():
377 def DumpSystem(self
):
378 sspi
= dbus
.Interface(self
.so
, PI
)
379 print "Unmanaged Devices"
380 umds
= sspi
.Get(NMI
, "UnmanagedDevices")
383 # dump_settings_conn(svc, conn) umd?
386 def myConnection(self
, opath
):
387 return cConnection(self
.svc
, opath
)
389 def Connections(self
):
390 opaths
= self
.si
.ListConnections()
391 return map(self
.myConnection
, opaths
)
394 def __init__(self
, svc
, opath
):
397 self
.co
= bus
.get_object(self
.svc
, self
.opath
)
398 self
.ci
= dbus
.Interface(self
.co
, 'org.freedesktop.NetworkManagerSettings.Connection')
401 print "Conn:", self
.opath
402 print " Id:", self
.ci
.GetID()
403 settings
= self
.Settings()
406 si
= dbus
.Interface(self
.co
, 'org.freedesktop.NetworkManagerSettings.Connection.Secrets')
407 security
= settings
.Security()
409 print " SECRETS:", security
411 secrets
= cSettings(si
.GetSecrets(security
,[],False))
415 return cSettings(self
.ci
.GetSettings())
419 def __init__(self
, conmap
):
423 return self
.conmap
["connection"]["type"]
426 return self
.conmap
["connection"]["id"]
430 return self
.conmap
[self
.Type()]["security"]
434 def isNet(self
, net_name
):
435 # FIXME also ssid ...
436 return self
.GetID() == net_name
438 # FIXME check spec/NM what to censor
439 secrets
= dict.fromkeys(["wep-key0", "psk"])
442 "For GetSettings: censor secrets."
445 for n1
, v1
in self
.conmap
.iteritems():
447 for n2
, v2
in v1
.iteritems():
449 if self
.secrets
.has_key(n2
):
455 "For GetSecrets: only secrets."
464 for n1
, v1
in self
.conmap
.iteritems():
466 for n2
, v2
in v1
.iteritems():
467 print " %s: %s" % (n2
, v2
)
469 # just an example, unused now
470 hardwired_conmaps
= [
474 "type": "802-11-wireless",
477 "ssid": dbus
.ByteArray("onenet"),
478 "mode": "infrastructure",
479 "security": "802-11-wireless-security",
483 "802-11-wireless-security": {
484 "key-mgmt": "wpa-psk",
486 "psk": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", # CENSORED
492 'type': '802-11-wireless',
495 'ssid': dbus
.ByteArray('frogs'),
496 'mode': 'infrastructure',
497 'security': '802-11-wireless-security',
499 '802-11-wireless-security': {
502 'wep-key0': 'aaaaaaaaaaaaaaaaaaaaaaaaaa', # CENSORED
507 # server analog of cApplet
508 class UserSettings(dbus
.service
.Object
):
510 def __init__(self
, opath
, conmaps
):
511 dbus
.service
.Object
.__init
__(self
, bus
, opath
)
512 #print "CONMAPS:", conmaps
513 self
.conns
= map(self
.newCon
, conmaps
)
516 def newCon(self
, conmap
):
517 cpath
= "/MyConnection/%d" % self
.counter
518 self
.counter
= self
.counter
+ 1
519 c
= Connection(cpath
, conmap
)
520 self
.NewConnection(cpath
) # announce it
523 @dbus.service
.method(dbus_interface
='org.freedesktop.NetworkManagerSettings',
524 in_signature
='', out_signature
='ao')
525 def ListConnections(self
):
526 return [c
.__dbus
_object
_path
__ for c
in self
.conns
]
528 #this is for EMITTING a signal, not receiving it
529 @dbus.service
.signal(dbus_interface
='org.freedesktop.NetworkManagerSettings',
531 def NewConnection(self
, opath
):
533 #print "signalling newconn:", opath
535 def GetByNet(self
, net_name
):
536 "Returns connection, or None"
538 if c
.isNet(net_name
):
543 # server analog of cConnection
544 class Connection(dbus
.service
.Object
):
545 def __init__(self
, opath
, conmap
):
546 dbus
.service
.Object
.__init
__(self
, bus
, opath
)
547 self
.settings
= cSettings(conmap
)
549 @dbus.service
.method(dbus_interface
='org.freedesktop.NetworkManagerSettings.Connection',
550 in_signature
='', out_signature
='a{sa{sv}}')
551 def GetSettings(self
):
552 #print "Getting settings:", self. __dbus_object_path__
553 # return self.settings.ConMap()
554 # grr, censoring secrets makes NM complain!?
555 return self
.settings
.conmap
557 @dbus.service
.method(dbus_interface
='org.freedesktop.NetworkManagerSettings.Connection.Secrets',
558 in_signature
='sasb', out_signature
='a{sa{sv}}')
559 def GetSecrets(self
, tag
, hints
, ask
):
561 print "Getting secrets:", self
.__dbus
_object
_path
__
562 return self
.settings
.SecMap()
564 @dbus.service
.method(dbus_interface
='org.freedesktop.NetworkManagerSettings.Connection',
565 in_signature
='', out_signature
='s')
567 return self
.settings
.GetID()
569 def isNet(self
, net_name
):
570 return self
.settings
.isNet(net_name
)
572 class ConfigParserKNM
:
573 "Parse ~/.kde/share/config/knetworkmanagerrc"
576 p
= ConfigParser
.RawConfigParser()
577 ok
= p
.read(os
.getenv("HOME") + "/.kde/share/config/knetworkmanagerrc")
580 for s
in p
.sections():
583 if path
[0] not in ["Connection", "Notification Messages"]:
585 self
.conmaps_d
.setdefault(cid
, {})
589 for (n
, v
) in p
.items(s
):
590 # WTF, Value_ is transfrmed to value_
591 if n
[:6] == "value_":
593 v
= self
.ParseValue(v
)
595 if len(values
) != 0: # empty 802-1x confuses NM!?
596 self
.conmaps_d
[cid
].setdefault(part
, {})
597 self
.conmaps_d
[cid
][part
].update(**values
)
598 #print "PARSED", cid, part, values
601 return self
.conmaps_d
.values()
603 def ParseValue(self
, v
):
604 v
= eval('"%s"' % v
) # unescape backslashes
605 dom
= xml
.dom
.minidom
.parseString(v
)
606 return self
.ParseNode(dom
.documentElement
)
608 def ParseNode(self
, n
):
616 return dbus
.Byte(int(v
))
619 elif t
== "int32" or t
== "uint32":
625 if c
.localName
!= None: # whitespace
626 v
.append(self
.ParseNode(c
))
630 def NodeText(self
, n
):
631 if n
.hasChildNodes():
632 return n
.firstChild
.wholeText
636 def abbr_signal_handler(*args
, **kwargs
):
637 ifc
= kwargs
["interface"]
638 sig
= kwargs
["member"]
639 opath
= kwargs
["path"]
640 line
= "SIG %s: %s.%s%s" % (abbrev(opath
,"/"), abbrev(ifc
,"."), sig
, args
)
646 bus
.add_signal_receiver(self
.abbr_signal_handler
,
648 interface_keyword
="interface",
649 member_keyword
="member")
651 def abbr_signal_handler(self
, *args
, **kwargs
):
652 ifc
= kwargs
["interface"]
653 sig
= kwargs
["member"]
654 opath
= kwargs
["path"]
655 line
= "SIG %s: %s.%s%s" % (self
.abbrev(opath
,"/"),
656 self
.abbrev(ifc
,"."),
660 def abbrev(self
, s
, sep
):
662 words
= map (self
.a1
, words
)
663 result
= sep
.join(words
)
664 if not self
.amap
.has_key(s
):
665 print "ABBR %s is %s" % (result
, s
)
666 self
.amap
[s
] = result
668 if self
.amap
[s
] != result
:
669 print "ABBR COLLISION %s was %s now %s" % (s
, self
.amap
[s
], result
)
680 op
= OptionParser(version
="%prog " + VERSION
)
681 op
.add_option("-d", "--dev",
682 action
="store_true", default
=False,
684 op
.add_option("-c", "--actcon",
685 action
="store_true", default
=False,
686 help="list active connections")
687 op
.add_option("-u", "--usrcon",
688 action
="store_true", default
=False,
689 help="list user connection settings (can CRASH nm-applet)")
690 op
.add_option("-s", "--syscon",
691 action
="store_true", default
=False,
692 help="list system connection settings")
693 op
.add_option("-a", "--ap",
694 action
="store_true", default
=False,
695 help="list found access points")
696 op
.add_option("-n", "--nets",
697 action
="store_true", default
=False,
698 help="list found wireless networks")
699 # TODO http://docs.python.org/lib/optparse-adding-new-types.html
700 op
.add_option("-w", "--wifi",
701 choices
=["0","1","off","on","no","yes","false","true"],
703 help="enable or disable wireless")
704 op
.add_option("-o", "--online",
705 choices
=["0","1","off","on","no","yes","false","true"],
707 help="enable or disable network at all")
709 op
.add_option("-C", "--connect",
710 help="connect to a wireless network NET (using knetworkmanagerrc)",
712 op
.add_option("-m", "--monitor",
713 action
="store_true", default
=False,
714 help="loop to show dbus signals")
717 (options
, args
) = op
.parse_args()
725 nmp
= '/org/freedesktop/NetworkManager'
727 if options
.dev
or options
.actcon
:
730 true_choices
= ["1", "on", "yes", "true"]
731 if options
.wifi
!= None:
732 nm
.SetWifiEnabled(options
.wifi
in true_choices
)
733 if options
.online
!= None:
734 nm
.SetOnline(options
.online
in true_choices
)
740 print "SYSTEM Connections"
741 ss
= cApplet(SSC
, '/org/freedesktop/NetworkManagerSettings')
745 print "USER Connections"
747 us
= cApplet(USC
, '/org/freedesktop/NetworkManagerSettings')
749 except dbus
.exceptions
.DBusException
, e
:
751 if e
.get_dbus_name() == "org.freedesktop.DBus.Error.ServiceUnknown":
752 print "Applet is not running"
754 nmo
= bus
.get_object(NMC
, nmp
)
755 nmi
= dbus
.Interface(nmo
, NMI
)
757 if options
.connect
!= None:
758 brn
= bus
.request_name(USC
, _dbus_bindings
.NAME_FLAG_DO_NOT_QUEUE
)
759 if brn
== _dbus_bindings
.REQUEST_NAME_REPLY_EXISTS
:
760 print "Could not provide settings service, another applet is running"
762 cfg
= ConfigParserKNM()
763 us
= UserSettings("/org/freedesktop/NetworkManagerSettings",
766 def Connect(wanted_net
): # any. or take arg. net is config name or ssid name
767 # ... in general, look for string in all config data. ssid for wifi, whatever for dialup
768 # TODO also respect autoconnect
770 # ActivateConn wants setting device ap; can find device from ap? ap is "specific" for wifi devices
771 #print "Connection wanted to", wanted_net
772 found_con
= found_ap
= found_dev
= None
773 for dev
in nm
.Devices():
776 if wanted_net
== ap
.Ssid():
779 break # FIXME both loops
780 found_con
= us
.GetByNet(wanted_net
)
782 print "No AP found with SSID", wanted_net
784 elif found_con
== None:
785 print "No settings for net", wanted_net
788 nm
.ActivateConnection(found_con
, found_dev
, found_ap
) # TODO async
789 # TODO run loop, exit it when we have serviced the required calls
792 if options
.connect
!= None:
793 if Connect(options
.connect
):
800 loop
= gobject
.MainLoop()