2
# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
# GNU General Public License for more details:
14
# Copyright (C) 2008 Novell, Inc.
15
# Copyright (C) 2009 Red Hat, Inc.
18
import sys, dbus, time, os, string, subprocess, socket
20
DBUS_INTERFACE_PROPERTIES='org.freedesktop.DBus.Properties'
21
MM_DBUS_SERVICE='org.freedesktop.ModemManager'
22
MM_DBUS_PATH='/org/freedesktop/ModemManager'
23
MM_DBUS_INTERFACE='org.freedesktop.ModemManager'
24
MM_DBUS_INTERFACE_MODEM='org.freedesktop.ModemManager.Modem'
25
MM_DBUS_INTERFACE_MODEM_CDMA='org.freedesktop.ModemManager.Modem.Cdma'
26
MM_DBUS_INTERFACE_MODEM_GSM_CARD='org.freedesktop.ModemManager.Modem.Gsm.Card'
27
MM_DBUS_INTERFACE_MODEM_GSM_NETWORK='org.freedesktop.ModemManager.Modem.Gsm.Network'
28
MM_DBUS_INTERFACE_MODEM_SIMPLE='org.freedesktop.ModemManager.Modem.Simple'
30
def get_cdma_band_class(band_class):
38
def get_reg_state(state):
40
return "registered (roaming unknown)"
42
return "registered on home network"
44
return "registered on roaming network"
48
def cdma_inspect(proxy, dump_private):
49
cdma = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM_CDMA)
55
except dbus.exceptions.DBusException:
59
print("ESN: %s" % esn)
62
(cdma_1x_state, evdo_state) = cdma.GetRegistrationState()
63
print("1x State: %s" % get_reg_state (cdma_1x_state))
64
print("EVDO State: %s" % get_reg_state (evdo_state))
65
except dbus.exceptions.DBusException as e:
66
print("Error reading registration state: %s" % e)
69
quality = cdma.GetSignalQuality()
70
print("Signal quality: %d" % quality)
71
except dbus.exceptions.DBusException as e:
72
print("Error reading signal quality: %s" % e)
75
info = cdma.GetServingSystem()
76
print("Class: %s" % get_cdma_band_class(info[0]))
77
print("Band: %s" % info[1])
78
print("SID: %d" % info[2])
79
except dbus.exceptions.DBusException as e:
80
print("Error reading serving system: %s" % e)
82
def cdma_connect(proxy, user, password):
83
# Modem.Simple interface
84
simple = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM_SIMPLE)
86
simple.Connect({'number':"#777"}, timeout=92)
89
except Exception as e:
90
print("Error connecting: %s" % e)
94
def get_gsm_network_mode(modem):
95
mode = modem.GetNetworkMode()
109
mode = "2G Preferred"
111
mode = "3G Preferred"
123
print("Mode: %s" % mode)
125
def get_gsm_band(modem):
126
band = modem.GetBand()
132
band = "EGSM (900 MHz)"
134
band = "DCS (1800 MHz)"
136
band = "PCS (1900 MHz)"
138
band = "G850 (850 MHz)"
140
band = "U2100 (WCSMA 2100 MHZ, Class I)"
142
band = "U1700 (WCDMA 3GPP UMTS1800 MHz, Class III)"
144
band = "17IV (WCDMA 3GPP AWS 1700/2100 MHz, Class IV)"
146
band = "U800 (WCDMA 3GPP UMTS800 MHz, Class VI)"
148
band = "U850 (WCDMA 3GPP UMT850 MHz, Class V)"
150
band = "U900 (WCDMA 3GPP UMTS900 MHz, Class VIII)"
152
band = "U17IX (WCDMA 3GPP UMTS MHz, Class IX)"
156
print("Band: %s" % band)
159
def gsm_inspect(proxy, dump_private, do_scan):
161
card = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM_GSM_CARD)
167
imei = card.GetImei()
168
except dbus.exceptions.DBusException:
169
imei = "<unavailable>"
171
imsi = card.GetImsi()
172
except dbus.exceptions.DBusException:
173
imsi = "<unavailable>"
175
print("IMEI: %s" % imei)
176
print("IMSI: %s" % imsi)
178
# Gsm.Network interface
179
net = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM_GSM_NETWORK)
181
quality = net.GetSignalQuality()
182
print("Signal quality: %d" % quality)
183
except dbus.exceptions.DBusException as e:
184
print("Error reading signal quality: %s" % e)
191
results = net.Scan(timeout=120)
192
except dbus.exceptions.DBusException as e:
193
print("Error scanning: %s" % e)
209
access_tech_num = r['access-tech']
210
if access_tech_num == "0":
211
access_tech = "(GSM)"
212
elif access_tech_num == "1":
213
access_tech = "(Compact GSM)"
214
elif access_tech_num == "2":
215
access_tech = "(UMTS)"
216
elif access_tech_num == "3":
217
access_tech = "(EDGE)"
218
elif access_tech_num == "4":
219
access_tech = "(HSDPA)"
220
elif access_tech_num == "5":
221
access_tech = "(HSUPA)"
222
elif access_tech_num == "6":
223
access_tech = "(HSPA)"
227
if 'operator-long' in r and len(r['operator-long']):
228
print("%s: %s %s" % (r['operator-long'], status, access_tech))
229
elif 'operator-short' in r and len(r['operator-short']):
230
print("%s: %s %s" % (r['operator-short'], status, access_tech))
232
print("%s: %s %s" % (r['operator-num'], status, access_tech))
234
def gsm_connect(proxy, apn, user, password):
235
# Modem.Simple interface
236
simple = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM_SIMPLE)
238
opts = {'number':"*99#"}
242
opts['username'] = user
243
if password is not None:
244
opts['password'] = password
245
simple.Connect(opts, timeout=120)
246
print("\nConnected!")
248
except Exception as e:
249
print("Error connecting: %s" % e)
253
paths = ["/usr/local/sbin/pppd", "/usr/sbin/pppd", "/sbin/pppd"]
255
if os.path.exists(p):
259
def ppp_start(device, user, password, tmpfile):
267
args += ["nodefaultroute"]
272
args += ["noipdefault"]
277
args += ["usepeerdns"]
291
args += ["mm-test-pppd-plugin.so"]
295
return subprocess.Popen(args, close_fds=True, cwd="/", env={})
297
def ppp_wait(p, tmpfile):
299
while p.poll() == None and i < 30:
301
if os.path.exists(tmpfile):
302
f = open(tmpfile, 'r')
304
idx = string.find(stuff, "DONE")
313
p.send_signal(signal.SIGTERM)
317
ip = socket.ntohl(ip)
322
a = "%c%c%c%c" % (n1, n2, n3, n4)
323
return socket.inet_ntop(socket.AF_INET, a)
325
def static_start(iface, modem):
326
(addr_num, dns1_num, dns2_num, dns3_num) = modem.GetIP4Config()
327
addr = ntop_helper(addr_num)
328
dns1 = ntop_helper(dns1_num)
329
dns2 = ntop_helper(dns2_num)
330
configure_iface(iface, addr, 0, dns1, dns2)
332
def down_iface(iface):
333
ip = ["ip", "addr", "flush", "dev", iface]
336
ip = ["ip", "link", "set", iface, "down"]
340
def configure_iface(iface, addr, gw, dns1, dns2):
341
print("\n\n******************************")
342
print("iface: %s" % iface)
343
print("addr: %s" % addr)
345
print("dns1: %s" % dns1)
346
print("dns2: %s" % dns2)
348
ifconfig = ["ifconfig", iface, "%s/32" % addr]
350
ifconfig += ["pointopoint", gw]
351
print(" ".join(ifconfig))
352
print("\n******************************\n")
354
subprocess.call(ifconfig)
356
def file_configure_iface(tmpfile):
363
f = open(tmpfile, 'r')
364
lines = f.readlines()
366
if l.startswith("addr"):
367
addr = l[len("addr"):].strip()
368
if l.startswith("gateway"):
369
gw = l[len("gateway"):].strip()
370
if l.startswith("iface"):
371
iface = l[len("iface"):].strip()
372
if l.startswith("dns1"):
373
dns1 = l[len("dns1"):].strip()
374
if l.startswith("dns2"):
375
dns2 = l[len("dns2"):].strip()
378
configure_iface(iface, addr, gw, dns1, dns2)
382
cmd = ["ping", "-I", iface, "-c", "4", "-i", "3", "-w", "20", "4.2.2.1"]
384
retcode = subprocess.call(cmd)
386
print("PING: failed")
388
print("PING: success")
399
while x < len(sys.argv):
400
if sys.argv[x] == "--private":
402
elif sys.argv[x] == "--connect":
404
elif (sys.argv[x] == "--user" or sys.argv[x] == "--username"):
407
elif sys.argv[x] == "--apn":
410
elif sys.argv[x] == "--password":
412
password = sys.argv[x]
413
elif sys.argv[x] == "--ip":
415
if os.geteuid() != 0:
416
print("You probably want to be root to use --ip")
418
elif sys.argv[x] == "--no-scan":
422
bus = dbus.SystemBus()
424
# Get available modems:
425
manager_proxy = bus.get_object('org.freedesktop.ModemManager', '/org/freedesktop/ModemManager')
426
manager_iface = dbus.Interface(manager_proxy, dbus_interface='org.freedesktop.ModemManager')
427
modems = manager_iface.EnumerateDevices()
430
print("No modems found")
434
connect_success = False
437
proxy = bus.get_object(MM_DBUS_SERVICE, m)
440
props_iface = dbus.Interface(proxy, dbus_interface='org.freedesktop.DBus.Properties')
442
type = props_iface.Get(MM_DBUS_INTERFACE_MODEM, 'Type')
448
print("Invalid modem type: %d" % type)
450
print("Driver: '%s'" % (props_iface.Get(MM_DBUS_INTERFACE_MODEM, 'Driver')))
451
print("Modem device: '%s'" % (props_iface.Get(MM_DBUS_INTERFACE_MODEM, 'MasterDevice')))
452
data_device = props_iface.Get(MM_DBUS_INTERFACE_MODEM, 'Device')
453
print("Data device: '%s'" % data_device)
456
modem = dbus.Interface(proxy, dbus_interface=MM_DBUS_INTERFACE_MODEM)
460
except dbus.exceptions.DBusException as e:
461
print("Error enabling modem: %s" % e)
464
info = modem.GetInfo()
465
print("Vendor: %s" % info[0])
466
print("Model: %s" % info[1])
467
print("Version: %s" % info[2])
470
gsm_inspect(proxy, dump_private, do_scan)
472
connect_success = gsm_connect(proxy, apn, user, password)
474
cdma_inspect(proxy, dump_private)
476
connect_success = cdma_connect(proxy, user, password)
479
if connect_success and do_ip:
480
tmpfile = "/tmp/mm-test-%d.tmp" % os.getpid()
483
ip_method = props_iface.Get(MM_DBUS_INTERFACE_MODEM, 'IpMethod')
486
p = ppp_start(data_device, user, password, tmpfile)
487
if ppp_wait(p, tmpfile):
488
data_device = file_configure_iface(tmpfile)
492
static_start(data_device, modem)
497
except Exception as e:
498
print("Error setting up IP: %s" % e)
501
try_ping(data_device)
502
print("Waiting for 30s...")
505
print("Disconnecting...")
515
down_iface(data_device)
518
down_iface(data_device)
521
except Exception as e:
522
print("Error tearing down IP: %s" % e)