Coverage Report

Created: 2025-02-15 06:25

/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