summaryrefslogtreecommitdiffstats
path: root/Src
diff options
context:
space:
mode:
authorTom2012-04-23 18:13:08 +0200
committerTom2012-04-23 18:13:08 +0200
commit336286e4ddde5b963035a1d16252291181712416 (patch)
tree57366b8a4d89d6d42caa315a96706481a2ebf938 /Src
parentfinished database implementation and documentation in thesis, incorporated ch... (diff)
downloadimsi-catcher-detection-336286e4ddde5b963035a1d16252291181712416.tar.gz
imsi-catcher-detection-336286e4ddde5b963035a1d16252291181712416.tar.xz
imsi-catcher-detection-336286e4ddde5b963035a1d16252291181712416.zip
implemented neighbourhood on all bads and csv exporter
Diffstat (limited to 'Src')
-rw-r--r--Src/PyCatcher/Databases/foo.csv3
-rw-r--r--Src/PyCatcher/Databases/foo.dbbin0 -> 2048 bytes
-rw-r--r--Src/PyCatcher/Databases/home.csv3
-rw-r--r--Src/PyCatcher/GUI/catcher_main.glade54
-rw-r--r--Src/PyCatcher/src/cellIDDatabase.py18
-rw-r--r--Src/PyCatcher/src/driverConnector.py29
-rw-r--r--Src/PyCatcher/src/filters.py8
-rw-r--r--Src/PyCatcher/src/pyCatcherController.py58
-rw-r--r--Src/PyCatcher/src/pyCatcherModel.py98
-rw-r--r--Src/PyCatcher/src/pyCatcherView.py9
-rw-r--r--Src/PyCatcher/src/rules.py36
-rw-r--r--Src/osmolib/src/host/layer23/src/misc/catcher.c84
-rw-r--r--Src/osmolib/src/host/layer23/src/mobile/gsm322.c2
13 files changed, 226 insertions, 176 deletions
diff --git a/Src/PyCatcher/Databases/foo.csv b/Src/PyCatcher/Databases/foo.csv
new file mode 100644
index 0000000..f04bea3
--- /dev/null
+++ b/Src/PyCatcher/Databases/foo.csv
@@ -0,0 +1,3 @@
+Country, Provider, ARFCN, rxlev, BSIC, LAC, Cell ID, Evaluation, Latitude, Longitude, Encryption, DB Status, DB Provider, Neighbours
+Germany, Vodafone, 6, -92, 7,6, 793, 19222, Critical, 0, 0, Not checked., 3, 0, 1 3 10 52 55 57 60 62 107 111 115 119 121
+Germany, O2, 711, -89, 7,3, 50945, 29789, Critical, 0, 0, Not checked., 3, 0, 644 654 659 667 669 675 685 1014 1021 1022
diff --git a/Src/PyCatcher/Databases/foo.db b/Src/PyCatcher/Databases/foo.db
new file mode 100644
index 0000000..3c1eacf
--- /dev/null
+++ b/Src/PyCatcher/Databases/foo.db
Binary files differ
diff --git a/Src/PyCatcher/Databases/home.csv b/Src/PyCatcher/Databases/home.csv
new file mode 100644
index 0000000..89e2960
--- /dev/null
+++ b/Src/PyCatcher/Databases/home.csv
@@ -0,0 +1,3 @@
+Country, Provider, ARFCN, rxlev, BSIC, LAC, Cell ID, Evaluation, Latitude, Longitude, Encryption, DB Status, DB Provider, Neighbours
+Germany, Vodafone, 62, -76, 7/4, 793, 21791, Ok, 0, 0, Not checked., Not looked up, None, 1 3 6 55 60 65 70 75 107 111 113 115 119
+Germany, Vodafone, 3, -83, 7/3, 793, 45352, Ok, 0, 0, Not checked., Not looked up, None, 1 6 55 62 65 70 75 111 113 119 725 729 731
diff --git a/Src/PyCatcher/GUI/catcher_main.glade b/Src/PyCatcher/GUI/catcher_main.glade
index f634bdb..fafe0e8 100644
--- a/Src/PyCatcher/GUI/catcher_main.glade
+++ b/Src/PyCatcher/GUI/catcher_main.glade
@@ -57,6 +57,9 @@
<property name="label" translatable="yes">
Cell ID Databases
</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
</object>
<packing>
<property name="expand">False</property>
@@ -169,6 +172,9 @@ Cell ID Databases
<property name="label" translatable="yes">
Local Area Database
</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
</object>
<packing>
<property name="expand">False</property>
@@ -239,6 +245,38 @@ Local Area Database
<property name="position">9</property>
</packing>
</child>
+ <child>
+ <object class="GtkLabel" id="label7">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">
+CSV
+</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">10</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="btn_csv">
+ <property name="label" translatable="yes">Export as CSV</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
+ <signal name="clicked" handler="_on_csv_clicked" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">11</property>
+ </packing>
+ </child>
</object>
<packing>
<property name="expand">False</property>
@@ -606,21 +644,7 @@ Local Area Database
</packing>
</child>
<child>
- <object class="GtkCheckButton" id="cb_filter_900">
- <property name="label" translatable="yes">Show only the 900 MHz band</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_action_appearance">False</property>
- <property name="xalign">0</property>
- <property name="active">True</property>
- <property name="draw_indicator">True</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">7</property>
- </packing>
+ <placeholder/>
</child>
</object>
<packing>
diff --git a/Src/PyCatcher/src/cellIDDatabase.py b/Src/PyCatcher/src/cellIDDatabase.py
index d12ce60..34c9463 100644
--- a/Src/PyCatcher/src/cellIDDatabase.py
+++ b/Src/PyCatcher/src/cellIDDatabase.py
@@ -8,10 +8,10 @@ import os
from settings import Database_path
class CIDDatabases:
- NONE = 0
- GOOGLE = 1
- OPENCID = 2
- LOCAL = 3
+ NONE = 'None'
+ GOOGLE = 'Google'
+ OPENCID = 'Open Cell ID'
+ LOCAL = 'Local'
class Translator:
Country = {
@@ -30,11 +30,11 @@ class Translator:
}
class CellIDDBStatus:
- CONFIRMED = 0
- APPROXIMATED = 1
- ERROR = 2
- NOT_LOOKED_UP = 3
- NOT_IN_DB = 4
+ CONFIRMED = 'Confirmed'
+ APPROXIMATED = 'Approximated'
+ ERROR = 'Error'
+ NOT_LOOKED_UP = 'Not looked up'
+ NOT_IN_DB = 'Not in DB.'
class CellIDDatabase:
diff --git a/Src/PyCatcher/src/driverConnector.py b/Src/PyCatcher/src/driverConnector.py
index 2e990fd..dea253f 100644
--- a/Src/PyCatcher/src/driverConnector.py
+++ b/Src/PyCatcher/src/driverConnector.py
@@ -84,12 +84,12 @@ class ScanThread(threading.Thread):
if re.search('SysInfo', line):
base_station = BaseStationInformation()
#get country
- line = line = scan_process.stdout.readline()
+ line = scan_process.stdout.readline()
match = re.search(r'Country:\s(\w+)',line)
if match:
base_station.country = match.group(1)
#get provider
- line = line = scan_process.stdout.readline()
+ line = scan_process.stdout.readline()
match = re.search(r'Provider:\s(.+)',line)
if match:
base_station.provider = match.group(1)
@@ -118,19 +118,38 @@ class ScanThread(threading.Thread):
match = re.search(r'rxlev:\s(.\d+)',line)
if match:
base_station.rxlev = int(match.group(1))
+ line = scan_process.stdout.readline()
+ match = re.search(r'\s((\d+)\s)*',line)
+ if match:
+ base_station.neighbours = map(int,match.group(0).strip().split(' '))
+ #get si1
+ line = scan_process.stdout.readline()
+ match = re.search(r'SI1:\s(.+)',line)
+ if match:
+ base_station.system_info_t1 = match.group(1).split(' ')
+ #get si3
+ line = scan_process.stdout.readline()
+ match = re.search(r'SI3:\s(.+)',line)
+ if match:
+ base_station.system_info_t3 = match.group(1).split(' ')
+ #get si4
+ line = scan_process.stdout.readline()
+ match = re.search(r'SI4:\s(.+)',line)
+ if match:
+ base_station.system_info_t4 = match.group(1).split(' ')
#get si2
line = scan_process.stdout.readline()
- match = re.search(r'si2\s(.+)',line)
+ match = re.search(r'SI2:\s(.+)',line)
if match:
base_station.system_info_t2 = match.group(1).split(' ')
#get si2ter
line = scan_process.stdout.readline()
- match = re.search(r'si2ter\s(.+)',line)
+ match = re.search(r'SI2ter:\s(.+)',line)
if match:
base_station.system_info_t2ter = match.group(1).split(' ')
#get si2bis
line = scan_process.stdout.readline()
- match = re.search(r'si2bis\s(.+)',line)
+ match = re.search(r'SI2bis:\s(.+)',line)
if match:
base_station.system_info_t2bis = match.group(1).split(' ')
#endinfo
diff --git a/Src/PyCatcher/src/filters.py b/Src/PyCatcher/src/filters.py
index b574ade..07cba41 100644
--- a/Src/PyCatcher/src/filters.py
+++ b/Src/PyCatcher/src/filters.py
@@ -6,12 +6,6 @@ class Filter:
def execute(self, station_list):
raise NotImplementedError('Filter not yet implemented')
-class BandFilter(Filter):
- band = 0
-
- def execute(self, station_list):
- raise NotImplementedError('Band Filters should not be executed!')
-
class ARFCNFilter(Filter):
def execute(self, station_list):
filtered_list = []
@@ -31,6 +25,4 @@ class ProviderFilter(Filter):
filtered_list.append(station)
return filtered_list
-class BandFilter900(BandFilter):
- band = 900
diff --git a/Src/PyCatcher/src/pyCatcherController.py b/Src/PyCatcher/src/pyCatcherController.py
index 924ada9..ebcc2fc 100644
--- a/Src/PyCatcher/src/pyCatcherController.py
+++ b/Src/PyCatcher/src/pyCatcherController.py
@@ -1,15 +1,17 @@
import gtk
-import gtk.glade
+import gtk.glade
+import io
from driverConnector import DriverConnector
from pyCatcherModel import BaseStationInformation, BaseStationInformationList
from pyCatcherView import PyCatcherGUI
-from filters import ARFCNFilter,ProviderFilter, BandFilter900
+from filters import ARFCNFilter,ProviderFilter
from evaluators import EvaluatorSelect, BayesEvaluator, ConservativeEvaluator, WeightedEvaluator
from rules import ProviderRule, ARFCNMappingRule, CountryMappingRule, LACMappingRule, UniqueCellIDRule, \
LACMedianRule, NeighbourhoodStructureRule, PureNeighbourhoodRule, FullyDiscoveredNeighbourhoodsRule, RuleResult, CellIDDatabaseRule, LocationAreaDatabaseRule
import pickle
from localAreaDatabse import LocalAreaDatabase
from cellIDDatabase import CellIDDatabase, CellIDDBStatus, CIDDatabases
+from settings import Database_path
class PyCatcherController:
def __init__(self):
@@ -23,9 +25,6 @@ class PyCatcherController:
self.arfcn_filter = ARFCNFilter()
self.provider_filter = ProviderFilter()
-
- self.band_filter = BandFilter900()
- self.band_filter.is_active = True
self._filters = [self.arfcn_filter, self.provider_filter]
@@ -133,11 +132,6 @@ class PyCatcherController:
station.latitude = lat
station.longitude = long
station.db_provider = CIDDatabases.GOOGLE
- #TODO: remove else clause once new scans are available
- else:
- station.latitude = 0
- station.longitude = 0
- station.db_provider = CIDDatabases.NONE
station.db_status = status
if self.use_open_cell_id and not found:
self._gui.log_line('Looking up %d on OpenCellID.'%station.cell)
@@ -153,11 +147,6 @@ class PyCatcherController:
station.latitude = lat
station.longitude = long
station.db_provider = CIDDatabases.OPENCID
- #TODO: remove else clause once new scans are available
- else:
- station.latitude = 0
- station.longitude = 0
- station.db_provider = CIDDatabases.NONE
station.db_status = status
if self.use_local_db[0] and not found:
self._gui.log_line('Looking up %d on Local.'%station.cell)
@@ -167,11 +156,6 @@ class PyCatcherController:
station.db_provider = CIDDatabases.LOCAL
station.latitude = 0
station.longitude = 0
- #TODO: remove else clause once new scans are available
- else:
- station.latitude = 0
- station.longitude = 0
- station.db_provider = CIDDatabases.NONE
station.db_status = status
self._gui.log_line('Finished online lookups.')
@@ -203,16 +187,16 @@ class PyCatcherController:
def trigger_evaluation(self):
self._gui.log_line('Re-evaluation')
self._base_station_list.evaluate(self._rules, self._active_evaluator)
- self._base_station_list.refill_store(self.bs_tree_list_data, self.band_filter, self._filters)
+ self._base_station_list.refill_store(self.bs_tree_list_data, self._filters)
self.trigger_redraw()
def trigger_redraw(self):
- dotcode = self._base_station_list.get_dot_code(self.band_filter, self._filters)
+ dotcode = self._base_station_list.get_dot_code(self._filters)
if dotcode != 'digraph bsnetwork { }':
self._gui.load_dot(dotcode)
result = RuleResult.IGNORE
at_least_warning = False
- for item in self._base_station_list._get_filtered_list(self.band_filter, self._filters):
+ for item in self._base_station_list._get_filtered_list(self._filters):
if item.evaluation == 'Ignore':
pass
if item.evaluation == 'Ok' and not at_least_warning:
@@ -223,4 +207,30 @@ class PyCatcherController:
elif item.evaluation == 'Critical':
result = RuleResult.CRITICAL
break
- self._gui.set_image(result) \ No newline at end of file
+ self._gui.set_image(result)
+
+ def export_csv(self):
+ if self._location == '':
+ self._gui.log_line('Set valid location before exporting!')
+ return
+ path = Database_path + self._location + '.csv'
+ file = open(path,'w')
+ file.write('Country, Provider, ARFCN, rxlev, BSIC, LAC, Cell ID, Evaluation, Latitude, Longitude, Encryption, DB Status, DB Provider, Neighbours\n')
+ for item in self._base_station_list._get_unfiltered_list():
+ file.write('%s, %s, %d, %d, %s, %d, %d, %s, %d, %d, %s, %s, %s, %s\n'%
+ (item.country,
+ item.provider,
+ item.arfcn,
+ item.rxlev,
+ item.bsic.replace(',','/'),
+ item.lac,
+ item.cell,
+ item.evaluation,
+ item.latitude,
+ item.longitude,
+ item.encryption,
+ item.db_status,
+ item.db_provider,
+ ' '.join(map(str,item.neighbours))))
+ file.close()
+ self._gui.log_line('Export done.')
diff --git a/Src/PyCatcher/src/pyCatcherModel.py b/Src/PyCatcher/src/pyCatcherModel.py
index 4e17217..f4615fc 100644
--- a/Src/PyCatcher/src/pyCatcherModel.py
+++ b/Src/PyCatcher/src/pyCatcherModel.py
@@ -5,20 +5,11 @@ from cellIDDatabase import CellIDDBStatus
from cellIDDatabase import CIDDatabases
from rules import RuleResult
-class EnumTranslator:
- CIDDBStatus = {
- 0:'Confirmed.',
- 1:'Approximated.',
- 2:'Error.',
- 3:'Not yet looked up.',
- 4:'Not in database.'
- }
- CIDDB = {
- 0:'None.',
- 1:'Google.',
- 2:'OpenCellID',
- 3:'Local Cell DB'
- }
+class Encryption:
+ A0 = 'A5/0'
+ A1 = 'A5/1'
+ A2 = 'A5/2'
+ NA = 'Not checked.'
class BaseStationInformation:
@@ -27,10 +18,14 @@ class BaseStationInformation:
self.provider = 'Carry'
self.arfcn = 0
self.rxlev = 0
- self.times_scanned = 0
+ self.times_scanned = 1
+ self.system_info_t1 = []
+ self.system_info_t3 = []
+ self.system_info_t4 = []
self.system_info_t2 = []
self.system_info_t2bis = []
self.system_info_t2ter = []
+ self.neighbours = []
self.discovery_time = datetime.datetime.now().strftime('%T')
self.found = False
self.bsic = ''
@@ -42,44 +37,13 @@ class BaseStationInformation:
self.evaluation_by = 'NYE'
self.latitude = 0
self.longitude = 0
+ self.encryption = Encryption.NA
self.db_status = CellIDDBStatus.NOT_LOOKED_UP
self.db_provider = CIDDatabases.NONE
+
def get_list_model(self):
- return self.provider, str(self.arfcn), str(self.rxlev), str(self.cell),self.evaluation, self.discovery_time,0
-
- def get_neighbour_arfcn(self):
- if 1 < self.arfcn < 125:
- return self._parse_900()
- return []
-
- def si_to_bin(self, si):
- neighbours = si[3:19]
- bin_representation = ''
- for value in neighbours:
- bin_representation += str(bin(int(value, 16))[2:].zfill(8))
- return bin_representation
-
- def parse_bit_mask(self, si, offset):
- bin_representation = self.si_to_bin(si)
- neighbours = []
- for x in xrange(1,125):
- index = 0-x
- bit = bin_representation[index]
- if bit == '1':
- neighbours.append(abs(index) + offset)
- return neighbours
-
-
- def _parse_900(self):
- neighbours = self.parse_bit_mask(self.system_info_t2, 0)
- return map(int, neighbours)
-
- def _parse_1800(self):
- pass
-
- def _parse_900_ext(self):
- pass
+ return self.provider, str(self.arfcn), str(self.rxlev), str(self.cell),self.evaluation, self.discovery_time,self.times_scanned
def create_report(self):
report_params = '''------- Base Station Parameters -----------
@@ -91,12 +55,13 @@ BSIC: %s
LAC: %s
Cell ID: %s
Neighbours: %s
+Encryption: %s
Latitude: %s
Longitude: %s
Database Status: %s
Database Provider: %s
Evaluation: %s\n
-'''%(self.country,self.provider, self.arfcn, self.rxlev, self.bsic, self.lac, self.cell, ', '.join(map(str,self.get_neighbour_arfcn())),self.latitude,self.longitude,EnumTranslator.CIDDBStatus[self.db_status], EnumTranslator.CIDDB[self.db_provider],self.evaluation)
+'''%(self.country,self.provider, self.arfcn, self.rxlev, self.bsic, self.lac, self.cell, ', '.join(map(str,self.neighbours)),self.encryption,self.latitude,self.longitude,self.db_status, self.db_provider,self.evaluation)
report_rules ='------- Rule Results -----------\n'
for key in self.rules_report.keys():
@@ -109,10 +74,14 @@ Evaluation: %s\n
report_evaluation +='\n\n'
report_raw = '''------- Raw Information -----------
+SystemInfo_1: %s
SystemInfo_2: %s
SystemInfo_2ter: %s
SystemInfo_2bis: %s
-'''%(' '.join(self.system_info_t2), ' '.join(self.system_info_t2ter), ' '.join(self.system_info_t2bis))
+SystemInfo_3: %s
+SystemInfo_4: %s
+
+'''%(' '.join(self.system_info_t1),' '.join(self.system_info_t2),' '.join(self.system_info_t2ter),' '.join(self.system_info_t2bis), ' '.join(self.system_info_t3), ' '.join(self.system_info_t4))
return report_params + report_rules + report_evaluation + report_raw
@@ -127,16 +96,17 @@ class BaseStationInformationList:
#TODO: check if this works like i thought
if item.arfcn == base_station.arfcn and item.bsic == base_station.bsic:
item.discovery_time = datetime.datetime.now().strftime('%T')
+ item.times_scanned += 1
break
else:
self._base_station_list.append(base_station)
-
- def get_dot_code(self, band_filter, filters=None):
+
+ def get_dot_code(self, filters=None):
preamble = r'digraph bsnetwork { '
postamble = r'}'
code = ''
- filtered_list = self._get_filtered_list(band_filter, filters)
+ filtered_list = self._get_filtered_list(filters)
for station in filtered_list:
if station.evaluation == RuleResult.OK:
@@ -147,33 +117,25 @@ class BaseStationInformationList:
code += str(station.arfcn) + r' [style = filled, fillcolor = red]; '
else:
code += str(station.arfcn) + r' [style = filled, fillcolor = white]; '
- for neighbour in station.get_neighbour_arfcn():
+ for neighbour in station.neighbours:
code += str(station.arfcn) + r' -> ' + str(neighbour) + r'; '
#TODO: make printing the source a fixed option
#print preamble + code + postamble
return preamble + code + postamble
- def refill_store(self, store, band_filter, filters=None):
+ def refill_store(self, store, filters=None):
store.clear()
- filtered_list = self._get_filtered_list(band_filter, filters)
+ filtered_list = self._get_filtered_list(filters)
for item in filtered_list:
store.append(item.get_list_model())
def _get_unfiltered_list(self):
return self._base_station_list
- def _get_filtered_list(self, band_filter, filters):
+ def _get_filtered_list(self, filters):
filtered_list = []
-
- #only implemented for 900 band so far, so no distinction
- if band_filter.is_active:
- for item in self._base_station_list:
- if 0 < item.arfcn < 125:
- filtered_list.append(item)
- else:
- for item in self._base_station_list:
- filtered_list.append(item)
-
+ for item in self._base_station_list:
+ filtered_list.append(item)
if filters is not None:
for filter in filters:
if filter.is_active:
diff --git a/Src/PyCatcher/src/pyCatcherView.py b/Src/PyCatcher/src/pyCatcherView.py
index c6f6457..68400a7 100644
--- a/Src/PyCatcher/src/pyCatcherView.py
+++ b/Src/PyCatcher/src/pyCatcherView.py
@@ -93,11 +93,6 @@ class PyCatcherGUI:
else:
self._catcher_controller.arfcn_filter.is_active = False
- if self._builder.get_object('cb_filter_900').get_active():
- self._catcher_controller.band_filter.is_active = True
- else:
- self._catcher_controller.band_filter.is_active = False
-
self._catcher_controller.trigger_evaluation()
def _update_rules(self):
@@ -117,6 +112,10 @@ class PyCatcherGUI:
def _update_evaluators(self):
pass
+ def _on_csv_clicked(self, widget):
+ self._update_databases()
+ self._catcher_controller.export_csv()
+
def _update_databases(self):
self._catcher_controller.use_google = self._builder.get_object('cb_google').get_active()
self._catcher_controller.use_open_cell_id = self._builder.get_object('cb_opencellid').get_active()
diff --git a/Src/PyCatcher/src/rules.py b/Src/PyCatcher/src/rules.py
index 8a8ba09..143739c 100644
--- a/Src/PyCatcher/src/rules.py
+++ b/Src/PyCatcher/src/rules.py
@@ -18,7 +18,7 @@ class Rule:
def _extract_neighbours(self, arfcn, base_station_list):
for item in base_station_list:
if item.arfcn == arfcn:
- return item.get_neighbour_arfcn()
+ return item.neighbours
def _extract_provider(self, arfcn, base_station_list):
for item in base_station_list:
@@ -128,24 +128,26 @@ class NeighbourhoodStructureRule (Rule):
identifier = 'Neighbourhood Structure'
def check(self, arfcn, base_station_list):
- #TODO: remove this when parser fully implemented
- if not 0 < arfcn < 125:
- return RuleResult.IGNORE
-
- neighbours = self._extract_neighbours(arfcn, base_station_list)
-
- if not len(neighbours):
+ own_neighbours = self._extract_neighbours(arfcn, base_station_list)
+ if not len(own_neighbours):
return RuleResult.CRITICAL
-
at_least_one_neighbour_found = False
+ at_least_one_indirect_neighbour = False
for item in base_station_list:
- if item.arfcn in neighbours:
+ if item.arfcn in own_neighbours:
at_least_one_neighbour_found = True
break
+ else:
+ if item.arfcn != arfcn:
+ for foreign_neighbour_arfcn in item.neighbours:
+ if foreign_neighbour_arfcn in own_neighbours:
+ at_least_one_indirect_neighbour = True
if at_least_one_neighbour_found:
return RuleResult.OK
+ elif at_least_one_indirect_neighbour:
+ return RuleResult.WARNING
else:
return RuleResult.CRITICAL
@@ -154,9 +156,6 @@ class PureNeighbourhoodRule (Rule):
identifier = 'Pure Neighbourhoods'
def check(self, arfcn, base_station_list):
- #TODO: remove this when parser fully implemented
- if not 0 < arfcn < 125:
- return RuleResult.IGNORE
neighbours = self._extract_neighbours(arfcn, base_station_list)
provider = self._extract_provider(arfcn, base_station_list)
@@ -176,18 +175,15 @@ class FullyDiscoveredNeighbourhoodsRule (Rule):
identifier = 'Fully Discovered Neighbourhoods'
def check(self, arfcn, base_station_list):
- #TODO: remove this when parser fully implemented
- if not 0 < arfcn < 125:
- return RuleResult.IGNORE
neighbours = self._extract_neighbours(arfcn, base_station_list)
- all_neighbours_discovered = True
+ found = 0
for item in base_station_list:
if item.arfcn in neighbours:
- neighbours.remove(item.arfcn)
+ found += 1
- if len(neighbours):
- return RuleResult.WARNING
+ if len(neighbours) != found:
+ return RuleResult.CRITICAL
else:
return RuleResult.OK
diff --git a/Src/osmolib/src/host/layer23/src/misc/catcher.c b/Src/osmolib/src/host/layer23/src/misc/catcher.c
index 82e7ea2..7ce7e88 100644
--- a/Src/osmolib/src/host/layer23/src/misc/catcher.c
+++ b/Src/osmolib/src/host/layer23/src/misc/catcher.c
@@ -58,7 +58,7 @@ enum {
};
/* ranges of bands */
-static uint16_t band_range[][2] = {{0, 124}, {512, 885}, {955, 1023}, {0, 0}};
+static uint16_t band_range[][2] = {{0, 124}, {512, 890}, {955, 1023}, {0, 0}};
#define INFO_FLG_PM 1
#define INFO_FLG_SYNC 2
@@ -175,46 +175,88 @@ static void log_pm(void)
LOGFLUSH();
}
+
+/* check if the cell 'talks' about DCS (0) or PCS (1) */
+uint8_t my_gsm_refer_pcs(uint16_t arfcn, struct gsm48_sysinfo *s)
+{
+ /* If ARFCN is PCS band, the cell refers to PCS */
+ if ((arfcn & ARFCN_PCS))
+ return 1;
+
+ /* If no SI1 is available, we assume DCS. Be sure to call this
+ * function only if SI 1 is available. */
+ if (!s->si1)
+ return 0;
+
+ /* If band indicator indicates PCS band, the cell refers to PCSThe */
+ return s->band_ind;
+}
+
+uint16_t my_index2arfcn(int index)
+{
+ if (index >= 1024)
+ return (index-1024+512) | ARFCN_PCS;
+ return index;
+}
+
static void log_sysinfo(void)
{
struct rx_meas_stat *meas = &ms->meas;
struct gsm48_sysinfo *s = &sysinfo;
struct gsm322_cellsel *cs = &ms->cellsel;
int8_t rxlev;
- char ta_str[32] = "";
-
- if (log_si.ta != 0xff)
- sprintf(ta_str, " TA=%d", log_si.ta);
-
+ int refer_pcs, index;
+ uint16_t arfcn;
-
- //LOGP(DSUM, LOGL_INFO, "Cell: ARFCN=%d MCC=%s MNC=%s (%s, %s)%s\n",
- // arfcn, gsm_print_mcc(s->mcc), gsm_print_mnc(s->mnc),
- // gsm_get_mcc(s->mcc), gsm_get_mnc(s->mcc, s->mnc), ta_str);
LOGFILE("[SysInfo]\n");
LOGFILE("Country: %s\n", gsm_get_mcc(s->mcc));
LOGFILE("Provider: %s\n", gsm_get_mnc(s->mcc, s->mnc));
LOGFILE("ARFCN: %d\n", s->arfcn);
LOGFILE("Cell ID: %d\n", s->cell_id);
LOGFILE("LAC: %d\n", s->lac);
- //log_time();
- //log_gps();
LOGFILE("BSIC: %d,%d\n", s->bsic >> 3, s->bsic & 7);
rxlev = meas->rxlev / meas->frames - 110;
LOGFILE("rxlev: %d\n", rxlev);
+ LOGFILE("Neighbours: ");
+
+ refer_pcs = my_gsm_refer_pcs(s->arfcn, s);
+ int i = 0;
+
+ for (i = 0; i <= 1023; i++) {
+#ifndef TEST_INCLUDE_SERV
+ if (s->freq[i].mask & FREQ_TYPE_NCELL) {
+#else
+ if (s->freq[i].mask & (FREQ_TYPE_NCELL | FREQ_TYPE_SERV)) {
+#endif
+ index = i;
+ if (refer_pcs && i >= 512 && i <= 810)
+ index = i-512+1024;
+ arfcn = my_index2arfcn(index);
+#ifndef TEST_INCLUDE_SERV
+ if (arfcn == s->arfcn) {
+ //LOGP(DNB, LOGL_INFO, "Omitting serving cell %s."
+ // "\n", gsm_print_arfcn(s->arfcn));
+ continue;
+ }
+#endif
+ LOGFILE("%d ", arfcn & 1023);
+ }
+ }
+
+ LOGFILE("\n");
- //if (s->si1)
- // log_frame("si1", s->si1_msg);
+ if (s->si1)
+ log_frame("SI1: ", s->si1_msg);
+ if (s->si3)
+ log_frame("SI3: ", s->si3_msg);
+ if (s->si4)
+ log_frame("SI4: ", s->si4_msg);
if (s->si2)
- log_frame("si2", s->si2_msg);
+ log_frame("SI2: ", s->si2_msg);
if (s->si2ter)
- log_frame("si2ter", s->si2t_msg);
+ log_frame("SI2ter: ", s->si2t_msg);
if (s->si2bis)
- log_frame("si2bis", s->si2b_msg);
- //if (s->si3)
- // log_frame("si3", s->si3_msg);
- //if (s->si4)
- // log_frame("si4", s->si4_msg);
+ log_frame("SI2bis: ", s->si2b_msg);
//if (s->si5)
// log_frame("si5", s->si5_msg);
//if (s->si5bis)
diff --git a/Src/osmolib/src/host/layer23/src/mobile/gsm322.c b/Src/osmolib/src/host/layer23/src/mobile/gsm322.c
index ce5e1e1..ebc7f63 100644
--- a/Src/osmolib/src/host/layer23/src/mobile/gsm322.c
+++ b/Src/osmolib/src/host/layer23/src/mobile/gsm322.c
@@ -4492,7 +4492,7 @@ static int gsm322_nb_start(struct osmocom_ms *ms, int synced)
#endif
nb = gsm322_nb_alloc(cs, arfcn);
LOGP(DNB, LOGL_INFO, "Adding neighbour cell %s to "
- "list.\n", gsm_print_arfcn(nb->arfcn));
+ "list (refer_pcs=%d, index=%d, map=%d) .\n", gsm_print_arfcn(nb->arfcn), refer_pcs, index, map[i >> 3]);
if (!(cs->list[index].flags & GSM322_CS_FLAG_SUPPORT))
nb->state = GSM322_NB_NOT_SUP;
changed = 1;