/src/wireshark/epan/reassemble.h
Line | Count | Source |
1 | | /** @file |
2 | | * Declarations of routines for {fragment,segment} reassembly |
3 | | * |
4 | | * Wireshark - Network traffic analyzer |
5 | | * By Gerald Combs <gerald@wireshark.org> |
6 | | * Copyright 1998 Gerald Combs |
7 | | * |
8 | | * SPDX-License-Identifier: GPL-2.0-or-later |
9 | | */ |
10 | | |
11 | | /* make sure that all flags that are set in a fragment entry is also set for |
12 | | * the flags field of fd_head !!! |
13 | | */ |
14 | | |
15 | | #ifndef REASSEMBLE_H |
16 | | #define REASSEMBLE_H |
17 | | |
18 | | #include "ws_symbol_export.h" |
19 | | |
20 | | /* only in fd_head: packet is defragmented */ |
21 | 55.5k | #define FD_DEFRAGMENTED 0x0001 |
22 | | |
23 | | /* there are overlapping fragments */ |
24 | 13.7k | #define FD_OVERLAP 0x0002 |
25 | | |
26 | | /* overlapping fragments contain different data */ |
27 | 23.8k | #define FD_OVERLAPCONFLICT 0x0004 |
28 | | |
29 | | /* more than one fragment which indicates end-of data */ |
30 | 23.2k | #define FD_MULTIPLETAILS 0x0008 |
31 | | |
32 | | /* fragment starts before the end of the datagram but extends |
33 | | past the end of the datagram */ |
34 | 21.7k | #define FD_TOOLONGFRAGMENT 0x0010 |
35 | | |
36 | | /* fragment tvb is subset, don't tvb_free() it */ |
37 | 10.6k | #define FD_SUBSET_TVB 0x0020 |
38 | | |
39 | | /* this flag is used to request fragment_add to continue the reassembly process */ |
40 | 439 | #define FD_PARTIAL_REASSEMBLY 0x0040 |
41 | | |
42 | | /* fragment offset is indicated by sequence number and not byte offset |
43 | | into the defragmented packet */ |
44 | 7.92k | #define FD_BLOCKSEQUENCE 0x0100 |
45 | | |
46 | | /* This flag is set in (only) fd_head to denote that datalen has been set to a valid value. |
47 | | * It's implied by FD_DEFRAGMENTED (we must know the total length of the |
48 | | * datagram if we have defragmented it...) |
49 | | */ |
50 | 37.3k | #define FD_DATALEN_SET 0x0400 |
51 | | |
52 | | typedef struct _fragment_item { |
53 | | struct _fragment_item *next; |
54 | | uint32_t frame; /**< frame number where the fragment is from */ |
55 | | uint32_t offset; /**< fragment number for FD_BLOCKSEQUENCE, byte |
56 | | * offset otherwise */ |
57 | | uint32_t len; /**< fragment length */ |
58 | | uint32_t flags; /**< XXX - do some of these apply only to reassembly |
59 | | * heads and others only to fragments within |
60 | | * a reassembly? */ |
61 | | tvbuff_t *tvb_data; |
62 | | } fragment_item; |
63 | | |
64 | | typedef struct _fragment_head { |
65 | | struct _fragment_item *next; |
66 | | struct _fragment_item *first_gap; /**< pointer to last fragment before first gap. |
67 | | * NULL if there is no fragment starting at offset 0 */ |
68 | | unsigned ref_count; /**< reference count in reassembled_table */ |
69 | | uint32_t contiguous_len; /**< contiguous length from head up to first gap */ |
70 | | uint32_t frame; /**< maximum of all frame numbers added to reassembly */ |
71 | | uint32_t len; /**< When flags&FD_BLOCKSEQUENCE and FD_DEFRAGMENTED |
72 | | * are set, the number of bytes of the full datagram. |
73 | | * Otherwise not valid. */ |
74 | | uint32_t fragment_nr_offset; /**< offset for frame numbering, for sequences, where the |
75 | | * provided fragment number of the first fragment does |
76 | | * not start with 0 */ |
77 | | uint32_t datalen; /**< When flags&FD_BLOCKSEQUENCE is set, the |
78 | | * index of the last block (segments in |
79 | | * datagram + 1); otherwise the number of |
80 | | * bytes of the full datagram. Only valid in |
81 | | * the first item of the fragments list when |
82 | | * flags&FD_DATALEN is set.*/ |
83 | | uint32_t reassembled_in; /**< frame where this PDU was reassembled, |
84 | | * only valid when FD_DEFRAGMENTED is set */ |
85 | | uint8_t reas_in_layer_num; /**< The current "depth" or layer number in the current |
86 | | * frame where reassembly was completed. |
87 | | * Example: in SCTP there can be several data chunks and |
88 | | * we want the reassembled tvb for the final segment only. */ |
89 | | uint32_t flags; /**< XXX - do some of these apply only to reassembly |
90 | | * heads and others only to fragments within |
91 | | * a reassembly? */ |
92 | | tvbuff_t *tvb_data; |
93 | | /** |
94 | | * Null if the reassembly had no error; non-null if it had |
95 | | * an error, in which case it's the string for the error. |
96 | | */ |
97 | | const char *error; |
98 | | } fragment_head; |
99 | | |
100 | | /* |
101 | | * Flags for fragment_add_seq_* |
102 | | */ |
103 | | |
104 | | /* we don't have any sequence numbers - fragments are assumed to appear in |
105 | | * order */ |
106 | 15.1k | #define REASSEMBLE_FLAGS_NO_FRAG_NUMBER 0x0001 |
107 | | |
108 | | /* a special fudge for the 802.11 dissector */ |
109 | 2.81k | #define REASSEMBLE_FLAGS_802_11_HACK 0x0002 |
110 | | |
111 | | /* |
112 | | * Flags for fragment_add_seq_single_* |
113 | | */ |
114 | | |
115 | | /* we want to age off old packets */ |
116 | 10.3k | #define REASSEMBLE_FLAGS_AGING 0x0001 |
117 | | |
118 | | /* |
119 | | * Generates a fragment identifier based on the given parameters. "data" is an |
120 | | * opaque type whose interpretation is up to the caller of fragment_add* |
121 | | * functions and the fragment key function (possibly NULL if you do not care). |
122 | | * |
123 | | * Keys returned by this function are only used within this packet scope. |
124 | | */ |
125 | | typedef void * (*fragment_temporary_key)(const packet_info *pinfo, |
126 | | const uint32_t id, const void *data); |
127 | | |
128 | | /* |
129 | | * Like fragment_temporary_key, but used for identifying reassembled fragments |
130 | | * which may persist through multiple packets. |
131 | | */ |
132 | | typedef void * (*fragment_persistent_key)(const packet_info *pinfo, |
133 | | const uint32_t id, const void *data); |
134 | | |
135 | | /* |
136 | | * Data structure to keep track of fragments and reassemblies. |
137 | | */ |
138 | | typedef struct { |
139 | | GHashTable *fragment_table; |
140 | | GHashTable *reassembled_table; |
141 | | fragment_temporary_key temporary_key_func; |
142 | | fragment_persistent_key persistent_key_func; |
143 | | GDestroyNotify free_temporary_key_func; /* temporary key destruction function */ |
144 | | } reassembly_table; |
145 | | |
146 | | /* |
147 | | * Table of functions for a reassembly table. |
148 | | */ |
149 | | typedef struct { |
150 | | /* Functions for fragment table */ |
151 | | GHashFunc hash_func; /* hash function */ |
152 | | GEqualFunc equal_func; /* comparison function */ |
153 | | fragment_temporary_key temporary_key_func; /* temporary key creation function */ |
154 | | fragment_persistent_key persistent_key_func; /* persistent key creation function */ |
155 | | GDestroyNotify free_temporary_key_func; /* temporary key destruction function */ |
156 | | GDestroyNotify free_persistent_key_func; /* persistent key destruction function */ |
157 | | } reassembly_table_functions; |
158 | | |
159 | | /* |
160 | | * Tables of functions exported for the benefit of dissectors that |
161 | | * don't need special items in their keys. |
162 | | */ |
163 | | WS_DLL_PUBLIC const reassembly_table_functions |
164 | | addresses_reassembly_table_functions; /* keys have endpoint addresses and an ID */ |
165 | | WS_DLL_PUBLIC const reassembly_table_functions |
166 | | addresses_ports_reassembly_table_functions; /* keys have endpoint addresses and ports and an ID */ |
167 | | |
168 | | /* |
169 | | * Register a reassembly table. By registering the table with epan, the creation and |
170 | | * destruction of the table can be managed by epan and not the dissector. |
171 | | */ |
172 | | WS_DLL_PUBLIC void |
173 | | reassembly_table_register(reassembly_table *table, |
174 | | const reassembly_table_functions *funcs); |
175 | | |
176 | | /* |
177 | | * Initialize/destroy a reassembly table. |
178 | | * |
179 | | * init: If table doesn't exist: create table; |
180 | | * else: just remove any entries; |
181 | | * destroy: remove entries and destroy table; |
182 | | */ |
183 | | WS_DLL_PUBLIC void |
184 | | reassembly_table_init(reassembly_table *table, |
185 | | const reassembly_table_functions *funcs); |
186 | | WS_DLL_PUBLIC void |
187 | | reassembly_table_destroy(reassembly_table *table); |
188 | | |
189 | | /* |
190 | | * This function adds a new fragment to the reassembly table |
191 | | * If this is the first fragment seen for this datagram, a new entry |
192 | | * is created in the table, otherwise this fragment is just added |
193 | | * to the linked list of fragments for this packet. |
194 | | * The list of fragments for a specific datagram is kept sorted for |
195 | | * easier handling. |
196 | | * |
197 | | * Datagrams (messages) are identified by a key generated by |
198 | | * fragment_temporary_key or fragment_persistent_key, based on the "pinfo", "id" |
199 | | * and "data" pairs. (This is the sole purpose of "data".) |
200 | | * |
201 | | * Fragments are identified by "frag_offset". |
202 | | * |
203 | | * Returns a pointer to the head of the fragment data list if we have all the |
204 | | * fragments, NULL otherwise. Note that the reassembled fragments list may have |
205 | | * a non-zero fragment offset, the only guarantee is that no gaps exist within |
206 | | * the list. |
207 | | * |
208 | | * @note Reused keys are assumed to refer to the same reassembled message |
209 | | * (i.e., retransmission). If the same "id" is used more than once on a |
210 | | * connection, then "data" and custom reassembly_table_functions should be |
211 | | * used so that the keys hash differently. |
212 | | */ |
213 | | WS_DLL_PUBLIC fragment_head * |
214 | | fragment_add(reassembly_table *table, tvbuff_t *tvb, const int offset, |
215 | | const packet_info *pinfo, const uint32_t id, const void *data, |
216 | | const uint32_t frag_offset, const uint32_t frag_data_len, |
217 | | const bool more_frags); |
218 | | /* |
219 | | * Like fragment_add, except that the fragment may be added to multiple |
220 | | * reassembly tables. This is needed when multiple protocol layers try |
221 | | * to add the same packet to the reassembly table. |
222 | | */ |
223 | | WS_DLL_PUBLIC fragment_head * |
224 | | fragment_add_multiple_ok(reassembly_table *table, tvbuff_t *tvb, |
225 | | const int offset, const packet_info *pinfo, |
226 | | const uint32_t id, const void *data, |
227 | | const uint32_t frag_offset, |
228 | | const uint32_t frag_data_len, |
229 | | const bool more_frags); |
230 | | |
231 | | /* |
232 | | * Like fragment_add, except that the fragment may originate from a frame |
233 | | * other than pinfo->num. For use when you are adding an out of order segment |
234 | | * that arrived in an earlier frame, so that show_fragment_tree will display |
235 | | * the correct fragment numbers. |
236 | | * |
237 | | * This is for protocols like TCP, where the correct reassembly to add a |
238 | | * segment to cannot be determined without processing previous segments |
239 | | * in sequence order, including handing them to subdissectors. |
240 | | * |
241 | | * Note that pinfo is still used to set reassembled_in if we have all the |
242 | | * fragments, so that results on subsequent passes can be the same as the |
243 | | * first pass. |
244 | | */ |
245 | | WS_DLL_PUBLIC fragment_head * |
246 | | fragment_add_out_of_order(reassembly_table *table, tvbuff_t *tvb, |
247 | | const int offset, const packet_info *pinfo, |
248 | | const uint32_t id, const void *data, |
249 | | const uint32_t frag_offset, |
250 | | const uint32_t frag_data_len, |
251 | | const bool more_frags, const uint32_t frag_frame); |
252 | | /* |
253 | | * Like fragment_add, but maintains a table for completed reassemblies. |
254 | | * |
255 | | * If the packet was seen before, return the head of the fully reassembled |
256 | | * fragments list (NULL if there was none). |
257 | | * |
258 | | * Otherwise (if reassembly was not possible before), try to add the new |
259 | | * fragment to the fragments table. If reassembly is now possible, remove all |
260 | | * (reassembled) fragments from the fragments table and store it as a completed |
261 | | * reassembly. The head of this reassembled fragments list is returned. |
262 | | * |
263 | | * Otherwise (if reassembly is still not possible after adding this fragment), |
264 | | * return NULL. |
265 | | * |
266 | | * @note Completed reassemblies are removed from the in-progress table, so |
267 | | * key can be reused to begin a new reassembled message. Conversely, |
268 | | * dissectors SHOULD NOT call this with a retransmitted fragment of a |
269 | | * completed reassembly. Dissectors atop a reliable protocol like TCP |
270 | | * may assume that the lower layer dissector handles retransmission, |
271 | | * but other dissectors (e.g., atop UDP or Ethernet) will have to handle |
272 | | * that situation themselves. |
273 | | */ |
274 | | WS_DLL_PUBLIC fragment_head * |
275 | | fragment_add_check(reassembly_table *table, tvbuff_t *tvb, const int offset, |
276 | | const packet_info *pinfo, const uint32_t id, |
277 | | const void *data, const uint32_t frag_offset, |
278 | | const uint32_t frag_data_len, const bool more_frags); |
279 | | |
280 | | /* |
281 | | * Like fragment_add_check, but handles retransmissions after reassembly. |
282 | | * |
283 | | * Start new reassembly only if there is no reassembly in progress and there |
284 | | * is no completed reassembly reachable from fallback_frame. If there is |
285 | | * completed reassembly (reachable from fallback_frame), simply links this |
286 | | * packet into the list, updating the flags if necessary (however actual data |
287 | | * and reassembled in frame won't be modified). |
288 | | */ |
289 | | WS_DLL_PUBLIC fragment_head * |
290 | | fragment_add_check_with_fallback(reassembly_table *table, tvbuff_t *tvb, const int offset, |
291 | | const packet_info *pinfo, const uint32_t id, |
292 | | const void *data, const uint32_t frag_offset, |
293 | | const uint32_t frag_data_len, const bool more_frags, |
294 | | const uint32_t fallback_frame); |
295 | | |
296 | | /* |
297 | | * Like fragment_add, but fragments have a block sequence number starting from |
298 | | * zero (for the first fragment of each datagram). This differs from |
299 | | * fragment_add for which the fragment may start at any offset. |
300 | | * |
301 | | * If this is the first fragment seen for this datagram, a new |
302 | | * "fragment_head" structure is allocated to refer to the reassembled |
303 | | * packet, and: |
304 | | * |
305 | | * if "more_frags" is false, and either we have no sequence numbers, or |
306 | | * are using the 802.11 hack (via fragment_add_seq_802_11), it is assumed that |
307 | | * this is the only fragment in the datagram. The structure is not added to the |
308 | | * hash table, and not given any fragments to refer to, but is just returned. |
309 | | * |
310 | | * In this latter case reassembly wasn't done (since there was only one |
311 | | * fragment in the packet); dissectors can check the 'next' pointer on the |
312 | | * returned list to see if this case was hit or not. |
313 | | * |
314 | | * Otherwise, this fragment is just added to the linked list of fragments |
315 | | * for this packet; the fragment_item is also added to the fragment hash if |
316 | | * necessary. |
317 | | * |
318 | | * If this packet completes assembly, these functions return the head of the |
319 | | * fragment data; otherwise, they return null. |
320 | | * |
321 | | * @note Reused keys are assumed to refer to the same reassembled message |
322 | | * (i.e., retransmission). If the same "id" is used more than once on a |
323 | | * connection, then "data" and custom reassembly_table_functions should be |
324 | | * used so that the keys hash differently. |
325 | | */ |
326 | | WS_DLL_PUBLIC fragment_head * |
327 | | fragment_add_seq(reassembly_table *table, tvbuff_t *tvb, const int offset, |
328 | | const packet_info *pinfo, const uint32_t id, const void *data, |
329 | | const uint32_t frag_number, const uint32_t frag_data_len, |
330 | | const bool more_frags, const uint32_t flags); |
331 | | |
332 | | /* |
333 | | * Like fragment_add_seq, but maintains a table for completed reassemblies |
334 | | * just like fragment_add_check. |
335 | | * |
336 | | * @note Completed reassemblies are removed from the in-progress table, so |
337 | | * key can be reused to begin a new reassembled message. Conversely, |
338 | | * dissectors SHOULD NOT call this with a retransmitted fragment of a |
339 | | * completed reassembly. Dissectors atop a reliable protocol like TCP |
340 | | * may assume that the lower layer dissector handles retransmission, |
341 | | * but other dissectors (e.g., atop UDP or Ethernet) will have to handle |
342 | | * that situation themselves. |
343 | | */ |
344 | | WS_DLL_PUBLIC fragment_head * |
345 | | fragment_add_seq_check(reassembly_table *table, tvbuff_t *tvb, const int offset, |
346 | | const packet_info *pinfo, const uint32_t id, |
347 | | const void *data, |
348 | | const uint32_t frag_number, const uint32_t frag_data_len, |
349 | | const bool more_frags); |
350 | | |
351 | | /* |
352 | | * Like fragment_add_seq_check, but immediately returns a fragment list for a |
353 | | * new fragment. This is a workaround specific for the 802.11 dissector, do not |
354 | | * use it elsewhere. |
355 | | */ |
356 | | WS_DLL_PUBLIC fragment_head * |
357 | | fragment_add_seq_802_11(reassembly_table *table, tvbuff_t *tvb, |
358 | | const int offset, const packet_info *pinfo, |
359 | | const uint32_t id, const void *data, |
360 | | const uint32_t frag_number, const uint32_t frag_data_len, |
361 | | const bool more_frags); |
362 | | |
363 | | /* |
364 | | * Like fragment_add_seq_check, but without explicit fragment number. Fragments |
365 | | * are simply appended until no "more_frags" is false. |
366 | | * |
367 | | * @note Out of order fragments will not be reassembled correctly. |
368 | | * Dissectors atop a reliable protocol like TCP may rely on the lower |
369 | | * level dissector reordering out or order segments (if the appropriate |
370 | | * out of order reassembly preference is enabled), but other dissectors |
371 | | * will have to handle out of order fragments themselves, if possible. |
372 | | */ |
373 | | WS_DLL_PUBLIC fragment_head * |
374 | | fragment_add_seq_next(reassembly_table *table, tvbuff_t *tvb, const int offset, |
375 | | const packet_info *pinfo, const uint32_t id, |
376 | | const void *data, const uint32_t frag_data_len, |
377 | | const bool more_frags); |
378 | | |
379 | | /* |
380 | | * Like fragment_add_seq_check, but for protocols like PPP MP with a single |
381 | | * sequence number that increments for each fragment, thus acting like the sum |
382 | | * of the PDU sequence number and explicit fragment number in other protocols. |
383 | | * See Appendix A of RFC 4623 (PWE3 Fragmentation and Reassembly) for a list |
384 | | * of protocols that use this style, including PPP MP (RFC 1990), PWE3 MPLS |
385 | | * (RFC 4385), L2TPv2 (RFC 2661), L2TPv3 (RFC 3931), ATM, and Frame Relay. |
386 | | * It is guaranteed to reassemble a packet split up to "max_frags" in size, |
387 | | * but may manage to reassemble more in certain cases. |
388 | | */ |
389 | | WS_DLL_PUBLIC fragment_head * |
390 | | fragment_add_seq_single(reassembly_table *table, tvbuff_t *tvb, |
391 | | const int offset, const packet_info *pinfo, const uint32_t id, |
392 | | const void* data, const uint32_t frag_data_len, |
393 | | const bool first, const bool last, |
394 | | const uint32_t max_frags); |
395 | | |
396 | | /* |
397 | | * A variation on the above that ages off fragments that have not been |
398 | | * reassembled. Useful if the sequence number loops to deal with leftover |
399 | | * fragments from the beginning of the capture or missing fragments. |
400 | | */ |
401 | | WS_DLL_PUBLIC fragment_head * |
402 | | fragment_add_seq_single_aging(reassembly_table *table, tvbuff_t *tvb, |
403 | | const int offset, const packet_info *pinfo, const uint32_t id, |
404 | | const void* data, const uint32_t frag_data_len, |
405 | | const bool first, const bool last, |
406 | | const uint32_t max_frags, const uint32_t max_age); |
407 | | |
408 | | /* |
409 | | * Start a reassembly, expecting "tot_len" as the number of given fragments (not |
410 | | * the number of bytes). Data can be added later using fragment_add_seq_check. |
411 | | */ |
412 | | WS_DLL_PUBLIC void |
413 | | fragment_start_seq_check(reassembly_table *table, const packet_info *pinfo, |
414 | | const uint32_t id, const void *data, |
415 | | const uint32_t tot_len); |
416 | | |
417 | | /* |
418 | | * Mark end of reassembly and returns the reassembled fragment (if completed). |
419 | | * Use it when fragments were added with "more_flags" set while you discovered |
420 | | * that no more fragments have to be added. |
421 | | * This is for fragments added with add_seq_next; it doesn't check for gaps, |
422 | | * and doesn't set datalen correctly for the fragment_add family. |
423 | | */ |
424 | | WS_DLL_PUBLIC fragment_head * |
425 | | fragment_end_seq_next(reassembly_table *table, const packet_info *pinfo, |
426 | | const uint32_t id, const void *data); |
427 | | |
428 | | /* To specify the offset for the fragment numbering, the first fragment is added with 0, and |
429 | | * afterwards this offset is set. All additional calls to off_seq_check will calculate |
430 | | * the number in sequence in regards to the offset */ |
431 | | WS_DLL_PUBLIC void |
432 | | fragment_add_seq_offset(reassembly_table *table, const packet_info *pinfo, const uint32_t id, |
433 | | const void *data, const uint32_t fragment_offset); |
434 | | |
435 | | /* |
436 | | * Sets the expected index for the last block (for fragment_add_seq functions) |
437 | | * or the expected number of bytes (for fragment_add functions). A reassembly |
438 | | * must already have started. |
439 | | * |
440 | | * Note that for FD_BLOCKSEQUENCE tot_len is the index for the tail fragment. |
441 | | * i.e. since the block numbers start at 0, if we specify tot_len==2, that |
442 | | * actually means we want to defragment 3 blocks, block 0, 1 and 2. |
443 | | */ |
444 | | WS_DLL_PUBLIC void |
445 | | fragment_set_tot_len(reassembly_table *table, const packet_info *pinfo, |
446 | | const uint32_t id, const void *data, const uint32_t tot_len); |
447 | | |
448 | | /* |
449 | | * Similar to fragment_set_tot_len, it sets the expected number of bytes (for |
450 | | * fragment_add functions) for a previously started reassembly. If the specified |
451 | | * length already matches the reassembled length, then nothing will be done. |
452 | | * |
453 | | * If the fragments were previously reassembled, then this state will be |
454 | | * cleared, allowing new fragments to extend the reassembled result again. |
455 | | */ |
456 | | void |
457 | | fragment_reset_tot_len(reassembly_table *table, const packet_info *pinfo, |
458 | | const uint32_t id, const void *data, const uint32_t tot_len); |
459 | | |
460 | | /* |
461 | | * Truncates the size of an already defragmented reassembly to tot_len, |
462 | | * discarding past that point, including splitting any fragments in the |
463 | | * middle as necessary. The specified length must be less than or equal |
464 | | * to the reassembled length. (If it already matches the reassembled length, |
465 | | * then nothing will be done.) |
466 | | * |
467 | | * Used for continuous streams like TCP, where the length of a segment cannot |
468 | | * be determined without first reassembling and handing to a subdissector. |
469 | | */ |
470 | | void |
471 | | fragment_truncate(reassembly_table *table, const packet_info *pinfo, |
472 | | const uint32_t id, const void *data, const uint32_t tot_len); |
473 | | |
474 | | /* |
475 | | * Return the expected index for the last block (for fragment_add_seq functions) |
476 | | * or the expected number of bytes (for fragment_add functions). |
477 | | */ |
478 | | WS_DLL_PUBLIC uint32_t |
479 | | fragment_get_tot_len(reassembly_table *table, const packet_info *pinfo, |
480 | | const uint32_t id, const void *data); |
481 | | |
482 | | /* |
483 | | * This function will set the partial reassembly flag(FD_PARTIAL_REASSEMBLY) for a fh. |
484 | | * When this function is called, the fh MUST already exist, i.e. |
485 | | * the fh MUST be created by the initial call to fragment_add() before |
486 | | * this function is called. Also note that this function MUST be called to indicate |
487 | | * a fh will be extended (increase the already stored data). After calling this function, |
488 | | * and if FD_DEFRAGMENTED is set, the reassembly process will be continued. |
489 | | */ |
490 | | WS_DLL_PUBLIC void |
491 | | fragment_set_partial_reassembly(reassembly_table *table, |
492 | | const packet_info *pinfo, const uint32_t id, |
493 | | const void *data); |
494 | | |
495 | | /* This function is used to check if there is partial or completed reassembly state |
496 | | * matching this packet. I.e. Are there reassembly going on or not for this packet? |
497 | | */ |
498 | | WS_DLL_PUBLIC fragment_head * |
499 | | fragment_get(reassembly_table *table, const packet_info *pinfo, |
500 | | const uint32_t id, const void *data); |
501 | | |
502 | | /* The same for the reassemble table */ |
503 | | WS_DLL_PUBLIC fragment_head * |
504 | | fragment_get_reassembled_id(reassembly_table *table, const packet_info *pinfo, |
505 | | const uint32_t id); |
506 | | |
507 | | /* This will free up all resources and delete reassembly state for this PDU. |
508 | | * Except if the PDU is completely reassembled, then it would NOT deallocate the |
509 | | * buffer holding the reassembled data but instead return the TVB |
510 | | * |
511 | | * So, if you call fragment_delete and it returns non-NULL, YOU are responsible to |
512 | | * tvb_free() . |
513 | | */ |
514 | | WS_DLL_PUBLIC tvbuff_t * |
515 | | fragment_delete(reassembly_table *table, const packet_info *pinfo, |
516 | | const uint32_t id, const void *data); |
517 | | |
518 | | /* This struct holds references to all the tree and field handles used when |
519 | | * displaying the reassembled fragment tree in the packet details view. A |
520 | | * dissector will populate this structure with its own tree and field handles |
521 | | * and then invoke show_fragment_tree to have those items added to the packet |
522 | | * details tree. |
523 | | */ |
524 | | typedef struct _fragment_items { |
525 | | int *ett_fragment; |
526 | | int *ett_fragments; |
527 | | |
528 | | int *hf_fragments; /* FT_NONE */ |
529 | | int *hf_fragment; /* FT_FRAMENUM */ |
530 | | int *hf_fragment_overlap; /* FT_BOOLEAN */ |
531 | | int *hf_fragment_overlap_conflict; /* FT_BOOLEAN */ |
532 | | int *hf_fragment_multiple_tails; /* FT_BOOLEAN */ |
533 | | int *hf_fragment_too_long_fragment; /* FT_BOOLEAN */ |
534 | | int *hf_fragment_error; /* FT_FRAMENUM */ |
535 | | int *hf_fragment_count; /* FT_UINT32 */ |
536 | | int *hf_reassembled_in; /* FT_FRAMENUM */ |
537 | | int *hf_reassembled_length; /* FT_UINT32 */ |
538 | | int *hf_reassembled_data; /* FT_BYTES */ |
539 | | |
540 | | const char *tag; |
541 | | } fragment_items; |
542 | | |
543 | | WS_DLL_PUBLIC tvbuff_t * |
544 | | process_reassembled_data(tvbuff_t *tvb, const int offset, packet_info *pinfo, |
545 | | const char *name, fragment_head *fd_head, const fragment_items *fit, |
546 | | bool *update_col_infop, proto_tree *tree); |
547 | | |
548 | | WS_DLL_PUBLIC bool |
549 | | show_fragment_tree(fragment_head *ipfd_head, const fragment_items *fit, |
550 | | proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, proto_item **fi); |
551 | | |
552 | | WS_DLL_PUBLIC bool |
553 | | show_fragment_seq_tree(fragment_head *ipfd_head, const fragment_items *fit, |
554 | | proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, proto_item **fi); |
555 | | |
556 | | /* Initialize internal structures |
557 | | */ |
558 | | extern void reassembly_tables_init(void); |
559 | | |
560 | | /* Cleanup internal structures |
561 | | */ |
562 | | extern void |
563 | | reassembly_table_cleanup(void); |
564 | | |
565 | | /* ===================== Streaming data reassembly helper ===================== */ |
566 | | /** |
567 | | * Macro to help to define ett or hf items variables for reassembly (especially for streaming reassembly). |
568 | | * The statement: |
569 | | * |
570 | | * REASSEMBLE_ITEMS_DEFINE(foo_body, "Foo Body"); // in global scope |
571 | | * |
572 | | * will create global variables: |
573 | | * |
574 | | * static int ett_foo_body_fragment; |
575 | | * static int ett_foo_body_fragments; |
576 | | * static int hf_foo_body_fragment; |
577 | | * static int hf_foo_body_fragments; |
578 | | * static int hf_foo_body_fragment_overlap; |
579 | | * ... |
580 | | * static int hf_foo_body_segment; |
581 | | * |
582 | | * static const fragment_items foo_body_fragment_items = { |
583 | | * &ett_foo_body_fragment, |
584 | | * &ett_foo_body_fragments, |
585 | | * &hf_foo_body_fragments, |
586 | | * &hf_foo_body_fragment, |
587 | | * &hf_foo_body_fragment_overlap, |
588 | | * ... |
589 | | * "Foo Body fragments" |
590 | | * }; |
591 | | */ |
592 | | #define REASSEMBLE_ITEMS_DEFINE(var_prefix, name_prefix) \ |
593 | | static int ett_##var_prefix##_fragment; \ |
594 | | static int ett_##var_prefix##_fragments; \ |
595 | | static int hf_##var_prefix##_fragments; \ |
596 | | static int hf_##var_prefix##_fragment; \ |
597 | | static int hf_##var_prefix##_fragment_overlap; \ |
598 | | static int hf_##var_prefix##_fragment_overlap_conflicts; \ |
599 | | static int hf_##var_prefix##_fragment_multiple_tails; \ |
600 | | static int hf_##var_prefix##_fragment_too_long_fragment; \ |
601 | | static int hf_##var_prefix##_fragment_error; \ |
602 | | static int hf_##var_prefix##_fragment_count; \ |
603 | | static int hf_##var_prefix##_reassembled_in; \ |
604 | | static int hf_##var_prefix##_reassembled_length; \ |
605 | | static int hf_##var_prefix##_reassembled_data; \ |
606 | | static int hf_##var_prefix##_segment; \ |
607 | | static const fragment_items var_prefix##_fragment_items = { \ |
608 | | &ett_##var_prefix##_fragment, \ |
609 | | &ett_##var_prefix##_fragments, \ |
610 | | &hf_##var_prefix##_fragments, \ |
611 | | &hf_##var_prefix##_fragment, \ |
612 | | &hf_##var_prefix##_fragment_overlap, \ |
613 | | &hf_##var_prefix##_fragment_overlap_conflicts, \ |
614 | | &hf_##var_prefix##_fragment_multiple_tails, \ |
615 | | &hf_##var_prefix##_fragment_too_long_fragment, \ |
616 | | &hf_##var_prefix##_fragment_error, \ |
617 | | &hf_##var_prefix##_fragment_count, \ |
618 | | &hf_##var_prefix##_reassembled_in, \ |
619 | | &hf_##var_prefix##_reassembled_length, \ |
620 | | &hf_##var_prefix##_reassembled_data, \ |
621 | | name_prefix " fragments" \ |
622 | | } |
623 | | |
624 | | /** |
625 | | * Macro to help to initialize hf (head field) items for reassembly. |
626 | | * The statement: |
627 | | * |
628 | | * void proto_register_foo(void) { |
629 | | * static hf_register_info hf[] = { |
630 | | * ... |
631 | | * { &hf_proto_foo_payload, |
632 | | * { "Payload", "foo.payload", |
633 | | * FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } |
634 | | * }, |
635 | | * |
636 | | * // Add fragments items |
637 | | * REASSEMBLE_INIT_HF_ITEMS(foo_body, "Foo Body", "foo.body"), |
638 | | * ... |
639 | | * }; |
640 | | * ... |
641 | | * } |
642 | | * |
643 | | * will expand like: |
644 | | * |
645 | | * void proto_register_foo(void) { |
646 | | * static hf_register_info hf[] = { |
647 | | * ... |
648 | | * { &hf_proto_foo_payload, |
649 | | * { "Payload", "foo.payload", |
650 | | * FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } |
651 | | * }, |
652 | | * |
653 | | * // Add fragments items |
654 | | * { &hf_foo_body_fragments, \ |
655 | | * { "Reassembled Foo Body fragments", "foo.body.fragments", \ |
656 | | * FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } \ |
657 | | * }, |
658 | | * { &hf_foo_body_fragment, \ |
659 | | * { "Foo Body fragment", "foo.body.fragment", \ |
660 | | * FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } \ |
661 | | * }, |
662 | | * { &hf_foo_body_fragment_overlap, \ |
663 | | * { "Foo Body fragment overlap", "foo.body.fragment.overlap", \ |
664 | | * FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } \ |
665 | | * }, |
666 | | * ... |
667 | | * }; |
668 | | * ... |
669 | | * } |
670 | | */ |
671 | | #define REASSEMBLE_INIT_HF_ITEMS(var_prefix, name_prefix, abbrev_prefix) \ |
672 | 14 | { &hf_##var_prefix##_fragments, \ |
673 | 14 | { "Reassembled " name_prefix " fragments", abbrev_prefix ".fragments", \ |
674 | 14 | FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } \ |
675 | 14 | }, \ |
676 | 14 | { &hf_##var_prefix##_fragment, \ |
677 | 14 | { name_prefix " fragment", abbrev_prefix ".fragment", \ |
678 | 14 | FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } \ |
679 | 14 | }, \ |
680 | 14 | { &hf_##var_prefix##_fragment_overlap, \ |
681 | 14 | { name_prefix " fragment overlap", abbrev_prefix ".fragment.overlap", \ |
682 | 14 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } \ |
683 | 14 | }, \ |
684 | 14 | { &hf_##var_prefix##_fragment_overlap_conflicts, \ |
685 | 14 | { name_prefix " fragment overlapping with conflicting data", abbrev_prefix ".fragment.overlap.conflicts", \ |
686 | 14 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } \ |
687 | 14 | }, \ |
688 | 14 | { &hf_##var_prefix##_fragment_multiple_tails, \ |
689 | 14 | { name_prefix " has multiple tail fragments", abbrev_prefix ".fragment.multiple_tails", \ |
690 | 14 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } \ |
691 | 14 | }, \ |
692 | 14 | { &hf_##var_prefix##_fragment_too_long_fragment, \ |
693 | 14 | { name_prefix " fragment too long", abbrev_prefix ".fragment.too_long_fragment", \ |
694 | 14 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } \ |
695 | 14 | }, \ |
696 | 14 | { &hf_##var_prefix##_fragment_error, \ |
697 | 14 | { name_prefix " defragment error", abbrev_prefix ".fragment.error", \ |
698 | 14 | FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } \ |
699 | 14 | }, \ |
700 | 14 | { &hf_##var_prefix##_fragment_count, \ |
701 | 14 | { name_prefix " fragment count", abbrev_prefix ".fragment.count", \ |
702 | 14 | FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } \ |
703 | 14 | }, \ |
704 | 14 | { &hf_##var_prefix##_reassembled_in, \ |
705 | 14 | { "Reassembled in", abbrev_prefix ".reassembled.in", \ |
706 | 14 | FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } \ |
707 | 14 | }, \ |
708 | 14 | { &hf_##var_prefix##_reassembled_length, \ |
709 | 14 | { "Reassembled length", abbrev_prefix ".reassembled.length", \ |
710 | 14 | FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } \ |
711 | 14 | }, \ |
712 | 14 | { &hf_##var_prefix##_reassembled_data, \ |
713 | 14 | { "Reassembled data", abbrev_prefix ".reassembled.data", \ |
714 | 14 | FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } \ |
715 | 14 | }, \ |
716 | 14 | { &hf_##var_prefix##_segment, \ |
717 | 14 | { name_prefix " segment", abbrev_prefix ".segment", \ |
718 | 14 | FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} \ |
719 | 14 | } |
720 | | |
721 | | /** |
722 | | * Macro to help to initialize protocol subtree (ett) items for reassembly. |
723 | | * The statement: |
724 | | * |
725 | | * void proto_register_foo(void) { |
726 | | * ... |
727 | | * static int* ett[] = { |
728 | | * &ett_foo_abc, |
729 | | * ... |
730 | | * // Add ett items |
731 | | * REASSEMBLE_INIT_ETT_ITEMS(foo_body), |
732 | | * ... |
733 | | * }; |
734 | | * ... |
735 | | * } |
736 | | * |
737 | | * will expand like: |
738 | | * |
739 | | * void proto_register_foo(void) { |
740 | | * ... |
741 | | * static int* ett[] = { |
742 | | * &ett_foo_abc, |
743 | | * ... |
744 | | * // Add ett items |
745 | | * &ett_foo_body_fragment, |
746 | | * &ett_foo_body_fragments, |
747 | | * ... |
748 | | * }; |
749 | | * ... |
750 | | * } |
751 | | */ |
752 | | #define REASSEMBLE_INIT_ETT_ITEMS(var_prefix) \ |
753 | 14 | &ett_##var_prefix##_fragment, \ |
754 | 14 | &ett_##var_prefix##_fragments |
755 | | |
756 | | /** a private structure for keeping streaming reassembly information */ |
757 | | typedef struct streaming_reassembly_info_t streaming_reassembly_info_t; |
758 | | |
759 | | /** |
760 | | * Allocate a streaming reassembly information in wmem_file_scope. |
761 | | */ |
762 | | WS_DLL_PUBLIC streaming_reassembly_info_t* |
763 | | streaming_reassembly_info_new(void); |
764 | | |
765 | | /** |
766 | | * This function provides a simple way to reassemble the streaming data of a higher level |
767 | | * protocol that is not on top of TCP but on another protocol which might be on top of TCP. |
768 | | * |
769 | | * For example, suppose there are two streaming protocols ProtoA and ProtoB. ProtoA is a protocol on top |
770 | | * of TCP. ProtoB is a protocol on top of ProtoA. |
771 | | * |
772 | | * ProtoA dissector should use tcp_dissect_pdus() or pinfo->can_desegment/desegment_offset/desegment_len |
773 | | * to reassemble its own messages on top of TCP. After the PDUs of ProtoA are reassembled, ProtoA dissector |
774 | | * can call reassemble_streaming_data_and_call_subdissector() to help ProtoB dissector to reassemble the |
775 | | * PDUs of ProtoB. ProtoB needs to use fields pinfo->can_desegment/desegment_offset/desegment_len to tell |
776 | | * its requirements about reassembly (to reassemble_streaming_data_and_call_subdissector()). |
777 | | * <pre> |
778 | | * ----- +-- Reassembled ProtoB PDU --+-- Reassembled ProtoB PDU --+-- Reassembled ProtoB PDU --+---------------- |
779 | | * ProtoB: | ProtoB header and payload | ProtoB header and payload | ProtoB header and payload | ... |
780 | | * +----------------------------+---------+------------------+--------+-------------------+--+------------- |
781 | | * ----- ^ >>> Reassemble with reassemble_streaming_data_and_call_subdissector() and pinfo->desegment_len.. <<< ^ |
782 | | * +----------------------------+---------+------------------+--------+-------------------+--+------------- |
783 | | * | ProtoA payload1 | ProtoA payload2 | ProtoA payload3 | ... |
784 | | * +--------------------------------------+---------------------------+----------------------+------------- |
785 | | * ^ ^ ^ ^ |
786 | | * | >>> Do de-chunk <<< |\ >>> Do de-chunk <<< \ \ >>> Do de-chunk <<< \ |
787 | | * | | \ \ \ \ |
788 | | * | | \ \ \ ... |
789 | | * | | \ \ \ \ |
790 | | * +-------- First Reassembled ProtoA PDU ---------+-- Second Reassembled ProtoA PDU ---+- Third Reassembled Prot... |
791 | | * ProtoA: | Header | ProtoA payload1 | Header | ProtoA payload2 | Header | ProtoA payload3 . |
792 | | * +--------+----------------------+---------------+--------+---------------------------+--------+-+---------------- |
793 | | * ----- ^ >>> Reassemble with tcp_dissect_pdus() or pinfo->can_desegment/desegment_offset/desegment_len <<< ^ |
794 | | * +--------+----------------------+---------------+--------+---------------------------+--------+-+---------------- |
795 | | * TCP: | TCP segment | TCP segment | TCP segment | ... |
796 | | * ----- +-------------------------------+-------------------------------+-------------------------------+---------------- |
797 | | * </pre> |
798 | | * |
799 | | * The function reassemble_streaming_data_and_call_subdissector() uses fragment_add() and process_reassembled_data() |
800 | | * to complete its reassembly task. |
801 | | * |
802 | | * The reassemble_streaming_data_and_call_subdissector() will handle many cases. The most complicated one is: |
803 | | * <pre> |
804 | | * +-------------------------------------- Payload of a ProtoA PDU -----------------------------------------------+ |
805 | | * | EoMSP: end of a multisegment PDU | OmNFP: one or more non-fragment PDUs | BoMSP: begin of a multisegment PDU | |
806 | | * +----------------------------------+--------------------------------------+------------------------------------+ |
807 | | * </pre> |
808 | | * |
809 | | * Note, we use short name 'MSP' for 'Multisegment PDU', and 'NFP' for 'Non-fragment PDU'. |
810 | | * |
811 | | * In this case, the payload of a ProtoA PDU contains: |
812 | | * - EoMSP (Part1): At the begin of the ProtoA payload, there is the last part of a multisegment PDU of ProtoB. |
813 | | * - OmNFP (Part2): The middle part of ProtoA payload payload contains one or more non-fragment PDUs of ProtoB. |
814 | | * - BoMSP (Part3): At the tail of the ProtoA payload, there is the begin of a new multisegment PDU of ProtoB. |
815 | | * |
816 | | * All of three parts are optional. For example, one ProtoA payload could contain only EoMSP, OmNFP or BoMSP; or contain |
817 | | * EoMSP and OmNFP without BoMSP; or contain EoMSP and BoMSP without OmNFP; or contain OmNFP and BoMSP without |
818 | | * EoMSP. |
819 | | * <pre> |
820 | | * +---- A ProtoB MSP ---+ +-- A ProtoB MSP --+-- A ProtoB MSP --+ +-- A ProtoB MSP --+ |
821 | | * | | | | | | | |
822 | | * +- A ProtoA payload -+ +-------+-------+-------+ +-------+-------+ +-------+-------+ +-------+ +-------+ +-------+ |
823 | | * | OmNFP | BoMSP | | EoMSP | OmNFP | BoMSP | | EoMSP | BoMSP | | EoMSP | OmNFP | | BoMSP | | EoMSP | | OmNFP | |
824 | | * +---------+----------+ +-------+-------+-------+ +-------+-------+ +-------+-------+ +-------+ +-------+ +-------+ |
825 | | * | | | | | | | |
826 | | * +---------------------+ +------------------+------------------+ +------------------+ |
827 | | * </pre> |
828 | | * |
829 | | * And another case is the entire ProtoA payload is one of middle parts of a multisegment PDU. We call it: |
830 | | * - MoMSP: The middle part of a multisegment PDU of ProtoB. |
831 | | * |
832 | | * Following case shows a multisegment PDU composed of [BoMSP + MoMSP + MoMSP + MoMSP + EoMSP]: |
833 | | * <pre> |
834 | | * +------------------ A Multisegment PDU of ProtoB ----------------------+ |
835 | | * | | |
836 | | * +--- ProtoA payload1 ---+ +- payload2 -+ +- Payload3 -+ +- Payload4 -+ +- ProtoA payload5 -+ |
837 | | * | EoMSP | OmNFP | BoMSP | | MoMSP | | MoMSP | | MoMSP | | EoMSP | BoMSP | |
838 | | * +-------+-------+-------+ +------------+ +------------+ +------------+ +---------+---------+ |
839 | | * | | |
840 | | * +----------------------------------------------------------------------+ |
841 | | * </pre> |
842 | | * |
843 | | * The function reassemble_streaming_data_and_call_subdissector() will handle all of the above cases and manage |
844 | | * the information used during the reassembly. The caller (ProtoA dissector) only needs to initialize the relevant |
845 | | * variables and pass these variables and its own completed payload to this function. |
846 | | * |
847 | | * The subdissector (ProtoB dissector) needs to set the pinfo->desegment_len to cooperate with the function |
848 | | * reassemble_streaming_data_and_call_subdissector() to complete the reassembly task. |
849 | | * The pinfo->desegment_len should be DESEGMENT_ONE_MORE_SEGMENT or contain the estimated number of additional bytes required for completing |
850 | | * the current PDU (MSP), and set pinfo->desegment_offset to the offset in the tvbuff at which the dissector will |
851 | | * continue processing when next called. Next time the subdissector is called, it will be passed a tvbuff composed |
852 | | * of the end of the data from the previous tvbuff together with desegment_len more bytes. If the dissector cannot |
853 | | * tell how many more bytes it will need, it should set pinfo->desegment_len to DESEGMENT_ONE_MORE_SEGMENT or additional bytes required for parsing |
854 | | * message head. It will then be called again as soon as more data becomes available. Subdissector MUST NOT set the |
855 | | * pinfo->desegment_len to DESEGMENT_UNTIL_FIN, we don't support it yet. |
856 | | * |
857 | | * Note that if the subdissector sets pinfo->desegment_len to additional bytes required for parsing the header of |
858 | | * the message rather than the entire message when the length of entire message is unable to be determined, it MUST |
859 | | * return the length of the tvb handled by itself (for example, return 0 length if nothing is parsed in MoMSP), |
860 | | * otherwise it may cause some unexpected dissecting errors. However, if you want to be compatible with TCP's reassembly |
861 | | * method by setting the pinfo->desegment_len, you MUST set the pinfo->desegment_len to DESEGMENT_ONE_MORE_SEGMENT |
862 | | * when the entire message length cannot be determined, and return a length other than 0 (such as tvb_captured_length(tvb)) |
863 | | * when exiting the subdissector dissect function (such as dissect_proto_b()). |
864 | | * |
865 | | * Following is sample code of ProtoB which on top of ProtoA mentioned above: |
866 | | * @code |
867 | | * // file packet-proto-b.c |
868 | | * ... |
869 | | * |
870 | | * static int |
871 | | * dissect_proto_b(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data) |
872 | | * { |
873 | | * while (offset < tvb_len) |
874 | | * { |
875 | | * if (tvb_len - offset < PROTO_B_MESSAGE_HEAD_LEN) { |
876 | | * // need at least X bytes for getting a ProtoB message |
877 | | * if (pinfo->can_desegment) { |
878 | | * pinfo->desegment_offset = offset; |
879 | | * // It is strongly recommended to set pinfo->desegment_len to DESEGMENT_ONE_MORE_SEGMENT |
880 | | * // if the length of entire message is unknown. |
881 | | * pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT; |
882 | | * return tvb_len; // MUST return a length other than 0 |
883 | | * |
884 | | * // Or set pinfo->desegment_len to how many additional bytes needed to parse head of |
885 | | * // a ProtoB message. |
886 | | * // pinfo->desegment_len = PROTO_B_MESSAGE_HEAD_LEN - (tvb_len - offset); |
887 | | * // return offset; // But you MUST return the length handled by ProtoB |
888 | | * } |
889 | | * ... |
890 | | * } |
891 | | * ... |
892 | | * // e.g. length is at offset 4 |
893 | | * body_len = (unsigned)tvb_get_ntohl(tvb, offset + 4); |
894 | | * |
895 | | * if (tvb_len - offset - PROTO_B_MESSAGE_HEAD_LEN < body_len) { |
896 | | * // need X bytes for dissecting a ProtoB message |
897 | | * if (pinfo->can_desegment) { |
898 | | * pinfo->desegment_offset = offset; |
899 | | * // calculate how many additional bytes need to parsing body of a ProtoB message |
900 | | * pinfo->desegment_len = body_len - (tvb_len - offset - PROTO_B_MESSAGE_HEAD_LEN); |
901 | | * // MUST return a length other than 0, if DESEGMENT_ONE_MORE_SEGMENT is used previously. |
902 | | * return tvb_len; |
903 | | * |
904 | | * // MUST return the length handled by ProtoB, |
905 | | * // if 'pinfo->desegment_len = PROTO_B_MESSAGE_HEAD_LEN - (tvb_len - offset);' is used previously. |
906 | | * // return offset; |
907 | | * } |
908 | | * ... |
909 | | * } |
910 | | * ... |
911 | | * } |
912 | | * return tvb_len; // all bytes of this tvb are parsed |
913 | | * } |
914 | | * @endcode |
915 | | * |
916 | | * Following is sample code of ProtoA mentioned above: |
917 | | * @code |
918 | | * // file packet-proto-a.c |
919 | | * ... |
920 | | * // reassembly table for streaming chunk mode |
921 | | * static reassembly_table proto_a_streaming_reassembly_table; |
922 | | * ... |
923 | | * // heads for displaying reassembly information |
924 | | * static int hf_msg_fragments; |
925 | | * static int hf_msg_fragment; |
926 | | * static int hf_msg_fragment_overlap; |
927 | | * static int hf_msg_fragment_overlap_conflicts; |
928 | | * static int hf_msg_fragment_multiple_tails; |
929 | | * static int hf_msg_fragment_too_long_fragment; |
930 | | * static int hf_msg_fragment_error; |
931 | | * static int hf_msg_fragment_count; |
932 | | * static int hf_msg_reassembled_in; |
933 | | * static int hf_msg_reassembled_length; |
934 | | * static int hf_msg_body_segment; |
935 | | * ... |
936 | | * static int ett_msg_fragment; |
937 | | * static int ett_msg_fragments; |
938 | | * ... |
939 | | * static const fragment_items msg_frag_items = { |
940 | | * &ett_msg_fragment, |
941 | | * &ett_msg_fragments, |
942 | | * &hf_msg_fragments, |
943 | | * &hf_msg_fragment, |
944 | | * &hf_msg_fragment_overlap, |
945 | | * &hf_msg_fragment_overlap_conflicts, |
946 | | * &hf_msg_fragment_multiple_tails, |
947 | | * &hf_msg_fragment_too_long_fragment, |
948 | | * &hf_msg_fragment_error, |
949 | | * &hf_msg_fragment_count, |
950 | | * &hf_msg_reassembled_in, |
951 | | * &hf_msg_reassembled_length, |
952 | | * "ProtoA Message fragments" |
953 | | * }; |
954 | | * ... |
955 | | * static int |
956 | | * dissect_proto_a(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data) |
957 | | * { |
958 | | * ... |
959 | | * streaming_reassembly_info_t* streaming_reassembly_info = NULL; |
960 | | * ... |
961 | | * proto_a_tree = proto_item_add_subtree(ti, ett_proto_a); |
962 | | * ... |
963 | | * if (!PINFO_FD_VISITED(pinfo)) { |
964 | | * streaming_reassembly_info = streaming_reassembly_info_new(); |
965 | | * // save streaming reassembly info in the stream conversation or something like that |
966 | | * save_reassembly_info(pinfo, stream_id, flow_dir, streaming_reassembly_info); |
967 | | * } else { |
968 | | * streaming_reassembly_info = get_reassembly_info(pinfo, stream_id, flow_dir); |
969 | | * } |
970 | | * ... |
971 | | * while (offset < tvb_len) |
972 | | * { |
973 | | * ... |
974 | | * payload_len = xxx; |
975 | | * ... |
976 | | * if (dissecting_in_streaming_mode) { |
977 | | * // reassemble and call subdissector |
978 | | * reassemble_streaming_data_and_call_subdissector(tvb, pinfo, offset, |
979 | | * payload_len, proto_a_tree, proto_tree_get_parent_tree(proto_a_tree), |
980 | | * proto_a_streaming_reassembly_table, streaming_reassembly_info, |
981 | | * get_virtual_frame_num64(tvb, pinfo, offset), subdissector_handle, |
982 | | * proto_tree_get_parent_tree(tree), NULL, |
983 | | * "ProtoA", &msg_frag_items, hf_msg_body_segment); |
984 | | * ... |
985 | | * } |
986 | | * } |
987 | | * |
988 | | * ... |
989 | | * void proto_register_proto_a(void) { |
990 | | * ... |
991 | | * static hf_register_info hf[] = { |
992 | | * ... |
993 | | * {&hf_msg_fragments, |
994 | | * {"Reassembled ProtoA Message fragments", "protoa.msg.fragments", |
995 | | * FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL } }, |
996 | | * {&hf_msg_fragment, |
997 | | * {"Message fragment", "protoa.msg.fragment", |
998 | | * FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } }, |
999 | | * {&hf_msg_fragment_overlap, |
1000 | | * {"Message fragment overlap", "protoa.msg.fragment.overlap", |
1001 | | * FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL } }, |
1002 | | * {&hf_msg_fragment_overlap_conflicts, |
1003 | | * {"Message fragment overlapping with conflicting data", |
1004 | | * "protoa.msg.fragment.overlap.conflicts", |
1005 | | * FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL } }, |
1006 | | * {&hf_msg_fragment_multiple_tails, |
1007 | | * {"Message has multiple tail fragments", |
1008 | | * "protoa.msg.fragment.multiple_tails", |
1009 | | * FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL } }, |
1010 | | * {&hf_msg_fragment_too_long_fragment, |
1011 | | * {"Message fragment too long", "protoa.msg.fragment.too_long_fragment", |
1012 | | * FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL } }, |
1013 | | * {&hf_msg_fragment_error, |
1014 | | * {"Message defragmentation error", "protoa.msg.fragment.error", |
1015 | | * FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } }, |
1016 | | * {&hf_msg_fragment_count, |
1017 | | * {"Message fragment count", "protoa.msg.fragment.count", |
1018 | | * FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } }, |
1019 | | * {&hf_msg_reassembled_in, |
1020 | | * {"Reassembled in", "protoa.msg.reassembled.in", |
1021 | | * FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } }, |
1022 | | * {&hf_msg_reassembled_length, |
1023 | | * {"Reassembled length", "protoa.msg.reassembled.length", |
1024 | | * FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } }, |
1025 | | * {&hf_msg_body_segment, |
1026 | | * {"ProtoA body segment", "protoa.msg.body.segment", |
1027 | | * FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL } }, |
1028 | | * } |
1029 | | * ... |
1030 | | * static int *ett[] = { |
1031 | | * ... |
1032 | | * &ett_msg_fragment, |
1033 | | * &ett_msg_fragments |
1034 | | * } |
1035 | | * ... |
1036 | | * reassembly_table_register(&proto_a_streaming_reassembly_table, |
1037 | | * &addresses_ports_reassembly_table_functions); |
1038 | | * ... |
1039 | | * } |
1040 | | * @endcode |
1041 | | * |
1042 | | * Alternatively, the code of ProtoA (packet-proto-a.c) can be made simpler with helper macros: |
1043 | | * @code |
1044 | | * // file packet-proto-a.c |
1045 | | * ... |
1046 | | * // reassembly table for streaming chunk mode |
1047 | | * static reassembly_table proto_a_streaming_reassembly_table; |
1048 | | * // reassembly head field items definition |
1049 | | * REASSEMBLE_ITEMS_DEFINE(proto_a_body, "ProtoA Body"); |
1050 | | * ... |
1051 | | * static int |
1052 | | * dissect_proto_a(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data) |
1053 | | * { |
1054 | | * ... |
1055 | | * streaming_reassembly_info_t* streaming_reassembly_info = NULL; |
1056 | | * ... |
1057 | | * proto_a_tree = proto_item_add_subtree(ti, ett_proto_a); |
1058 | | * ... |
1059 | | * if (!PINFO_FD_VISITED(pinfo)) { |
1060 | | * streaming_reassembly_info = streaming_reassembly_info_new(); |
1061 | | * // save streaming reassembly info in the stream conversation or something like that |
1062 | | * save_reassembly_info(pinfo, stream_id, flow_dir, streaming_reassembly_info); |
1063 | | * } else { |
1064 | | * streaming_reassembly_info = get_reassembly_info(pinfo, stream_id, flow_dir); |
1065 | | * } |
1066 | | * ... |
1067 | | * while (offset < tvb_len) |
1068 | | * { |
1069 | | * ... |
1070 | | * payload_len = xxx; |
1071 | | * ... |
1072 | | * if (dissecting_in_streaming_mode) { |
1073 | | * // reassemble and call subdissector |
1074 | | * reassemble_streaming_data_and_call_subdissector(tvb, pinfo, offset, |
1075 | | * payload_len, proto_a_tree, proto_tree_get_parent_tree(proto_a_tree), |
1076 | | * proto_a_streaming_reassembly_table, streaming_reassembly_info, |
1077 | | * get_virtual_frame_num64(tvb, pinfo, offset), subdissector_handle, |
1078 | | * proto_tree_get_parent_tree(tree), NULL, "ProtoA Body", |
1079 | | * &proto_a_body_fragment_items, hf_proto_a_body_segment); |
1080 | | * ... |
1081 | | * } |
1082 | | * } |
1083 | | * |
1084 | | * ... |
1085 | | * void proto_register_proto_a(void) { |
1086 | | * ... |
1087 | | * static hf_register_info hf[] = { |
1088 | | * ... |
1089 | | * REASSEMBLE_INIT_HF_ITEMS(proto_a_body, "ProtoA Body", "protoa.body") |
1090 | | * } |
1091 | | * ... |
1092 | | * static int *ett[] = { |
1093 | | * ... |
1094 | | * REASSEMBLE_INIT_ETT_ITEMS(proto_a_body) |
1095 | | * } |
1096 | | * ... |
1097 | | * reassembly_table_register(&proto_a_streaming_reassembly_table, |
1098 | | * &addresses_ports_reassembly_table_functions); |
1099 | | * ... |
1100 | | * } |
1101 | | * @endcode |
1102 | | * |
1103 | | * @param tvb TVB contains (ProtoA) payload which will be passed to subdissector. |
1104 | | * @param pinfo Packet information. |
1105 | | * @param offset The beginning offset of payload in TVB. |
1106 | | * @param length The length of payload in TVB. |
1107 | | * @param segment_tree The tree for adding segment items. |
1108 | | * @param reassembled_tree The tree for adding reassembled information items. |
1109 | | * @param streaming_reassembly_table The reassembly table used for this kind of streaming reassembly. |
1110 | | * @param reassembly_info The structure for keeping streaming reassembly information. This should be initialized |
1111 | | * by streaming_reassembly_info_new(). Subdissector should keep it for each flow of per stream, |
1112 | | * like per direction flow of a STREAM of HTTP/2 or each request or response message flow of |
1113 | | * HTTP/1.1 chunked stream. |
1114 | | * @param cur_frame_num The uniq index of current payload and number must always be increasing from the previous frame |
1115 | | * number, so we can use "<" and ">" comparisons to determine before and after in time. You can use |
1116 | | * get_virtual_frame_num64() if the ProtoA does not has a suitable field representing payload frame num. |
1117 | | * @param subdissector_handle The subdissector the reassembly for. We will call subdissector for reassembly and dissecting. |
1118 | | * The subdissector should set pinfo->desegment_len to the length it needed if the payload is |
1119 | | * not enough for it to dissect. |
1120 | | * @param subdissector_tree The tree to be passed to subdissector. |
1121 | | * @param subdissector_data The data argument to be passed to subdissector. |
1122 | | * @param label The name of the data being reassembling. It can just be the name of protocol (ProtoA), for |
1123 | | * example, "[ProtoA segment of a reassembled PDU]". |
1124 | | * @param frag_hf_items The fragment field items for displaying fragment and reassembly information in tree. Please |
1125 | | * refer to process_reassembled_data(). |
1126 | | * @param hf_segment_data The field item to show something like "ProtoA segment data (123 bytes)". |
1127 | | * |
1128 | | * @return Handled data length. Just equal to the length argument now. |
1129 | | */ |
1130 | | WS_DLL_PUBLIC int |
1131 | | reassemble_streaming_data_and_call_subdissector( |
1132 | | tvbuff_t* tvb, packet_info* pinfo, unsigned offset, int length, |
1133 | | proto_tree* segment_tree, proto_tree* reassembled_tree, reassembly_table streaming_reassembly_table, |
1134 | | streaming_reassembly_info_t* reassembly_info, uint64_t cur_frame_num, |
1135 | | dissector_handle_t subdissector_handle, proto_tree* subdissector_tree, void* subdissector_data, |
1136 | | const char* label, const fragment_items* frag_hf_items, int hf_segment_data |
1137 | | ); |
1138 | | |
1139 | | /** |
1140 | | * Return a 64 bits virtual frame number that is identified as follows: |
1141 | | * <pre> |
1142 | | * +--- 32 bits ---+--------- 8 bits -------+----- 24 bits --------------+ |
1143 | | * | pinfo->num | pinfo->curr_layer_num | tvb->raw_offset + offset | |
1144 | | * +---------------------------------------------------------------------+ |
1145 | | * </pre> |
1146 | | * This allows for a single virtual frame to be uniquely identified across a capture with the |
1147 | | * added benefit that the number will always be increasing from the previous virtual frame so |
1148 | | * we can use "<" and ">" comparisons to determine before and after in time. |
1149 | | * |
1150 | | * This frame number similar to HTTP2 frame number. |
1151 | | */ |
1152 | | static inline uint64_t |
1153 | | get_virtual_frame_num64(tvbuff_t* tvb, packet_info* pinfo, int offset) |
1154 | 22 | { |
1155 | 22 | return (((uint64_t)pinfo->num) << 32) + (((uint64_t)pinfo->curr_layer_num) << 24) |
1156 | 22 | + ((uint64_t)tvb_raw_offset(tvb) + offset); |
1157 | 22 | } Unexecuted instantiation: epan.c:get_virtual_frame_num64 Unexecuted instantiation: packet.c:get_virtual_frame_num64 Unexecuted instantiation: reassemble.c:get_virtual_frame_num64 Unexecuted instantiation: stream.c:get_virtual_frame_num64 Unexecuted instantiation: packet-5co-legacy.c:get_virtual_frame_num64 Unexecuted instantiation: packet-5co-rap.c:get_virtual_frame_num64 Unexecuted instantiation: packet-6lowpan.c:get_virtual_frame_num64 Unexecuted instantiation: packet-9p.c:get_virtual_frame_num64 Unexecuted instantiation: packet-acn.c:get_virtual_frame_num64 Unexecuted instantiation: packet-adwin-config.c:get_virtual_frame_num64 Unexecuted instantiation: packet-afs.c:get_virtual_frame_num64 Unexecuted instantiation: packet-agentx.c:get_virtual_frame_num64 Unexecuted instantiation: packet-aim.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ajp13.c:get_virtual_frame_num64 Unexecuted instantiation: packet-amqp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ancp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-aol.c:get_virtual_frame_num64 Unexecuted instantiation: packet-artemis.c:get_virtual_frame_num64 Unexecuted instantiation: packet-asphodel.c:get_virtual_frame_num64 Unexecuted instantiation: packet-assa_r3.c:get_virtual_frame_num64 Unexecuted instantiation: packet-atalk.c:get_virtual_frame_num64 Unexecuted instantiation: packet-bacapp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-batadv.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ber.c:get_virtual_frame_num64 Unexecuted instantiation: packet-bgp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-bitcoin.c:get_virtual_frame_num64 Unexecuted instantiation: packet-bittorrent.c:get_virtual_frame_num64 Unexecuted instantiation: packet-bmp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-bpv7.c:get_virtual_frame_num64 Unexecuted instantiation: packet-btatt.c:get_virtual_frame_num64 Unexecuted instantiation: packet-btbredr_rf.c:get_virtual_frame_num64 Unexecuted instantiation: packet-btl2cap.c:get_virtual_frame_num64 Unexecuted instantiation: packet-btle.c:get_virtual_frame_num64 Unexecuted instantiation: packet-btmesh.c:get_virtual_frame_num64 Unexecuted instantiation: packet-btmesh-pbadv.c:get_virtual_frame_num64 Unexecuted instantiation: packet-btmesh-proxy.c:get_virtual_frame_num64 Unexecuted instantiation: packet-capwap.c:get_virtual_frame_num64 Unexecuted instantiation: packet-cast.c:get_virtual_frame_num64 Unexecuted instantiation: packet-cell_broadcast.c:get_virtual_frame_num64 Unexecuted instantiation: packet-clnp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-cmpp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-coap.c:get_virtual_frame_num64 Unexecuted instantiation: packet-cops.c:get_virtual_frame_num64 Unexecuted instantiation: packet-couchbase.c:get_virtual_frame_num64 Unexecuted instantiation: packet-cql.c:get_virtual_frame_num64 Unexecuted instantiation: packet-db-lsp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-dbus.c:get_virtual_frame_num64 Unexecuted instantiation: packet-dcerpc.c:get_virtual_frame_num64 Unexecuted instantiation: packet-dcm.c:get_virtual_frame_num64 Unexecuted instantiation: packet-dcp-etsi.c:get_virtual_frame_num64 Unexecuted instantiation: packet-dect-dlc.c:get_virtual_frame_num64 Unexecuted instantiation: packet-dhcp-failover.c:get_virtual_frame_num64 Unexecuted instantiation: packet-dhcpv6.c:get_virtual_frame_num64 Unexecuted instantiation: packet-diameter.c:get_virtual_frame_num64 Unexecuted instantiation: packet-dji-uav.c:get_virtual_frame_num64 Unexecuted instantiation: packet-dlep.c:get_virtual_frame_num64 Unexecuted instantiation: packet-dlm3.c:get_virtual_frame_num64 Unexecuted instantiation: packet-dlsw.c:get_virtual_frame_num64 Unexecuted instantiation: packet-dlt.c:get_virtual_frame_num64 Unexecuted instantiation: packet-dnp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-dns.c:get_virtual_frame_num64 Unexecuted instantiation: packet-docsis.c:get_virtual_frame_num64 Unexecuted instantiation: packet-docsis-macmgmt.c:get_virtual_frame_num64 Unexecuted instantiation: packet-docsis-tlv.c:get_virtual_frame_num64 Unexecuted instantiation: packet-dof.c:get_virtual_frame_num64 Unexecuted instantiation: packet-doip.c:get_virtual_frame_num64 Unexecuted instantiation: packet-do-irp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-drbd.c:get_virtual_frame_num64 Unexecuted instantiation: packet-drda.c:get_virtual_frame_num64 Unexecuted instantiation: packet-dsi.c:get_virtual_frame_num64 Unexecuted instantiation: packet-dtls.c:get_virtual_frame_num64 Unexecuted instantiation: packet-dvb-s2-bb.c:get_virtual_frame_num64 Unexecuted instantiation: packet-dvbci.c:get_virtual_frame_num64 Unexecuted instantiation: packet-eap.c:get_virtual_frame_num64 Unexecuted instantiation: packet-edonkey.c:get_virtual_frame_num64 Unexecuted instantiation: packet-elasticsearch.c:get_virtual_frame_num64 Unexecuted instantiation: packet-enip.c:get_virtual_frame_num64 Unexecuted instantiation: packet-epl.c:get_virtual_frame_num64 Unexecuted instantiation: packet-erldp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-etch.c:get_virtual_frame_num64 Unexecuted instantiation: packet-eti.c:get_virtual_frame_num64 Unexecuted instantiation: packet-exported_pdu.c:get_virtual_frame_num64 Unexecuted instantiation: packet-f5ethtrailer.c:get_virtual_frame_num64 Unexecuted instantiation: packet-fc.c:get_virtual_frame_num64 Unexecuted instantiation: packet-fcgi.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ff.c:get_virtual_frame_num64 Unexecuted instantiation: packet-finger.c:get_virtual_frame_num64 Unexecuted instantiation: packet-fix.c:get_virtual_frame_num64 Unexecuted instantiation: packet-fmtp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-fpp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ftdi-ft.c:get_virtual_frame_num64 Unexecuted instantiation: packet-gadu-gadu.c:get_virtual_frame_num64 Unexecuted instantiation: packet-gbcs.c:get_virtual_frame_num64 Unexecuted instantiation: packet-gearman.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ged125.c:get_virtual_frame_num64 Unexecuted instantiation: packet-gelf.c:get_virtual_frame_num64 Unexecuted instantiation: packet-giop.c:get_virtual_frame_num64 Unexecuted instantiation: packet-git.c:get_virtual_frame_num64 Unexecuted instantiation: packet-gnutella.c:get_virtual_frame_num64 Unexecuted instantiation: packet-gsm_cbch.c:get_virtual_frame_num64 Unexecuted instantiation: packet-gsm_cbsp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-gsm_rlp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-gsm_sms.c:get_virtual_frame_num64 Unexecuted instantiation: packet-gsm_sms_ud.c:get_virtual_frame_num64 Unexecuted instantiation: packet-gssapi.c:get_virtual_frame_num64 Unexecuted instantiation: packet-h223.c:get_virtual_frame_num64 Unexecuted instantiation: packet-hartip.c:get_virtual_frame_num64 Unexecuted instantiation: packet-hazelcast.c:get_virtual_frame_num64 Unexecuted instantiation: packet-hci_usb.c:get_virtual_frame_num64 Unexecuted instantiation: packet-hdfs.c:get_virtual_frame_num64 Unexecuted instantiation: packet-hdfsdata.c:get_virtual_frame_num64 Unexecuted instantiation: packet-hiqnet.c:get_virtual_frame_num64 Unexecuted instantiation: packet-hislip.c:get_virtual_frame_num64 Unexecuted instantiation: packet-hpfeeds.c:get_virtual_frame_num64 Unexecuted instantiation: packet-hsfz.c:get_virtual_frame_num64 Unexecuted instantiation: packet-hsms.c:get_virtual_frame_num64 Unexecuted instantiation: packet-http.c:get_virtual_frame_num64 Unexecuted instantiation: packet-http2.c:get_virtual_frame_num64 Unexecuted instantiation: packet-http3.c:get_virtual_frame_num64 Unexecuted instantiation: packet-iax2.c:get_virtual_frame_num64 Unexecuted instantiation: packet-icep.c:get_virtual_frame_num64 Unexecuted instantiation: packet-iec104.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ieee1905.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ieee80211.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ifcp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-infiniband.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ip.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ipdc.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ipdr.c:get_virtual_frame_num64 Unexecuted instantiation: packet-iperf3.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ipv6.c:get_virtual_frame_num64 Unexecuted instantiation: packet-isakmp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-isns.c:get_virtual_frame_num64 Unexecuted instantiation: packet-iso10681.c:get_virtual_frame_num64 Unexecuted instantiation: packet-iso14443.c:get_virtual_frame_num64 Unexecuted instantiation: packet-iso15765.c:get_virtual_frame_num64 Unexecuted instantiation: packet-iso8583.c:get_virtual_frame_num64 Unexecuted instantiation: packet-isobus.c:get_virtual_frame_num64 Unexecuted instantiation: packet-isup.c:get_virtual_frame_num64 Unexecuted instantiation: packet-iwarp-ddp-rdmap.c:get_virtual_frame_num64 Unexecuted instantiation: packet-iwarp-mpa.c:get_virtual_frame_num64 Unexecuted instantiation: packet-jdwp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-kafka.c:get_virtual_frame_num64 Unexecuted instantiation: packet-kdsp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-knet.c:get_virtual_frame_num64 Unexecuted instantiation: packet-knxip.c:get_virtual_frame_num64 Unexecuted instantiation: packet-kpasswd.c:get_virtual_frame_num64 Unexecuted instantiation: packet-lapdm.c:get_virtual_frame_num64 Unexecuted instantiation: packet-laplink.c:get_virtual_frame_num64 Unexecuted instantiation: packet-lapsat.c:get_virtual_frame_num64 Unexecuted instantiation: packet-lbmpdmtcp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-lbmsrs.c:get_virtual_frame_num64 Unexecuted instantiation: packet-lbttcp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ldss.c:get_virtual_frame_num64 Unexecuted instantiation: packet-lg8979.c:get_virtual_frame_num64 Unexecuted instantiation: packet-lisp-tcp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-llrp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-lnet.c:get_virtual_frame_num64 Unexecuted instantiation: packet-lsc.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ltp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-lustre.c:get_virtual_frame_num64 Unexecuted instantiation: packet-m3ua.c:get_virtual_frame_num64 Unexecuted instantiation: packet-mausb.c:get_virtual_frame_num64 Unexecuted instantiation: packet-mbim.c:get_virtual_frame_num64 Unexecuted instantiation: packet-mbtcp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-mctp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-memcache.c:get_virtual_frame_num64 Unexecuted instantiation: packet-monero.c:get_virtual_frame_num64 Unexecuted instantiation: packet-mongo.c:get_virtual_frame_num64 Unexecuted instantiation: packet-mp2t.c:get_virtual_frame_num64 Unexecuted instantiation: packet-mq.c:get_virtual_frame_num64 Unexecuted instantiation: packet-mqtt.c:get_virtual_frame_num64 Unexecuted instantiation: packet-mrcpv2.c:get_virtual_frame_num64 Unexecuted instantiation: packet-msproxy.c:get_virtual_frame_num64 Unexecuted instantiation: packet-mtp2.c:get_virtual_frame_num64 Unexecuted instantiation: packet-mux27010.c:get_virtual_frame_num64 Unexecuted instantiation: packet-mysql.c:get_virtual_frame_num64 Unexecuted instantiation: packet-nano.c:get_virtual_frame_num64 Unexecuted instantiation: packet-nas_5gs.c:get_virtual_frame_num64 Unexecuted instantiation: packet-nbd.c:get_virtual_frame_num64 Unexecuted instantiation: packet-nbt.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ncp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ndmp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ndps.c:get_virtual_frame_num64 Unexecuted instantiation: packet-netbios.c:get_virtual_frame_num64 Unexecuted instantiation: packet-netflow.c:get_virtual_frame_num64 Unexecuted instantiation: packet-netsync.c:get_virtual_frame_num64 Unexecuted instantiation: packet-nmf.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ns-mep.c:get_virtual_frame_num64 Unexecuted instantiation: packet-nts-ke.c:get_virtual_frame_num64 Unexecuted instantiation: packet-nvme-tcp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-nfapi.c:get_virtual_frame_num64 Unexecuted instantiation: packet-obex.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ocfs2.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ocp1.c:get_virtual_frame_num64 Unexecuted instantiation: packet-omron-fins.c:get_virtual_frame_num64 Unexecuted instantiation: packet-opa-fe.c:get_virtual_frame_num64 Unexecuted instantiation: packet-opa-mad.c:get_virtual_frame_num64 Unexecuted instantiation: packet-openflow.c:get_virtual_frame_num64 Unexecuted instantiation: packet-opensafety.c:get_virtual_frame_num64 packet-openvpn.c:get_virtual_frame_num64 Line | Count | Source | 1154 | 22 | { | 1155 | 22 | return (((uint64_t)pinfo->num) << 32) + (((uint64_t)pinfo->curr_layer_num) << 24) | 1156 | 22 | + ((uint64_t)tvb_raw_offset(tvb) + offset); | 1157 | 22 | } |
Unexecuted instantiation: packet-openwire.c:get_virtual_frame_num64 Unexecuted instantiation: packet-opsi.c:get_virtual_frame_num64 Unexecuted instantiation: packet-optommp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-osc.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ositp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-p_mul.c:get_virtual_frame_num64 Unexecuted instantiation: packet-paltalk.c:get_virtual_frame_num64 Unexecuted instantiation: packet-pcep.c:get_virtual_frame_num64 Unexecuted instantiation: packet-pcp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-pdc.c:get_virtual_frame_num64 Unexecuted instantiation: packet-pdu-transport.c:get_virtual_frame_num64 Unexecuted instantiation: packet-pgsql.c:get_virtual_frame_num64 Unexecuted instantiation: packet-pnrp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-pop.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ppi.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ppp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-proxy.c:get_virtual_frame_num64 Unexecuted instantiation: packet-pvfs2.c:get_virtual_frame_num64 Unexecuted instantiation: packet-q931.c:get_virtual_frame_num64 Unexecuted instantiation: packet-quic.c:get_virtual_frame_num64 Unexecuted instantiation: packet-raknet.c:get_virtual_frame_num64 Unexecuted instantiation: packet-reload-framing.c:get_virtual_frame_num64 Unexecuted instantiation: packet-reload.c:get_virtual_frame_num64 Unexecuted instantiation: packet-resp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-riemann.c:get_virtual_frame_num64 Unexecuted instantiation: packet-rk512.c:get_virtual_frame_num64 Unexecuted instantiation: packet-rlc-nr.c:get_virtual_frame_num64 Unexecuted instantiation: packet-rlogin.c:get_virtual_frame_num64 Unexecuted instantiation: packet-rpc.c:get_virtual_frame_num64 Unexecuted instantiation: packet-rpcap.c:get_virtual_frame_num64 Unexecuted instantiation: packet-rpcrdma.c:get_virtual_frame_num64 Unexecuted instantiation: packet-rpki-rtr.c:get_virtual_frame_num64 Unexecuted instantiation: packet-rtitcp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-rtmpt.c:get_virtual_frame_num64 Unexecuted instantiation: packet-rtp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-rtps.c:get_virtual_frame_num64 Unexecuted instantiation: packet-rtps-virtual-transport.c:get_virtual_frame_num64 Unexecuted instantiation: packet-rtps-processed.c:get_virtual_frame_num64 Unexecuted instantiation: packet-s101.c:get_virtual_frame_num64 Unexecuted instantiation: packet-s5066sis.c:get_virtual_frame_num64 Unexecuted instantiation: packet-s5066dts.c:get_virtual_frame_num64 Unexecuted instantiation: packet-s7comm.c:get_virtual_frame_num64 Unexecuted instantiation: packet-sametime.c:get_virtual_frame_num64 Unexecuted instantiation: packet-sane.c:get_virtual_frame_num64 Unexecuted instantiation: packet-saphdb.c:get_virtual_frame_num64 Unexecuted instantiation: packet-sapni.c:get_virtual_frame_num64 Unexecuted instantiation: packet-sasp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-sccp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-scop.c:get_virtual_frame_num64 Unexecuted instantiation: packet-scsi.c:get_virtual_frame_num64 Unexecuted instantiation: packet-scylla.c:get_virtual_frame_num64 Unexecuted instantiation: packet-selfm.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ses.c:get_virtual_frame_num64 Unexecuted instantiation: packet-simulcrypt.c:get_virtual_frame_num64 Unexecuted instantiation: packet-skinny.c:get_virtual_frame_num64 Unexecuted instantiation: packet-slsk.c:get_virtual_frame_num64 Unexecuted instantiation: packet-smb-pipe.c:get_virtual_frame_num64 Unexecuted instantiation: packet-smb-direct.c:get_virtual_frame_num64 Unexecuted instantiation: packet-smb.c:get_virtual_frame_num64 Unexecuted instantiation: packet-smb2.c:get_virtual_frame_num64 Unexecuted instantiation: packet-smc.c:get_virtual_frame_num64 Unexecuted instantiation: packet-smp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-smpp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-smtp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-sna.c:get_virtual_frame_num64 Unexecuted instantiation: packet-sndcp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-socks.c:get_virtual_frame_num64 Unexecuted instantiation: packet-someip.c:get_virtual_frame_num64 Unexecuted instantiation: packet-soupbintcp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-spdy.c:get_virtual_frame_num64 Unexecuted instantiation: packet-srvloc.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ssh.c:get_virtual_frame_num64 Unexecuted instantiation: packet-sstp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-starteam.c:get_virtual_frame_num64 Unexecuted instantiation: packet-stt.c:get_virtual_frame_num64 Unexecuted instantiation: packet-stun.c:get_virtual_frame_num64 Unexecuted instantiation: packet-synergy.c:get_virtual_frame_num64 Unexecuted instantiation: packet-synphasor.c:get_virtual_frame_num64 Unexecuted instantiation: packet-syslog.c:get_virtual_frame_num64 Unexecuted instantiation: packet-tacacs.c:get_virtual_frame_num64 Unexecuted instantiation: packet-tali.c:get_virtual_frame_num64 Unexecuted instantiation: packet-tcp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-tcpcl.c:get_virtual_frame_num64 Unexecuted instantiation: packet-tcpros.c:get_virtual_frame_num64 Unexecuted instantiation: packet-tds.c:get_virtual_frame_num64 Unexecuted instantiation: packet-teamspeak2.c:get_virtual_frame_num64 Unexecuted instantiation: packet-tftp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-thrift.c:get_virtual_frame_num64 Unexecuted instantiation: packet-tibia.c:get_virtual_frame_num64 Unexecuted instantiation: packet-tipc.c:get_virtual_frame_num64 Unexecuted instantiation: packet-tls.c:get_virtual_frame_num64 Unexecuted instantiation: packet-tns.c:get_virtual_frame_num64 Unexecuted instantiation: packet-tplink-smarthome.c:get_virtual_frame_num64 Unexecuted instantiation: packet-tpncp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-turnchannel.c:get_virtual_frame_num64 Unexecuted instantiation: packet-twamp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-uavcan-can.c:get_virtual_frame_num64 Unexecuted instantiation: packet-uci.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ucp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-udpcp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-uma.c:get_virtual_frame_num64 Unexecuted instantiation: packet-usb-audio.c:get_virtual_frame_num64 Unexecuted instantiation: packet-usbip.c:get_virtual_frame_num64 Unexecuted instantiation: packet-usbll.c:get_virtual_frame_num64 Unexecuted instantiation: packet-vsomeip.c:get_virtual_frame_num64 Unexecuted instantiation: packet-wai.c:get_virtual_frame_num64 Unexecuted instantiation: packet-wassp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-websocket.c:get_virtual_frame_num64 Unexecuted instantiation: packet-whois.c:get_virtual_frame_num64 Unexecuted instantiation: packet-wifi-dpp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-winsrepl.c:get_virtual_frame_num64 Unexecuted instantiation: packet-wisun.c:get_virtual_frame_num64 Unexecuted instantiation: packet-wow.c:get_virtual_frame_num64 Unexecuted instantiation: packet-wtp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-x25.c:get_virtual_frame_num64 Unexecuted instantiation: packet-xcp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-xmcp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-xot.c:get_virtual_frame_num64 Unexecuted instantiation: packet-xti.c:get_virtual_frame_num64 Unexecuted instantiation: packet-yami.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ymsg.c:get_virtual_frame_num64 Unexecuted instantiation: packet-z3950.c:get_virtual_frame_num64 Unexecuted instantiation: packet-zabbix.c:get_virtual_frame_num64 Unexecuted instantiation: packet-zbee-aps.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ziop.c:get_virtual_frame_num64 Unexecuted instantiation: packet-zmtp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-zvt.c:get_virtual_frame_num64 Unexecuted instantiation: packet-c1222.c:get_virtual_frame_num64 Unexecuted instantiation: packet-cmp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-cosem.c:get_virtual_frame_num64 Unexecuted instantiation: packet-e1ap.c:get_virtual_frame_num64 Unexecuted instantiation: packet-idmp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ilp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-kerberos.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ldap.c:get_virtual_frame_num64 Unexecuted instantiation: packet-lte-rrc.c:get_virtual_frame_num64 Unexecuted instantiation: packet-nr-rrc.c:get_virtual_frame_num64 Unexecuted instantiation: packet-rtse.c:get_virtual_frame_num64 Unexecuted instantiation: packet-sabp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-t38.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ulp.c:get_virtual_frame_num64 Unexecuted instantiation: packet-ncp2222.c:get_virtual_frame_num64 |
1158 | | |
1159 | | /** |
1160 | | * How many additional bytes are still expected to complete this reassembly? |
1161 | | * |
1162 | | * @return How many additional bytes are expected to complete this reassembly. |
1163 | | * It may also be DESEGMENT_ONE_MORE_SEGMENT. |
1164 | | * 0 means this reassembly is completed. |
1165 | | */ |
1166 | | WS_DLL_PUBLIC int |
1167 | | additional_bytes_expected_to_complete_reassembly(streaming_reassembly_info_t* reassembly_info); |
1168 | | |
1169 | | /* ========================================================================= */ |
1170 | | |
1171 | | #endif |