1PKTT(3) pktt 2.3 PKTT(3)
2
3
4
6 packet.pktt - Packet trace module
7
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
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
360 baseobj(3), formatstr(3), packet.link.ethernet(3), packet.pkt(3),
361 packet.record(3), packet.unpack(3)
362
363
365 No known bugs.
366
368 Jorge Mora (mora@netapp.com)
369
370
371
372NFStest 2.1.5 14 February 2017 PKTT(3)