Provided by: nfstest_3.2-3_all bug

NAME

       packet.pktt - Packet trace module

DESCRIPTION

       The  Packet trace module is a python module that takes a trace file created by tcpdump and
       unpacks the contents of each packet. You can decode one packet at a time, or do  a  search
       for  specific  packets.  The main difference between these modules and other tools used to
       decode trace files is that you can use this module to completely automate your tests.

       How does it work? It opens the trace file and reads one record at  a  time  keeping  track
       where each record starts. This way, very large trace files can be opened without having to
       wait for the file to load and avoid loading the whole file into memory.

       Packet layers supported:
           - ETHERNET II (RFC 894)
           - IP layer (supports IPv4 and IPv6)
           - UDP layer
           - TCP layer
           - RPC layer
           - NFS v4.0
           - NFS v4.1 including pNFS file layouts
           - NFS v4.2
           - PORTMAP v2
           - MOUNT v3
           - NLM v4

CLASSES

   class Header(baseobj.BaseObj)
       Base class so objects will inherit the methods providing the string
       representation of the object and a simple debug printing and logging
       mechanism.

       Usage:
           from baseobj import BaseObj

           # Named arguments
           x = BaseObj(a=1, b=2)

           # Dictionary argument
           x = BaseObj({'a':1, 'b':2})

           # Tuple arguments: first for keys and second for the values
           x = BaseObj(['a', 'b'], [1, 2])

           # All of the above will create an object having two attributes:
           x.a = 1 and x.b = 2

           # Add attribute name, this will be the only attribute to be displayed
           x.set_attrlist("a")

           # Add list of attribute names to be displayed in that order
           x.set_attrlist(["a", "b"])

           # Set attribute with ordered display rights
           x.set_attr("a", 1)
           # This is the same as
           setattr(x, "a", 1) or x.a = 1
           x.set_attrlist("a")

           # Set attribute with switch duplicate
           # The following creates an extra attribute "switch" with
           # the same value as attribute "a":
           #   x.a == x.switch
           #   x.a is x.switch
           x.set_attr("a", 1, switch=True)

           # Make the current object flat by allowing all the attributes
           # for the new attribute to be accessed directly by the current
           # object so the following is True:
           #   x.d == x.c.d
           x.set_attr("c", BaseObj(d=11, e=22), switch=True)

           # Set the comparison attribute so x == x.a is True
           x.set_eqattr("a")

           # Set verbose level of object's string representation
           x.debug_repr(level)

           # Set string format for verbose level 1
           x.set_strfmt(1, "arg1:{0}")
           # In the above example the first positional argument is "a"
           # so the str(x) gives "arg1:1"

           # Set attribute shared by all instances
           # If a global or shared attribute is set on one instance,
           # all other instances will have access to it:
           #   y = BaseObj(d=2, e=3)
           # then the following is true
           #   x.g == y.g
           #   x.g is y.g
           x.set_global("g", 5)

           # Set level mask to display all debug messages matching mask
           x.debug_level(0xFF)

           # Add a debug mapping for mask 0x100
           x.debug_map(0x100, 'opts', "OPTS: ")

           # Set global indentation to 4 spaces for dprint
           x.dindent(4)

           # Set global indentation to 4 spaces for displaying objects
           x.sindent(4)

           # Set global truncation to 64 for displaying string objects
           x.strsize(64)

           # Do not display timestamp for dprint messages
           x.tstamp(enable=False)

           # Change timestamp format to include the date
           x.tstamp(fmt="{0:date:%Y-%m-%d %H:%M:%S.%q} ")

           # Get timestamp if enabled, else return an empty string
           out = x.timestamp()

           # Open log file
           x.open_log(logfile)

           # Close log file
           x.close_log()

           # Write data to log file
           x.write_log(data)

           # Format the given arguments
           out = x.format("{0:x} - {1}", 1, "hello")

           # Format the object attributes set by set_attrlist()
           out = x.format("{0:x} - {1}")

           # Print debug message only if OPTS bitmap matches the current
           # debug level mask
           x.dprint("OPTS", "This is an OPTS debug message")

       Methods defined here:
       ---------------------

       __init__(self, pktt)
       Constructor

       Initialize object's private data according to the arguments given.
       Arguments can be given as positional, named arguments or a
       combination of both.

   class Pktt(baseobj.BaseObj)
       Packet trace object

       Usage:
           from packet.pktt import Pktt

           x = Pktt("/traces/tracefile.cap")

           # Iterate over all packets found in the trace file
           for pkt in x:
               print pkt

       Methods defined here:
       ---------------------

       __contains__(self, expr)
       Implement membership test operator.
       Return true if expr matches a packet in the trace file,
       false otherwise.

       The packet is also stored in the object attribute pkt.

       Examples:
           # Find the next READ request
           if ("NFS.argop == 25" in x):
               print x.pkt.nfs

       See match() method for more information

       __del__(self)
       Destructor

       Gracefully close the tcpdump trace file if it is opened.

       __getitem__(self, index)
       Get the packet from the trace file given by the index
       or raise IndexError.

       The packet is also stored in the object attribute pkt.

       Examples:
           pkt = x[index]

       __init__(self, tfile, live=False, rpc_replies=True)
       Constructor

       Initialize object's private data, note that this will not check the
       file for existence nor will open the file to verify if it is a valid
       tcpdump file. The tcpdump trace file will be opened the first time a
       packet is retrieved.

              tracefile:
                     Name of tcpdump trace file or a list of trace file names
                     (little or big endian format)

              live:  If set to True, methods will not return if encountered <EOF>,
                     they will keep on trying until more data is available in the
                     file. This is useful when running tcpdump in parallel,
                     especially when tcpdump is run with the '-C' option, in which
                     case when <EOF> is encountered the next trace file created by
                     tcpdump will be opened and the object will be re-initialized,
                     all private data referencing the previous file is lost.

       __iter__(self)
       Make this object iterable.

       __next__(self)
       Get the next packet from the trace file or raise StopIteration.

       The packet is also stored in the object attribute pkt.

       Examples:
           # Iterate over all packets found in the trace file using
           # the iterable properties of the object
           for pkt in x:
               print pkt

           # Iterate over all packets found in the trace file using it
           # as a method and using the object variable as the packet
           # Must use the try statement to catch StopIteration exception
           try:
               while (x.next()):
                   print x.pkt
           except StopIteration:
               pass

           # Iterate over all packets found in the trace file using it
           # as a method and using the return value as the packet
           # Must use the try statement to catch StopIteration exception
           while True:
               try:
                   print x.next()
               except StopIteration:
                   break

       NOTE:
           Supports only single active iteration

       clear_xid_list(self)
       Clear list of outstanding xids

       close(self)
       Gracefully close the tcpdump trace file and cleanup attributes.

       get_index(self)
       Get current packet index

       match(self, expr, maxindex=None, rewind=True, reply=False)
       Return the packet that matches the given expression, also the packet
       index points to the next packet after the matched packet.
       Returns None if packet is not found and the packet index points
       to the packet at the beginning of the search.

              expr:  String of expressions to be evaluated

              maxindex:
                     The match fails if packet index hits this limit

              rewind:
                     Rewind to index where matching started if match fails

              reply: Match RPC replies of previously matched calls as well

              Examples:
                  # Find the packet with both the ACK and SYN TCP flags set to 1
                  pkt = x.match("TCP.flags.ACK == 1 and TCP.flags.SYN == 1")

                  # Find the next NFS EXCHANGE_ID request
                  pkt = x.match("NFS.argop == 42")

                  # Find the next NFS EXCHANGE_ID or CREATE_SESSION request
                  pkt = x.match("NFS.argop in [42,43]")

                  # Find the next NFS OPEN request or reply
                  pkt = x.match("NFS.op == 18")

                  # Find all packets coming from subnet 192.168.1.0/24 using
                  # a regular expression
                  while x.match(r"re.search('192.168.1.*', IP.src)"):
                      print x.pkt.tcp

                  # Find packet having a GETATTR asking for FATTR4_FS_LAYOUT_TYPES(bit 62)
                  pkt_call = x.match("NFS.attr_request & 0x4000000000000000L != 0")
                  if pkt_call:
                      # Find GETATTR reply
                      xid = pkt_call.rpc.xid
                      # Find reply where the number 62 is in the array NFS.attributes
                      pkt_reply = x.match("RPC.xid == %d and 62 in NFS.attributes" % xid)

                  # Find the next WRITE request
                  pkt = x.match("NFS.argop == 38")
                  if pkt:
                      print pkt.nfs

                  # Same as above, but using membership test operator instead
                  if ("NFS.argop == 38" in x):
                      print x.pkt.nfs

                  # Get a list of all OPEN and CLOSE packets then use buffered
                  # matching to process each OPEN and its corresponding CLOSE
                  # at a time including both requests and replies
                  pktlist = []
                  while x.match("NFS.op in [4,18]"):
                      pktlist.append(x.pkt)
                  # Enable buffered matching
                  x.set_pktlist(pktlist)
                  while x.match("NFS.argop == 18"): # Find OPEN request
                      print x.pkt
                      index = x.get_index()
                      # Find OPEN reply
                      x.match("RPC.xid == %d and NFS.resop == 18" % x.pkt.rpc.xid)
                      print x.pkt
                      # Find corresponding CLOSE request
                      stid = x.escape(x.pkt.NFSop.stateid.other)
                      x.match("NFS.argop == 4 and NFS.stateid == '%s'" % stid)
                      print x.pkt
                      # Find CLOSE reply
                      x.match("RPC.xid == %d and NFS.resop == 4" % x.pkt.rpc.xid)
                      print x.pkt
                      # Rewind to right after the OPEN request
                      x.rewind(index)
                  # Disable buffered matching
                  x.set_pktlist()

              See also:
                  match_ethernet(), match_ip(), match_tcp(), match_rpc(), match_nfs()

       match_nfs(self, expr)
       Match NFS values on current packet.

       In NFSv4, there is a single compound procedure with multiple
       operations, matching becomes a little bit tricky in order to make
       the matching expression easy to use. The NFS object's name space
       gets converted into a flat name space for the sole purpose of
       matching. In other words, all operation objects in array are
       treated as being part of the NFS object's top level attributes.

       Consider the following NFS object:
           nfsobj = COMPOUND4res(
               status=NFS4_OK,
               tag='NFSv4_tag',
               array = [
                   nfs_resop4(
                       resop=OP_SEQUENCE,
                       opsequence=SEQUENCE4res(
                           status=NFS4_OK,
                           resok=SEQUENCE4resok(
                               sessionid='sessionid',
                               sequenceid=29,
                               slotid=0,
                               highest_slotid=179,
                               target_highest_slotid=179,
                               status_flags=0,
                           ),
                       ),
                   ),
                   nfs_resop4(
                       resop=OP_PUTFH,
                       opputfh = PUTFH4res(
                           status=NFS4_OK,
                       ),
                   ),
                   ...
               ]
           ),

       The result for operation PUTFH is the second in the list:
           putfh = nfsobj.array[1]

       From this putfh object the status operation can be accessed as:
           status = putfh.opputfh.status

       or simply as (this is how the NFS object works):
           status = putfh.status

       In this example, the following match expression 'NFS.status == 0'
       could match the top level status of the compound (nfsobj.status)
       or the putfh status (nfsobj.array[1].status)

       The following match expression 'NFS.sequenceid == 25' will also
       match this packet as well, even though the actual expression should
       be 'nfsobj.array[0].opsequence.resok.sequenceid == 25' or
       simply 'nfsobj.array[0].sequenceid == 25'.

       This approach makes the match expressions simpler at the expense of
       having some ambiguities on where the actual match occurred. If a
       match is desired on a specific operation, a more qualified name can
       be given. In the above example, in order to match the status of the
       PUTFH operation the match expression 'NFS.opputfh.status == 0' can
       be used. On the other hand, consider a compound having multiple
       PUTFH results the above match expression will always match the first
       occurrence of PUTFH where the status is 0. There is no way to tell
       the match engine to match the second or Nth occurrence of an
       operation.

       match_pkt(self, expr)
       Default wrapper function to evaluate a simple string expression.

       rewind(self, index=0)
       Rewind the trace file by setting the file pointer to the start of
       the given packet index. Returns False if unable to rewind the file,
       e.g., when the given index is greater than the maximum number
       of packets processed so far.

       seek(self, offset, whence=0, hard=False)
       Position the read offset correctly
       If new position is outside the current read buffer then clear the
       buffer so a new chunk of data will be read from the file instead

       set_pktlist(self, pktlist=None)
       Set the current packet list for buffered matching in which the
       match method will only use this list instead of getting the next
       packet from the packet trace file.
       This could be used when there is a lot of matching going back
       and forth but only on a particular set of packets.
       See the match() method for an example of buffered matching.

       show_progress(self, done=False)
       Display progress bar if enabled and if running on correct terminal

       Static methods defined here:
       ----------------------------

       escape(data)
       Escape special characters.

       Examples:
           # Call as an instance
           escaped_data = x.escape(data)

           # Call as a class
           escaped_data = Pktt.escape(data)

       ip_tcp_dst_expr(ipaddr, port=None)
       Return a match expression to find a packet going to ipaddr:port.

       Examples:
           # Call as an instance
           expr = x.ip_tcp_dst_expr('192.168.1.50', 2049)

           # Call as a class
           expr = Pktt.ip_tcp_dst_expr('192.168.1.50', 2049)

           # Returns "IP.dst == '192.168.1.50' and TCP.dst_port == 2049"
           # Expression ready for x.match()
           pkt = x.match(expr)

       ip_tcp_src_expr(ipaddr, port=None)
       Return a match expression to find a packet coming from ipaddr:port.

       Examples:
           # Call as an instance
           expr = x.ip_tcp_src_expr('192.168.1.50', 2049)

           # Call as a class
           expr = Pktt.ip_tcp_src_expr('192.168.1.50', 2049)

           # Returns "IP.src == '192.168.1.50' and TCP.src_port == 2049"
           # Expression ready for x.match()
           pkt = x.match(expr)

FUNCTIONS

       convert_attrs(tree)
       Convert all valid layer AST Attributes to fully qualified names.
       Also, return the name of the correct wrapper function to be used.

       NOTE:
         The tree argument is modified so when tree is unparsed, all layer
         attributes are expanded correctly.

       get_binop(op)
       Return the string representation of the operator AST object

       get_bool(op)
       Return the string representation of the logical operator AST object

       get_op(op)
       Return the string representation of the logical operator AST object

       get_precedence(op)
       Return the precedence of operator AST object

       get_unary(op)
       Return the string representation of the unary operator AST object

       unparse(tree)
       Older Python releases do not define ast.unparse(). Create function
       unparse with limited functionality but enough for the matching
       language it is needed for match(). This function runs twice as fast
       as ast.unparse(), so always use it regardless if it is defined or
       not on the ast module.

SEE ALSO

       baseobj(3),      formatstr(3),      packet.internet.ipv4(3),      packet.internet.ipv6(3),
       packet.link.erf(3),  packet.link.ethernet(3),  packet.link.sllv1(3), packet.link.sllv2(3),
       packet.pkt(3), packet.record(3), packet.transport.rdmainfo(3), packet.unpack(3)

BUGS

       No known bugs.

AUTHOR

       Jorge Mora (mora@netapp.com)