2005-10-03 18:34:21 +00:00
|
|
|
/* stream.c
|
|
|
|
*
|
|
|
|
* Definititions for handling circuit-switched protocols
|
|
|
|
* which are handled as streams, and don't have lengths
|
|
|
|
* and IDs such as are required for reassemble.h
|
|
|
|
*
|
2006-05-21 05:12:17 +00:00
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
2005-10-03 18:34:21 +00:00
|
|
|
* Copyright 1998 Gerald Combs
|
|
|
|
*
|
2018-02-08 16:59:17 +00:00
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
2005-10-03 18:34:21 +00:00
|
|
|
*/
|
|
|
|
|
2012-09-20 01:48:30 +00:00
|
|
|
#include "config.h"
|
2005-10-03 18:34:21 +00:00
|
|
|
|
|
|
|
#include <glib.h>
|
|
|
|
#include <epan/packet.h>
|
|
|
|
#include <epan/reassemble.h>
|
|
|
|
#include <epan/stream.h>
|
|
|
|
#include <epan/tvbuff.h>
|
2021-06-18 18:21:42 +00:00
|
|
|
#include <wsutil/ws_assert.h>
|
2005-10-03 18:34:21 +00:00
|
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
2013-07-17 21:12:24 +00:00
|
|
|
fragment_head *fd_head; /* the reassembled data, NULL
|
2009-10-12 21:36:54 +00:00
|
|
|
* until we add the last fragment */
|
|
|
|
guint32 pdu_number; /* Number of this PDU within the stream */
|
2005-10-03 18:34:21 +00:00
|
|
|
|
|
|
|
/* id of this pdu (globally unique) */
|
|
|
|
guint32 id;
|
|
|
|
} stream_pdu_t;
|
|
|
|
|
|
|
|
|
|
|
|
struct stream_pdu_fragment
|
|
|
|
{
|
2009-10-12 21:36:54 +00:00
|
|
|
guint32 len; /* the length of this fragment */
|
2005-10-03 18:34:21 +00:00
|
|
|
stream_pdu_t *pdu;
|
|
|
|
gboolean final_fragment;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct stream {
|
|
|
|
/* the key used to add this stream to stream_hash */
|
|
|
|
struct stream_key *key;
|
|
|
|
|
|
|
|
/* pdu to add the next fragment to, or NULL if we need to start
|
|
|
|
* a new PDU.
|
|
|
|
*/
|
|
|
|
stream_pdu_t *current_pdu;
|
|
|
|
|
|
|
|
/* number of PDUs added to this stream so far */
|
|
|
|
guint32 pdu_counter;
|
|
|
|
|
|
|
|
/* the framenumber and offset of the last fragment added;
|
|
|
|
used for sanity-checking */
|
|
|
|
guint32 lastfrag_framenum;
|
|
|
|
guint32 lastfrag_offset;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
|
|
|
* Stream hash
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* key */
|
|
|
|
typedef struct stream_key {
|
2021-06-12 15:25:37 +00:00
|
|
|
/* streams are attached to conversations */
|
|
|
|
const struct conversation *conv;
|
2005-10-03 18:34:21 +00:00
|
|
|
int p2p_dir;
|
|
|
|
} stream_key_t;
|
|
|
|
|
|
|
|
|
|
|
|
/* hash func */
|
2009-10-12 21:36:54 +00:00
|
|
|
static guint stream_hash_func(gconstpointer k)
|
2005-10-03 18:34:21 +00:00
|
|
|
{
|
|
|
|
const stream_key_t *key = (const stream_key_t *)k;
|
|
|
|
|
2021-06-12 15:25:37 +00:00
|
|
|
return (GPOINTER_TO_UINT(key->conv)) ^ key->p2p_dir;
|
2005-10-03 18:34:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* compare func */
|
2009-10-12 21:36:54 +00:00
|
|
|
static gboolean stream_compare_func(gconstpointer a,
|
|
|
|
gconstpointer b)
|
2005-10-03 18:34:21 +00:00
|
|
|
{
|
|
|
|
const stream_key_t *key1 = (const stream_key_t *)a;
|
|
|
|
const stream_key_t *key2 = (const stream_key_t *)b;
|
2021-06-12 15:25:37 +00:00
|
|
|
if( key1 -> p2p_dir != key2 -> p2p_dir)
|
2009-10-12 21:36:54 +00:00
|
|
|
return FALSE;
|
2009-09-06 18:25:23 +00:00
|
|
|
|
2021-06-12 15:25:37 +00:00
|
|
|
return (key1 -> conv == key2 -> conv );
|
2005-10-03 18:34:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* the hash table */
|
|
|
|
static GHashTable *stream_hash;
|
|
|
|
|
|
|
|
|
2009-09-06 18:25:23 +00:00
|
|
|
/* cleanup reset function, call from stream_cleanup() */
|
|
|
|
static void cleanup_stream_hash( void ) {
|
2009-10-12 21:36:54 +00:00
|
|
|
if( stream_hash != NULL ) {
|
|
|
|
g_hash_table_destroy( stream_hash );
|
|
|
|
stream_hash = NULL;
|
|
|
|
}
|
2009-09-06 18:25:23 +00:00
|
|
|
}
|
2005-10-03 18:34:21 +00:00
|
|
|
|
2009-09-06 18:25:23 +00:00
|
|
|
/* init function, call from stream_init() */
|
|
|
|
static void init_stream_hash( void ) {
|
2021-06-18 18:21:42 +00:00
|
|
|
ws_assert(stream_hash==NULL);
|
2005-10-03 22:17:32 +00:00
|
|
|
stream_hash = g_hash_table_new(stream_hash_func,
|
2009-10-12 21:36:54 +00:00
|
|
|
stream_compare_func);
|
2005-10-03 18:34:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* lookup function, returns null if not found */
|
2021-06-12 15:25:37 +00:00
|
|
|
static stream_t *stream_hash_lookup( const struct conversation *conv, int p2p_dir )
|
2005-10-03 18:34:21 +00:00
|
|
|
{
|
2005-11-11 04:35:22 +00:00
|
|
|
stream_key_t key;
|
2021-06-12 15:25:37 +00:00
|
|
|
key.conv = conv;
|
2005-11-11 04:35:22 +00:00
|
|
|
key.p2p_dir=p2p_dir;
|
2005-10-03 18:34:21 +00:00
|
|
|
return (stream_t *)g_hash_table_lookup(stream_hash, &key);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static stream_t *new_stream( stream_key_t *key )
|
|
|
|
{
|
|
|
|
stream_t *val;
|
2009-09-06 18:25:23 +00:00
|
|
|
|
2015-01-16 13:29:57 +00:00
|
|
|
val = wmem_new(wmem_file_scope(), stream_t);
|
2005-10-03 18:34:21 +00:00
|
|
|
val -> key = key;
|
|
|
|
val -> pdu_counter = 0;
|
|
|
|
val -> current_pdu = NULL;
|
|
|
|
val -> lastfrag_framenum = 0;
|
|
|
|
val -> lastfrag_offset = 0;
|
|
|
|
g_hash_table_insert(stream_hash, key, val);
|
|
|
|
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* insert function */
|
2021-06-12 15:25:37 +00:00
|
|
|
static stream_t *stream_hash_insert( const struct conversation *conv, int p2p_dir )
|
2005-10-03 18:34:21 +00:00
|
|
|
{
|
|
|
|
stream_key_t *key;
|
|
|
|
|
2015-01-16 13:29:57 +00:00
|
|
|
key = wmem_new(wmem_file_scope(), stream_key_t);
|
2021-06-12 15:25:37 +00:00
|
|
|
key->conv = conv;
|
2005-10-03 18:34:21 +00:00
|
|
|
key->p2p_dir = p2p_dir;
|
|
|
|
|
|
|
|
return new_stream(key);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
*
|
|
|
|
* PDU data
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* pdu counter, for generating unique pdu ids */
|
|
|
|
static guint32 pdu_counter;
|
|
|
|
|
2009-09-06 18:25:23 +00:00
|
|
|
static void stream_cleanup_pdu_data(void)
|
2005-10-03 18:34:21 +00:00
|
|
|
{
|
2009-09-06 18:25:23 +00:00
|
|
|
}
|
2005-10-03 18:34:21 +00:00
|
|
|
|
2009-09-06 18:25:23 +00:00
|
|
|
static void stream_init_pdu_data(void)
|
|
|
|
{
|
2005-10-03 18:34:21 +00:00
|
|
|
pdu_counter = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* new pdu in this stream */
|
|
|
|
static stream_pdu_t *stream_new_pdu(stream_t *stream)
|
|
|
|
{
|
|
|
|
stream_pdu_t *pdu;
|
2015-01-16 13:29:57 +00:00
|
|
|
pdu = wmem_new(wmem_file_scope(), stream_pdu_t);
|
2005-10-03 18:34:21 +00:00
|
|
|
pdu -> fd_head = NULL;
|
|
|
|
pdu -> pdu_number = stream -> pdu_counter++;
|
|
|
|
pdu -> id = pdu_counter++;
|
|
|
|
return pdu;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
|
|
|
* fragment hash
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* key */
|
|
|
|
typedef struct fragment_key {
|
|
|
|
const stream_t *stream;
|
|
|
|
guint32 framenum;
|
|
|
|
guint32 offset;
|
|
|
|
} fragment_key_t;
|
|
|
|
|
|
|
|
|
|
|
|
/* hash func */
|
2009-10-12 21:36:54 +00:00
|
|
|
static guint fragment_hash_func(gconstpointer k)
|
2005-10-03 18:34:21 +00:00
|
|
|
{
|
|
|
|
const fragment_key_t *key = (const fragment_key_t *)k;
|
2015-06-04 14:12:04 +00:00
|
|
|
return (GPOINTER_TO_UINT(key->stream)) + ((guint)key -> framenum) + ((guint)key->offset);
|
2005-10-03 18:34:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* compare func */
|
2009-10-12 21:36:54 +00:00
|
|
|
static gboolean fragment_compare_func(gconstpointer a,
|
|
|
|
gconstpointer b)
|
2005-10-03 18:34:21 +00:00
|
|
|
{
|
|
|
|
const fragment_key_t *key1 = (const fragment_key_t *)a;
|
|
|
|
const fragment_key_t *key2 = (const fragment_key_t *)b;
|
|
|
|
return (key1 -> stream == key2 -> stream &&
|
2009-10-12 21:36:54 +00:00
|
|
|
key1 -> framenum == key2 -> framenum &&
|
|
|
|
key1 -> offset == key2 -> offset );
|
2005-10-03 18:34:21 +00:00
|
|
|
}
|
2009-09-06 18:25:23 +00:00
|
|
|
|
2005-10-03 18:34:21 +00:00
|
|
|
/* the hash table */
|
|
|
|
static GHashTable *fragment_hash;
|
|
|
|
|
|
|
|
|
2009-09-06 18:25:23 +00:00
|
|
|
/* cleanup function, call from stream_cleanup() */
|
|
|
|
static void cleanup_fragment_hash( void ) {
|
2009-10-12 21:36:54 +00:00
|
|
|
if( fragment_hash != NULL ) {
|
|
|
|
g_hash_table_destroy( fragment_hash );
|
|
|
|
fragment_hash = NULL;
|
|
|
|
}
|
2009-09-06 18:25:23 +00:00
|
|
|
}
|
2005-10-03 18:34:21 +00:00
|
|
|
|
2009-09-06 18:25:23 +00:00
|
|
|
/* init function, call from stream_init() */
|
|
|
|
static void init_fragment_hash( void ) {
|
2021-06-18 18:21:42 +00:00
|
|
|
ws_assert(fragment_hash==NULL);
|
2005-10-03 18:34:21 +00:00
|
|
|
fragment_hash = g_hash_table_new(fragment_hash_func,
|
2009-10-12 21:36:54 +00:00
|
|
|
fragment_compare_func);
|
2005-10-03 18:34:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* lookup function, returns null if not found */
|
|
|
|
static stream_pdu_fragment_t *fragment_hash_lookup( const stream_t *stream, guint32 framenum, guint32 offset )
|
|
|
|
{
|
2005-11-11 04:35:22 +00:00
|
|
|
fragment_key_t key;
|
|
|
|
stream_pdu_fragment_t *val;
|
|
|
|
|
|
|
|
key.stream = stream;
|
|
|
|
key.framenum = framenum;
|
|
|
|
key.offset = offset;
|
2013-03-19 04:54:30 +00:00
|
|
|
val = (stream_pdu_fragment_t *)g_hash_table_lookup(fragment_hash, &key);
|
2005-10-03 18:34:21 +00:00
|
|
|
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* insert function */
|
|
|
|
static stream_pdu_fragment_t *fragment_hash_insert( const stream_t *stream, guint32 framenum, guint32 offset,
|
2009-10-12 21:36:54 +00:00
|
|
|
guint32 length)
|
2005-10-03 18:34:21 +00:00
|
|
|
{
|
|
|
|
fragment_key_t *key;
|
|
|
|
stream_pdu_fragment_t *val;
|
|
|
|
|
2015-01-16 13:29:57 +00:00
|
|
|
key = wmem_new(wmem_file_scope(), fragment_key_t);
|
2005-10-03 18:34:21 +00:00
|
|
|
key->stream = stream;
|
|
|
|
key->framenum = framenum;
|
|
|
|
key->offset = offset;
|
|
|
|
|
2015-01-16 13:29:57 +00:00
|
|
|
val = wmem_new(wmem_file_scope(), stream_pdu_fragment_t);
|
2005-10-03 18:34:21 +00:00
|
|
|
val->len = length;
|
|
|
|
val->pdu = NULL;
|
|
|
|
val->final_fragment = FALSE;
|
|
|
|
|
|
|
|
g_hash_table_insert(fragment_hash, key, val);
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
2013-03-22 23:59:54 +00:00
|
|
|
/* reassembly table */
|
|
|
|
static reassembly_table stream_reassembly_table;
|
2005-10-03 18:34:21 +00:00
|
|
|
|
|
|
|
/* Initialise a new stream. Call this when you first identify a distinct
|
|
|
|
* stream. */
|
2021-06-12 15:25:37 +00:00
|
|
|
stream_t *stream_new ( const struct conversation *conv, int p2p_dir )
|
2005-10-03 18:34:21 +00:00
|
|
|
{
|
|
|
|
stream_t * stream;
|
|
|
|
|
|
|
|
/* we don't want to replace the previous data if we get called twice on the
|
|
|
|
same conversation, so do a lookup first */
|
2021-06-12 15:25:37 +00:00
|
|
|
stream = stream_hash_lookup(conv, p2p_dir);
|
2007-02-21 06:25:13 +00:00
|
|
|
DISSECTOR_ASSERT( stream == NULL );
|
2005-10-03 18:34:21 +00:00
|
|
|
|
2021-06-12 15:25:37 +00:00
|
|
|
stream = stream_hash_insert(conv, p2p_dir);
|
2005-10-03 18:34:21 +00:00
|
|
|
return stream;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* retrieve a previously-created stream.
|
|
|
|
*
|
|
|
|
* Returns null if no matching stream was found.
|
|
|
|
*/
|
2021-06-12 15:25:37 +00:00
|
|
|
stream_t *find_stream ( const struct conversation *conv, int p2p_dir )
|
2005-10-03 18:34:21 +00:00
|
|
|
{
|
2021-06-12 15:25:37 +00:00
|
|
|
return stream_hash_lookup(conv,p2p_dir);
|
2005-10-03 18:34:21 +00:00
|
|
|
}
|
|
|
|
|
2009-09-06 18:25:23 +00:00
|
|
|
/* cleanup the stream routines */
|
2009-10-12 21:36:54 +00:00
|
|
|
/* Note: stream_cleanup must only be called when seasonal memory
|
2014-02-25 20:42:35 +00:00
|
|
|
* is also freed since the hash tables countain pointers to
|
2015-01-16 13:29:57 +00:00
|
|
|
* wmem_file_scoped memory.
|
2009-10-12 21:36:54 +00:00
|
|
|
*/
|
2009-09-06 18:25:23 +00:00
|
|
|
void stream_cleanup( void )
|
|
|
|
{
|
|
|
|
cleanup_stream_hash();
|
|
|
|
cleanup_fragment_hash();
|
|
|
|
stream_cleanup_pdu_data();
|
2017-02-02 13:41:46 +00:00
|
|
|
reassembly_table_destroy(&stream_reassembly_table);
|
2009-09-06 18:25:23 +00:00
|
|
|
}
|
2005-10-03 18:34:21 +00:00
|
|
|
|
|
|
|
/* initialise the stream routines */
|
|
|
|
void stream_init( void )
|
|
|
|
{
|
|
|
|
init_stream_hash();
|
|
|
|
init_fragment_hash();
|
|
|
|
stream_init_pdu_data();
|
|
|
|
|
2013-03-22 23:59:54 +00:00
|
|
|
reassembly_table_init(&stream_reassembly_table,
|
|
|
|
&addresses_reassembly_table_functions);
|
2005-10-03 18:34:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
stream_pdu_fragment_t *stream_find_frag( stream_t *stream, guint32 framenum, guint32 offset )
|
|
|
|
{
|
|
|
|
return fragment_hash_lookup( stream, framenum, offset );
|
|
|
|
}
|
2009-09-06 18:25:23 +00:00
|
|
|
|
2005-10-03 18:34:21 +00:00
|
|
|
stream_pdu_fragment_t *stream_add_frag( stream_t *stream, guint32 framenum, guint32 offset,
|
2009-10-12 21:36:54 +00:00
|
|
|
tvbuff_t *tvb, packet_info *pinfo, gboolean more_frags )
|
2005-10-03 18:34:21 +00:00
|
|
|
{
|
2013-07-17 21:12:24 +00:00
|
|
|
fragment_head *fd_head;
|
2005-10-03 18:34:21 +00:00
|
|
|
stream_pdu_t *pdu;
|
|
|
|
stream_pdu_fragment_t *frag_data;
|
|
|
|
|
2007-02-21 06:25:13 +00:00
|
|
|
DISSECTOR_ASSERT(stream);
|
2005-10-03 18:34:21 +00:00
|
|
|
|
|
|
|
/* check that this fragment is at the end of the stream */
|
2007-02-21 06:25:13 +00:00
|
|
|
DISSECTOR_ASSERT( framenum > stream->lastfrag_framenum ||
|
2009-10-12 21:36:54 +00:00
|
|
|
(framenum == stream->lastfrag_framenum && offset > stream->lastfrag_offset));
|
2005-10-03 18:34:21 +00:00
|
|
|
|
|
|
|
|
|
|
|
pdu = stream->current_pdu;
|
|
|
|
if( pdu == NULL ) {
|
2009-10-12 21:36:54 +00:00
|
|
|
/* start a new pdu */
|
|
|
|
pdu = stream->current_pdu = stream_new_pdu(stream);
|
2005-10-03 18:34:21 +00:00
|
|
|
}
|
2009-09-06 18:25:23 +00:00
|
|
|
|
2005-10-03 18:34:21 +00:00
|
|
|
/* add it to the reassembly tables */
|
2013-03-22 23:59:54 +00:00
|
|
|
fd_head = fragment_add_seq_next(&stream_reassembly_table,
|
|
|
|
tvb, 0, pinfo, pdu->id, NULL,
|
2009-10-12 21:36:54 +00:00
|
|
|
tvb_reported_length(tvb), more_frags);
|
2005-10-03 18:34:21 +00:00
|
|
|
/* add it to our hash */
|
|
|
|
frag_data = fragment_hash_insert( stream, framenum, offset, tvb_reported_length(tvb));
|
|
|
|
frag_data -> pdu = pdu;
|
|
|
|
|
|
|
|
if( fd_head != NULL ) {
|
2009-10-12 21:36:54 +00:00
|
|
|
/* if this was the last fragment, update the pdu data.
|
|
|
|
*/
|
|
|
|
pdu -> fd_head = fd_head;
|
2009-09-06 18:25:23 +00:00
|
|
|
|
2009-10-12 21:36:54 +00:00
|
|
|
/* start a new pdu next time */
|
|
|
|
stream->current_pdu = NULL;
|
2005-10-03 18:34:21 +00:00
|
|
|
|
|
|
|
frag_data -> final_fragment = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* stashing the framenum and offset permit future sanity checks */
|
|
|
|
stream -> lastfrag_framenum = framenum;
|
|
|
|
stream -> lastfrag_offset = offset;
|
|
|
|
|
|
|
|
return frag_data;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
tvbuff_t *stream_process_reassembled(
|
|
|
|
tvbuff_t *tvb, int offset, packet_info *pinfo,
|
2008-06-25 09:12:35 +00:00
|
|
|
const char *name, const stream_pdu_fragment_t *frag,
|
2005-10-03 18:34:21 +00:00
|
|
|
const struct _fragment_items *fit,
|
|
|
|
gboolean *update_col_infop, proto_tree *tree)
|
|
|
|
{
|
|
|
|
stream_pdu_t *pdu;
|
2007-02-21 06:25:13 +00:00
|
|
|
DISSECTOR_ASSERT(frag);
|
2005-10-03 18:34:21 +00:00
|
|
|
pdu = frag->pdu;
|
|
|
|
|
|
|
|
/* we handle non-terminal fragments ourselves, because
|
|
|
|
reassemble.c messes them up */
|
|
|
|
if(!frag->final_fragment) {
|
|
|
|
if (pdu->fd_head != NULL && fit->hf_reassembled_in != NULL) {
|
|
|
|
proto_tree_add_uint(tree,
|
|
|
|
*(fit->hf_reassembled_in), tvb,
|
|
|
|
0, 0, pdu->fd_head->reassembled_in);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return process_reassembled_data(tvb, offset, pinfo, name, pdu->fd_head,
|
|
|
|
fit, update_col_infop, tree);
|
|
|
|
}
|
2009-09-06 18:25:23 +00:00
|
|
|
|
2005-10-03 18:34:21 +00:00
|
|
|
guint32 stream_get_frag_length( const stream_pdu_fragment_t *frag)
|
|
|
|
{
|
2007-02-21 06:25:13 +00:00
|
|
|
DISSECTOR_ASSERT( frag );
|
2005-10-03 18:34:21 +00:00
|
|
|
return frag->len;
|
|
|
|
}
|
|
|
|
|
2013-07-17 21:12:24 +00:00
|
|
|
fragment_head *stream_get_frag_data( const stream_pdu_fragment_t *frag)
|
2005-10-03 18:34:21 +00:00
|
|
|
{
|
2007-02-21 06:25:13 +00:00
|
|
|
DISSECTOR_ASSERT( frag );
|
2005-10-03 18:34:21 +00:00
|
|
|
return frag->pdu->fd_head;
|
|
|
|
}
|
|
|
|
|
|
|
|
guint32 stream_get_pdu_no( const stream_pdu_fragment_t *frag)
|
|
|
|
{
|
2007-02-21 06:25:13 +00:00
|
|
|
DISSECTOR_ASSERT( frag );
|
2005-10-03 18:34:21 +00:00
|
|
|
return frag->pdu->pdu_number;
|
|
|
|
}
|
2014-10-10 14:41:10 +00:00
|
|
|
|
|
|
|
/*
|
2019-07-26 18:43:17 +00:00
|
|
|
* Editor modelines - https://www.wireshark.org/tools/modelines.html
|
2014-10-10 14:41:10 +00:00
|
|
|
*
|
|
|
|
* Local variables:
|
|
|
|
* c-basic-offset: 4
|
|
|
|
* tab-width: 8
|
|
|
|
* indent-tabs-mode: nil
|
|
|
|
* End:
|
|
|
|
*
|
|
|
|
* vi: set shiftwidth=4 tabstop=8 expandtab:
|
|
|
|
* :indentSize=4:tabSize=8:noTabs=true:
|
|
|
|
*/
|