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");
21 from optparse
import OptionParser
27 print "Install python-1-dbus.rpm or or python-dbus.rpm or python-dbus.deb"
32 # todo - only if loop wanted
33 print "Install python-gobject2.rpm or pygobject2.rpm or python-gobject.deb"
35 # python-gnome.rpm has gconf for nm-applet...
39 from dbus
.mainloop
.glib
import DBusGMainLoop
40 DBusGMainLoop(set_as_default
=True)
43 from monitor
import MonitorBase
44 from configparser_knm
import ConfigParserKNM
45 from mkconmap
import *
50 from manager06
import cNM_06
51 from manager07
import cNM_07
52 from device
import cDevice
53 from device06
import cDevice_06
54 from device07
import cDevice_07
56 from ap06
import cAP_06
57 from ap07
import cAP_07
58 from applet
import cApplet
, SSC
, USC
, NMIC
59 from applet06
import cApplet_06
63 bus
= dbus
.SystemBus()
65 # FOOC = connection (service) string
66 # FOOI = interface string
69 # foopi = property interface
71 ii
= dbus
.Interface(obj
, 'org.freedesktop.DBus.Introspectable')
75 "Detects NM version and chooses appropriate class"
77 nmo
= bus
.get_object(NMC
, opath
)
78 nmi
= dbus
.Interface(nmo
, NMI
)
80 dummy
= nmi
.getDevices()
81 return cNM_06(opath
, options
)
82 except dbus
.exceptions
.DBusException
, e
:
83 if e
.get_dbus_name() == 'org.freedesktop.DBus.Error.AccessDenied':
85 return cNM_07(opath
, options
)
87 def opath_validchar(c
):
88 # _ is also escaped even though it is valid
90 string
.ascii_letters
.find(c
) != -1 or \
91 string
.digits
.find(c
) != -1
96 # TODO find a more elegant way
97 if not opath_validchar(c
):
103 def opath_unescape(s
):
105 unhex
= lambda xx
: chr(eval("0x"+xx
))
107 return re
.sub("_.._", lambda p
: unhex(p
.group()[1:3]), s
)
109 def dump_time(unixtime
):
110 return time
.asctime(time
.localtime(unixtime
))
112 # server analog of cApplet
113 class UserSettings(dbus
.service
.Object
):
115 def __init__(self
, opath
, conmaps
):
116 dbus
.service
.Object
.__init
__(self
, bus
, opath
)
117 #print "CONMAPS:", conmaps
118 self
.conns
= map(self
.newCon
, conmaps
)
120 def addCon(self
, conmap
):
121 c
= self
.newCon(conmap
)
126 def newCon(self
, conmap
):
127 cpath
= "/MyConnection/%d" % self
.counter
128 self
.counter
= self
.counter
+ 1
129 c
= Connection(cpath
, conmap
)
130 self
.NewConnection(cpath
) # announce it
133 @dbus.service
.method(dbus_interface
='org.freedesktop.NetworkManagerSettings',
134 in_signature
='', out_signature
='ao')
135 def ListConnections(self
):
136 return [c
.__dbus
_object
_path
__ for c
in self
.conns
]
138 #this is for EMITTING a signal, not receiving it
139 @dbus.service
.signal(dbus_interface
='org.freedesktop.NetworkManagerSettings',
141 def NewConnection(self
, opath
):
143 #print "signalling newconn:", opath
145 def GetByNet(self
, net_name
):
146 "Returns connection, or None"
148 if c
.isNet(net_name
):
153 class UserSettings_06(UserSettings
):
155 def __init__(self
, opath
, conmaps
):
156 dbus
.service
.Object
.__init
__(self
, bus
, opath
)
157 #print "CONMAPS:", conmaps
158 self
.conns
= map(self
.newCon
, conmaps
)
161 def newCon(self
, conmap
):
162 cpath
= "/MyConnection/%d" % self
.counter
163 self
.counter
= self
.counter
+ 1
164 c
= Connection_06(cpath
, conmap
)
165 #self.NewConnection(cpath) # announce it
168 @dbus.service
.method(dbus_interface
="org.freedesktop.NetworkManagerInfo",
169 in_signature
="i", out_signature
='as')
170 def getNetworks(self
, i
):
171 # FIXME bytearray to str WHERE?
172 #n = [ssid_str(c.Ssid()) for c in self.conns]
173 n
= [c
.ID() for c
in self
.conns
]
174 print "getNetworks:", n
177 @dbus.service
.method(dbus_interface
="org.freedesktop.NetworkManagerInfo",
178 in_signature
="", out_signature
='ao') # out??
179 def getVPNConnections(self
):
182 @dbus.service
.method(dbus_interface
="org.freedesktop.NetworkManagerInfo",
184 #out_signature='sibasi') #varies
185 def getNetworkProperties(self
, net
, type):
187 # type is 1, NETWORK_TYPE_ALLOWED
188 c
= self
.GetByNet(net
)
190 return c
.getNetworkProperties()
191 print "Oops, could not getNetworkProperties for " + net
194 @dbus.service
.method(dbus_interface
="org.freedesktop.NetworkManagerInfo",
195 in_signature
="oosib")
196 #out_signature="isi") varies
197 def getKeyForNetwork(self
, dev
, net
, ssid
, attempt
, newkey
):
198 print "GKFN", dev
, net
, ssid
, attempt
, bool(newkey
)
200 m
= "Cannot ask for key"
202 raise dbus
.exceptions
.DBusException(m
)
204 snet
= opath_unescape(net
[net
.rfind("/")+1 : ]) # only stuff after /
205 c
= self
.GetByNet(snet
)
207 return c
.getKeyForNetwork()
208 print "Oops, could not getKeyForNetwork " + net
210 @dbus.service
.method(dbus_interface
="org.freedesktop.NetworkManagerInfo",
212 #in_signature="sbs isi", varies
213 def updateNetworkInfo(self
, ssid
, automatic
, bssid
, *security
):
214 print "Connected successfully"
218 print " automatic:", bool(automatic
)
219 print " bssid:", bssid
220 print " security:", security
223 def GetByNet(self
, net_name
):
224 "Returns connection, or None"
226 if c
.isNet(net_name
):
231 # server analog of cConnection
232 class Connection(dbus
.service
.Object
):
233 def __init__(self
, opath
, conmap
):
234 dbus
.service
.Object
.__init
__(self
, bus
, opath
)
235 self
.settings
= cSettings(conmap
)
237 @dbus.service
.method(dbus_interface
='org.freedesktop.NetworkManagerSettings.Connection',
238 sender_keyword
='sender',
239 in_signature
='', out_signature
='a{sa{sv}}')
240 def GetSettings(self
, sender
):
241 #print "Getting settings:", self. __dbus_object_path__
242 # return self.settings.ConMap()
243 # grr, censoring secrets makes NM complain!?
244 # bnc#479566#c3: Until I figure out how to make it work with
245 # censored secrets, only pass the settings to the same user.
246 sender_uid
= bus
.get_unix_user(sender
)
247 if sender_uid
!= 0 and sender_uid
!= os
.geteuid():
248 e
= "User %u is not permitted to read the settings" % sender_uid
250 raise dbus
.exceptions
.DBusException(e
) # could do NM_SETTINGS_ERROR_* instead
251 return self
.settings
.conmap
253 @dbus.service
.method(dbus_interface
='org.freedesktop.NetworkManagerSettings.Connection.Secrets',
254 in_signature
='sasb', out_signature
='a{sa{sv}}')
255 def GetSecrets(self
, tag
, hints
, ask
):
257 print "Getting secrets:", self
.__dbus
_object
_path
__
258 return self
.settings
.SecMap()
260 @dbus.service
.method(dbus_interface
='org.freedesktop.NetworkManagerSettings.Connection',
261 in_signature
='', out_signature
='s')
263 return self
.settings
.ID()
266 return self
.settings
.Ssid()
268 def isNet(self
, net_name
):
269 return self
.settings
.isNet(net_name
)
271 class Connection_06(Connection
):
272 def __init__(self
, opath
, conmap
):
273 dbus
.service
.Object
.__init
__(self
, bus
, opath
)
275 self
.settings
= cSettings(conmap
)
277 # dbus.service.method
278 def getNetworkProperties(self
):
279 # essid, timestamp, ?, bssids, we_cipher, ?, ...
280 # we_cipher=16: i wep_auth_algorithm
281 # we_cipher=0: i wpa_psk_key_mgt, i wpa_psk_wpa_version
282 ssid
= ssid_str(self
.settings
.Ssid())
283 time
= self
.settings
.Timestamp() # last sucessfully connected? seen?
284 trusted
= self
.settings
.Trusted()
285 bssids
= dbus
.Array(self
.settings
.SeenBssids(), signature
="s")
286 r
= [ssid
, time
, trusted
, bssids
]
287 security
= self
.getKeyForNetwork("fake key")
291 # dbus.service.method
292 def getKeyForNetwork(self
, fake
="no"):
294 key
= self
.settings
.Key()
299 cip
= self
.settings
.WeCipher()
300 if cip
== NM_AUTH_TYPE_NONE
:
301 security
= tuple([cip
])
302 elif cip
== NM_AUTH_TYPE_WEP40
or cip
== NM_AUTH_TYPE_WEP104
:
303 wep_auth_algorithm
= self
.settings
.WepAuthAlgorithm()
304 security
= (cip
, key
, wep_auth_algorithm
)
305 elif cip
== NM_AUTH_TYPE_WPA_PSK_AUTO
or cip
== NM_AUTH_TYPE_TKIP
or \
306 cip
== NM_AUTH_TYPE_CCMP
:
307 wpa_psk_key_mgt
= self
.settings
.PskKeyMgt()
308 wpa_psk_wpa_version
= self
.settings
.PskWpaVersion()
309 security
= (cip
, key
, wpa_psk_key_mgt
, wpa_psk_wpa_version
)
310 elif cip
== NM_AUTH_TYPE_WPA_EAP
:
311 security
= tuple([cip
]) # TODO more...
312 elif cip
== NM_AUTH_TYPE_LEAP
:
313 security
= tuple([cip
]) # TODO more...
318 class Monitor(MonitorBase
):
319 def __init__(self
, bus
):
320 MonitorBase
.__init
__(self
, bus
)
324 dbus_interface
="org.freedesktop.NetworkManager.Device.Wireless",
325 signal_name
="PropertiesChanged")
328 dbus_interface
="org.freedesktop.NetworkManager.AccessPoint",
329 signal_name
="PropertiesChanged")
331 self
.ignore("org.freedesktop.Hal.Device", "PropertyModified")
332 self
.ignore("fi.epitest.hostap.WPASupplicant.Interface", "ScanResultsAvailable")
333 self
.ignore("com.redhat.PrinterSpooler", "QueueChanged")
334 self
.ignore("org.freedesktop.NetworkManager", "StateChange") # deprecated
335 self
.watch(self
.nm_sc_h
, "org.freedesktop.NetworkManager", "StateChanged")
336 self
.watch(self
.wpas_isc_h
, "fi.epitest.hostap.WPASupplicant.Interface", "StateChange")
337 self
.watch(self
.nmd_sc_h
, "org.freedesktop.NetworkManager.Device", "StateChanged")
338 self
.watch(self
.bus_noc_h
, "org.freedesktop.DBus", "NameOwnerChanged")
340 def bus_noc_h(self
, *args
, **kwargs
):
341 (name
, old
, new
) = args
346 print "\tBUS NOC\t%s %s" % (name
, new
)
348 def wpas_isc_h(self
, *args
, **kwargs
):
349 opath
= kwargs
["path"]
351 print "\tWPAS %s\t(%s, was %s)" % (new
, opath
, old
.lower())
353 def nmd_sc_h(self
, *args
, **kwargs
):
354 opath
= kwargs
["path"]
355 (new
, old
, reason
) = args
356 news
= cDevice_07
.NM_DEVICE_STATE
[new
]
357 olds
= cDevice_07
.NM_DEVICE_STATE
[old
]
360 reasons
= "reason %d" % reason
361 print "\tDevice State %s\t(%s, was %s%s)" % (news
, opath
, olds
.lower(), reasons
)
363 def nm_sc_h(self
, *args
, **kwargs
):
366 print "\tNM State:", ss
368 def propc_h(self
, *args
, **kwargs
):
369 opath
= kwargs
["path"]
371 for k
, v
in props
.iteritems():
374 line
= "\tPROP\t%s\t%s\t(%s)" % (k
, v
, opath
)
381 op
= OptionParser(version
="%prog " + VERSION
)
382 op
.add_option("-d", "--dev",
383 action
="store_true", default
=False,
385 op
.add_option("-c", "--actcon",
386 action
="store_true", default
=False,
387 help="list active connections")
388 op
.add_option("-u", "--usrcon",
389 action
="store_true", default
=False,
390 help="list user connection settings (can CRASH nm-applet)")
391 op
.add_option("-s", "--syscon",
392 action
="store_true", default
=False,
393 help="list system connection settings")
394 op
.add_option("-a", "--ap",
395 action
="store_true", default
=False,
396 help="list found access points")
397 op
.add_option("-n", "--nets",
398 action
="store_true", default
=False,
399 help="list found wireless networks")
400 # TODO http://docs.python.org/lib/optparse-adding-new-types.html
401 op
.add_option("-w", "--wifi",
402 choices
=["0","1","off","on","no","yes","false","true"],
404 help="enable or disable wireless")
405 op
.add_option("-o", "--online",
406 choices
=["0","1","off","on","no","yes","false","true"],
408 help="enable or disable network at all")
410 op
.add_option("--activate-connection",
411 help="raw API: activate the KIND(user/system) connection CON on device DEV using AP",
412 metavar
="[KIND],CON,DEV,[AP]")
413 op
.add_option("-C", "--connect",
414 help="connect to a wireless network NET (using knetworkmanagerrc or the key options below)",
416 op
.add_option("--unprotected",
417 action
="store_true", default
=False,
418 help="network does not require a key")
419 op
.add_option("--wep-hex",
421 help="use this WEP key of 26 hex digits")
422 op
.add_option("--wep-pass",
424 help="use this WEP passphrase")
425 op
.add_option("--wpa-psk-hex",
427 help="use this WPA key of 64 hex digits")
428 op
.add_option("--wpa-pass",
430 help="use this WPA passphrase")
431 op
.add_option("-m", "--monitor",
432 action
="store_true", default
=False,
433 help="loop to show dbus signals")
436 (options
, args
) = op
.parse_args()
444 nmp
= '/org/freedesktop/NetworkManager'
447 except dbus
.exceptions
.DBusException
, e
:
448 print "NetworkManager is not running or running as an other user"
450 if options
.dev
or options
.actcon
:
453 true_choices
= ["1", "on", "yes", "true"]
454 if options
.wifi
!= None:
455 nm
.SetWifiEnabled(options
.wifi
in true_choices
)
456 if options
.online
!= None:
457 nm
.SetOnline(options
.online
in true_choices
)
463 print "SYSTEM Connections"
465 print "Cannot do that with NM 0.6"
468 ss
= cApplet(SSC
, '/org/freedesktop/NetworkManagerSettings')
472 print "USER Connections"
475 us
= cApplet_06(NMIC
, "/org/freedesktop/NetworkManagerInfo")
477 us
= cApplet(USC
, '/org/freedesktop/NetworkManagerSettings')
479 except dbus
.exceptions
.DBusException
, e
:
481 #if e.get_dbus_name() == "org.freedesktop.DBus.Error.ServiceUnknown":
482 print "Applet is not running"
485 nmo
= bus
.get_object(NMC
, nmp
)
486 nmi
= dbus
.Interface(nmo
, NMI
)
488 def service_pid(name
):
489 DBS
= 'org.freedesktop.DBus'
491 dbo
= bus
.get_object(DBS
, '/')
492 dbi
= dbus
.Interface(dbo
, DBI
)
493 owner
= dbi
.GetNameOwner(name
)
494 pid
= dbi
.GetConnectionUnixProcessID(owner
)
497 # TODO UserSettings_06
498 if options
.connect
!= None:
503 brn
= bus
.request_name(name
, _dbus_bindings
.NAME_FLAG_DO_NOT_QUEUE
)
504 if brn
== _dbus_bindings
.REQUEST_NAME_REPLY_EXISTS
:
505 print "Could not provide settings service, another applet is running (pid %s)" % service_pid(name
)
507 cfg
= ConfigParserKNM()
509 us
= UserSettings_06("/org/freedesktop/NetworkManagerInfo",
512 us
= UserSettings("/org/freedesktop/NetworkManagerSettings",
515 def Connect(wanted_net
): # any. or take arg. net is config name or ssid name
516 # ... in general, look for string in all config data. ssid for wifi, whatever for dialup
517 # TODO also respect autoconnect
519 # ActivateConn wants setting device ap; can find device from ap? ap is "specific" for wifi devices
520 #print "Connection wanted to", wanted_net
521 found_con
= found_ap
= found_dev
= None
522 for dev
in nm
.Devices():
524 if wanted_net
== ap
.Ssid():
527 break # FIXME both loops
528 found_con
= us
.GetByNet(wanted_net
)
530 print "No AP found with SSID", wanted_net
532 if found_con
== None:
533 print "No settings for net %s, assuming no key is needed" % wanted_net
534 c
= mkconmap_wifi(wanted_net
)
535 found_con
= us
.addCon(c
)
536 nm
.ActivateConnection(found_con
, found_dev
, found_ap
) # TODO async
537 # TODO run loop, exit it when we have serviced the required calls
540 if options
.connect
!= None:
541 if options
.unprotected
:
542 c
= mkconmap_wifi(options
.connect
)
544 if options
.wep_hex
!= None:
545 c
= mkconmap_wep(options
.connect
, options
.wep_hex
)
547 if options
.wep_pass
!= None:
548 c
= mkconmap_wep_pass(options
.connect
, options
.wep_pass
)
550 if options
.wpa_psk_hex
!= None:
551 c
= mkconmap_psk(options
.connect
, options
.wpa_psk_hex
)
553 if options
.wpa_pass
!= None:
554 c
= mkconmap_psk(options
.connect
, options
.wpa_pass
)
557 if Connect(options
.connect
):
562 if options
.activate_connection
!= None:
563 (svc
, conpath
, devpath
, appath
) = options
.activate_connection
.split(',')
564 if svc
== "" or svc
== "user":
566 elif svc
== "system":
574 nm
.nmi
.ActivateConnection(svc
, conpath
, devpath
, appath
,
575 reply_handler
=nm
.silent_handler
,
576 error_handler
=nm
.err_handler
,
584 loop
= gobject
.MainLoop()