Changeset 9623 for src/django_gheat/gheat/management/commands/kismet.py
- Timestamp:
- Aug 30, 2011, 6:13:57 PM (13 years ago)
- File:
-
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
src/django_gheat/gheat/management/commands/kismet.py
r9592 r9623 2 2 # -*- coding: utf-8 -*- 3 3 # 4 # Script for importing .gpsxml and .netxml files (Kismet output)5 #6 4 # Rick van der Zwet <info@rickvanderzwet.nl> 7 5 # 8 from django.core.management.base import BaseCommand,CommandError9 from django.db.utils import IntegrityError10 from optparse import OptionParser, make_option11 from gheat.models import *12 6 from lxml import etree 13 import datetime14 import gzip15 import os16 import sys17 7 import logging 18 8 19 9 from collections import defaultdict 20 10 21 from import_droidstumbler import bulk_sql,get_organization_id_by_ssid22 23 11 logger = logging.getLogger(__name__) 24 12 logger.setLevel(logging.INFO) 25 13 26 # Open files for reading 27 def open_file(file): 28 if file.endswith('.gz'): 29 return gzip.open(file,'rb') 30 else: 31 return open(file,'rb') 32 33 34 35 def import_kismet_netxml(netxml_file): 36 netxml_doc = etree.parse(open_file(netxml_file)) 37 38 counters = { 'ap_added' : 0, 'ap_total' : 0, 'ap_failed' : 0, 'ap_ignored' : 0, 39 'client_added' : 0, 'client_total' : 0, 'client_failed' : 0, 'client_ignored' : 0} 14 def process_netxml(fh,counters): 15 netxml_doc = etree.parse(fh) 40 16 41 17 # Prepare new accespoints and measurements … … 65 41 logger.error('Unknown type %s - %s',bssid, wnetwork.attrib['type']) 66 42 67 68 # Determine which Accespoints to add 69 bssid_list_present = Accespoint.objects.filter(mac__in=ap_pool.keys()).values_list('mac', flat=True) 70 bssid_list_insert = set(ap_pool.keys()) - set(bssid_list_present) 71 72 # Create a bulk import list and import 73 if bssid_list_insert: 74 sql_values = [] 75 for bssid in bssid_list_insert: 76 ssid, encryption = ap_pool[bssid] 77 # Special trick in SSID ts avoid escaping in later stage 78 item = str((bssid.upper(),ssid.replace('%','%%'),encryption,get_organization_id_by_ssid(ssid))) 79 sql_values.append(item) 80 counters['ap_added'] = bulk_sql('gheat_accespoint (`mac`, `ssid`, `encryptie`, `organization_id`)',sql_values) 81 82 # Determine which Wireless Clients to add 83 bssid_list_present = WirelessClient.objects.filter(mac__in=client_pool.keys()).values_list('mac', flat=True) 84 bssid_list_insert = set(client_pool.keys()) - set(bssid_list_present) 85 86 # Create a bulk import list and import 87 if bssid_list_insert: 88 sql_values = [] 89 for bssid in bssid_list_insert: 90 sql_values.append("('%s')" % bssid.upper()) 91 counters['client_added'] = bulk_sql('gheat_wirelessclient (`mac`)',sql_values) 92 93 return counters 43 return (counters, ap_pool, None, None) 94 44 95 45 96 46 97 def import_kismet_gpsxml(gpsxml_file, meetrondje): 98 gpsxml_doc = etree.parse(open_file(gpsxml_file)) 99 100 #Various statistics 101 counters = {'meting_added' : 0, 'meting_total' : 0, 'meting_failed' : 0, 'meting_ignored' :0} 47 def process_gpsxml(fh,counters): 48 gpsxml_doc = etree.parse(fh) 102 49 103 50 bssid_failed = defaultdict(int) … … 130 77 signaal=100 + int(level) 131 78 meting_pool[key].append(signaal) 132 133 bssid_list = [x[0] for x in meting_pool.keys()] 134 # Build mapping for meting import 135 mac2id = {} 136 for mac,id in Accespoint.objects.filter(mac__in=bssid_list).values_list('mac','id'): 137 mac2id[mac] = int(id) 138 139 clients = {} 140 for mac in WirelessClient.objects.filter(mac__in=bssid_list).values_list('mac',flat=True): 141 clients[mac] = True 142 143 sql_values = [] 144 for (bssid,lat,lon),signals in meting_pool.iteritems(): 145 if clients.has_key(bssid): 146 counters['meting_ignored'] += len(signals) 147 elif not mac2id.has_key(bssid): 148 counters['meting_failed'] += len(signals) 149 bssid_failed[bssid] += len(signals) 150 else: 151 item = str((int(meetrondje.id),mac2id[bssid],float(lat),float(lon),max(signals))) 152 sql_values.append(item) 153 154 for bssid,count in sorted(bssid_failed.items(), 155 key=lambda item: item[1], reverse=True): 156 logger.debug("Missing BSSID %s found %3s times", bssid, count) 157 158 if sql_values: 159 counters['meting_added'] = bulk_sql('gheat_meting (`meetrondje_id`, `accespoint_id`, `lat`, `lng`, `signaal`)',sql_values) 160 return counters 161 162 163 class Command(BaseCommand): 164 args = '<gpsxml|netxml>[.gz] [gpsxml2[.gz] gpsxml3[.gz] ...]' 165 option_list = BaseCommand.option_list + ( 166 make_option('-k', '--kaart', dest='kaart', default='onbekend', help="Kaart gebruikt"), 167 make_option('-m', '--meetrondje', dest='meetrondje', default=None), 168 make_option('-g', '--gebruiker', dest='gebruiker', default='username',help='Naam van de persoon die de meting uitgevoerd heeft'), 169 make_option('-e', '--email', dest='email', default='foo@bar.org',help='Email van de persoon die de meting uitgevoerd heeft'), 170 make_option('-d', '--datum', dest='datum', default=None, help="Provide date \ 171 in following format: '%Y%m%d-%H-%M-%S-1', by default it will be generated from \ 172 the filename"), 173 ) 174 175 def handle(self, *args, **options): 176 if len(args) == 0: 177 self.print_help(sys.argv[0],sys.argv[1]) 178 raise CommandError("Not all arguments are provided") 179 180 # Please first the netxml and then the gpsxml files 181 sorted_args = [x for x in args if "netxml" in x] + [x for x in args if "gpsxml" in x] 182 remainder = list(set(args) - set(sorted_args)) 183 args = sorted_args + remainder 184 logger.debug("Parsing files in the following order: %s", args) 185 186 for xml_file in args: 187 if not os.path.isfile(xml_file): 188 raise CommandError("xml file '%s' does not exists" % xml_file) 189 190 for xml_file in args: 191 logger.info("Processing '%s'" % xml_file) 192 if 'netxml' in xml_file: 193 counters = import_kismet_netxml(xml_file) 194 logger.info("summary accespoints: total:%(ap_total)-6s added:%(ap_added)-6s failed:%(ap_failed)-6s ignored:%(ap_ignored)-6s" % counters) 195 logger.info("summary client : total:%(client_total)-6s added:%(client_added)-6s failed:%(client_failed)-6s ignored:%(client_ignored)-6s" % counters) 196 elif 'gpsxml' in xml_file: 197 if options['datum'] == None: 198 datum = os.path.basename(xml_file).lstrip('Kismet-').rstrip('.gz').rstrip('.gpsxml').rstrip('.netxml') 199 else: 200 datum = options['datum'] 201 try: 202 # Kismet-20110805-15-37-30-1 203 datum = datetime.datetime.strptime(datum,'%Y%m%d-%H-%M-%S-1') 204 except ValueError: 205 raise CommandError("Invalid date '%s'" % options['datum']) 206 207 # Meetrondje from filename if needed 208 if options['meetrondje'] == None: 209 meetrondje = os.path.basename(xml_file).rstrip('.gz').rstrip('.gpsxml') 210 else: 211 meetrondje = options['meetrondje'] 212 213 # Create meetrondje object 214 g, created = Gebruiker.objects.get_or_create(naam=options['gebruiker'] , email=options['email']) 215 a, created = Apparatuur.objects.get_or_create(kaart=options['kaart']) 216 mr, created = MeetRondje.objects.get_or_create(datum=datum , naam=meetrondje , gebruiker=g , apparatuur=a) 217 logger.info('Meetrondje: %s @ %s' % (meetrondje, datum)) 218 if not created: 219 logger.error("Meetrondje '%s' already imported" % mr) 220 continue 221 counters = import_kismet_gpsxml(xml_file, mr) 222 logger.info("summary metingen : total:%(meting_total)-6s added:%(meting_added)-6s failed:%(meting_failed)-6s ignored:%(meting_ignored)-6s" % counters) 223 else: 224 raise CommandError("xml file '%s' format not recognized" % xml_file) 79 return (counters, None, None, meting_pool)
Note:
See TracChangeset
for help on using the changeset viewer.