1PKTT(3)                            pktt 2.3                            PKTT(3)
2
3
4

NAME

6       packet.pktt - Packet trace module
7

DESCRIPTION

9       The Packet trace module is a python module that takes a trace file cre‐
10       ated by tcpdump and unpacks the contents of each packet. You can decode
11       one  packet  at  a  time, or do a search for specific packets. The main
12       difference between these modules and other tools used to  decode  trace
13       files  is  that  you  can  use  this module to completely automate your
14       tests.
15
16       How does it work? It opens the trace file and reads  one  record  at  a
17       time keeping track where each record starts. This way, very large trace
18       files can be opened without having to wait for the  file  to  load  and
19       avoid loading the whole file into memory.
20
21       Packet layers supported:
22           - ETHERNET II (RFC 894)
23           - IP layer (supports IPv4 and IPv6)
24           - UDP layer
25           - TCP layer
26           - RPC layer
27           - NFS v4.0
28           - NFS v4.1 including pNFS file layouts
29           - NFS v4.2
30           - PORTMAP v2
31           - MOUNT v3
32           - NLM v4
33

CLASSES

35   class Header(baseobj.BaseObj)
36       Methods defined here:
37       ---------------------
38
39       __init__(self, pktt)
40
41   class Pktt(baseobj.BaseObj, packet.unpack.Unpack)
42       Packet trace object
43
44       Usage:
45           from packet.pktt import Pktt
46
47           x = Pktt("/traces/tracefile.cap")
48
49           # Iterate over all packets found in the trace file
50           for pkt in x:
51               print pkt
52
53
54       Methods defined here:
55       ---------------------
56
57       __contains__(self, expr)
58       Implement membership test operator.
59       Return true if expr matches a packet in the trace file,
60       false otherwise.
61
62       The packet is also stored in the object attribute pkt.
63
64       Examples:
65           # Find the next READ request
66           if ("NFS.argop == 25" in x):
67               print x.pkt.nfs
68
69       See match() method for more information
70
71       __del__(self)
72       Destructor
73
74       Gracefully close the tcpdump trace file if it is opened.
75
76       __getitem__(self, index)
77       Get the packet from the trace file given by the index
78       or raise IndexError.
79
80       The packet is also stored in the object attribute pkt.
81
82       Examples:
83           pkt = x[index]
84
85       __init__(self, tfile, live=False, state=True)
86       Constructor
87
88       Initialize object's private data, note that this will not check the
89       file for existence nor will open the file to verify if it is a valid
90       tcpdump file. The tcpdump trace file will be opened the first time a
91       packet is retrieved.
92
93
94              tracefile:
95                     Name of tcpdump trace file or a list of trace file names
96                     (little or big endian format)
97
98              live:  If set to True, methods will not return if encountered <EOF>,
99                     they will keep on trying until more data is available in the
100                     file. This is useful when running tcpdump in parallel,
101                     especially when tcpdump is run with the '-C' option, in which
102                     case when <EOF> is encountered the next trace file created by
103                     tcpdump will be opened and the object will be re-initialized,
104                     all private data referencing the previous file is lost.
105
106       __iter__(self)
107       Make this object iterable.
108
109       clear_xid_list(self)
110       Clear list of outstanding xids
111
112       get_index(self)
113       Get current packet index
114
115       match(self, expr, maxindex=None, rewind=True, reply=False)
116       Return the packet that matches the given expression, also the packet
117       index points to the next packet after the matched packet.
118       Returns None if packet is not found and the packet index points
119       to the packet at the beginning of the search.
120
121
122              expr:  String of expressions to be evaluated
123
124              maxindex:
125                     The match fails if packet index hits this limit
126
127              rewind:
128                     Rewind to index where matching started if match fails
129
130              reply: Match RPC replies of previously matched calls as well
131
132              Examples:
133                  # Find the packet with both the ACK and SYN TCP flags set to 1
134                  pkt = x.match("TCP.flags.ACK == 1 and TCP.flags.SYN == 1")
135
136                  # Find the next NFS EXCHANGE_ID request
137                  pkt = x.match("NFS.argop == 42")
138
139                  # Find the next NFS EXCHANGE_ID or CREATE_SESSION request
140                  pkt = x.match("NFS.argop in [42,43]")
141
142                  # Find the next NFS OPEN request or reply
143                  pkt = x.match("NFS.op == 18")
144
145                  # Find all packets coming from subnet 192.168.1.0/24 using
146                  # a regular expression
147                  while x.match(r"IP.src == re('192.168.1.*')"):
148                      print x.pkt.tcp
149
150                  # Find packet having a GETATTR asking for FATTR4_FS_LAYOUT_TYPES(bit 62)
151                  pkt_call = x.match("NFS.attr_request & 0x4000000000000000L != 0")
152                  if pkt_call:
153                      # Find GETATTR reply
154                      xid = pkt_call.rpc.xid
155                      # Find reply where the number 62 is in the array NFS.attributes
156                      pkt_reply = x.match("RPC.xid == %d and 62 in NFS.attributes" % xid)
157
158                  # Find the next WRITE request
159                  pkt = x.match("NFS.argop == 38")
160                  if pkt:
161                      print pkt.nfs
162
163                  # Same as above, but using membership test operator instead
164                  if ("NFS.argop == 38" in x):
165                      print x.pkt.nfs
166
167                  # Get a list of all OPEN and CLOSE packets then use buffered
168                  # matching to process each OPEN and its corresponding CLOSE
169                  # at a time including both requests and replies
170                  pktlist = []
171                  while x.match("NFS.op in [4,18]"):
172                      pktlist.append(x.pkt)
173                  # Enable buffered matching
174                  x.set_pktlist(pktlist)
175                  while x.match("NFS.argop == 18"): # Find OPEN request
176                      print x.pkt
177                      index = x.get_index()
178                      # Find OPEN reply
179                      x.match("RPC.xid == %d and NFS.resop == 18" % x.pkt.rpc.xid)
180                      print x.pkt
181                      # Find corresponding CLOSE request
182                      stid = x.escape(x.pkt.NFSop.stateid.other)
183                      x.match("NFS.argop == 4 and NFS.stateid == '%s'" % stid)
184                      print x.pkt
185                      # Find CLOSE reply
186                      x.match("RPC.xid == %d and NFS.resop == 4" % x.pkt.rpc.xid)
187                      print x.pkt
188                      # Rewind to right after the OPEN request
189                      x.rewind(index)
190                  # Disable buffered matching
191                  x.set_pktlist()
192
193              See also:
194                  match_ethernet(), match_ip(), match_tcp(), match_rpc(), match_nfs()
195
196       match_nfs(self, uargs)
197       Match NFS values on current packet.
198
199       In NFSv4, there is a single compound procedure with multiple
200       operations, matching becomes a little bit tricky in order to make
201       the matching expression easy to use. The NFS object's name space
202       gets converted into a flat name space for the sole purpose of
203       matching. In other words, all operation objects in array are
204       treated as being part of the NFS object's top level attributes.
205
206       Consider the following NFS object:
207           nfsobj = COMPOUND4res(
208               status=NFS4_OK,
209               tag='NFSv4_tag',
210               array = [
211                   nfs_resop4(
212                       resop=OP_SEQUENCE,
213                       opsequence=SEQUENCE4res(
214                           status=NFS4_OK,
215                           resok=SEQUENCE4resok(
216                               sessionid='sessionid',
217                               sequenceid=29,
218                               slotid=0,
219                               highest_slotid=179,
220                               target_highest_slotid=179,
221                               status_flags=0,
222                           ),
223                       ),
224                   ),
225                   nfs_resop4(
226                       resop=OP_PUTFH,
227                       opputfh = PUTFH4res(
228                           status=NFS4_OK,
229                       ),
230                   ),
231                   ...
232               ]
233           ),
234
235       The result for operation PUTFH is the second in the list:
236           putfh = nfsobj.array[1]
237
238       From this putfh object the status operation can be accessed as:
239           status = putfh.opputfh.status
240
241       or simply as (this is how the NFS object works):
242           status = putfh.status
243
244       In this example, the following match expression 'NFS.status == 0'
245       could match the top level status of the compound (nfsobj.status)
246       or the putfh status (nfsobj.array[1].status)
247
248       The following match expression 'NFS.sequenceid == 25' will also
249       match this packet as well, even though the actual expression should
250       be 'nfsobj.array[0].opsequence.resok.sequenceid == 25' or
251       simply 'nfsobj.array[0].sequenceid == 25'.
252
253       This approach makes the match expressions simpler at the expense of
254       having some ambiguities on where the actual match occurred. If a
255       match is desired on a specific operation, a more qualified name can
256       be given. In the above example, in order to match the status of the
257       PUTFH operation the match expression 'NFS.opputfh.status == 0' can
258       be used. On the other hand, consider a compound having multiple
259       PUTFH results the above match expression will always match the first
260       occurrence of PUTFH where the status is 0. There is no way to tell
261       the match engine to match the second or Nth occurrence of an
262       operation.
263
264       next(self)
265       Get the next packet from the trace file or raise StopIteration.
266
267       The packet is also stored in the object attribute pkt.
268
269       Examples:
270           # Iterate over all packets found in the trace file using
271           # the iterable properties of the object
272           for pkt in x:
273               print pkt
274
275           # Iterate over all packets found in the trace file using it
276           # as a method and using the object variable as the packet
277           # Must use the try statement to catch StopIteration exception
278           try:
279               while (x.next()):
280                   print x.pkt
281           except StopIteration:
282               pass
283
284           # Iterate over all packets found in the trace file using it
285           # as a method and using the return value as the packet
286           # Must use the try statement to catch StopIteration exception
287           while True:
288               try:
289                   print x.next()
290               except StopIteration:
291                   break
292
293       NOTE:
294           Supports only single active iteration
295
296       rewind(self, index=0)
297       Rewind the trace file by setting the file pointer to the start of
298       the given packet index. Returns False if unable to rewind the file,
299       e.g., when the given index is greater than the maximum number
300       of packets processed so far.
301
302       seek(self, offset, whence=0, hard=False)
303       Position the read offset correctly
304       If new position is outside the current read buffer then clear the
305       buffer so a new chunk of data will be read from the file instead
306
307       set_pktlist(self, pktlist=None)
308       Set the current packet list for buffered matching in which the
309       match method will only use this list instead of getting the next
310       packet from the packet trace file.
311       This could be used when there is a lot of matching going back
312       and forth but only on a particular set of packets.
313       See the match() method for an example of buffered matching.
314
315       show_progress(self, done=False)
316       Display progress bar if enabled and if running on correct terminal
317
318       Static methods defined here:
319       ----------------------------
320
321       escape(data)
322       Escape special characters.
323
324       Examples:
325           # Call as an instance
326           escaped_data = x.escape(data)
327
328           # Call as a class
329           escaped_data = Pktt.escape(data)
330
331       ip_tcp_dst_expr(ipaddr, port)
332       Return a match expression to find a packet going to ipaddr:port.
333
334       Examples:
335           # Call as an instance
336           expr = x.ip_tcp_dst_expr('192.168.1.50', 2049)
337
338           # Call as a class
339           expr = Pktt.ip_tcp_dst_expr('192.168.1.50', 2049)
340
341           # Returns "IP.dst == '192.168.1.50' and TCP.dst_port == 2049"
342           # Expression ready for x.match()
343           pkt = x.match(expr)
344
345       ip_tcp_src_expr(ipaddr, port)
346       Return a match expression to find a packet coming from ipaddr:port.
347
348       Examples:
349           # Call as an instance
350           expr = x.ip_tcp_src_expr('192.168.1.50', 2049)
351
352           # Call as a class
353           expr = Pktt.ip_tcp_src_expr('192.168.1.50', 2049)
354
355           # Returns "IP.src == '192.168.1.50' and TCP.src_port == 2049"
356           # Expression ready for x.match()
357           pkt = x.match(expr)
358

SEE ALSO

360       baseobj(3),   formatstr(3),   packet.link.ethernet(3),   packet.pkt(3),
361       packet.record(3), packet.unpack(3)
362
363

BUGS

365       No known bugs.
366

AUTHOR

368       Jorge Mora (mora@netapp.com)
369
370
371
372NFStest 2.1.5                  14 February 2017                        PKTT(3)
Impressum