scan-and-livemon 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. #
  4. # Author: Petter Reinholdtsen
  5. # Lisence: GPL v2 or later at your own choice
  6. """
  7. Script to scan for base stations and start submitt GSM packages on one
  8. or more the frequencies found using grgsm_livemon_headless to the
  9. loopback network device
  10. The idea is to gather GSM packages from as many of the GSM base
  11. stations and phones in the area as possible, by spreading across as
  12. many operators as possible.
  13. """
  14. import imp
  15. from optparse import OptionParser
  16. import subprocess
  17. import sys
  18. import distutils.spawn
  19. def find_gsm_bases():
  20. grgsm_scanner_path = distutils.spawn.find_executable("grgsm_scanner")
  21. scanner = imp.load_source('scanner', grgsm_scanner_path)
  22. sys.modules['scanner'] = scanner
  23. (options, args) = scanner.argument_parser().parse_args()
  24. list = scanner.do_scan(options.samp_rate, options.band, options.speed,
  25. options.ppm, options.gain, options.args)
  26. return list
  27. def select_freqs(serverlist, count = 1):
  28. """
  29. Select the requested number of frequencies, spread across as many base
  30. station operators (mcc+mnc) as possible, pick the ones with the
  31. strongest signals.
  32. Could consider arfcn, freq, cid, lac, mcc, mnc, ccch_conf, power,
  33. neighbours, cell_arfcns to get as wide spread as possible, but is
  34. only using mcc, mnc and power at the moment.
  35. """
  36. # Make shallow copy to avoid modifying the list of the caller when
  37. # removing elements below.
  38. listcopy = []
  39. for s in serverlist:
  40. listcopy.append(s)
  41. freqs = []
  42. operatorscount = {}
  43. # First, initialize operatorscount[] to zero for all operators
  44. for s in listcopy:
  45. if not (s.mcc, s.mnc) in operatorscount:
  46. operatorscount[(s.mcc, s.mnc)] = 0
  47. # Next, pick the number of unique frequences we want, one a the
  48. # time, while trying to get as many operators as we cal.
  49. while 0 < count:
  50. sorted_list = sorted(listcopy, key=lambda s:
  51. (operatorscount[(s.mcc,s.mnc)], s.mcc,
  52. s.mnc, -s.power))
  53. if 0 in sorted_list:
  54. s = sorted_list[0]
  55. freqs.append(s.freq)
  56. operatorscount[(s.mcc, s.mnc)] = operatorscount[(s.mcc, s.mnc)] + 1
  57. listcopy.remove(s)
  58. count = count - 1
  59. return freqs
  60. def argument_parser():
  61. parser = OptionParser(usage="%prog: [options]")
  62. parser.add_option("-n", "--numrecv", dest="numrecv", type="int",
  63. default=1,
  64. help="Set number of livemon processes to start (use one per receiver) [default=%default]")
  65. return parser
  66. def main(options = None):
  67. if options is None:
  68. (options, args) = argument_parser().parse_args()
  69. print("Locating potential GSM base station frequencies (this can take a few minutes).")
  70. list = find_gsm_bases()
  71. print("Found %d frequences" % len(list))
  72. if len(list) > 0:
  73. numreceivers = options.numrecv
  74. freqs = select_freqs(list, numreceivers)
  75. print("Listening on the frequencies for %d potential GSM base stations." % numreceivers)
  76. # Make sure a user process can listen on port 4729 by asking
  77. # livemon processes to listen on other ports.
  78. serverport = 4730
  79. procs = []
  80. for freq in freqs:
  81. print("Starting livemon for freqency %.0f, server on port %d" % (freq, serverport))
  82. proc = subprocess.Popen(["grgsm_livemon_headless",
  83. "--serverport=%d" % serverport,
  84. "-f", str(freq)])
  85. procs.append(proc)
  86. serverport = serverport + 1
  87. # Keep the processes in our process group, to make sure they all die when scan-and-livemon is killed
  88. for proc in procs:
  89. proc.wait()
  90. if __name__ == '__main__':
  91. main()