Esempio n. 1
0
def fetch(path=None,verbose=False):
    """
     retrieves oui.txt from IEEE and writes to data file
     :param path: fullpath of oui.txt
     :param verbose: write updates to stdout
    """
    # determine if data path is legit
    if path is None:
        ouipath = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                               os.path.abspath('../data/oui.txt'))
    else:
        ouipath = path
    if not os.path.isdir(os.path.dirname(ouipath)):
        print "Path to data is incorrect {0}".format(ouipath)
        sys.exit(1)

    # fetch oui file from ieee
    fout = None
    #pattern = r'^([-|\w]*)   \(hex\)\t\t(.*)\r'

    # set up url request
    ouiurl = 'http://standards-oui.ieee.org/oui.txt'
    req = urllib2.Request(ouiurl)
    req.add_header('User-Agent',"wraith-rt +https://github.com/wraith-wireless/wraith/")
    try:
        # retrieve the oui file and parse out generated date
        if verbose: print 'Fetching ', ouiurl
        res = urllib2.urlopen(req)
        if verbose: print "Parsing OUI file"

        if verbose: print "Opening data file {0} for writing".format(ouipath)
        fout = open(ouipath,'w')
        gen = ts2iso(time.time()) # use current time as the first line
        fout.write(gen+'\n')

        # pull out ouis
        t = time.time()
        cnt = 0
        for l in res:
            if '(hex)' in l:
                # extract oui and manufacturer
                oui,manuf = l.split('(hex)')
                oui = oui.strip().replace('-',':')
                manuf = manuf.strip()
                if manuf.startswith("IEEE REGISTRATION AUTHORITY"):
                    manuf = "IEEE REGISTRATION AUTHORITY"

                # write to file & update count
                fout.write('{0}\t{1}\n'.format(oui,manuf))
                cnt += 1
                if verbose: print "{0}:\t{1}\t{2}".format(cnt,oui,manuf)
        print "Wrote {0} OUIs in {1:.3} secs".format(cnt,time.time()-t)
    except urllib2.URLError as e:
        print "Error fetching oui file: {0}".format(e)
    except IOError as e:
        print "Error opening output file {0}".format(e)
    except Exception as e:
        print "Error parsing oui file: {0}".format(e)
    finally:
        if fout: fout.close()
Esempio n. 2
0
 def _send(self,t,ts,d):
     """
      send - sends message msg m of type t with timestamp ts to Nidus
       t - message type
       ts - message timestamp
       d - data
      returns None on success otherwise returns reason for failure
     """
     # convert the timestamp to utc isoformat before crafting
     ts = ts2iso(ts)
     
     # craft the message
     try:
         send = "\x01*%s:\x02" % t
         if t == 'DEVICE': send += self._craftdevice(ts,d)
         elif t == 'PLATFORM': send += self._craftplatform(d)
         elif t == 'RADIO': send += self._craftradio(ts,d)
         elif t == 'ANTENNA': send += self._craftantenna(ts,d)
         elif t == 'GPSD': send += self._craftgpsd(ts,d)
         elif t == 'FRAME': send += self._craftframe(ts,d)
         elif t == 'GPS': send += self._craftflt(ts,d,self._mgrs)
         elif t == 'RADIO_EVENT': send += self._craftradioevent(ts,d)
         send += "\x03\x12\x15\04"
         if not self._nidus.send(send): return "Nidus socket closed unexpectantly"
         return None
     except socket.error, ret:
         return ret
Esempio n. 3
0
    def submitdropped(self):
        """ sensor exited unexpectantly, close out open ended records """
        if not self._sid: return
        try:
            # get current time
            ts = ts2iso(time.time())

            # close out the sensor
            sql = """
                   update sensor set period = tstzrange(lower(period),%s)
                   where session_id = %s;
                  """
            self._curs.execute(sql,(ts,self._sid))

            # close out radios
            # get radios currently used by sensor
            sql = " select mac from using_radio where sid=%s;"
            self._curs.execute(sql,(self._sid,))
            for row in self._curs.fetchall():
                mac = row[0]
                # close out using_radio
                sql = """
                       update using_radio set period = tstzrange(lower(period),%s)
                       where sid=%s and mac=%s;
                      """
                self._curs.execute(sql,(ts,self._sid,mac))

            # close out gpsd
            sql = """
                   update using_gpsd set period = tstzrange(lower(period),%s)
                   where sid=%s;
                  """
            self._curs.execute(sql,(ts,self._sid))
        except:
            # don't raise an exception here, nidus is already exiting
            self._conn.rollback()
        else:
            self._conn.commit()
Esempio n. 4
0
    def submitdropped(self):
        """ sensor exited unexpectantly, close out open ended records """
        if not self._sid: return
        try:
            # get current time
            ts = ts2iso(time.time())

            # close out the sensor
            sql = """
                   update sensor set period = tstzrange(lower(period),%s)
                   where session_id = %s;
                  """
            self._curs.execute(sql, (ts, self._sid))

            # close out radios
            # get radios currently used by sensor
            sql = " select mac from using_radio where sid=%s;"
            self._curs.execute(sql, (self._sid, ))
            for row in self._curs.fetchall():
                mac = row[0]
                # close out using_radio
                sql = """
                       update using_radio set period = tstzrange(lower(period),%s)
                       where sid=%s and mac=%s;
                      """
                self._curs.execute(sql, (ts, self._sid, mac))

            # close out gpsd
            sql = """
                   update using_gpsd set period = tstzrange(lower(period),%s)
                   where sid=%s;
                  """
            self._curs.execute(sql, (ts, self._sid))
        except:
            # don't raise an exception here, nidus is already exiting
            self._conn.rollback()
        else:
            self._conn.commit()
Esempio n. 5
0
    def run(self):
        """ switch channels based on associted dwell times """
        # ignore signals being used by main program
        signal.signal(signal.SIGINT, signal.SIG_IGN)
        signal.signal(signal.SIGTERM, signal.SIG_IGN)

        # starting paused or scanning?
        if self._state == TUNE_PAUSE:
            self._qR.put((RDO_PAUSE, isots(), [-1, ' ']))
        else:
            self._qR.put((RDO_SCAN, isots(), [-1, self._chs]))

        # execution loop - wait on the internal connection for each channels
        # dwell time. IOT avoid a state where we would continue to scan the same
        # channel, i.e. 'state' commands, use a remaining time counter
        remaining = 0  # remaining dwell time counter
        dwell = self._ds[0]  # save original dwell time
        while True:
            # set the poll timeout to remaining if we need to finish this scan
            # or to None if we are in a static state
            if self._state in [TUNE_PAUSE, TUNE_HOLD, TUNE_LISTEN]: to = None
            else: to = self._ds[self._i] if not remaining else remaining

            ts1 = time()  # get timestamp
            if self._cI.poll(
                    to):  # we hold on the iyri connection during poll time
                tkn = self._cI.recv()
                ts = time()

                # tokens will have 2 flavor's POISON and 'cmd:cmdid:params'
                # where params is empty (for POISON) or a '-' separated list
                if tkn == POISON:
                    # for a POISON, quit and notify the RadioController
                    self._qR.put((POISON, ts2iso(ts), [-1, ' ']))
                    break

                # calculate time remaining for this channel
                if not remaining: remaining = self._ds[self._i] - (ts - ts1)
                else: remaining -= (ts - ts1)

                # parse the requested command
                cmd, cid, ps = tkn.split(':')  # force into 3 components
                cid = int(cid)  # & convert id to int
                if cmd == 'state':
                    self._qR.put((RDO_STATE, ts2iso(ts), [cid, self.meta]))
                elif cmd == 'scan':
                    if self._state != TUNE_SCAN:
                        self._state = TUNE_SCAN
                        self._qR.put((RDO_SCAN, ts2iso(ts), [cid, self._chs]))
                    else:
                        self._qR.put(
                            (CMD_ERR, ts2iso(ts), [cid, "redundant cmd"]))
                elif cmd == 'txpwr':
                    err = "txpwr not currently supported"
                    self._qR.put((CMD_ERR, ts2iso(ts), [cid, err]))
                elif cmd == 'spoof':
                    err = "spoof not currently supported"
                    self._qR.put((CMD_ERR, ts2iso(ts), [cid, err]))
                elif cmd == 'hold':
                    if self._state != TUNE_HOLD:
                        self._state = TUNE_HOLD
                        self._qR.put(
                            (RDO_HOLD, ts2iso(ts), [cid, self.channel]))
                    else:
                        self._qR.put(
                            (CMD_ERR, ts2iso(ts), [cid, "redundant cmd"]))
                elif cmd == 'pause':
                    if self._state != TUNE_PAUSE:
                        self._state = TUNE_PAUSE
                        self._qR.put(
                            (RDO_PAUSE, ts2iso(ts), [cid, self.channel]))
                    else:
                        self._qR.put(
                            (CMD_ERR, ts2iso(ts), [cid, "redundant cmd"]))
                elif cmd == 'listen':
                    if self._state != TUNE_LISTEN:
                        try:
                            ch, chw = ps.split('-')
                            if chw == 'None': chw = None
                            self._rdo.setch(ch, chw)
                            self._state = TUNE_LISTEN
                            details = "{0}:{1}".format(ch, chw)
                            self._qR.put(
                                (RDO_LISTEN, ts2iso(ts), [cid, details]))
                        except ValueError:
                            err = "invalid param format"
                            self._qR.put((CMD_ERR, ts2iso(ts), [cid, err]))
                        except radio.RadioException as e:
                            self._qR.put((CMD_ERR, ts2iso(ts), [cid, str(e)]))
                    else:
                        self._qR.put(
                            (CMD_ERR, ts2iso(ts), [cid, "redundant cmd"]))
                else:
                    err = "invalid command {0}".format(cmd)
                    self._qR.put((CMD_ERR, ts2iso(ts), [cid, err]))
            else:
                try:
                    # no token, go to next channel, reset remaining
                    self._i = (self._i + 1) % len(self._chs)
                    self._rdo.setch(self._chs[self._i][0],
                                    self._chs[self._i][1])
                    remaining = 0  # reset remaining timeout
                except radio.RadioException as e:
                    self._qR.put((RDO_FAIL, isots(), [-1, e]))
                except Exception as e:  # blanket exception
                    self._qR.put((RDO_FAIL, isots(), [-1, e]))
Esempio n. 6
0
    def run(self):
        """ run execution loop """
        # ignore signals being used by main program
        signal.signal(signal.SIGINT,signal.SIG_IGN)
        signal.signal(signal.SIGTERM,signal.SIG_IGN)

        # basic variables
        rmap = {}    # radio map: maps callsigns to mac addr
        #bulk = {}    # stored frames
        gpsid = None # id of gps device

        # send sensor up notification, platform details and gpsid
        ret = self._send('DEVICE',time.time(),['sensor',socket.gethostname(),1])
        if ret: self._conn.send(('err','RTO','Nidus',ret))
        else:
            ret = self._send('PLATFORM',time.time(),self._pfdetails())
            if ret: self._conn.send(('err','RTO','Nidus',ret))
            else: self._setgpsd()

        # execution loop
        while True:
            # 1. anything from DySKT
            if self._conn.poll() and self._conn.recv() == '!STOP!': break

            # 2. gps device/frontline trace?
            try:
                t,ts,msg = self._q.get_nowait()
            except (Empty,AttributeError): pass
            else:
                if t == '!DEV!': # device up message
                    gpsid = msg['id']
                    self._conn.send(('info','RTO','GPSD',"%s initiated" % gpsid))
                    ret = self._send('GPSD',ts,msg)
                    if ret: self._conn.send(('err','RTO','Nidus',ret))
                elif t == '!FLT!': # frontline trace
                    ret = self._send('FLT',ts,msg)
                    if ret: self._conn.send(('err','RTO','Nidus',ret))

            # 3. queued data from internal comms
            ev = msg = None
            try:
                rpt = self._icomms.get(True,0.5)
                cs,ts,ev,msg = rpt[0],rpt[1],rpt[2],rpt[3]

                if ev == '!UP!': # should be the 1st message we get from radio(s)
                    # NOTE: send the radio, nidus will take care of setting the
                    # radio device status, initial radio events and using_radio.
                    # Send each antenna separately
                    rmap[cs] = msg['mac']
                    self._bulk[cs] = {'cob':None,       # zlib compressobj
                                      'mac':msg['mac'], # mac addr of collecting radio
                                      'start':0,        # time first frame was seen
                                      'cnt':0,          # ttl # of frames
                                      'sz':0,           # ttl size of uncompressed frames
                                      'frames':''}      # the compressed frames
                    self._conn.send(('info','RTO','Radio',"%s initiated" % cs))
                    ret = self._send('RADIO',ts,msg)
                    if ret: self._conn.send(('err','RTO','Nidus',ret))
                    else:
                        # send antennas
                        for i in xrange(msg['nA']):
                            ret = self._send('ANTENNA',ts,
                                             {'mac':msg['mac'],'index':i,
                                              'type':msg['type'][i],'gain':msg['gain'][i],
                                              'loss':msg['loss'][i],'x':msg['x'][i],
                                              'y':msg['y'][i],'z':msg['z'][i]})
                            if ret: self._conn.send(('err','RTO','Nidus',ret))
                elif ev == '!FAIL!':
                    # send bulked frames, notify nidus & DySKT & delete cs
                    ret = self._flushbulk(ts,rmap[cs],cs)
                    if not ret: ret = self._send('RADIO_EVENT',ts,[rmap[cs],'fail',msg])
                    if ret: self._conn.send(('err','RTO','Nidus',ret))
                    del rmap[cs]
                    del self._bulk[cs]
                elif ev == '!SCAN!':
                    # compile the scan list into a string before sending
                    sl = ",".join(["%d:%s" % (c,w) for (c,w) in msg])
                    ret = self._send('RADIO_EVENT',ts,[rmap[cs],'scan',sl])
                    if ret: self._conn.send(('err','RTO','Nidus',ret))
                elif ev == '!LISTEN!':
                    ret = self._send('RADIO_EVENT',ts,[rmap[cs],'listen',msg])
                    if ret: self._conn.send(('err','RTO','Nidus',ret))
                elif ev == '!HOLD!':
                    ret = self._send('RADIO_EVENT',ts,[rmap[cs],'hold',msg])
                    if ret: self._conn.send(('err','RTO','Nidus',ret))
                elif ev == '!PAUSE!':
                    # send bulked frames
                    ret = self._flushbulk(ts,rmap[cs],cs)
                    if not ret: ret = self._send('RADIO_EVENT',ts,[rmap[cs],'pause',' '])
                    if ret: self._conn.send(('err','RTO','Nidus',ret))
                elif ev == '!SPOOF!':
                    ret = self._send('RADIO_EVENT',ts,[rmap[cs],'spoof',msg])
                    if ret: self._conn.send(('err','RTO','Nidus',ret))
                elif ev == '!TXPWR!':
                    ret = self._send('RADIO_EVENT',ts,[rmap[cs],'txpwr',msg])
                    if ret: self._conn.send(('err','RTO','Nidus',ret))
                elif ev == '!FRAME!':
                    # save the frame and update bulk details
                    if self._bulk[cs]['cnt'] == 0:
                        self._bulk[cs]['start'] = ts               # reset start
                        self._bulk[cs]['cob'] = zlib.compressobj() # new compression obj

                    # add new frame and update metrics
                    self._bulk[cs]['cnt'] += 1
                    self._bulk[cs]['sz'] += len(msg)
                    self._bulk[cs]['frames'] += self._bulk[cs]['cob'].compress('%s \x1EFB\x1F%s\x1FFE\x1E' % (ts2iso(ts),msg))

                    # if we have hit our limit, compress and send the bulk frames
                    if self._bulk[cs]['sz'] > _BSZ_ or (ts - self._bulk[cs]['start'])/1000 > _BTM_:
                        self._flushbulk(ts,rmap[cs],cs)
                else: # unidentified event type, notify dyskt
                    self._conn.send(('warn','RTO','Radio',"unknown event %s" % ev))
            except Empty: # nothing on queue
                continue
            except IndexError as e: # something wrong with antenna indexing
                self._conn.send(('err','RTO',"Radio","misconfigured antennas"))
            except KeyError as e: # a radio sent a message without initiating
                self._conn.send(('warn','RTO','Radio %s' % e,"uninitiated data (%s)" % ev))
            except Exception as e: # handle catchall error
                self._conn.send(('err','RTO','Unknown',e))

        # any bulked frames not yet sent?
        for cs in rmap: self._flushbulk(time.time(),rmap[cs],cs)

        # notify Nidus of closing (radios,sensor,gpsd). hopefully no errors on send
        ts = time.time()
        for cs in rmap: self._send('DEVICE',ts,['radio',rmap[cs],0])
        self._send('DEVICE',ts,['gpsd',gpsid,0])
        self._send('DEVICE',ts,['sensor',socket.gethostname(),0])

        # shut down
        if not self._shutdown():
            try:
                self._conn.send(('warn','RTO','Shutdown',"Incomplete shutdown"))
            except IOError:
                # most likely DySKT(.py) closed their side of the pipe
                pass
Esempio n. 7
0
    def run(self):
        """ run execution loop """
        # ignore signals being used by main program
        signal.signal(signal.SIGINT, signal.SIG_IGN)
        signal.signal(signal.SIGTERM, signal.SIG_IGN)

        # basic variables
        rmap = {}  # radio map: maps callsigns to mac addr
        #bulk = {}    # stored frames
        gpsid = None  # id of gps device

        # send sensor up notification, platform details and gpsid
        ret = self._send('DEVICE', time.time(),
                         ['sensor', socket.gethostname(), 1])
        if ret: self._conn.send(('err', 'RTO', 'Nidus', ret))
        else:
            ret = self._send('PLATFORM', time.time(), self._pfdetails())
            if ret: self._conn.send(('err', 'RTO', 'Nidus', ret))
            else: self._setgpsd()

        # execution loop
        while True:
            # 1. anything from DySKT
            if self._conn.poll() and self._conn.recv() == '!STOP!': break

            # 2. gps device/frontline trace?
            try:
                t, ts, msg = self._q.get_nowait()
            except (Empty, AttributeError):
                pass
            else:
                if t == '!DEV!':  # device up message
                    gpsid = msg['id']
                    self._conn.send(
                        ('info', 'RTO', 'GPSD', "%s initiated" % gpsid))
                    ret = self._send('GPSD', ts, msg)
                    if ret: self._conn.send(('err', 'RTO', 'Nidus', ret))
                elif t == '!FLT!':  # frontline trace
                    ret = self._send('FLT', ts, msg)
                    if ret: self._conn.send(('err', 'RTO', 'Nidus', ret))

            # 3. queued data from internal comms
            ev = msg = None
            try:
                rpt = self._icomms.get(True, 0.5)
                cs, ts, ev, msg = rpt[0], rpt[1], rpt[2], rpt[3]

                if ev == '!UP!':  # should be the 1st message we get from radio(s)
                    # NOTE: send the radio, nidus will take care of setting the
                    # radio device status, initial radio events and using_radio.
                    # Send each antenna separately
                    rmap[cs] = msg['mac']
                    self._bulk[cs] = {
                        'cob': None,  # zlib compressobj
                        'mac': msg['mac'],  # mac addr of collecting radio
                        'start': 0,  # time first frame was seen
                        'cnt': 0,  # ttl # of frames
                        'sz': 0,  # ttl size of uncompressed frames
                        'frames': ''
                    }  # the compressed frames
                    self._conn.send(
                        ('info', 'RTO', 'Radio', "%s initiated" % cs))
                    ret = self._send('RADIO', ts, msg)
                    if ret: self._conn.send(('err', 'RTO', 'Nidus', ret))
                    else:
                        # send antennas
                        for i in xrange(msg['nA']):
                            ret = self._send(
                                'ANTENNA', ts, {
                                    'mac': msg['mac'],
                                    'index': i,
                                    'type': msg['type'][i],
                                    'gain': msg['gain'][i],
                                    'loss': msg['loss'][i],
                                    'x': msg['x'][i],
                                    'y': msg['y'][i],
                                    'z': msg['z'][i]
                                })
                            if ret:
                                self._conn.send(('err', 'RTO', 'Nidus', ret))
                elif ev == '!FAIL!':
                    # send bulked frames, notify nidus & DySKT & delete cs
                    ret = self._flushbulk(ts, rmap[cs], cs)
                    if not ret:
                        ret = self._send('RADIO_EVENT', ts,
                                         [rmap[cs], 'fail', msg])
                    if ret: self._conn.send(('err', 'RTO', 'Nidus', ret))
                    del rmap[cs]
                    del self._bulk[cs]
                elif ev == '!SCAN!':
                    # compile the scan list into a string before sending
                    sl = ",".join(["%d:%s" % (c, w) for (c, w) in msg])
                    ret = self._send('RADIO_EVENT', ts, [rmap[cs], 'scan', sl])
                    if ret: self._conn.send(('err', 'RTO', 'Nidus', ret))
                elif ev == '!LISTEN!':
                    ret = self._send('RADIO_EVENT', ts,
                                     [rmap[cs], 'listen', msg])
                    if ret: self._conn.send(('err', 'RTO', 'Nidus', ret))
                elif ev == '!HOLD!':
                    ret = self._send('RADIO_EVENT', ts,
                                     [rmap[cs], 'hold', msg])
                    if ret: self._conn.send(('err', 'RTO', 'Nidus', ret))
                elif ev == '!PAUSE!':
                    # send bulked frames
                    ret = self._flushbulk(ts, rmap[cs], cs)
                    if not ret:
                        ret = self._send('RADIO_EVENT', ts,
                                         [rmap[cs], 'pause', ' '])
                    if ret: self._conn.send(('err', 'RTO', 'Nidus', ret))
                elif ev == '!SPOOF!':
                    ret = self._send('RADIO_EVENT', ts,
                                     [rmap[cs], 'spoof', msg])
                    if ret: self._conn.send(('err', 'RTO', 'Nidus', ret))
                elif ev == '!TXPWR!':
                    ret = self._send('RADIO_EVENT', ts,
                                     [rmap[cs], 'txpwr', msg])
                    if ret: self._conn.send(('err', 'RTO', 'Nidus', ret))
                elif ev == '!FRAME!':
                    # save the frame and update bulk details
                    if self._bulk[cs]['cnt'] == 0:
                        self._bulk[cs]['start'] = ts  # reset start
                        self._bulk[cs]['cob'] = zlib.compressobj(
                        )  # new compression obj

                    # add new frame and update metrics
                    self._bulk[cs]['cnt'] += 1
                    self._bulk[cs]['sz'] += len(msg)
                    self._bulk[cs]['frames'] += self._bulk[cs]['cob'].compress(
                        '%s \x1EFB\x1F%s\x1FFE\x1E' % (ts2iso(ts), msg))

                    # if we have hit our limit, compress and send the bulk frames
                    if self._bulk[cs]['sz'] > _BSZ_ or (
                            ts - self._bulk[cs]['start']) / 1000 > _BTM_:
                        self._flushbulk(ts, rmap[cs], cs)
                else:  # unidentified event type, notify dyskt
                    self._conn.send(
                        ('warn', 'RTO', 'Radio', "unknown event %s" % ev))
            except Empty:  # nothing on queue
                continue
            except IndexError as e:  # something wrong with antenna indexing
                self._conn.send(
                    ('err', 'RTO', "Radio", "misconfigured antennas"))
            except KeyError as e:  # a radio sent a message without initiating
                self._conn.send(('warn', 'RTO', 'Radio %s' % e,
                                 "uninitiated data (%s)" % ev))
            except Exception as e:  # handle catchall error
                self._conn.send(('err', 'RTO', 'Unknown', e))

        # any bulked frames not yet sent?
        for cs in rmap:
            self._flushbulk(time.time(), rmap[cs], cs)

        # notify Nidus of closing (radios,sensor,gpsd). hopefully no errors on send
        ts = time.time()
        for cs in rmap:
            self._send('DEVICE', ts, ['radio', rmap[cs], 0])
        self._send('DEVICE', ts, ['gpsd', gpsid, 0])
        self._send('DEVICE', ts, ['sensor', socket.gethostname(), 0])

        # shut down
        if not self._shutdown():
            try:
                self._conn.send(
                    ('warn', 'RTO', 'Shutdown', "Incomplete shutdown"))
            except IOError:
                # most likely DySKT(.py) closed their side of the pipe
                pass