ieee802154.py

Go to the documentation of this file.
00001 #   Copyright (c) 2008 Axel Wachtler
00002 #   All rights reserved.
00003 #
00004 #   Redistribution and use in source and binary forms, with or without
00005 #   modification, are permitted provided that the following conditions
00006 #   are met:
00007 #
00008 #   * Redistributions of source code must retain the above copyright
00009 #     notice, this list of conditions and the following disclaimer.
00010 #   * Redistributions in binary form must reproduce the above copyright
00011 #     notice, this list of conditions and the following disclaimer in the
00012 #     documentation and/or other materials provided with the distribution.
00013 #   * Neither the name of the authors nor the names of its contributors
00014 #     may be used to endorse or promote products derived from this software
00015 #     without specific prior written permission.
00016 #
00017 #   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018 #   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019 #   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020 #   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021 #   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022 #   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023 #   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024 #   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025 #   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026 #   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027 #   POSSIBILITY OF SUCH DAMAGE.
00028 
00029 # $Id: ieee802154.py,v 1.21 2010/02/22 20:44:32 awachtler Exp $
00030 
00031 ##
00032 # @page pgCCUCap Application Description
00033 #
00034 # (@ref pgContribCapture "back")
00035 #
00036 # @section secCapSyn Synopsis
00037 #
00038 #   <tt>python ieee802154.py -p PORT|-r FILE [OPTIONS]</tt>
00039 #
00040 # @section secCapOpt Options
00041 #
00042 # @par General IO Options
00043 #
00044 # - @opt2{-p,portname}\n  Name of the port which is read, e.g. @c /dev/ttyUSB0
00045 # - @opt2{-r,capfile}\n   Name of the capture file which is read @c mytrace.dat
00046 # - @opt2{-i,pipename}\n  Name of the pipe
00047 #
00048 # @par Options for use with -p
00049 #
00050 # - @opt2{-c,channel}\n set IEEE802.15.4 channel number.
00051 # - @opt2{-R, <r>} \n set IEEE802.15.4 data rate.
00052 #
00053 # @par General Options
00054 #
00055 # - @opt2{-N,pkgcnt}\n    Stop after @c <pkgcnt> packages are received.
00056 # - @opt{-v}\n            Set verbose output, multiple @c -v options
00057 #                         increase the message details.
00058 #
00059 # @section secCapCmd Online Commands
00060 #
00061 # At the prompt @c "cmd:" the following commands are available:
00062 #
00063 #    - @opt{reopen} - reopens the named pipe and places a pcap header,
00064 #                 so that wireshark can reconnect.
00065 #    - @opt2{chan,<n>} \n set new channel to sniff.
00066 #    - @opt2{rate, <r>} \n set new data rate.
00067 #    - @opt{devrst}   \n reinitialize the sniffer device
00068 #    - @opt{debug}    \n start python debugger
00069 #    - @opt{info}     \n show status of sniffer DEVIN
00070 #    - @opt{quit}     \n end session and terminate all threads
00071 #    - @opt{help}     \n show command help
00072 #
00073 # <hr/>
00074 
00075 ##
00076 # @file
00077 # @ingroup grpContribCapture
00078 # @brief Capture converter script
00079 #
00080 # This script implements a bridge between a file or a serial port
00081 # to a socket. This socket is the interface for wireshark/libpcap
00082 # in order to do a live capture.
00083 #
00084 # How the script is used is described @ref pgContribCapture "here".
00085 #
00086 
00087 # === import ==================================================================
00088 import sys, os, pdb, atexit
00089 import traceback, getopt
00090 
00091 # === import local moduls =====================================================
00092 from ieee802154_base import ProgramContext
00093 from ieee802154_io import FileIn, PortIn
00094 from ieee802154_socket import SocketOut
00095 from ieee802154_pipe import PipeOut
00096 from ieee802154_gui import *
00097 
00098 # === globals =================================================================
00099 VERSION = "0.1"
00100 CTX = ProgramContext()
00101 DEVOUT = PipeOut()
00102 DEVIN = None
00103 # === classes =================================================================
00104 
00105 # === functions ===============================================================
00106 
00107 ##
00108 # Terminate all instances of the IO classes
00109 #
00110 def do_quit(exclude=[]):
00111     global CTX,DEVIN,DEVOUT,gui
00112     print "quit: exclude:",exclude
00113     if gui != None and 'gui' not in exclude:
00114         print "quit_gui"
00115         gui.cancel()
00116         gui = None
00117     if DEVIN != None:
00118         print "quit_DEVIN"
00119         DEVIN.reset()
00120         DEVIN.close()
00121         DEVIN = None
00122     if DEVOUT != None:
00123         print "quit_socket"
00124         DEVOUT.close()
00125         DEVOUT = None
00126 
00127 def print_options():
00128     print """\
00129 Usage:
00130   %s [OPTIONS]
00131   Options:
00132    -p PORT     Name of the serial port where the sniffer plattform
00133                is connected, e.g. /dev/ttyUSB0 or COM1.
00134    -r CAPFILE  Name of a capture file which is read @c mytrace.dat.
00135    -i PIPE     Name of the named pipe.
00136                 On a Linux system, PIPE can be a absolut path name, e.g.
00137                 /tmp/ieee802154. On a Windows system PIPE is a name in a
00138                 special pipe directory, e.g. foo maps to \\\\.\\pipe\\foo.
00139                 [ieee802154]
00140    -c CHAN     IEEE802.15.4 channel number
00141    -R RATE     IEEE802.15.4 data rate
00142    -v          increase verbose level
00143    -h          show help and exit.
00144    -V          print version and exit.
00145 
00146   Note:
00147    * -r and -p can be used only exclusively,
00148    * -c works only with -p.
00149 """ % sys.argv[0]
00150 
00151 
00152 ##
00153 # print a list of the commands available on the
00154 # "cmd:" prompt
00155 def print_help():
00156     print """\
00157 Commands:
00158    reopen   - reopens the named pipe and places a pcap header,
00159               so that wireshark can reconnect.
00160    chan <n> - set IEEE 802.15.4 channel.
00161    rate <r> - set IEEE 802.15.4 data rate (e.g. BPSK20, OQPSK100, ...)
00162    devrst   - reinitialize the sniffer device
00163    debug    - start python debugger
00164    info     - show status of sniffer DEVIN
00165    verbose  - verbose command
00166    quit     - end session and terminate all threads
00167    help     - show command help
00168 """
00169 
00170 ##
00171 # print startup message with some essential information about
00172 # the current configuration.
00173 #
00174 def print_banner():
00175     global VERSION, DEVIN
00176     fmtstr = {'file':'%(file)s, frames: %(frames)s',
00177               'port':'%(port)s, %(platform)s, channel=%(chan)s, rate=%(crate)s',
00178              }
00179     print "\nuracoli sniffer to wireshark bridge V%s" % VERSION
00180     inf = DEVIN.info()
00181     fmt = fmtstr.get(inf['type'],"UNKNOWN INTERFACE TYPE")
00182     print ' OPTS:  ', " ".join(sys.argv[1:])
00183     print ' INPUT: ', fmt % inf
00184     print ' OUTPUT:', str(DEVOUT.TxPipe),'\n'
00185 ##
00186 # Interpretation of command line options.
00187 # @param argv  list with command line elements.
00188 #
00189 def process_command_line_args(argv):
00190     global CTX
00191     opts,args = getopt.getopt(argv,"i:hp:r:vVNR::c:x")
00192     for o,v in opts:
00193         if o == "-i":
00194             v = v.strip()
00195             if os.path.isfile(v) or os.path.islink(v):
00196                 print "Can't overwrite existing file or link with a pipe"
00197                 sys.exit(1)
00198             CTX.SOCKNAME = v
00199         if o == "-r":
00200             CTX.CAPFILE = v.strip()
00201             CTX.PORT = None
00202         if o == "-p":
00203             CTX.CAPFILE = None
00204             CTX.PORT = v.strip()
00205         if o == "-v":
00206             CTX.VERBOSE += 1
00207         if o == "-N":
00208             CTX.MAXPACKETS = eval(v)
00209         if o == "-c":
00210             CTX.CHANNEL = eval(v)
00211         if o == "-R":
00212             CTX.RATE = v.strip()
00213         if o == "-x":
00214             CTX.GUI = True
00215         if o == "-h":
00216             print_options()
00217             print_help()
00218             sys.exit(0)
00219         if o == "-V":
00220             print "%s V%s" % (sys.argv[0],VERSION)
00221             sys.exit(0)
00222 
00223     if not CTX.CAPFILE and not CTX.PORT:
00224         CTX.PORT = raw_input('Enter Capture Port:')
00225 
00226 ##
00227 # process interactive command
00228 #
00229 def process_command(cmd):
00230     ret = 1
00231     cmd = cmd.strip()
00232     if len(cmd) == 0:
00233         pass
00234     elif cmd == "help":
00235         print_help()
00236     elif cmd == "quit":
00237         do_quit()
00238         ret = 0
00239     elif cmd == "info":
00240         inf = DEVIN.info()
00241         ks = inf.keys()
00242         ks.sort()
00243         fmt = " % 9s : %s"
00244         print "INPUT:"
00245         for k in ks:
00246             print fmt  % (k,inf[k])
00247         print "OUTPUT:"
00248         print fmt % ("pipe",DEVOUT.TxPipe)
00249     elif cmd == "reopen":
00250         DEVOUT.reopen()
00251     elif cmd.find("chan")>=0:
00252         try:
00253             CTX.CHANNEL = eval(cmd.split(" ")[1])
00254         except:
00255             CTX.CHANNEL = eval(raw_input("channel:"))
00256         DEVIN.set_channel(CTX.CHANNEL)
00257     elif cmd.find("rate")>=0:
00258         CTX.RATE = cmd.split(" ")[1].strip()
00259         DEVIN.set_rate(CTX.RATE)
00260     elif cmd.find("debug")>=0:
00261         pdb.set_trace()
00262     elif cmd.find("N")>=0:
00263         CTX.MAXPACKETS = eval(cmd.split(" ")[1])
00264         DEVIN.FCNT=0
00265     elif cmd.find("devrst")>=0:
00266         DEVIN.init()
00267         DEVIN.set_channel(CTX.CHANNEL)
00268     elif cmd.find("verbose") == 0:
00269         try:
00270             lvl = eval(cmd.split(" ")[1].strip())
00271         except:
00272             print "command '%s' was ignored" % cmd
00273         else:
00274             setverbose(lvl)
00275             print "verbose level is now %d" % CTX.VERBOSE
00276     else:
00277         print "\n  Unknown Command: \"%s\"," %cmd
00278         print "  type \"help\" to see a list of available commands.\n"
00279     return ret
00280 
00281 def setverbose(level):
00282     CTX.VERBOSE = level
00283     DEVOUT.setverbose(CTX.VERBOSE)
00284     DEVIN.setverbose(CTX.VERBOSE)
00285     
00286 ##
00287 # exit handler, prompts on all Non-*NIX systems for "ENTER" in
00288 # order to see the last error message in the terminal.
00289 def do_exit(*argv,**argd):
00290     do_quit()
00291     if os.name != 'posix':
00292         raw_input("Type Enter to Exit...")
00293 
00294 # === init ====================================================================
00295 if __name__ == "__main__":
00296     try:
00297         import rlcompleter
00298         import readline
00299         readline.parse_and_bind("tab:complete")
00300     except:
00301         pass
00302 
00303     atexit.register(do_exit)
00304 
00305     ## This class instance stores the global programm context
00306     process_command_line_args(sys.argv[1:])
00307 
00308     # create input reader classes
00309     if CTX.CAPFILE:
00310         DEVIN = FileIn()
00311         DEVIN.open(CTX.CAPFILE)
00312     elif CTX.PORT:
00313         DEVIN = PortIn()
00314         DEVIN.open(CTX.PORT)
00315         if CTX.CHANNEL != None:
00316             DEVIN.set_channel(CTX.CHANNEL)
00317         if CTX.RATE != None:
00318             DEVIN.set_rate(CTX.RATE)
00319     else:
00320         raise Exception, 'no port or capture file given'
00321 
00322     #DEVOUT = PcapSocket(CTX.SOCKNAME, DEVIN)
00323     DEVOUT.open(CTX.SOCKNAME, DEVIN)
00324     setverbose(CTX.VERBOSE)
00325     DEVIN.maxpackets = CTX.MAXPACKETS
00326 
00327     if CTX.GUI:
00328         gui = CtrlGui(lambda : do_quit(['gui']))
00329         gui.start()
00330         gui.setDEVIN(DEVIN)
00331     else:
00332         gui = None
00333 
00334     run = 1
00335     print_banner()
00336     while run:
00337         try:
00338             cmd = raw_input("cmd:")
00339             run = process_command(cmd)
00340         except:
00341             traceback.print_exc()
00342             break

This documentation for µracoli was generated on Wed Feb 2 2011 by  doxygen 1.7.1