1999-07-07 22:52:57 +00:00
/* proto.c
* Routines for protocol tree
*
2006-05-21 05:12:17 +00:00
* Wireshark - Network traffic analyzer
* By Gerald Combs < gerald @ wireshark . org >
1999-07-07 22:52:57 +00:00
* Copyright 1998 Gerald Combs
2002-08-28 20:41:00 +00:00
*
1999-07-07 22:52:57 +00:00
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
2002-08-28 20:41:00 +00:00
*
1999-07-07 22:52:57 +00:00
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
2002-08-28 20:41:00 +00:00
*
1999-07-07 22:52:57 +00:00
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
2007-01-10 07:47:00 +00:00
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
1999-07-07 22:52:57 +00:00
*/
2012-09-20 01:48:30 +00:00
# include "config.h"
1999-07-07 22:52:57 +00:00
# include <stdio.h>
# include <string.h>
# include <glib.h>
2003-07-04 03:41:00 +00:00
# include <float.h>
2014-04-12 04:32:20 +00:00
# include <errno.h>
2013-11-08 22:01:12 +00:00
# include <wsutil/bits_ctz.h>
2013-11-09 04:47:08 +00:00
# include <wsutil/bits_count_ones.h>
2013-12-17 21:36:33 +00:00
# include <wsutil/sign_ext.h>
1999-07-07 22:52:57 +00:00
2013-11-10 13:14:09 +00:00
# include <ftypes/ftypes-int.h>
1999-07-07 22:52:57 +00:00
# include "packet.h"
2013-11-10 16:04:15 +00:00
# include "exceptions.h"
2005-10-22 05:43:09 +00:00
# include "ptvcursor.h"
2000-11-13 07:19:37 +00:00
# include "strutil.h"
2004-08-06 19:57:49 +00:00
# include "addr_resolv.h"
2015-02-08 03:15:55 +00:00
# include "address_types.h"
2007-08-25 01:14:24 +00:00
# include "oids.h"
2000-08-11 13:37:21 +00:00
# include "proto.h"
Rename "proto_alloc_dfilter_string()" to
"proto_construct_dfilter_string()", to more accurately reflect what it
does.
Give it, and "proto_can_match_selected()", an "epan_dissect_t *"
argument, which replaces the raw data pointer argument to
"proto_construct_dfilter_string()".
For fields that don't have a type we can directly filter on, we don't
support filtering on the field as raw data if:
the "epan_dissect_t *" argument is null;
the data source tvbuff for the field isn't the tvbuff for the
"epan_dissect_t" in question (i.e., it's in the result of a
reassembly, and "frame[N:M]" can't get at it).
Trim the length the raw data in the case of such a field to the length
of the tvbuff for the "epan_dissect_t" in question, so we don't go past
it. Fetch the raw data bytes to match from that tvbuff.
Have "proto_construct_dfilter_string()" return a null pointer if it
can't construct the filter string, and have "protocolinfo_packet()" in
the tap-protocolinfo tap ignore a field if
"proto_construct_dfilter_string()" can't construct a filter string for
it - and have it pass NULL as the "epan_dissect_t *", for now. If
somebody decides it makes sense to dump out a "frame[N:M] =" value for
non-registered fields, it can be changed to pass "edt".
svn path=/trunk/; revision=7635
2003-05-03 00:48:37 +00:00
# include "epan_dissect.h"
2003-12-02 10:23:18 +00:00
# include "tvbuff.h"
2013-10-12 17:32:41 +00:00
# include "wmem/wmem.h"
2007-11-19 21:27:01 +00:00
# include "charsets.h"
2007-11-28 10:18:16 +00:00
# include "asm_utils.h"
2008-02-13 05:05:33 +00:00
# include "column-utils.h"
2013-11-09 11:26:41 +00:00
# include "to_str-int.h"
2010-01-25 18:26:47 +00:00
# include "to_str.h"
2013-12-23 15:18:48 +00:00
# include "osi-utils.h"
2012-08-10 23:05:04 +00:00
# include "expert.h"
Move show_exception() and show_reported_bounds_error() to
epan/show_exception.c, as it's used outside
epan/dissectors/packet-frame.c. Update their callers to include
<epan/show_exception.h> to get their declaration.
Add a CATCH_NONFATAL_ERRORS macro that catches all exceptions that, if
there's more stuff in the packet to dissect after the dissector call
that threw the exception, doesn't mean you shouldn't go ahead and
dissect that stuff. Use it in all those cases, including ones where
BoundsError was inappropriately being caught (you want those passed up
to the top level, so that the packet is reported as having been cut
short in the capture process).
Add a CATCH_BOUNDS_ERRORS macro that catches all exceptions that
correspond to running past the end of the data for a tvbuff; use it
rather than explicitly catching those exceptions individually, and
rather than just catching all exceptions (the only place that
DissectorError should be caught, for example, is at the top level, so
dissector bugs show up in the protocol tree).
Don't catch and then immediately rethrow exceptions without doing
anything else; just let the exceptions go up to the final catcher.
Use show_exception() to report non-fatal errors, rather than doing it
yourself.
If a dissector is called from Lua, catch all non-fatal errors and use
show_exception() to report them rather than catching only
ReportedBoundsError and adding a proto_malformed item.
Don't catch exceptions when constructing a trailer tvbuff in
packet-ieee8023.c - just construct it after the payload has been
dissected, and let whatever exceptions that throws be handled at the top
level.
Avoid some TRY/CATCH/ENDTRY cases by using checks such as
tvb_bytes_exist() before even looking in the tvbuff.
svn path=/trunk/; revision=47924
2013-02-27 22:43:54 +00:00
# include "show_exception.h"
2000-08-10 19:41:45 +00:00
2013-12-02 08:30:29 +00:00
# include <wsutil/plugins.h>
2016-04-11 22:38:14 +00:00
/* Ptvcursor limits */
2007-03-30 00:21:39 +00:00
# define SUBTREE_ONCE_ALLOCATION_NUMBER 8
# define SUBTREE_MAX_LEVELS 256
2016-04-11 22:38:14 +00:00
/* Throw an exception if our tree exceeds these. */
/* XXX - These should probably be preferences */
2009-09-08 22:56:55 +00:00
# define MAX_TREE_ITEMS (1 * 1000 * 1000)
2016-04-11 22:38:14 +00:00
# define MAX_TREE_LEVELS (5 * 100)
2007-03-30 00:21:39 +00:00
typedef struct __subtree_lvl {
2012-03-15 14:15:48 +00:00
gint cursor_offset ;
proto_item * it ;
proto_tree * tree ;
2012-03-14 17:11:39 +00:00
} subtree_lvl ;
2007-03-30 00:21:39 +00:00
2005-10-22 05:43:09 +00:00
struct ptvcursor {
2012-03-14 17:11:39 +00:00
subtree_lvl * pushed_tree ;
guint8 pushed_tree_index ;
guint8 pushed_tree_max ;
proto_tree * tree ;
tvbuff_t * tvb ;
gint offset ;
2005-10-22 05:43:09 +00:00
} ;
1999-07-07 22:52:57 +00:00
# define cVALS(x) (const value_string*)(x)
2016-01-09 02:25:26 +00:00
/** See inlined comments.
@ param tree the tree to append this item to
@ param free_block a code block to call to free resources if this returns
@ return NULL if ' tree ' is null */
# define CHECK_FOR_NULL_TREE_AND_FREE(tree, free_block) \
if ( ! tree ) { \
free_block ; \
return NULL ; \
}
/** See inlined comments.
@ param tree the tree to append this item to
@ param free_block a code block to call to free resources if this returns
@ return NULL if ' tree ' is null */
# define CHECK_FOR_NULL_TREE(tree) \
CHECK_FOR_NULL_TREE_AND_FREE ( tree , ( ( void ) 0 ) )
2009-08-17 11:13:36 +00:00
/** See inlined comments.
@ param tree the tree to append this item to
@ param hfindex field index
@ param hfinfo header_field
2014-04-13 03:20:15 +00:00
@ param free_block a code block to call to free resources if this returns
2009-08-17 11:13:36 +00:00
@ return the header field matching ' hfinfo ' */
2014-09-12 21:18:49 +00:00
# define TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfindex, hfinfo, free_block) \
2014-09-16 15:25:17 +00:00
/* If this item is not referenced we don't have to do much work \
2012-08-08 03:02:27 +00:00
at all but we should still return a node so that field items \
below this node ( think proto_item_add_subtree ( ) ) will still \
have somewhere to attach to or else filtering will not work \
( they would be ignored since tree would be NULL ) . \
2014-09-16 15:25:17 +00:00
DON ' T try to fake a node where PTREE_FINFO ( tree ) is NULL \
2010-04-10 19:19:13 +00:00
since dissectors that want to do proto_item_set_len ( ) or \
other operations that dereference this would crash . \
2009-09-23 16:27:37 +00:00
We fake FT_PROTOCOL unless some clients have requested us \
2014-09-12 21:21:53 +00:00
not to do so . \
2005-04-11 08:43:51 +00:00
*/ \
2009-09-08 22:56:55 +00:00
PTREE_DATA ( tree ) - > count + + ; \
if ( PTREE_DATA ( tree ) - > count > MAX_TREE_ITEMS ) { \
2014-04-13 03:20:15 +00:00
free_block ; \
2013-06-30 16:16:13 +00:00
if ( getenv ( " WIRESHARK_ABORT_ON_TOO_MANY_ITEMS " ) ! = NULL ) \
2012-12-02 03:34:06 +00:00
g_error ( " More than %d items in the tree -- possible infinite loop " , MAX_TREE_ITEMS ) ; \
2009-09-08 22:56:55 +00:00
/* Let the exception handler add items to the tree */ \
PTREE_DATA ( tree ) - > count = 0 ; \
THROW_MESSAGE ( DissectorError , \
2015-01-18 17:15:26 +00:00
wmem_strdup_printf ( wmem_packet_scope ( ) , " More than %d items in the tree -- possible infinite loop " , MAX_TREE_ITEMS ) ) ; \
2009-09-08 22:56:55 +00:00
} \
PROTO_REGISTRAR_GET_NTH ( hfindex , hfinfo ) ; \
2012-03-14 17:11:39 +00:00
if ( ! ( PTREE_DATA ( tree ) - > visible ) ) { \
2014-09-12 21:18:49 +00:00
if ( PTREE_FINFO ( tree ) ) { \
2012-03-14 17:11:39 +00:00
if ( ( hfinfo - > ref_type ! = HF_REF_TYPE_DIRECT ) \
& & ( hfinfo - > type ! = FT_PROTOCOL | | \
PTREE_DATA ( tree ) - > fake_protocols ) ) { \
2014-04-13 03:20:15 +00:00
free_block ; \
2005-04-11 08:43:51 +00:00
/* just return tree back to the caller */ \
return tree ; \
} \
2010-04-10 19:19:13 +00:00
} \
2005-04-11 08:43:51 +00:00
}
2014-04-13 03:20:15 +00:00
/** See inlined comments.
@ param tree the tree to append this item to
@ param hfindex field index
@ param hfinfo header_field
@ return the header field matching ' hfinfo ' */
2014-09-12 21:18:49 +00:00
# define TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo) \
TRY_TO_FAKE_THIS_ITEM_OR_FREE ( tree , hfindex , hfinfo , ( ( void ) 0 ) )
2014-04-13 03:20:15 +00:00
2009-09-06 07:33:07 +00:00
/** See inlined comments.
@ param pi the created protocol item we ' re about to return */
2014-09-12 21:21:53 +00:00
# define TRY_TO_FAKE_THIS_REPR(pi) \
2012-08-08 03:02:27 +00:00
g_assert ( pi ) ; \
2013-07-02 20:51:58 +00:00
if ( ! ( PTREE_DATA ( pi ) - > visible ) ) { \
2009-09-06 07:33:07 +00:00
/* If the tree (GUI) isn't visible it's pointless for us to generate the protocol \
* items string representation */ \
return pi ; \
}
2014-09-12 21:21:53 +00:00
/* Same as above but returning void */
# define TRY_TO_FAKE_THIS_REPR_VOID(pi) \
if ( ! pi ) \
return ; \
if ( ! ( PTREE_DATA ( pi ) - > visible ) ) { \
/* If the tree (GUI) isn't visible it's pointless for us to generate the protocol \
* items string representation */ \
return ; \
}
2009-09-06 07:33:07 +00:00
2013-06-27 22:26:34 +00:00
static const char * hf_try_val_to_str ( guint32 value , const header_field_info * hfinfo ) ;
2014-12-17 20:19:20 +00:00
static const char * hf_try_val64_to_str ( guint64 value , const header_field_info * hfinfo ) ;
2016-01-12 11:20:46 +00:00
static int hfinfo_container_bitwidth ( const header_field_info * hfinfo ) ;
2013-06-27 22:26:34 +00:00
2014-03-01 21:08:42 +00:00
static void label_mark_truncated ( char * label_str , gsize name_pos ) ;
# define LABEL_MARK_TRUNCATED_START(label_str) label_mark_truncated(label_str, 0)
1999-10-12 06:21:15 +00:00
static void fill_label_boolean ( field_info * fi , gchar * label_str ) ;
2013-08-26 16:23:55 +00:00
static void fill_label_bitfield ( field_info * fi , gchar * label_str , gboolean is_signed ) ;
2014-12-17 20:19:20 +00:00
static void fill_label_bitfield64 ( field_info * fi , gchar * label_str , gboolean is_signed ) ;
2013-06-28 22:47:50 +00:00
static void fill_label_number ( field_info * fi , gchar * label_str , gboolean is_signed ) ;
2013-07-01 15:24:42 +00:00
static void fill_label_number64 ( field_info * fi , gchar * label_str , gboolean is_signed ) ;
1999-10-12 06:21:15 +00:00
2013-07-13 09:14:25 +00:00
static const char * hfinfo_number_value_format_display ( const header_field_info * hfinfo , int display , char buf [ 32 ] , guint32 value ) ;
2015-02-23 15:50:18 +00:00
static const char * hfinfo_number_value_format_display64 ( const header_field_info * hfinfo , int display , char buf [ 48 ] , guint64 value ) ;
2013-06-28 19:54:04 +00:00
static const char * hfinfo_number_vals_format ( const header_field_info * hfinfo , char buf [ 32 ] , guint32 value ) ;
2015-02-23 15:50:18 +00:00
static const char * hfinfo_number_vals_format64 ( const header_field_info * hfinfo , char buf [ 48 ] , guint64 value ) ;
2013-06-28 21:46:41 +00:00
static const char * hfinfo_number_value_format ( const header_field_info * hfinfo , char buf [ 32 ] , guint32 value ) ;
2015-02-23 15:50:18 +00:00
static const char * hfinfo_number_value_format64 ( const header_field_info * hfinfo , char buf [ 48 ] , guint64 value ) ;
2013-07-01 09:46:50 +00:00
static const char * hfinfo_numeric_value_format ( const header_field_info * hfinfo , char buf [ 32 ] , guint32 value ) ;
2015-02-23 15:50:18 +00:00
static const char * hfinfo_numeric_value_format64 ( const header_field_info * hfinfo , char buf [ 48 ] , guint64 value ) ;
2013-06-28 19:34:48 +00:00
2010-04-26 20:48:13 +00:00
static proto_item *
2000-03-12 04:48:32 +00:00
proto_tree_add_node ( proto_tree * tree , field_info * fi ) ;
2013-06-18 20:52:31 +00:00
static void
2013-07-11 15:03:43 +00:00
get_hfi_length ( header_field_info * hfinfo , tvbuff_t * tvb , const gint start , gint * length ,
gint * item_length ) ;
2005-10-22 05:43:09 +00:00
2016-01-09 02:25:26 +00:00
static gint
get_full_length ( header_field_info * hfinfo , tvbuff_t * tvb , const gint start ,
gint length , guint item_length , const gint encoding ) ;
2005-10-22 05:43:09 +00:00
static field_info *
new_field_info ( proto_tree * tree , header_field_info * hfinfo , tvbuff_t * tvb ,
2010-04-26 20:48:13 +00:00
const gint start , const gint item_length ) ;
2005-10-22 05:43:09 +00:00
2000-03-12 04:48:32 +00:00
static proto_item *
2013-06-18 20:52:31 +00:00
proto_tree_add_pi ( proto_tree * tree , header_field_info * hfinfo , tvbuff_t * tvb ,
2013-08-22 21:20:50 +00:00
gint start , gint * length ) ;
2002-02-18 22:26:29 +00:00
2006-02-09 04:18:23 +00:00
static void
proto_tree_set_representation_value ( proto_item * pi , const char * format , va_list ap ) ;
2000-05-31 05:09:07 +00:00
static void
proto_tree_set_representation ( proto_item * pi , const char * format , va_list ap ) ;
2000-03-12 04:48:32 +00:00
2001-02-01 21:48:02 +00:00
static void
proto_tree_set_protocol_tvb ( field_info * fi , tvbuff_t * tvb ) ;
2000-03-12 04:48:32 +00:00
static void
2000-03-14 06:03:26 +00:00
proto_tree_set_bytes ( field_info * fi , const guint8 * start_ptr , gint length ) ;
2000-03-12 04:48:32 +00:00
static void
2000-05-31 05:09:07 +00:00
proto_tree_set_bytes_tvb ( field_info * fi , tvbuff_t * tvb , gint offset , gint length ) ;
static void
2014-04-13 03:20:15 +00:00
proto_tree_set_bytes_gbytearray ( field_info * fi , const GByteArray * value ) ;
static void
2014-01-15 01:05:03 +00:00
proto_tree_set_time ( field_info * fi , const nstime_t * value_ptr ) ;
2000-03-12 04:48:32 +00:00
static void
2013-10-29 21:18:22 +00:00
proto_tree_set_string ( field_info * fi , const char * value ) ;
2000-03-12 04:48:32 +00:00
static void
2012-08-02 16:54:43 +00:00
proto_tree_set_ax25 ( field_info * fi , const guint8 * value ) ;
static void
proto_tree_set_ax25_tvb ( field_info * fi , tvbuff_t * tvb , gint start ) ;
static void
2013-07-28 00:07:49 +00:00
proto_tree_set_vines ( field_info * fi , const guint8 * value ) ;
static void
proto_tree_set_vines_tvb ( field_info * fi , tvbuff_t * tvb , gint start ) ;
static void
2000-05-31 05:09:07 +00:00
proto_tree_set_ether ( field_info * fi , const guint8 * value ) ;
static void
proto_tree_set_ether_tvb ( field_info * fi , tvbuff_t * tvb , gint start ) ;
2000-03-12 04:48:32 +00:00
static void
proto_tree_set_ipxnet ( field_info * fi , guint32 value ) ;
static void
proto_tree_set_ipv4 ( field_info * fi , guint32 value ) ;
static void
2000-05-31 05:09:07 +00:00
proto_tree_set_ipv6 ( field_info * fi , const guint8 * value_ptr ) ;
static void
2009-08-28 09:38:34 +00:00
proto_tree_set_ipv6_tvb ( field_info * fi , tvbuff_t * tvb , gint start , gint length ) ;
2000-03-12 04:48:32 +00:00
static void
2014-12-24 05:06:35 +00:00
proto_tree_set_fcwwn_tvb ( field_info * fi , tvbuff_t * tvb , gint start , gint length ) ;
static void
2006-03-10 11:58:22 +00:00
proto_tree_set_guid ( field_info * fi , const e_guid_t * value_ptr ) ;
2005-07-04 13:04:53 +00:00
static void
2010-05-24 06:06:17 +00:00
proto_tree_set_guid_tvb ( field_info * fi , tvbuff_t * tvb , gint start , const guint encoding ) ;
2005-07-04 13:04:53 +00:00
static void
2005-12-02 13:16:58 +00:00
proto_tree_set_oid ( field_info * fi , const guint8 * value_ptr , gint length ) ;
static void
proto_tree_set_oid_tvb ( field_info * fi , tvbuff_t * tvb , gint start , gint length ) ;
static void
2013-12-23 15:18:48 +00:00
proto_tree_set_system_id ( field_info * fi , const guint8 * value_ptr , gint length ) ;
static void
proto_tree_set_system_id_tvb ( field_info * fi , tvbuff_t * tvb , gint start , gint length ) ;
static void
2014-09-17 16:39:22 +00:00
proto_tree_set_boolean ( field_info * fi , guint64 value ) ;
2000-03-12 04:48:32 +00:00
static void
2002-08-24 19:45:28 +00:00
proto_tree_set_float ( field_info * fi , float value ) ;
static void
2000-03-12 04:48:32 +00:00
proto_tree_set_double ( field_info * fi , double value ) ;
static void
proto_tree_set_uint ( field_info * fi , guint32 value ) ;
2000-04-25 21:43:50 +00:00
static void
proto_tree_set_int ( field_info * fi , gint32 value ) ;
2004-08-22 00:31:58 +00:00
static void
proto_tree_set_uint64 ( field_info * fi , guint64 value ) ;
static void
2014-12-17 20:19:20 +00:00
proto_tree_set_int64 ( field_info * fi , gint64 value ) ;
static void
2011-05-08 10:23:53 +00:00
proto_tree_set_eui64 ( field_info * fi , const guint64 value ) ;
static void
proto_tree_set_eui64_tvb ( field_info * fi , tvbuff_t * tvb , gint start , const guint encoding ) ;
2013-10-03 01:54:02 +00:00
/* Handle type length mismatch (now filterable) expert info */
static int proto_type_length_mismatch = - 1 ;
static expert_field ei_type_length_mismatch_error = EI_INIT ;
static expert_field ei_type_length_mismatch_warn = EI_INIT ;
static void register_type_length_mismatch ( void ) ;
2000-03-12 04:48:32 +00:00
2014-04-12 04:32:20 +00:00
/* Handle number string decoding errors with expert info */
static int proto_number_string_decoding_error = - 1 ;
static expert_field ei_number_string_decoding_failed_error = EI_INIT ;
static expert_field ei_number_string_decoding_erange_error = EI_INIT ;
static void register_number_string_decoding_error ( void ) ;
2010-04-03 18:18:50 +00:00
static int proto_register_field_init ( header_field_info * hfinfo , const int parent ) ;
1999-07-15 15:33:52 +00:00
/* special-case header field used within proto.c */
2013-06-30 16:16:13 +00:00
static header_field_info hfi_text_only =
2013-06-18 20:52:31 +00:00
{ " Text item " , " text " , FT_NONE , BASE_NONE , NULL , 0x0 , NULL , HFILL } ;
2003-08-25 00:15:02 +00:00
int hf_text_only = - 1 ;
1999-07-07 22:52:57 +00:00
2001-01-03 06:56:03 +00:00
/* Structure for information about a protocol */
2003-11-16 23:17:27 +00:00
struct _protocol {
2012-03-14 17:11:39 +00:00
const char * name ; /* long description */
const char * short_name ; /* short description */
const char * filter_name ; /* name of this protocol in filters */
2014-04-20 21:27:18 +00:00
GPtrArray * fields ; /* fields for this protocol */
2013-11-14 22:50:55 +00:00
int proto_id ; /* field ID for this protocol */
2012-03-14 17:11:39 +00:00
gboolean is_enabled ; /* TRUE if protocol is enabled */
gboolean can_toggle ; /* TRUE if is_enabled can be changed */
2015-07-21 17:32:42 +00:00
GList * heur_list ; /* Heuristic dissectors associated with this protocol */
2003-11-16 23:17:27 +00:00
} ;
2003-08-25 00:15:02 +00:00
2001-01-03 06:56:03 +00:00
/* List of all protocols */
2005-01-12 21:31:22 +00:00
static GList * protocols = NULL ;
2001-01-03 06:56:03 +00:00
2014-11-06 10:19:25 +00:00
/* Deregistered fields */
static GPtrArray * deregistered_fields = NULL ;
static GPtrArray * deregistered_data = NULL ;
2006-12-22 09:01:12 +00:00
/* Contains information about a field when a dissector calls
* proto_tree_add_item . */
2013-10-12 21:01:17 +00:00
# define FIELD_INFO_NEW(pool, fi) fi = wmem_new(pool, field_info)
# define FIELD_INFO_FREE(pool, fi) wmem_free(pool, fi)
2006-12-22 09:01:12 +00:00
2001-12-18 19:09:08 +00:00
/* Contains the space for proto_nodes. */
2013-10-20 10:03:32 +00:00
# define PROTO_NODE_INIT(node) \
node - > first_child = NULL ; \
node - > last_child = NULL ; \
2003-12-04 10:59:34 +00:00
node - > next = NULL ;
2013-10-12 21:01:17 +00:00
# define PROTO_NODE_FREE(pool, node) \
wmem_free ( pool , node )
2003-11-26 12:22:22 +00:00
2006-12-22 09:01:12 +00:00
/* String space for protocol and field items for the GUI */
2013-10-12 21:01:17 +00:00
# define ITEM_LABEL_NEW(pool, il) \
il = wmem_new ( pool , item_label_t ) ;
# define ITEM_LABEL_FREE(pool, il) \
wmem_free ( pool , il ) ;
2006-12-22 09:01:12 +00:00
2012-12-02 03:34:06 +00:00
# define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
if ( ( guint ) hfindex > = gpa_hfinfo . len & & getenv ( " WIRESHARK_ABORT_ON_DISSECTOR_BUG " ) ) \
g_error ( " Unregistered hf! index=%d " , hfindex ) ; \
2013-02-10 18:38:46 +00:00
DISSECTOR_ASSERT_HINT ( ( guint ) hfindex < gpa_hfinfo . len , " Unregistered hf! " ) ; \
2015-08-11 12:08:08 +00:00
DISSECTOR_ASSERT_HINT ( gpa_hfinfo . hfi [ hfindex ] ! = NULL , " Unregistered hf! " ) ; \
2012-03-14 17:11:39 +00:00
hfinfo = gpa_hfinfo . hfi [ hfindex ] ;
2005-04-11 08:43:51 +00:00
1999-07-07 22:52:57 +00:00
/* List which stores protocols and fields that have been registered */
2003-11-21 14:58:49 +00:00
typedef struct _gpa_hfinfo_t {
2012-03-14 17:11:39 +00:00
guint32 len ;
guint32 allocated_len ;
2003-11-21 14:58:49 +00:00
header_field_info * * hfi ;
} gpa_hfinfo_t ;
2013-07-27 20:57:58 +00:00
static gpa_hfinfo_t gpa_hfinfo ;
1999-07-07 22:52:57 +00:00
2014-04-20 20:45:57 +00:00
/* Hash table of abbreviations and IDs */
static GHashTable * gpa_name_map = NULL ;
2007-11-28 10:18:16 +00:00
static header_field_info * same_name_hfinfo ;
2015-08-27 00:14:39 +00:00
/*
* We ' re called repeatedly with the same field name when sorting a column .
* Cache our last gpa_name_map hit for faster lookups .
*/
static char * last_field_name = NULL ;
static header_field_info * last_hfinfo ;
2007-11-28 10:18:16 +00:00
static void save_same_name_hfinfo ( gpointer data )
{
2012-03-14 17:11:39 +00:00
same_name_hfinfo = ( header_field_info * ) data ;
2007-11-28 10:18:16 +00:00
}
2002-04-29 07:55:32 +00:00
2013-07-07 17:13:17 +00:00
/* Points to the first element of an array of bits, indexed by
1999-11-16 11:44:20 +00:00
a subtree item type ; that array element is TRUE if subtrees of
an item of that type are to be expanded . */
2013-07-07 17:13:17 +00:00
static guint32 * tree_is_expanded ;
1999-11-16 11:44:20 +00:00
/* Number of elements in that array. */
int num_tree_types ;
2005-01-12 21:31:22 +00:00
/* Name hashtables for fast detection of duplicate names */
2012-03-15 14:15:48 +00:00
static GHashTable * proto_names = NULL ;
static GHashTable * proto_short_names = NULL ;
2005-01-12 21:31:22 +00:00
static GHashTable * proto_filter_names = NULL ;
static gint
proto_compare_name ( gconstpointer p1_arg , gconstpointer p2_arg )
{
2013-03-02 12:10:56 +00:00
const protocol_t * p1 = ( const protocol_t * ) p1_arg ;
const protocol_t * p2 = ( const protocol_t * ) p2_arg ;
2005-01-12 21:31:22 +00:00
strcasecmp(), strncasecmp(), g_strcasecmp(), and g_strncasecmp() delenda
est. Use g_ascii_strcasecmp() and g_ascii_strncasecmp(), and supply our
own versions if they're missing from GLib (as is the case with GLib
1.x).
In the code to build the list of named fields for Diameter, don't use
g_strdown(); do our own g_ascii_-style upper-case to lower-case mapping
in the hash function and use g_ascii_strcasecmp() in the compare
function.
We do this because there is no guarantee that toupper(), tolower(), and
functions that use them will, for example, map between "I" and "i" in
all locales; in Turkish locales, for example, there are, in both
upper case and lower case, versions of "i" with and without a dot, and
the upper-case version of "i" is "I"-with-a-dot and the lower-case
version of "I" is "i"-without-a-dot. This causes strings that should
match not to match.
This finishes fixing bug 2010 - an earlier checkin prevented the crash
(as there are other ways to produce the same crash, e.g. a bogus
dictionary.xml file), but didn't fix the case-insensitive string matching.
svn path=/trunk/; revision=23623
2007-11-27 18:52:51 +00:00
return g_ascii_strcasecmp ( p1 - > short_name , p2 - > short_name ) ;
2005-01-12 21:31:22 +00:00
}
2013-12-02 08:30:29 +00:00
# ifdef HAVE_PLUGINS
/*
* List of dissector plugins .
*/
typedef struct {
void ( * register_protoinfo ) ( void ) ; /* routine to call to register protocol information */
void ( * reg_handoff ) ( void ) ; /* routine to call to register dissector handoff */
} dissector_plugin ;
static GSList * dissector_plugins = NULL ;
/*
* Callback for each plugin found .
*/
static gboolean
check_for_dissector_plugin ( GModule * handle )
{
gpointer gp ;
void ( * register_protoinfo ) ( void ) ;
void ( * reg_handoff ) ( void ) ;
dissector_plugin * plugin ;
/*
* Do we have a register routine ?
*/
2015-12-13 23:18:36 +00:00
if ( g_module_symbol ( handle , " plugin_register " , & gp ) ) {
DIAG_OFF ( pedantic )
2013-12-02 08:30:29 +00:00
register_protoinfo = ( void ( * ) ( void ) ) gp ;
2015-12-13 23:18:36 +00:00
DIAG_ON ( pedantic )
}
else {
2013-12-23 17:20:07 +00:00
register_protoinfo = NULL ;
2015-12-13 23:18:36 +00:00
}
2013-12-02 08:30:29 +00:00
/*
* Do we have a reg_handoff routine ?
*/
2015-12-13 23:18:36 +00:00
if ( g_module_symbol ( handle , " plugin_reg_handoff " , & gp ) ) {
DIAG_OFF ( pedantic )
2013-12-02 08:30:29 +00:00
reg_handoff = ( void ( * ) ( void ) ) gp ;
2015-12-13 23:18:36 +00:00
DIAG_ON ( pedantic )
}
else {
2013-12-02 08:30:29 +00:00
reg_handoff = NULL ;
2015-12-13 23:18:36 +00:00
}
2013-12-02 08:30:29 +00:00
/*
* If we have neither , we ' re not a dissector plugin .
*/
if ( register_protoinfo = = NULL & & reg_handoff = = NULL )
return FALSE ;
/*
* Add this one to the list of dissector plugins .
*/
plugin = ( dissector_plugin * ) g_malloc ( sizeof ( dissector_plugin ) ) ;
plugin - > register_protoinfo = register_protoinfo ;
plugin - > reg_handoff = reg_handoff ;
dissector_plugins = g_slist_append ( dissector_plugins , plugin ) ;
return TRUE ;
}
static void
register_dissector_plugin ( gpointer data , gpointer user_data _U_ )
{
dissector_plugin * plugin = ( dissector_plugin * ) data ;
if ( plugin - > register_protoinfo )
( plugin - > register_protoinfo ) ( ) ;
}
static void
reg_handoff_dissector_plugin ( gpointer data , gpointer user_data _U_ )
{
dissector_plugin * plugin = ( dissector_plugin * ) data ;
if ( plugin - > reg_handoff )
( plugin - > reg_handoff ) ( ) ;
}
/*
* Register dissector plugin type .
*/
void
register_dissector_plugin_type ( void )
{
add_plugin_type ( " dissector " , check_for_dissector_plugin ) ;
}
# endif /* HAVE_PLUGINS */
2005-01-12 21:31:22 +00:00
1999-07-07 22:52:57 +00:00
/* initialize data structures and register protocols and fields */
void
2008-06-23 20:15:30 +00:00
proto_init ( void ( register_all_protocols_func ) ( register_cb cb , gpointer client_data ) ,
void ( register_all_handoffs_func ) ( register_cb cb , gpointer client_data ) ,
2007-05-07 17:55:42 +00:00
register_cb cb ,
gpointer client_data )
1999-07-07 22:52:57 +00:00
{
2009-09-01 18:16:55 +00:00
proto_cleanup ( ) ;
2005-01-12 21:31:22 +00:00
2012-03-15 14:15:48 +00:00
proto_names = g_hash_table_new_full ( g_int_hash , g_int_equal , g_free , NULL ) ;
proto_short_names = g_hash_table_new ( wrs_str_hash , g_str_equal ) ;
2007-11-30 09:22:01 +00:00
proto_filter_names = g_hash_table_new ( wrs_str_hash , g_str_equal ) ;
2005-01-12 21:31:22 +00:00
2012-03-14 17:11:39 +00:00
gpa_hfinfo . len = 0 ;
gpa_hfinfo . allocated_len = 0 ;
gpa_hfinfo . hfi = NULL ;
2014-04-20 20:45:57 +00:00
gpa_name_map = g_hash_table_new_full ( g_str_hash , g_str_equal , NULL , save_same_name_hfinfo ) ;
2014-11-06 10:19:25 +00:00
deregistered_fields = g_ptr_array_new ( ) ;
deregistered_data = g_ptr_array_new ( ) ;
1999-07-07 22:52:57 +00:00
2001-02-01 20:21:25 +00:00
/* Initialize the ftype subsystem */
ftypes_initialize ( ) ;
2015-02-08 03:15:55 +00:00
/* Initialize the addres type subsystem */
address_types_initialize ( ) ;
2003-08-25 00:15:02 +00:00
/* Register one special-case FT_TEXT_ONLY field for use when
2006-05-21 05:12:17 +00:00
converting wireshark to new - style proto_tree . These fields
2003-08-25 00:15:02 +00:00
are merely strings on the GUI tree ; they are not filterable */
2013-06-18 20:52:31 +00:00
hf_text_only = proto_register_field_init ( & hfi_text_only , - 1 ) ;
2003-08-25 00:15:02 +00:00
Move show_exception() and show_reported_bounds_error() to
epan/show_exception.c, as it's used outside
epan/dissectors/packet-frame.c. Update their callers to include
<epan/show_exception.h> to get their declaration.
Add a CATCH_NONFATAL_ERRORS macro that catches all exceptions that, if
there's more stuff in the packet to dissect after the dissector call
that threw the exception, doesn't mean you shouldn't go ahead and
dissect that stuff. Use it in all those cases, including ones where
BoundsError was inappropriately being caught (you want those passed up
to the top level, so that the packet is reported as having been cut
short in the capture process).
Add a CATCH_BOUNDS_ERRORS macro that catches all exceptions that
correspond to running past the end of the data for a tvbuff; use it
rather than explicitly catching those exceptions individually, and
rather than just catching all exceptions (the only place that
DissectorError should be caught, for example, is at the top level, so
dissector bugs show up in the protocol tree).
Don't catch and then immediately rethrow exceptions without doing
anything else; just let the exceptions go up to the final catcher.
Use show_exception() to report non-fatal errors, rather than doing it
yourself.
If a dissector is called from Lua, catch all non-fatal errors and use
show_exception() to report them rather than catching only
ReportedBoundsError and adding a proto_malformed item.
Don't catch exceptions when constructing a trailer tvbuff in
packet-ieee8023.c - just construct it after the payload has been
dissected, and let whatever exceptions that throws be handled at the top
level.
Avoid some TRY/CATCH/ENDTRY cases by using checks such as
tvb_bytes_exist() before even looking in the tvbuff.
svn path=/trunk/; revision=47924
2013-02-27 22:43:54 +00:00
/* Register the pseudo-protocols used for exceptions. */
register_show_exception ( ) ;
2013-10-03 01:54:02 +00:00
register_type_length_mismatch ( ) ;
2014-04-12 04:32:20 +00:00
register_number_string_decoding_error ( ) ;
Move show_exception() and show_reported_bounds_error() to
epan/show_exception.c, as it's used outside
epan/dissectors/packet-frame.c. Update their callers to include
<epan/show_exception.h> to get their declaration.
Add a CATCH_NONFATAL_ERRORS macro that catches all exceptions that, if
there's more stuff in the packet to dissect after the dissector call
that threw the exception, doesn't mean you shouldn't go ahead and
dissect that stuff. Use it in all those cases, including ones where
BoundsError was inappropriately being caught (you want those passed up
to the top level, so that the packet is reported as having been cut
short in the capture process).
Add a CATCH_BOUNDS_ERRORS macro that catches all exceptions that
correspond to running past the end of the data for a tvbuff; use it
rather than explicitly catching those exceptions individually, and
rather than just catching all exceptions (the only place that
DissectorError should be caught, for example, is at the top level, so
dissector bugs show up in the protocol tree).
Don't catch and then immediately rethrow exceptions without doing
anything else; just let the exceptions go up to the final catcher.
Use show_exception() to report non-fatal errors, rather than doing it
yourself.
If a dissector is called from Lua, catch all non-fatal errors and use
show_exception() to report them rather than catching only
ReportedBoundsError and adding a proto_malformed item.
Don't catch exceptions when constructing a trailer tvbuff in
packet-ieee8023.c - just construct it after the payload has been
dissected, and let whatever exceptions that throws be handled at the top
level.
Avoid some TRY/CATCH/ENDTRY cases by using checks such as
tvb_bytes_exist() before even looking in the tvbuff.
svn path=/trunk/; revision=47924
2013-02-27 22:43:54 +00:00
Clean up the dissector registration up a bit - arrange that all plugins
be loaded and their initialization routines called in right after we
call the initialization routines for built-in dissectors, but don't call
their handoff registration routines yet, and then call the handoff
registration routines right after calling the handoff registration
routines for built-in dissectors.
Do all that in "proto_init()", rather than "epan_init()".
That way, we call all dissector registration routines together, and then
call all dissector handoff registration routines together; all the
registration routines are called before any handoff registration
routines, as is required, and, as "proto_init()" is called by
"epan_init()" before "dfilter_init()" is called, all filterable fields
have been registered before "dfilter_init()" is called, and no plugins
have to call "dfilter_init()" themselves to get their fields registered.
Remove pointers to "dfilter_init()" and "dfilter_cleanup()" from the
plugin address table, as plugins shouldn't be calling them any more, and
remove calls to them from plugins.
svn path=/trunk/; revision=2940
2001-01-26 06:14:53 +00:00
/* Have each built-in dissector register its protocols, fields,
dissector tables , and dissectors to be called through a
handle , and do whatever one - time initialization it needs to
do . */
2008-06-23 20:15:30 +00:00
register_all_protocols_func ( cb , client_data ) ;
1999-07-07 22:52:57 +00:00
Clean up the dissector registration up a bit - arrange that all plugins
be loaded and their initialization routines called in right after we
call the initialization routines for built-in dissectors, but don't call
their handoff registration routines yet, and then call the handoff
registration routines right after calling the handoff registration
routines for built-in dissectors.
Do all that in "proto_init()", rather than "epan_init()".
That way, we call all dissector registration routines together, and then
call all dissector handoff registration routines together; all the
registration routines are called before any handoff registration
routines, as is required, and, as "proto_init()" is called by
"epan_init()" before "dfilter_init()" is called, all filterable fields
have been registered before "dfilter_init()" is called, and no plugins
have to call "dfilter_init()" themselves to get their fields registered.
Remove pointers to "dfilter_init()" and "dfilter_cleanup()" from the
plugin address table, as plugins shouldn't be calling them any more, and
remove calls to them from plugins.
svn path=/trunk/; revision=2940
2001-01-26 06:14:53 +00:00
# ifdef HAVE_PLUGINS
2013-12-02 08:30:29 +00:00
/* Now call the registration routines for all disssector
plugins . */
2012-03-14 17:11:39 +00:00
if ( cb )
2011-03-20 00:05:39 +00:00
( * cb ) ( RA_PLUGIN_REGISTER , NULL , client_data ) ;
2013-12-02 08:30:29 +00:00
g_slist_foreach ( dissector_plugins , register_dissector_plugin , NULL ) ;
Clean up the dissector registration up a bit - arrange that all plugins
be loaded and their initialization routines called in right after we
call the initialization routines for built-in dissectors, but don't call
their handoff registration routines yet, and then call the handoff
registration routines right after calling the handoff registration
routines for built-in dissectors.
Do all that in "proto_init()", rather than "epan_init()".
That way, we call all dissector registration routines together, and then
call all dissector handoff registration routines together; all the
registration routines are called before any handoff registration
routines, as is required, and, as "proto_init()" is called by
"epan_init()" before "dfilter_init()" is called, all filterable fields
have been registered before "dfilter_init()" is called, and no plugins
have to call "dfilter_init()" themselves to get their fields registered.
Remove pointers to "dfilter_init()" and "dfilter_cleanup()" from the
plugin address table, as plugins shouldn't be calling them any more, and
remove calls to them from plugins.
svn path=/trunk/; revision=2940
2001-01-26 06:14:53 +00:00
# endif
/* Now call the "handoff registration" routines of all built-in
dissectors ; those routines register the dissector in other
dissectors ' handoff tables , and fetch any dissector handles
they need . */
2008-06-23 20:15:30 +00:00
register_all_handoffs_func ( cb , client_data ) ;
2000-04-04 06:17:30 +00:00
2001-04-05 19:25:16 +00:00
# ifdef HAVE_PLUGINS
Clean up the dissector registration up a bit - arrange that all plugins
be loaded and their initialization routines called in right after we
call the initialization routines for built-in dissectors, but don't call
their handoff registration routines yet, and then call the handoff
registration routines right after calling the handoff registration
routines for built-in dissectors.
Do all that in "proto_init()", rather than "epan_init()".
That way, we call all dissector registration routines together, and then
call all dissector handoff registration routines together; all the
registration routines are called before any handoff registration
routines, as is required, and, as "proto_init()" is called by
"epan_init()" before "dfilter_init()" is called, all filterable fields
have been registered before "dfilter_init()" is called, and no plugins
have to call "dfilter_init()" themselves to get their fields registered.
Remove pointers to "dfilter_init()" and "dfilter_cleanup()" from the
plugin address table, as plugins shouldn't be calling them any more, and
remove calls to them from plugins.
svn path=/trunk/; revision=2940
2001-01-26 06:14:53 +00:00
/* Now do the same with plugins. */
2012-03-14 17:11:39 +00:00
if ( cb )
2011-03-20 00:05:39 +00:00
( * cb ) ( RA_PLUGIN_HANDOFF , NULL , client_data ) ;
2013-12-02 08:30:29 +00:00
g_slist_foreach ( dissector_plugins , reg_handoff_dissector_plugin , NULL ) ;
2001-04-05 19:25:16 +00:00
# endif
Clean up the dissector registration up a bit - arrange that all plugins
be loaded and their initialization routines called in right after we
call the initialization routines for built-in dissectors, but don't call
their handoff registration routines yet, and then call the handoff
registration routines right after calling the handoff registration
routines for built-in dissectors.
Do all that in "proto_init()", rather than "epan_init()".
That way, we call all dissector registration routines together, and then
call all dissector handoff registration routines together; all the
registration routines are called before any handoff registration
routines, as is required, and, as "proto_init()" is called by
"epan_init()" before "dfilter_init()" is called, all filterable fields
have been registered before "dfilter_init()" is called, and no plugins
have to call "dfilter_init()" themselves to get their fields registered.
Remove pointers to "dfilter_init()" and "dfilter_cleanup()" from the
plugin address table, as plugins shouldn't be calling them any more, and
remove calls to them from plugins.
svn path=/trunk/; revision=2940
2001-01-26 06:14:53 +00:00
Add a WIRESHARK_RUN_FROM_BUILD_DIRECTORY environment variable on UN*X;
if set, and if the program isn't running with additional privileges,
it'll treat the directory in which the program is found as the data
directory.
If, on Windows, the version-number subdirectory of {data
directory}\plugins doesn't exist (which is assumed to mean that the
program is being run from the build directory), or if, on UN*X,
WIRESHARK_RUN_FROM_BUILD_DIRECTORY is set, the plugin directory is the
"plugins" subdirectory of the data directory, and all subdirectories of
that directory are scanned for plugins, as the "plugins" subdirectory of
the build directory contains subdirectories for the plugins; this means
that if we're running from the build directory, we'll find the plugins
we built in the build tree.
When generating the wireshark-filter man page, run tshark with
WIRESHARK_RUN_FROM_BUILD_DIRECTORY set, so it uses the plugins from the
build to generate the list of filters.
svn path=/trunk/; revision=20261
2007-01-02 06:49:40 +00:00
/* sort the protocols by protocol name */
protocols = g_list_sort ( protocols , proto_compare_name ) ;
2005-01-12 21:31:22 +00:00
1999-11-16 11:44:20 +00:00
/* We've assigned all the subtree type values; allocate the array
for them , and zero it out . */
2013-07-07 17:13:17 +00:00
tree_is_expanded = g_new0 ( guint32 , ( num_tree_types / 32 ) + 1 ) ;
1999-07-07 22:52:57 +00:00
}
1999-08-26 06:20:50 +00:00
void
proto_cleanup ( void )
{
2015-01-18 19:45:30 +00:00
/* Free the abbrev/ID hash table */
2014-04-20 20:45:57 +00:00
if ( gpa_name_map ) {
g_hash_table_destroy ( gpa_name_map ) ;
gpa_name_map = NULL ;
2002-04-29 07:55:32 +00:00
}
2015-08-27 00:14:39 +00:00
g_free ( last_field_name ) ;
last_field_name = NULL ;
2002-04-29 07:55:32 +00:00
2009-09-01 18:16:55 +00:00
while ( protocols ) {
2013-03-02 12:10:56 +00:00
protocol_t * protocol = ( protocol_t * ) protocols - > data ;
2009-10-11 09:18:51 +00:00
header_field_info * hfinfo ;
PROTO_REGISTRAR_GET_NTH ( protocol - > proto_id , hfinfo ) ;
DISSECTOR_ASSERT ( protocol - > proto_id = = hfinfo - > id ) ;
g_slice_free ( header_field_info , hfinfo ) ;
2014-04-20 21:27:18 +00:00
g_ptr_array_free ( protocol - > fields , TRUE ) ;
2015-07-21 17:32:42 +00:00
g_list_free ( protocol - > heur_list ) ;
2009-09-01 18:16:55 +00:00
protocols = g_list_remove ( protocols , protocol ) ;
g_free ( protocol ) ;
}
if ( proto_names ) {
g_hash_table_destroy ( proto_names ) ;
proto_names = NULL ;
}
2009-09-06 07:24:54 +00:00
2009-09-01 18:16:55 +00:00
if ( proto_short_names ) {
g_hash_table_destroy ( proto_short_names ) ;
proto_short_names = NULL ;
}
if ( proto_filter_names ) {
g_hash_table_destroy ( proto_filter_names ) ;
proto_filter_names = NULL ;
}
2012-03-14 17:11:39 +00:00
if ( gpa_hfinfo . allocated_len ) {
gpa_hfinfo . len = 0 ;
gpa_hfinfo . allocated_len = 0 ;
2003-11-21 14:58:49 +00:00
g_free ( gpa_hfinfo . hfi ) ;
2012-03-14 17:11:39 +00:00
gpa_hfinfo . hfi = NULL ;
2003-11-21 14:58:49 +00:00
}
2014-11-06 10:19:25 +00:00
if ( deregistered_fields ) {
g_ptr_array_free ( deregistered_fields , FALSE ) ;
deregistered_fields = NULL ;
}
if ( deregistered_data ) {
g_ptr_array_free ( deregistered_data , FALSE ) ;
deregistered_data = NULL ;
}
2009-03-13 22:06:48 +00:00
g_free ( tree_is_expanded ) ;
2011-03-20 00:05:39 +00:00
tree_is_expanded = NULL ;
1999-08-26 06:20:50 +00:00
}
2003-12-04 10:59:34 +00:00
static gboolean
proto_tree_traverse_pre_order ( proto_tree * tree , proto_tree_traverse_func func ,
2010-04-26 20:48:13 +00:00
gpointer data )
2003-12-04 10:59:34 +00:00
{
proto_node * pnode = tree ;
proto_node * child ;
proto_node * current ;
if ( func ( pnode , data ) )
return TRUE ;
child = pnode - > first_child ;
while ( child ! = NULL ) {
/*
* The routine we call might modify the child , e . g . by
* freeing it , so we get the child ' s successor before
* calling that routine .
*/
current = child ;
2012-03-15 14:15:48 +00:00
child = current - > next ;
2012-03-14 17:11:39 +00:00
if ( proto_tree_traverse_pre_order ( ( proto_tree * ) current , func , data ) )
2003-12-04 10:59:34 +00:00
return TRUE ;
}
return FALSE ;
}
2007-07-30 23:32:47 +00:00
gboolean
2008-10-15 20:02:15 +00:00
proto_tree_traverse_post_order ( proto_tree * tree , proto_tree_traverse_func func ,
2010-04-26 20:48:13 +00:00
gpointer data )
2003-12-04 10:59:34 +00:00
{
proto_node * pnode = tree ;
proto_node * child ;
proto_node * current ;
child = pnode - > first_child ;
2008-10-15 20:02:15 +00:00
while ( child ! = NULL ) {
2003-12-04 10:59:34 +00:00
/*
* The routine we call might modify the child , e . g . by
* freeing it , so we get the child ' s successor before
* calling that routine .
*/
current = child ;
2012-03-15 14:15:48 +00:00
child = current - > next ;
2012-03-14 17:11:39 +00:00
if ( proto_tree_traverse_post_order ( ( proto_tree * ) current , func , data ) )
2003-12-04 10:59:34 +00:00
return TRUE ;
}
2008-10-15 20:02:15 +00:00
if ( func ( pnode , data ) )
return TRUE ;
2003-12-04 10:59:34 +00:00
return FALSE ;
}
void
proto_tree_children_foreach ( proto_tree * tree , proto_tree_foreach_func func ,
2010-04-26 20:48:13 +00:00
gpointer data )
2003-12-04 10:59:34 +00:00
{
proto_node * node = tree ;
proto_node * current ;
2013-05-29 03:19:31 +00:00
if ( ! node )
return ;
2003-12-04 10:59:34 +00:00
node = node - > first_child ;
while ( node ! = NULL ) {
current = node ;
2012-03-15 14:15:48 +00:00
node = current - > next ;
2003-12-04 10:59:34 +00:00
func ( ( proto_tree * ) current , data ) ;
}
}
2001-12-18 19:09:08 +00:00
static void
2012-11-03 20:51:19 +00:00
free_GPtrArray_value ( gpointer key , gpointer value , gpointer user_data _U_ )
1999-07-07 22:52:57 +00:00
{
2013-03-02 12:10:56 +00:00
GPtrArray * ptrs = ( GPtrArray * ) value ;
2015-06-04 14:12:04 +00:00
gint hfid = GPOINTER_TO_UINT ( key ) ;
2005-04-11 08:43:51 +00:00
header_field_info * hfinfo ;
PROTO_REGISTRAR_GET_NTH ( hfid , hfinfo ) ;
2012-03-14 17:11:39 +00:00
if ( hfinfo - > ref_type ! = HF_REF_TYPE_NONE ) {
2006-07-20 21:29:45 +00:00
/* when a field is referenced by a filter this also
2005-04-11 08:43:51 +00:00
affects the refcount for the parent protocol so we need
to adjust the refcount for the parent as well
*/
2012-03-14 17:11:39 +00:00
if ( hfinfo - > parent ! = - 1 ) {
2005-04-11 08:43:51 +00:00
header_field_info * parent_hfinfo ;
PROTO_REGISTRAR_GET_NTH ( hfinfo - > parent , parent_hfinfo ) ;
2009-09-30 14:02:49 +00:00
parent_hfinfo - > ref_type = HF_REF_TYPE_NONE ;
2005-04-11 08:43:51 +00:00
}
2009-09-30 14:02:49 +00:00
hfinfo - > ref_type = HF_REF_TYPE_NONE ;
2005-04-11 08:43:51 +00:00
}
2015-08-14 11:46:01 +00:00
g_ptr_array_free ( ptrs , TRUE ) ;
2001-12-18 19:09:08 +00:00
}
2012-10-20 16:38:55 +00:00
static void
2003-12-04 10:59:34 +00:00
proto_tree_free_node ( proto_node * node , gpointer data _U_ )
2001-12-18 19:09:08 +00:00
{
2012-03-15 14:15:48 +00:00
field_info * finfo = PNODE_FINFO ( node ) ;
2001-12-18 19:09:08 +00:00
2012-10-20 16:38:55 +00:00
proto_tree_children_foreach ( node , proto_tree_free_node , NULL ) ;
2013-10-12 21:01:17 +00:00
FVALUE_CLEANUP ( & finfo - > value ) ;
2012-10-20 16:38:55 +00:00
}
2013-10-20 10:21:25 +00:00
void
proto_tree_reset ( proto_tree * tree )
{
tree_data_t * tree_data = PTREE_DATA ( tree ) ;
proto_tree_children_foreach ( tree , proto_tree_free_node , NULL ) ;
/* free tree data */
if ( tree_data - > interesting_hfids ) {
/* Free all the GPtrArray's in the interesting_hfids hash. */
g_hash_table_foreach ( tree_data - > interesting_hfids ,
free_GPtrArray_value , NULL ) ;
2014-06-19 22:41:49 +00:00
/* And then remove all values. */
g_hash_table_remove_all ( tree_data - > interesting_hfids ) ;
2013-10-20 10:21:25 +00:00
}
/* Reset track of the number of children */
tree_data - > count = 0 ;
PROTO_NODE_INIT ( tree ) ;
}
2012-10-20 16:38:55 +00:00
/* frees the resources that the dissection a proto_tree uses */
void
proto_tree_free ( proto_tree * tree )
{
tree_data_t * tree_data = PTREE_DATA ( tree ) ;
proto_tree_children_foreach ( tree , proto_tree_free_node , NULL ) ;
2013-10-12 18:14:19 +00:00
/* free tree data */
2013-10-12 21:01:17 +00:00
if ( tree_data - > interesting_hfids ) {
/* Free all the GPtrArray's in the interesting_hfids hash. */
g_hash_table_foreach ( tree_data - > interesting_hfids ,
free_GPtrArray_value , NULL ) ;
/* And then destroy the hash. */
g_hash_table_destroy ( tree_data - > interesting_hfids ) ;
}
2013-10-20 10:21:25 +00:00
g_slice_free ( tree_data_t , tree_data ) ;
g_slice_free ( proto_tree , tree ) ;
2001-12-18 19:09:08 +00:00
}
/* Is the parsing being done for a visible proto_tree or an invisible one?
* By setting this correctly , the proto_tree creation is sped up by not
2005-08-18 19:31:15 +00:00
* having to call g_vsnprintf and copy strings around .
2001-12-18 19:09:08 +00:00
*/
2009-09-06 06:33:13 +00:00
gboolean
2001-12-18 19:09:08 +00:00
proto_tree_set_visible ( proto_tree * tree , gboolean visible )
{
2009-09-06 06:33:13 +00:00
gboolean old_visible = PTREE_DATA ( tree ) - > visible ;
2002-04-18 20:19:10 +00:00
PTREE_DATA ( tree ) - > visible = visible ;
2009-09-06 06:33:13 +00:00
return old_visible ;
2001-12-18 19:09:08 +00:00
}
1999-07-07 22:52:57 +00:00
2009-08-11 18:08:03 +00:00
void
proto_tree_set_fake_protocols ( proto_tree * tree , gboolean fake_protocols )
{
PTREE_DATA ( tree ) - > fake_protocols = fake_protocols ;
}
2005-04-11 08:43:51 +00:00
/* Assume dissector set only its protocol fields.
2009-09-22 20:17:31 +00:00
This function is called by dissectors and allows the speeding up of filtering
in wireshark ; if this function returns FALSE it is safe to reset tree to NULL
2005-04-11 08:43:51 +00:00
and thus skip calling most of the expensive proto_tree_add_ . . . ( )
functions .
2009-09-22 20:17:31 +00:00
If the tree is visible we implicitly assume the field is referenced .
2005-04-11 08:43:51 +00:00
*/
gboolean
proto_field_is_referenced ( proto_tree * tree , int proto_id )
{
register header_field_info * hfinfo ;
if ( ! tree )
return FALSE ;
if ( PTREE_DATA ( tree ) - > visible )
return TRUE ;
PROTO_REGISTRAR_GET_NTH ( proto_id , hfinfo ) ;
2009-09-30 14:02:49 +00:00
if ( hfinfo - > ref_type ! = HF_REF_TYPE_NONE )
2005-04-11 08:43:51 +00:00
return TRUE ;
2009-08-15 08:38:50 +00:00
if ( hfinfo - > type = = FT_PROTOCOL & & ! PTREE_DATA ( tree ) - > fake_protocols )
return TRUE ;
2005-04-11 08:43:51 +00:00
return FALSE ;
}
2003-11-22 04:41:31 +00:00
2013-07-11 14:58:11 +00:00
/* Finds a record in the hfinfo array by id. */
2010-04-26 20:48:13 +00:00
header_field_info *
2003-11-21 14:58:49 +00:00
proto_registrar_get_nth ( guint hfindex )
1999-07-07 22:52:57 +00:00
{
2012-03-14 17:11:39 +00:00
register header_field_info * hfinfo ;
2003-11-22 04:41:31 +00:00
PROTO_REGISTRAR_GET_NTH ( hfindex , hfinfo ) ;
return hfinfo ;
1999-07-07 22:52:57 +00:00
}
2008-04-03 22:13:52 +00:00
2009-09-23 16:27:37 +00:00
/* Prefix initialization
* this allows for a dissector to register a display filter name prefix
* so that it can delay the initialization of the hf array as long as
* possible .
2008-04-03 22:13:52 +00:00
*/
/* compute a hash for the part before the dot of a display filter */
2009-06-12 14:32:32 +00:00
static guint
prefix_hash ( gconstpointer key ) {
2008-04-03 22:13:52 +00:00
/* end the string at the dot and compute its hash */
2013-12-23 21:19:06 +00:00
gchar * copy = g_strdup ( ( const gchar * ) key ) ;
2012-03-14 17:11:39 +00:00
gchar * c = copy ;
2013-12-23 21:19:06 +00:00
guint tmp ;
2008-04-03 22:13:52 +00:00
2012-03-15 14:15:48 +00:00
for ( ; * c ; c + + ) {
2008-04-03 22:13:52 +00:00
if ( * c = = ' . ' ) {
* c = 0 ;
break ;
}
}
2009-09-06 07:24:54 +00:00
2013-12-23 21:19:06 +00:00
tmp = g_str_hash ( copy ) ;
g_free ( copy ) ;
return tmp ;
2008-04-03 22:13:52 +00:00
}
/* are both strings equal up to the end or the dot? */
2009-06-12 14:32:32 +00:00
static gboolean
2012-03-14 17:11:39 +00:00
prefix_equal ( gconstpointer ap , gconstpointer bp ) {
2013-03-02 12:10:56 +00:00
const gchar * a = ( const gchar * ) ap ;
const gchar * b = ( const gchar * ) bp ;
2009-09-06 07:24:54 +00:00
2008-04-03 22:13:52 +00:00
do {
gchar ac = * a + + ;
gchar bc = * b + + ;
2009-09-06 07:24:54 +00:00
2012-03-14 17:11:39 +00:00
if ( ( ac = = ' . ' | | ac = = ' \0 ' ) & & ( bc = = ' . ' | | bc = = ' \0 ' ) ) return TRUE ;
2009-09-06 07:24:54 +00:00
2008-04-03 22:13:52 +00:00
if ( ( ac = = ' . ' | | ac = = ' \0 ' ) & & ! ( bc = = ' . ' | | bc = = ' \0 ' ) ) return FALSE ;
if ( ( bc = = ' . ' | | bc = = ' \0 ' ) & & ! ( ac = = ' . ' | | ac = = ' \0 ' ) ) return FALSE ;
2009-09-06 07:24:54 +00:00
2008-04-03 22:13:52 +00:00
if ( ac ! = bc ) return FALSE ;
2012-03-14 17:11:39 +00:00
} while ( 1 ) ;
2009-09-06 07:24:54 +00:00
2008-04-03 22:13:52 +00:00
return FALSE ;
}
2008-04-03 22:18:08 +00:00
/* indexed by prefix, contains initializers */
2008-04-03 22:13:52 +00:00
static GHashTable * prefixes = NULL ;
/* Register a new prefix for "delayed" initialization of field arrays */
void
proto_register_prefix ( const char * prefix , prefix_initializer_t pi ) {
if ( ! prefixes ) {
2012-03-14 17:11:39 +00:00
prefixes = g_hash_table_new ( prefix_hash , prefix_equal ) ;
2008-04-03 22:13:52 +00:00
}
2009-09-06 07:24:54 +00:00
2016-02-12 05:15:35 +00:00
g_hash_table_insert ( prefixes , ( gpointer ) prefix , ( gpointer ) pi ) ;
2008-04-03 22:13:52 +00:00
}
/* helper to call all prefix initializers */
2009-06-12 14:32:32 +00:00
static gboolean
initialize_prefix ( gpointer k , gpointer v , gpointer u _U_ ) {
2013-03-02 12:10:56 +00:00
( ( prefix_initializer_t ) v ) ( ( const char * ) k ) ;
2008-04-03 22:13:52 +00:00
return TRUE ;
}
/** Initialize every remaining uninitialized prefix. */
2009-06-12 14:32:32 +00:00
void
proto_initialize_all_prefixes ( void ) {
2008-04-03 22:13:52 +00:00
g_hash_table_foreach_remove ( prefixes , initialize_prefix , NULL ) ;
}
2013-07-11 14:58:11 +00:00
/* Finds a record in the hfinfo array by name.
2008-04-03 22:13:52 +00:00
* If it fails to find it in the already registered fields ,
2008-04-03 22:18:08 +00:00
* it tries to find and call an initializer in the prefixes
2008-04-03 22:13:52 +00:00
* table and if so it looks again .
2002-04-18 20:19:10 +00:00
*/
2015-08-27 00:14:39 +00:00
2010-04-26 20:48:13 +00:00
header_field_info *
2004-12-31 02:02:19 +00:00
proto_registrar_get_byname ( const char * field_name )
2002-04-18 20:19:10 +00:00
{
2012-03-14 17:11:39 +00:00
header_field_info * hfinfo ;
prefix_initializer_t pi ;
2009-09-06 07:24:54 +00:00
2009-07-23 05:48:39 +00:00
if ( ! field_name )
return NULL ;
2008-04-03 22:13:52 +00:00
2015-08-27 00:14:39 +00:00
if ( g_strcmp0 ( field_name , last_field_name ) = = 0 ) {
return last_hfinfo ;
}
2014-04-20 20:45:57 +00:00
hfinfo = ( header_field_info * ) g_hash_table_lookup ( gpa_name_map , field_name ) ;
2009-09-06 07:24:54 +00:00
2015-08-27 00:14:39 +00:00
if ( hfinfo ) {
g_free ( last_field_name ) ;
last_field_name = g_strdup ( field_name ) ;
last_hfinfo = hfinfo ;
2012-03-14 17:11:39 +00:00
return hfinfo ;
2015-08-27 00:14:39 +00:00
}
2009-09-06 07:24:54 +00:00
2012-03-14 17:11:39 +00:00
if ( ! prefixes )
return NULL ;
2009-09-06 07:24:54 +00:00
2013-03-02 12:10:56 +00:00
if ( ( pi = ( prefix_initializer_t ) g_hash_table_lookup ( prefixes , field_name ) ) ! = NULL ) {
2008-04-03 22:13:52 +00:00
pi ( field_name ) ;
2012-03-14 17:11:39 +00:00
g_hash_table_remove ( prefixes , field_name ) ;
2008-04-03 22:13:52 +00:00
} else {
return NULL ;
}
2009-09-06 07:24:54 +00:00
2015-08-27 00:14:39 +00:00
hfinfo = ( header_field_info * ) g_hash_table_lookup ( gpa_name_map , field_name ) ;
if ( hfinfo ) {
g_free ( last_field_name ) ;
last_field_name = g_strdup ( field_name ) ;
last_hfinfo = hfinfo ;
}
return hfinfo ;
2002-04-18 20:19:10 +00:00
}
2000-03-12 04:48:32 +00:00
2013-02-07 22:04:02 +00:00
int
proto_registrar_get_id_byname ( const char * field_name )
{
header_field_info * hfinfo ;
hfinfo = proto_registrar_get_byname ( field_name ) ;
if ( ! hfinfo )
return - 1 ;
return hfinfo - > id ;
}
2007-03-30 00:21:39 +00:00
2011-05-18 03:28:26 +00:00
static void
2012-03-14 17:11:39 +00:00
ptvcursor_new_subtree_levels ( ptvcursor_t * ptvc )
2007-03-30 00:21:39 +00:00
{
2012-03-14 17:11:39 +00:00
subtree_lvl * pushed_tree ;
2007-03-30 00:21:39 +00:00
2009-06-12 14:32:32 +00:00
DISSECTOR_ASSERT ( ptvc - > pushed_tree_max < = SUBTREE_MAX_LEVELS - SUBTREE_ONCE_ALLOCATION_NUMBER ) ;
ptvc - > pushed_tree_max + = SUBTREE_ONCE_ALLOCATION_NUMBER ;
2007-03-30 00:21:39 +00:00
2015-01-08 18:59:33 +00:00
pushed_tree = ( subtree_lvl * ) wmem_alloc ( wmem_packet_scope ( ) , sizeof ( subtree_lvl ) * ptvc - > pushed_tree_max ) ;
2009-06-12 14:32:32 +00:00
DISSECTOR_ASSERT ( pushed_tree ! = NULL ) ;
if ( ptvc - > pushed_tree )
memcpy ( pushed_tree , ptvc - > pushed_tree , ptvc - > pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER ) ;
ptvc - > pushed_tree = pushed_tree ;
2007-03-30 00:21:39 +00:00
}
2011-05-18 03:28:26 +00:00
static void
2012-03-14 17:11:39 +00:00
ptvcursor_free_subtree_levels ( ptvcursor_t * ptvc )
2007-03-30 00:21:39 +00:00
{
2012-03-14 17:11:39 +00:00
ptvc - > pushed_tree = NULL ;
ptvc - > pushed_tree_max = 0 ;
DISSECTOR_ASSERT ( ptvc - > pushed_tree_index = = 0 ) ;
2009-06-12 14:32:32 +00:00
ptvc - > pushed_tree_index = 0 ;
2007-03-30 00:21:39 +00:00
}
2005-10-22 05:43:09 +00:00
/* Allocates an initializes a ptvcursor_t with 3 variables:
2009-09-23 16:27:37 +00:00
* proto_tree , tvbuff , and offset . */
2010-04-26 20:48:13 +00:00
ptvcursor_t *
2005-10-22 05:43:09 +00:00
ptvcursor_new ( proto_tree * tree , tvbuff_t * tvb , gint offset )
{
2012-03-15 14:15:48 +00:00
ptvcursor_t * ptvc ;
2005-10-22 05:43:09 +00:00
2015-01-08 18:59:33 +00:00
ptvc = ( ptvcursor_t * ) wmem_alloc ( wmem_packet_scope ( ) , sizeof ( ptvcursor_t ) ) ;
2012-03-14 17:11:39 +00:00
ptvc - > tree = tree ;
ptvc - > tvb = tvb ;
ptvc - > offset = offset ;
ptvc - > pushed_tree = NULL ;
ptvc - > pushed_tree_max = 0 ;
ptvc - > pushed_tree_index = 0 ;
2005-10-22 05:43:09 +00:00
return ptvc ;
}
2007-03-30 00:21:39 +00:00
2005-10-22 05:43:09 +00:00
/* Frees memory for ptvcursor_t, but nothing deeper than that. */
void
ptvcursor_free ( ptvcursor_t * ptvc )
{
2007-03-30 00:21:39 +00:00
ptvcursor_free_subtree_levels ( ptvc ) ;
/*g_free(ptvc);*/
2005-10-22 05:43:09 +00:00
}
/* Returns tvbuff. */
2010-04-26 20:48:13 +00:00
tvbuff_t *
2012-03-14 17:11:39 +00:00
ptvcursor_tvbuff ( ptvcursor_t * ptvc )
2005-10-22 05:43:09 +00:00
{
return ptvc - > tvb ;
}
/* Returns current offset. */
gint
2012-03-14 17:11:39 +00:00
ptvcursor_current_offset ( ptvcursor_t * ptvc )
2005-10-22 05:43:09 +00:00
{
return ptvc - > offset ;
}
2010-04-26 20:48:13 +00:00
proto_tree *
2012-03-14 17:11:39 +00:00
ptvcursor_tree ( ptvcursor_t * ptvc )
2005-10-22 05:43:09 +00:00
{
2009-06-12 14:32:32 +00:00
if ( ! ptvc )
return NULL ;
2007-03-30 00:21:39 +00:00
2009-06-12 14:32:32 +00:00
return ptvc - > tree ;
2005-10-22 05:43:09 +00:00
}
void
2012-03-14 17:11:39 +00:00
ptvcursor_set_tree ( ptvcursor_t * ptvc , proto_tree * tree )
2005-10-22 05:43:09 +00:00
{
ptvc - > tree = tree ;
}
2007-12-07 18:50:41 +00:00
/* creates a subtree, sets it as the working tree and pushes the old working tree */
2010-04-26 20:48:13 +00:00
proto_tree *
2007-12-07 18:50:41 +00:00
ptvcursor_push_subtree ( ptvcursor_t * ptvc , proto_item * it , gint ett_subtree )
2007-03-30 00:21:39 +00:00
{
2012-03-14 17:11:39 +00:00
subtree_lvl * subtree ;
2009-06-12 14:32:32 +00:00
if ( ptvc - > pushed_tree_index > = ptvc - > pushed_tree_max )
ptvcursor_new_subtree_levels ( ptvc ) ;
2012-03-15 14:15:48 +00:00
subtree = ptvc - > pushed_tree + ptvc - > pushed_tree_index ;
2009-06-12 14:32:32 +00:00
subtree - > tree = ptvc - > tree ;
subtree - > it = NULL ;
ptvc - > pushed_tree_index + + ;
return ptvcursor_set_subtree ( ptvc , it , ett_subtree ) ;
2007-03-30 00:21:39 +00:00
}
/* pops a subtree */
2007-12-07 18:50:41 +00:00
void
ptvcursor_pop_subtree ( ptvcursor_t * ptvc )
2007-03-30 00:21:39 +00:00
{
2012-03-14 17:11:39 +00:00
subtree_lvl * subtree ;
2012-03-15 14:15:48 +00:00
2009-06-12 14:32:32 +00:00
if ( ptvc - > pushed_tree_index < = 0 )
return ;
ptvc - > pushed_tree_index - - ;
2012-03-15 14:15:48 +00:00
subtree = ptvc - > pushed_tree + ptvc - > pushed_tree_index ;
2009-06-12 14:32:32 +00:00
if ( subtree - > it ! = NULL )
proto_item_set_len ( subtree - > it , ptvcursor_current_offset ( ptvc ) - subtree - > cursor_offset ) ;
ptvc - > tree = subtree - > tree ;
2007-03-30 00:21:39 +00:00
}
/* saves the current tvb offset and the item in the current subtree level */
2008-06-11 18:16:04 +00:00
static void
2012-03-14 17:11:39 +00:00
ptvcursor_subtree_set_item ( ptvcursor_t * ptvc , proto_item * it )
2007-03-30 00:21:39 +00:00
{
2012-03-14 17:11:39 +00:00
subtree_lvl * subtree ;
2007-03-30 00:21:39 +00:00
2009-06-12 14:32:32 +00:00
DISSECTOR_ASSERT ( ptvc - > pushed_tree_index > 0 ) ;
2007-03-30 00:21:39 +00:00
2012-03-15 14:15:48 +00:00
subtree = ptvc - > pushed_tree + ptvc - > pushed_tree_index - 1 ;
subtree - > it = it ;
2009-06-12 14:32:32 +00:00
subtree - > cursor_offset = ptvcursor_current_offset ( ptvc ) ;
2007-03-30 00:21:39 +00:00
}
/* Creates a subtree and adds it to the cursor as the working tree but does not
* save the old working tree */
2010-04-26 20:48:13 +00:00
proto_tree *
2007-12-07 18:50:41 +00:00
ptvcursor_set_subtree ( ptvcursor_t * ptvc , proto_item * it , gint ett_subtree )
2007-03-30 00:21:39 +00:00
{
2009-06-12 14:32:32 +00:00
ptvc - > tree = proto_item_add_subtree ( it , ett_subtree ) ;
return ptvc - > tree ;
2007-03-30 00:21:39 +00:00
}
2011-05-18 03:28:26 +00:00
static proto_tree *
2012-03-14 17:11:39 +00:00
ptvcursor_add_subtree_item ( ptvcursor_t * ptvc , proto_item * it , gint ett_subtree , gint length )
2007-03-30 00:21:39 +00:00
{
2009-06-12 14:32:32 +00:00
ptvcursor_push_subtree ( ptvc , it , ett_subtree ) ;
if ( length = = SUBTREE_UNDEFINED_LENGTH )
ptvcursor_subtree_set_item ( ptvc , it ) ;
return ptvcursor_tree ( ptvc ) ;
2007-03-30 00:21:39 +00:00
}
/* Add an item to the tree and create a subtree
* If the length is unknown , length may be defined as SUBTREE_UNDEFINED_LENGTH .
* In this case , when the subtree will be closed , the parent item length will
* be equal to the advancement of the cursor since the creation of the subtree .
*/
2010-04-26 20:48:13 +00:00
proto_tree *
2012-03-14 17:11:39 +00:00
ptvcursor_add_with_subtree ( ptvcursor_t * ptvc , int hfindex , gint length ,
2010-05-24 06:06:17 +00:00
const guint encoding , gint ett_subtree )
2007-03-30 00:21:39 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * it ;
2009-06-12 14:32:32 +00:00
2010-05-24 06:06:17 +00:00
it = ptvcursor_add_no_advance ( ptvc , hfindex , length , encoding ) ;
2009-06-12 14:32:32 +00:00
return ptvcursor_add_subtree_item ( ptvc , it , ett_subtree , length ) ;
2007-03-30 00:21:39 +00:00
}
static proto_item *
proto_tree_add_text_node ( proto_tree * tree , tvbuff_t * tvb , gint start , gint length ) ;
/* Add a text node to the tree and create a subtree
* If the length is unknown , length may be defined as SUBTREE_UNDEFINED_LENGTH .
* In this case , when the subtree will be closed , the item length will be equal
* to the advancement of the cursor since the creation of the subtree .
*/
2009-06-12 14:32:32 +00:00
proto_tree *
2012-03-14 17:11:39 +00:00
ptvcursor_add_text_with_subtree ( ptvcursor_t * ptvc , gint length ,
2009-06-12 14:32:32 +00:00
gint ett_subtree , const char * format , . . . )
2007-03-30 00:21:39 +00:00
{
2012-08-08 03:02:27 +00:00
proto_item * pi ;
2012-03-14 17:11:39 +00:00
va_list ap ;
header_field_info * hfinfo ;
2012-08-08 03:02:27 +00:00
proto_tree * tree ;
tree = ptvcursor_tree ( ptvc ) ;
2009-08-19 19:08:34 +00:00
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hf_text_only , hfinfo ) ;
2007-03-30 00:21:39 +00:00
2012-08-08 03:02:27 +00:00
pi = proto_tree_add_text_node ( tree , ptvcursor_tvbuff ( ptvc ) ,
2010-04-26 20:48:13 +00:00
ptvcursor_current_offset ( ptvc ) , length ) ;
2007-03-30 00:21:39 +00:00
2013-07-02 20:51:58 +00:00
TRY_TO_FAKE_THIS_REPR ( pi ) ;
2009-06-12 14:32:32 +00:00
va_start ( ap , format ) ;
2012-08-08 03:02:27 +00:00
proto_tree_set_representation ( pi , format , ap ) ;
2009-06-12 14:32:32 +00:00
va_end ( ap ) ;
2007-03-30 00:21:39 +00:00
2012-08-08 03:02:27 +00:00
return ptvcursor_add_subtree_item ( ptvc , pi , ett_subtree , length ) ;
2007-03-30 00:21:39 +00:00
}
Get rid of "proto_tree_add_notext()" - if you create a subtree using it,
but, before you set the text, you throw an exception while putting stuff
under the subtree, you end up with an absolutely blank protocol tree
item, which is really gross. Instead of calling
"proto_tree_add_notext()", call "proto_tree_add_text()" with at least a
minimal label - yes, it does mean you do some work that will probably be
unnecessary, but, absent a scheme to arrange to do that work if it *is*
necessary (e.g., catching exceptions), the alternative is an ugly
protocol tree display.
svn path=/trunk/; revision=3879
2001-08-28 08:28:19 +00:00
/* Add a text-only node, leaving it to our caller to fill the text in */
static proto_item *
proto_tree_add_text_node ( proto_tree * tree , tvbuff_t * tvb , gint start , gint length )
1999-07-07 22:52:57 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
2009-08-11 18:08:03 +00:00
2013-07-02 18:56:48 +00:00
if ( tree = = NULL )
return NULL ;
2013-08-22 21:20:50 +00:00
pi = proto_tree_add_pi ( tree , & hfi_text_only , tvb , start , & length ) ;
2000-03-12 04:48:32 +00:00
1999-07-07 22:52:57 +00:00
return pi ;
}
2015-09-21 02:20:40 +00:00
/* (INTERNAL USE ONLY) Add a text-only node to the proto_tree */
1999-07-07 22:52:57 +00:00
proto_item *
2015-09-21 02:20:40 +00:00
proto_tree_add_text_internal ( proto_tree * tree , tvbuff_t * tvb , gint start , gint length ,
2010-04-26 20:48:13 +00:00
const char * format , . . . )
1999-07-07 22:52:57 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
header_field_info * hfinfo ;
2009-08-19 19:08:34 +00:00
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hf_text_only , hfinfo ) ;
1999-07-07 22:52:57 +00:00
Get rid of "proto_tree_add_notext()" - if you create a subtree using it,
but, before you set the text, you throw an exception while putting stuff
under the subtree, you end up with an absolutely blank protocol tree
item, which is really gross. Instead of calling
"proto_tree_add_notext()", call "proto_tree_add_text()" with at least a
minimal label - yes, it does mean you do some work that will probably be
unnecessary, but, absent a scheme to arrange to do that work if it *is*
necessary (e.g., catching exceptions), the alternative is an ugly
protocol tree display.
svn path=/trunk/; revision=3879
2001-08-28 08:28:19 +00:00
pi = proto_tree_add_text_node ( tree , tvb , start , length ) ;
1999-07-07 22:52:57 +00:00
2013-07-02 20:51:58 +00:00
TRY_TO_FAKE_THIS_REPR ( pi ) ;
2009-09-06 07:33:07 +00:00
2000-05-31 05:09:07 +00:00
va_start ( ap , format ) ;
proto_tree_set_representation ( pi , format , ap ) ;
va_end ( ap ) ;
1999-07-07 22:52:57 +00:00
return pi ;
}
2015-09-21 02:20:40 +00:00
/* (INTERNAL USE ONLY) Add a text-only node to the proto_tree (va_list version) */
2000-08-10 16:04:33 +00:00
proto_item *
2015-09-21 02:20:40 +00:00
proto_tree_add_text_valist_internal ( proto_tree * tree , tvbuff_t * tvb , gint start ,
2009-06-12 14:32:32 +00:00
gint length , const char * format , va_list ap )
2000-08-10 16:04:33 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
header_field_info * hfinfo ;
2009-08-19 19:08:34 +00:00
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hf_text_only , hfinfo ) ;
2000-08-10 16:04:33 +00:00
Get rid of "proto_tree_add_notext()" - if you create a subtree using it,
but, before you set the text, you throw an exception while putting stuff
under the subtree, you end up with an absolutely blank protocol tree
item, which is really gross. Instead of calling
"proto_tree_add_notext()", call "proto_tree_add_text()" with at least a
minimal label - yes, it does mean you do some work that will probably be
unnecessary, but, absent a scheme to arrange to do that work if it *is*
necessary (e.g., catching exceptions), the alternative is an ugly
protocol tree display.
svn path=/trunk/; revision=3879
2001-08-28 08:28:19 +00:00
pi = proto_tree_add_text_node ( tree , tvb , start , length ) ;
2000-08-10 16:04:33 +00:00
2013-07-02 20:51:58 +00:00
TRY_TO_FAKE_THIS_REPR ( pi ) ;
2009-09-06 07:33:07 +00:00
2000-08-10 16:04:33 +00:00
proto_tree_set_representation ( pi , format , ap ) ;
return pi ;
}
2014-06-20 06:52:37 +00:00
/* Add a text-only node that creates a subtree underneath.
*/
proto_tree *
proto_tree_add_subtree ( proto_tree * tree , tvbuff_t * tvb , gint start , gint length , gint idx , proto_item * * tree_item , const char * text )
{
return proto_tree_add_subtree_format ( tree , tvb , start , length , idx , tree_item , " %s " , text ) ;
}
/* Add a text-only node that creates a subtree underneath.
*/
proto_tree *
proto_tree_add_subtree_format ( proto_tree * tree , tvbuff_t * tvb , gint start , gint length , gint idx , proto_item * * tree_item , const char * format , . . . )
{
2014-08-04 05:39:49 +00:00
proto_tree * pt ;
proto_item * pi ;
va_list ap ;
2014-06-20 06:52:37 +00:00
va_start ( ap , format ) ;
2015-09-21 02:20:40 +00:00
pi = proto_tree_add_text_valist_internal ( tree , tvb , start , length , format , ap ) ;
2014-06-20 06:52:37 +00:00
va_end ( ap ) ;
if ( tree_item ! = NULL )
* tree_item = pi ;
2014-08-04 05:39:49 +00:00
pt = proto_item_add_subtree ( pi , idx ) ;
2014-06-20 06:52:37 +00:00
return pt ;
}
Convert IPX-and-friend dissectors in packet-ipx.c to use
tvbuffs.
In doing so, I realied that my recommendation for using
tvb_new_subset(pi.compat_top_tvb, -1, -1) was incorrect, because
some dissectors (ethernet!) change pi.len and pi.cap_len. So, I have
to take those two variables into account instead of using -1 and -1.
So, I provide a macro called tvb_create_from_top(offset), where
offset is the name of your offset variable. It is a wrapper around
tvb_new_subset().
I converted the lines that followed my suggestion to use
tvb_create_from_top().
In proto.c I added
proto_tree_add_debug_text(proto_tree*, const char*, ...)
It's much like proto_tree_add_text(), except that it takes no offset
or length; it's soley for temporarily putting debug text into the
proto_tree while debugging a dissector. In making sure that its
use is temporary, the funciton also prints the debug string to stdout
to remind the programmer that the debug code needs to be removed
before shipping the code.
svn path=/trunk/; revision=2068
2000-06-15 03:49:00 +00:00
/* Add a text-only node for debugging purposes. The caller doesn't need
* to worry about tvbuff , start , or length . Debug message gets sent to
* STDOUT , too */
proto_item *
proto_tree_add_debug_text ( proto_tree * tree , const char * format , . . . )
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
Convert IPX-and-friend dissectors in packet-ipx.c to use
tvbuffs.
In doing so, I realied that my recommendation for using
tvb_new_subset(pi.compat_top_tvb, -1, -1) was incorrect, because
some dissectors (ethernet!) change pi.len and pi.cap_len. So, I have
to take those two variables into account instead of using -1 and -1.
So, I provide a macro called tvb_create_from_top(offset), where
offset is the name of your offset variable. It is a wrapper around
tvb_new_subset().
I converted the lines that followed my suggestion to use
tvb_create_from_top().
In proto.c I added
proto_tree_add_debug_text(proto_tree*, const char*, ...)
It's much like proto_tree_add_text(), except that it takes no offset
or length; it's soley for temporarily putting debug text into the
proto_tree while debugging a dissector. In making sure that its
use is temporary, the funciton also prints the debug string to stdout
to remind the programmer that the debug code needs to be removed
before shipping the code.
svn path=/trunk/; revision=2068
2000-06-15 03:49:00 +00:00
Get rid of "proto_tree_add_notext()" - if you create a subtree using it,
but, before you set the text, you throw an exception while putting stuff
under the subtree, you end up with an absolutely blank protocol tree
item, which is really gross. Instead of calling
"proto_tree_add_notext()", call "proto_tree_add_text()" with at least a
minimal label - yes, it does mean you do some work that will probably be
unnecessary, but, absent a scheme to arrange to do that work if it *is*
necessary (e.g., catching exceptions), the alternative is an ugly
protocol tree display.
svn path=/trunk/; revision=3879
2001-08-28 08:28:19 +00:00
pi = proto_tree_add_text_node ( tree , NULL , 0 , 0 ) ;
Convert IPX-and-friend dissectors in packet-ipx.c to use
tvbuffs.
In doing so, I realied that my recommendation for using
tvb_new_subset(pi.compat_top_tvb, -1, -1) was incorrect, because
some dissectors (ethernet!) change pi.len and pi.cap_len. So, I have
to take those two variables into account instead of using -1 and -1.
So, I provide a macro called tvb_create_from_top(offset), where
offset is the name of your offset variable. It is a wrapper around
tvb_new_subset().
I converted the lines that followed my suggestion to use
tvb_create_from_top().
In proto.c I added
proto_tree_add_debug_text(proto_tree*, const char*, ...)
It's much like proto_tree_add_text(), except that it takes no offset
or length; it's soley for temporarily putting debug text into the
proto_tree while debugging a dissector. In making sure that its
use is temporary, the funciton also prints the debug string to stdout
to remind the programmer that the debug code needs to be removed
before shipping the code.
svn path=/trunk/; revision=2068
2000-06-15 03:49:00 +00:00
2010-05-26 02:25:13 +00:00
if ( pi ) {
va_start ( ap , format ) ;
2008-01-16 18:39:32 +00:00
proto_tree_set_representation ( pi , format , ap ) ;
2010-05-26 02:25:13 +00:00
va_end ( ap ) ;
}
va_start ( ap , format ) ;
Convert IPX-and-friend dissectors in packet-ipx.c to use
tvbuffs.
In doing so, I realied that my recommendation for using
tvb_new_subset(pi.compat_top_tvb, -1, -1) was incorrect, because
some dissectors (ethernet!) change pi.len and pi.cap_len. So, I have
to take those two variables into account instead of using -1 and -1.
So, I provide a macro called tvb_create_from_top(offset), where
offset is the name of your offset variable. It is a wrapper around
tvb_new_subset().
I converted the lines that followed my suggestion to use
tvb_create_from_top().
In proto.c I added
proto_tree_add_debug_text(proto_tree*, const char*, ...)
It's much like proto_tree_add_text(), except that it takes no offset
or length; it's soley for temporarily putting debug text into the
proto_tree while debugging a dissector. In making sure that its
use is temporary, the funciton also prints the debug string to stdout
to remind the programmer that the debug code needs to be removed
before shipping the code.
svn path=/trunk/; revision=2068
2000-06-15 03:49:00 +00:00
vprintf ( format , ap ) ;
va_end ( ap ) ;
printf ( " \n " ) ;
return pi ;
}
2014-05-18 07:56:20 +00:00
proto_item *
proto_tree_add_format_text ( proto_tree * tree , tvbuff_t * tvb , gint start , gint length )
{
proto_item * pi ;
header_field_info * hfinfo ;
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hf_text_only , hfinfo ) ;
2014-05-18 07:56:20 +00:00
pi = proto_tree_add_text_node ( tree , tvb , start , length ) ;
TRY_TO_FAKE_THIS_REPR ( pi ) ;
proto_item_set_text ( pi , " %s " , tvb_format_text ( tvb , start , length ) ) ;
return pi ;
}
2014-08-09 17:43:44 +00:00
proto_item *
proto_tree_add_format_wsp_text ( proto_tree * tree , tvbuff_t * tvb , gint start , gint length )
{
proto_item * pi ;
header_field_info * hfinfo ;
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-14 21:08:11 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hf_text_only , hfinfo ) ;
2014-08-09 17:43:44 +00:00
pi = proto_tree_add_text_node ( tree , tvb , start , length ) ;
TRY_TO_FAKE_THIS_REPR ( pi ) ;
proto_item_set_text ( pi , " %s " , tvb_format_text_wsp ( tvb , start , length ) ) ;
return pi ;
}
2013-11-10 16:04:15 +00:00
void proto_report_dissector_bug ( const char * message )
{
if ( getenv ( " WIRESHARK_ABORT_ON_DISSECTOR_BUG " ) ! = NULL )
abort ( ) ;
else
THROW_MESSAGE ( DissectorError , message ) ;
}
2012-08-10 23:05:04 +00:00
/* We could probably get away with changing is_error to a minimum length value. */
static void
report_type_length_mismatch ( proto_tree * tree , const gchar * descr , int length , gboolean is_error ) {
2013-10-03 01:54:02 +00:00
if ( is_error ) {
expert_add_info_format ( NULL , tree , & ei_type_length_mismatch_error , " Trying to fetch %s with length %d " , descr , length ) ;
} else {
expert_add_info_format ( NULL , tree , & ei_type_length_mismatch_warn , " Trying to fetch %s with length %d " , descr , length ) ;
}
2012-08-13 22:43:17 +00:00
2012-08-10 23:05:04 +00:00
if ( is_error ) {
THROW ( ReportedBoundsError ) ;
}
}
2000-05-31 05:09:07 +00:00
static guint32
2012-08-10 23:05:04 +00:00
get_uint_value ( proto_tree * tree , tvbuff_t * tvb , gint offset , gint length , const guint encoding )
2000-05-31 05:09:07 +00:00
{
guint32 value ;
2012-08-10 23:05:04 +00:00
gboolean length_error ;
2000-05-31 05:09:07 +00:00
switch ( length ) {
case 1 :
value = tvb_get_guint8 ( tvb , offset ) ;
break ;
case 2 :
2013-07-22 23:11:07 +00:00
value = ( encoding & ENC_LITTLE_ENDIAN ) ? tvb_get_letohs ( tvb , offset )
: tvb_get_ntohs ( tvb , offset ) ;
2000-05-31 05:09:07 +00:00
break ;
case 3 :
2013-07-22 23:11:07 +00:00
value = ( encoding & ENC_LITTLE_ENDIAN ) ? tvb_get_letoh24 ( tvb , offset )
: tvb_get_ntoh24 ( tvb , offset ) ;
2000-05-31 05:09:07 +00:00
break ;
case 4 :
2013-07-22 23:11:07 +00:00
value = ( encoding & ENC_LITTLE_ENDIAN ) ? tvb_get_letohl ( tvb , offset )
: tvb_get_ntohl ( tvb , offset ) ;
2000-05-31 05:09:07 +00:00
break ;
default :
2012-08-10 23:05:04 +00:00
if ( length < 1 ) {
length_error = TRUE ;
value = 0 ;
} else {
length_error = FALSE ;
2013-07-22 23:11:07 +00:00
value = ( encoding & ENC_LITTLE_ENDIAN ) ? tvb_get_letohl ( tvb , offset )
: tvb_get_ntohl ( tvb , offset ) ;
2012-08-10 23:05:04 +00:00
}
report_type_length_mismatch ( tree , " an unsigned integer " , length , length_error ) ;
2000-05-31 05:09:07 +00:00
break ;
}
return value ;
}
2014-09-12 07:48:45 +00:00
static inline guint64
get_uint64_value ( proto_tree * tree , tvbuff_t * tvb , gint offset , guint length , const guint encoding )
{
guint64 value ;
gboolean length_error ;
switch ( length ) {
case 1 :
value = tvb_get_guint8 ( tvb , offset ) ;
break ;
case 2 :
value = ( encoding & ENC_LITTLE_ENDIAN ) ? tvb_get_letohs ( tvb , offset )
: tvb_get_ntohs ( tvb , offset ) ;
break ;
case 3 :
value = ( encoding & ENC_LITTLE_ENDIAN ) ? tvb_get_letoh24 ( tvb , offset )
: tvb_get_ntoh24 ( tvb , offset ) ;
break ;
case 4 :
value = ( encoding & ENC_LITTLE_ENDIAN ) ? tvb_get_letohl ( tvb , offset )
: tvb_get_ntohl ( tvb , offset ) ;
break ;
case 5 :
value = ( encoding & ENC_LITTLE_ENDIAN ) ? tvb_get_letoh40 ( tvb , offset )
: tvb_get_ntoh40 ( tvb , offset ) ;
break ;
case 6 :
value = ( encoding & ENC_LITTLE_ENDIAN ) ? tvb_get_letoh48 ( tvb , offset )
: tvb_get_ntoh48 ( tvb , offset ) ;
break ;
case 7 :
value = ( encoding & ENC_LITTLE_ENDIAN ) ? tvb_get_letoh56 ( tvb , offset )
: tvb_get_ntoh56 ( tvb , offset ) ;
break ;
case 8 :
value = ( encoding & ENC_LITTLE_ENDIAN ) ? tvb_get_letoh64 ( tvb , offset )
: tvb_get_ntoh64 ( tvb , offset ) ;
break ;
default :
if ( length < 1 ) {
length_error = TRUE ;
value = 0 ;
} else {
length_error = FALSE ;
value = ( encoding & ENC_LITTLE_ENDIAN ) ? tvb_get_letoh64 ( tvb , offset )
: tvb_get_ntoh64 ( tvb , offset ) ;
}
report_type_length_mismatch ( tree , " an unsigned integer " , length , length_error ) ;
break ;
}
return value ;
}
2000-05-31 05:09:07 +00:00
static gint32
2012-08-10 23:05:04 +00:00
get_int_value ( proto_tree * tree , tvbuff_t * tvb , gint offset , gint length , const guint encoding )
2000-05-31 05:09:07 +00:00
{
gint32 value ;
2012-08-10 23:05:04 +00:00
gboolean length_error ;
2000-05-31 05:09:07 +00:00
switch ( length ) {
case 1 :
value = ( gint8 ) tvb_get_guint8 ( tvb , offset ) ;
break ;
case 2 :
2010-05-24 06:06:17 +00:00
value = ( gint16 ) ( encoding ? tvb_get_letohs ( tvb , offset )
: tvb_get_ntohs ( tvb , offset ) ) ;
2000-05-31 05:09:07 +00:00
break ;
case 3 :
2010-05-24 06:06:17 +00:00
value = encoding ? tvb_get_letoh24 ( tvb , offset )
: tvb_get_ntoh24 ( tvb , offset ) ;
2000-05-31 05:09:07 +00:00
if ( value & 0x00800000 ) {
/* Sign bit is set; sign-extend it. */
value | = 0xFF000000 ;
}
break ;
case 4 :
2010-05-24 06:06:17 +00:00
value = encoding ? tvb_get_letohl ( tvb , offset )
: tvb_get_ntohl ( tvb , offset ) ;
2000-05-31 05:09:07 +00:00
break ;
default :
2012-08-10 23:05:04 +00:00
if ( length < 1 ) {
length_error = TRUE ;
value = 0 ;
} else {
length_error = FALSE ;
value = encoding ? tvb_get_letohl ( tvb , offset )
: tvb_get_ntohl ( tvb , offset ) ;
}
2012-09-03 19:33:45 +00:00
report_type_length_mismatch ( tree , " a signed integer " , length , length_error ) ;
2000-05-31 05:09:07 +00:00
break ;
}
return value ;
}
2014-09-12 07:48:45 +00:00
/* Note: this returns an unsigned int64, but with the appropriate bit(s) set to
* be cast - able as a gint64 . This is weird , but what the code has always done .
*/
static inline guint64
get_int64_value ( proto_tree * tree , tvbuff_t * tvb , gint start , guint length , const guint encoding )
{
guint64 value = get_uint64_value ( tree , tvb , start , length , encoding ) ;
switch ( length )
{
case 7 :
value = ws_sign_ext64 ( value , 56 ) ;
break ;
case 6 :
value = ws_sign_ext64 ( value , 48 ) ;
break ;
case 5 :
value = ws_sign_ext64 ( value , 40 ) ;
break ;
case 4 :
value = ws_sign_ext64 ( value , 32 ) ;
break ;
case 3 :
value = ws_sign_ext64 ( value , 24 ) ;
break ;
case 2 :
value = ws_sign_ext64 ( value , 16 ) ;
break ;
case 1 :
value = ws_sign_ext64 ( value , 8 ) ;
break ;
}
return value ;
}
2016-02-02 04:56:56 +00:00
/* For FT_STRING */
static inline const guint8 *
get_string_value ( wmem_allocator_t * scope , tvbuff_t * tvb , gint start ,
gint length , gint * ret_length , const guint encoding )
{
if ( length = = - 1 ) {
length = tvb_ensure_captured_length_remaining ( tvb , start ) ;
}
* ret_length = length ;
return tvb_get_string_enc ( scope , tvb , start , length , encoding ) ;
}
/* For FT_STRINGZ */
static inline const guint8 *
get_stringz_value ( wmem_allocator_t * scope , proto_tree * tree , tvbuff_t * tvb ,
gint start , gint length , gint * ret_length , const guint encoding )
{
const guint8 * value ;
if ( length < - 1 ) {
report_type_length_mismatch ( tree , " a string " , length , TRUE ) ;
}
if ( length = = - 1 ) {
/* This can throw an exception */
value = tvb_get_stringz_enc ( scope , tvb , start , & length , encoding ) ;
} else if ( length = = 0 ) {
value = " [Empty] " ;
} else {
/* In this case, length signifies the length of the string.
*
* This could either be a null - padded string , which doesn ' t
* necessarily have a ' \0 ' at the end , or a null - terminated
* string , with a trailing ' \0 ' . ( Yes , there are cases
* where you have a string that ' s both counted and null -
* terminated . )
*
* In the first case , we must allocate a buffer of length
* " length+1 " , to make room for a trailing ' \0 ' .
*
* In the second case , we don ' t assume that there is a
* trailing ' \0 ' there , as the packet might be malformed .
* ( XXX - should we throw an exception if there ' s no
* trailing ' \0 ' ? ) Therefore , we allocate a buffer of
* length " length+1 " , and put in a trailing ' \0 ' , just to
* be safe .
*
* ( XXX - this would change if we made string values counted
* rather than null - terminated . )
*/
value = tvb_get_string_enc ( scope , tvb , start , length , encoding ) ;
}
* ret_length = length ;
return value ;
}
/* For FT_UINT_STRING */
static inline const guint8 *
get_uint_string_value ( wmem_allocator_t * scope , proto_tree * tree ,
tvbuff_t * tvb , gint start , gint length , gint * ret_length ,
const guint encoding )
{
guint32 n ;
const guint8 * value ;
/* I believe it's ok if this is called with a NULL tree */
n = get_uint_value ( tree , tvb , start , length , encoding & ~ ENC_CHARENCODING_MASK ) ;
value = tvb_get_string_enc ( scope , tvb , start + length , n , encoding ) ;
length + = n ;
* ret_length = length ;
return value ;
}
/* For FT_STRINGZPAD */
static inline const guint8 *
get_stringzpad_value ( wmem_allocator_t * scope , tvbuff_t * tvb , gint start ,
gint length , gint * ret_length , const guint encoding )
{
/*
* XXX - currently , string values are null -
* terminated , so a " zero-padded " string
* isn ' t special . If we represent string
* values as something that includes a counted
* array of bytes , we ' ll need to strip
* trailing NULs .
*/
if ( length = = - 1 ) {
length = tvb_ensure_captured_length_remaining ( tvb , start ) ;
}
* ret_length = length ;
return tvb_get_string_enc ( scope , tvb , start , length , encoding ) ;
}
2014-04-12 04:32:20 +00:00
/* this can be called when there is no tree, so don't add that as a param */
static void
get_time_value ( tvbuff_t * tvb , const gint start , const gint length , const guint encoding ,
nstime_t * time_stamp , const gboolean is_relative )
{
guint32 tmpsecs ;
guint64 todsecs ;
/* relative timestamps don't do TOD/NTP */
if ( is_relative & &
( encoding ! = ( ENC_TIME_TIMESPEC | ENC_BIG_ENDIAN ) ) & &
( encoding ! = ( ENC_TIME_TIMESPEC | ENC_LITTLE_ENDIAN ) ) )
{
/* XXX: I think this should call REPORT_DISSECTOR_BUG(), but
the existing code didn ' t do that , so I ' m not either */
return ;
}
switch ( encoding ) {
case ENC_TIME_TIMESPEC | ENC_BIG_ENDIAN :
/*
* 4 - byte UNIX epoch , possibly followed by
* 4 - byte fractional time in nanoseconds ,
* both big - endian .
*/
time_stamp - > secs = ( time_t ) tvb_get_ntohl ( tvb , start ) ;
if ( length = = 8 )
time_stamp - > nsecs = tvb_get_ntohl ( tvb , start + 4 ) ;
else
time_stamp - > nsecs = 0 ;
break ;
case ENC_TIME_TIMESPEC | ENC_LITTLE_ENDIAN :
/*
* 4 - byte UNIX epoch , possibly followed by
* 4 - byte fractional time in nanoseconds ,
* both little - endian .
*/
time_stamp - > secs = ( time_t ) tvb_get_letohl ( tvb , start ) ;
if ( length = = 8 )
time_stamp - > nsecs = tvb_get_letohl ( tvb , start + 4 ) ;
else
time_stamp - > nsecs = 0 ;
break ;
case ENC_TIME_TOD | ENC_BIG_ENDIAN :
/*
* TOD time stamp , big - endian .
*/
/* XXX - where should this go? */
# define TOD_BASETIME G_GUINT64_CONSTANT(2208988800)
todsecs = tvb_get_ntoh64 ( tvb , start ) > > 12 ;
time_stamp - > secs = ( time_t ) ( ( todsecs / 1000000 ) - TOD_BASETIME ) ;
time_stamp - > nsecs = ( int ) ( ( todsecs % 1000000 ) * 1000 ) ;
break ;
case ENC_TIME_TOD | ENC_LITTLE_ENDIAN :
/*
* TOD time stamp , big - endian .
*/
todsecs = tvb_get_letoh64 ( tvb , start ) > > 12 ;
time_stamp - > secs = ( time_t ) ( ( todsecs / 1000000 ) - TOD_BASETIME ) ;
time_stamp - > nsecs = ( int ) ( ( todsecs % 1000000 ) * 1000 ) ;
break ;
case ENC_TIME_NTP | ENC_BIG_ENDIAN :
/*
* NTP time stamp , big - endian .
*/
/* XXX - where should this go? */
# define NTP_BASETIME G_GUINT64_CONSTANT(2208988800)
/* We need a temporary variable here so the unsigned math
* works correctly ( for years > 2036 according to RFC 2030
* chapter 3 ) .
*/
tmpsecs = tvb_get_ntohl ( tvb , start ) ;
if ( tmpsecs )
time_stamp - > secs = ( time_t ) ( tmpsecs - ( guint32 ) NTP_BASETIME ) ;
else
time_stamp - > secs = tmpsecs ; /* 0 */
if ( length = = 8 ) {
/*
* We ' re using nanoseconds here ( and we will
* display nanoseconds ) , but NTP ' s timestamps
* have a precision in microseconds or greater .
* Round to 1 microsecond .
*/
time_stamp - > nsecs = ( int ) ( 1000000 * ( tvb_get_ntohl ( tvb , start + 4 ) / 4294967296.0 ) ) ;
time_stamp - > nsecs * = 1000 ;
} else {
time_stamp - > nsecs = 0 ;
}
break ;
case ENC_TIME_NTP | ENC_LITTLE_ENDIAN :
/*
* NTP time stamp , big - endian .
*/
tmpsecs = tvb_get_letohl ( tvb , start ) ;
if ( tmpsecs )
time_stamp - > secs = ( time_t ) ( tmpsecs - ( guint32 ) NTP_BASETIME ) ;
else
time_stamp - > secs = tmpsecs ; /* 0 */
if ( length = = 8 ) {
/*
* We ' re using nanoseconds here ( and we will
* display nanoseconds ) , but NTP ' s timestamps
* have a precision in microseconds or greater .
* Round to 1 microsecond .
*/
time_stamp - > nsecs = ( int ) ( 1000000 * ( tvb_get_letohl ( tvb , start + 4 ) / 4294967296.0 ) ) ;
time_stamp - > nsecs * = 1000 ;
} else {
time_stamp - > nsecs = 0 ;
}
break ;
2016-02-01 20:50:07 +00:00
case ENC_TIME_NTP_BASE_ZERO | ENC_BIG_ENDIAN :
/*
* DDS NTP time stamp , big - endian .
*/
2015-10-20 15:05:42 +00:00
# define NTP_BASETIME_ZERO G_GUINT64_CONSTANT(0)
2016-02-01 20:50:07 +00:00
tmpsecs = tvb_get_ntohl ( tvb , start ) ;
if ( tmpsecs )
time_stamp - > secs = ( time_t ) ( tmpsecs - ( guint32 ) NTP_BASETIME_ZERO ) ;
else
time_stamp - > secs = tmpsecs ; /* 0 */
if ( length = = 8 ) {
/*
* We ' re using nanoseconds here ( and we will
* display nanoseconds ) , but NTP ' s timestamps
* have a precision in microseconds or greater .
* Round to 1 microsecond .
*/
time_stamp - > nsecs = ( int ) ( 1000000 * ( tvb_get_ntohl ( tvb , start + 4 ) / 4294967296.0 ) ) ;
time_stamp - > nsecs * = 1000 ;
} else {
time_stamp - > nsecs = 0 ;
}
break ;
case ENC_TIME_NTP_BASE_ZERO | ENC_LITTLE_ENDIAN :
/*
* NTP time stamp , big - endian .
*/
tmpsecs = tvb_get_letohl ( tvb , start ) ;
if ( tmpsecs )
time_stamp - > secs = ( time_t ) ( tmpsecs - ( guint32 ) NTP_BASETIME_ZERO ) ;
else
time_stamp - > secs = tmpsecs ; /* 0 */
time_stamp - > secs = ( time_t ) tvb_get_letohl ( tvb , start ) ;
if ( length = = 8 ) {
/*
* We ' re using nanoseconds here ( and we will
* display nanoseconds ) , but NTP ' s timestamps
* have a precision in microseconds or greater .
* Round to 1 microsecond .
*/
time_stamp - > nsecs = ( int ) ( 1000000 * ( tvb_get_letohl ( tvb , start + 4 ) / 4294967296.0 ) ) ;
time_stamp - > nsecs * = 1000 ;
} else {
time_stamp - > nsecs = 0 ;
}
break ;
2014-04-12 04:32:20 +00:00
default :
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
break ;
}
}
2013-07-02 19:23:10 +00:00
static void
2013-07-02 21:26:14 +00:00
tree_data_add_maybe_interesting_field ( tree_data_t * tree_data , field_info * fi )
2009-07-18 20:10:14 +00:00
{
2013-07-02 21:26:14 +00:00
const header_field_info * hfinfo = fi - > hfinfo ;
2009-07-18 20:10:14 +00:00
2009-09-30 14:02:49 +00:00
if ( hfinfo - > ref_type = = HF_REF_TYPE_DIRECT ) {
2013-07-02 21:26:14 +00:00
GPtrArray * ptrs = NULL ;
2013-07-02 19:23:10 +00:00
if ( tree_data - > interesting_hfids = = NULL ) {
2009-07-18 20:10:14 +00:00
/* Initialize the hash because we now know that it is needed */
2013-07-02 19:23:10 +00:00
tree_data - > interesting_hfids =
2012-11-03 20:51:19 +00:00
g_hash_table_new ( g_direct_hash , NULL /* g_direct_equal */ ) ;
2014-06-19 22:41:49 +00:00
} else if ( g_hash_table_size ( tree_data - > interesting_hfids ) ) {
2013-07-02 21:26:14 +00:00
ptrs = ( GPtrArray * ) g_hash_table_lookup ( tree_data - > interesting_hfids ,
2010-04-26 20:48:13 +00:00
GINT_TO_POINTER ( hfinfo - > id ) ) ;
2014-06-19 22:41:49 +00:00
}
2009-07-18 20:10:14 +00:00
if ( ! ptrs ) {
/* First element triggers the creation of pointer array */
ptrs = g_ptr_array_new ( ) ;
2013-07-02 19:23:10 +00:00
g_hash_table_insert ( tree_data - > interesting_hfids ,
2010-04-26 20:48:13 +00:00
GINT_TO_POINTER ( hfinfo - > id ) , ptrs ) ;
2009-07-18 20:10:14 +00:00
}
2013-07-02 19:23:10 +00:00
g_ptr_array_add ( ptrs , fi ) ;
}
2009-07-18 20:10:14 +00:00
}
2000-05-31 05:09:07 +00:00
/* Add an item to a proto_tree, using the text label registered to that item;
the item is extracted from the tvbuff handed to it . */
2005-10-22 05:43:09 +00:00
static proto_item *
2009-07-18 20:10:14 +00:00
proto_tree_new_item ( field_info * new_fi , proto_tree * tree ,
2010-04-26 20:48:13 +00:00
tvbuff_t * tvb , gint start , gint length ,
2012-11-02 11:44:50 +00:00
guint encoding )
1999-07-07 22:52:57 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
guint32 value , n ;
float floatval ;
double doubleval ;
2016-02-02 04:56:56 +00:00
const char * stringval ;
2012-03-14 17:11:39 +00:00
nstime_t time_stamp ;
2012-08-10 23:05:04 +00:00
gboolean length_error ;
2000-03-12 04:48:32 +00:00
2012-03-14 17:11:39 +00:00
switch ( new_fi - > hfinfo - > type ) {
2000-05-31 05:09:07 +00:00
case FT_NONE :
/* no value to set for FT_NONE */
break ;
2001-02-01 20:21:25 +00:00
case FT_PROTOCOL :
proto_tree_set_protocol_tvb ( new_fi , tvb ) ;
break ;
2000-05-31 05:09:07 +00:00
case FT_BYTES :
proto_tree_set_bytes_tvb ( new_fi , tvb , start , length ) ;
break ;
2002-05-09 23:50:34 +00:00
case FT_UINT_BYTES :
2011-02-07 08:18:12 +00:00
/*
* Map all non - zero values to little - endian for
* backwards compatibility .
*/
if ( encoding )
encoding = ENC_LITTLE_ENDIAN ;
2012-08-10 23:05:04 +00:00
n = get_uint_value ( tree , tvb , start , length , encoding ) ;
2002-05-09 23:50:34 +00:00
proto_tree_set_bytes_tvb ( new_fi , tvb , start + length , n ) ;
/* Instead of calling proto_item_set_len(), since we don't yet
* have a proto_item , we set the field_info ' s length ourselves . */
new_fi - > length = n + length ;
break ;
2000-05-31 05:09:07 +00:00
case FT_BOOLEAN :
2011-02-07 08:18:12 +00:00
/*
* Map all non - zero values to little - endian for
* backwards compatibility .
*/
if ( encoding )
encoding = ENC_LITTLE_ENDIAN ;
2000-05-31 05:09:07 +00:00
proto_tree_set_boolean ( new_fi ,
2014-09-17 16:39:22 +00:00
get_uint64_value ( tree , tvb , start , length , encoding ) ) ;
2000-05-31 05:09:07 +00:00
break ;
/* XXX - make these just FT_UINT? */
case FT_UINT8 :
case FT_UINT16 :
case FT_UINT24 :
case FT_UINT32 :
2011-02-07 08:18:12 +00:00
/*
* Map all non - zero values to little - endian for
* backwards compatibility .
*/
if ( encoding )
encoding = ENC_LITTLE_ENDIAN ;
2000-05-31 05:09:07 +00:00
proto_tree_set_uint ( new_fi ,
2012-08-10 23:05:04 +00:00
get_uint_value ( tree , tvb , start , length , encoding ) ) ;
2000-05-31 05:09:07 +00:00
break ;
2014-12-17 20:19:20 +00:00
case FT_UINT40 :
case FT_UINT48 :
case FT_UINT56 :
2001-10-29 21:13:13 +00:00
case FT_UINT64 :
2011-02-07 08:18:12 +00:00
/*
* Map all non - zero values to little - endian for
* backwards compatibility .
*/
if ( encoding )
encoding = ENC_LITTLE_ENDIAN ;
2014-09-12 07:48:45 +00:00
proto_tree_set_uint64 ( new_fi ,
get_uint64_value ( tree , tvb , start , length , encoding ) ) ;
2001-10-29 21:13:13 +00:00
break ;
2000-05-31 05:09:07 +00:00
/* XXX - make these just FT_INT? */
case FT_INT8 :
case FT_INT16 :
case FT_INT24 :
case FT_INT32 :
2011-02-07 08:18:12 +00:00
/*
* Map all non - zero values to little - endian for
* backwards compatibility .
*/
if ( encoding )
encoding = ENC_LITTLE_ENDIAN ;
2000-05-31 05:09:07 +00:00
proto_tree_set_int ( new_fi ,
2012-08-10 23:05:04 +00:00
get_int_value ( tree , tvb , start , length , encoding ) ) ;
2000-05-31 05:09:07 +00:00
break ;
2014-12-17 20:19:20 +00:00
case FT_INT40 :
case FT_INT48 :
case FT_INT56 :
2014-09-12 07:48:45 +00:00
case FT_INT64 :
/*
* Map all non - zero values to little - endian for
* backwards compatibility .
*/
if ( encoding )
encoding = ENC_LITTLE_ENDIAN ;
2015-02-22 07:26:06 +00:00
proto_tree_set_int64 ( new_fi ,
2014-09-12 07:48:45 +00:00
get_int64_value ( tree , tvb , start , length , encoding ) ) ;
break ;
2000-05-31 05:09:07 +00:00
case FT_IPv4 :
2011-02-07 08:18:12 +00:00
/*
* Map all non - zero values to little - endian for
* backwards compatibility .
*/
if ( encoding )
encoding = ENC_LITTLE_ENDIAN ;
2012-08-10 23:05:04 +00:00
if ( length ! = FT_IPv4_LEN ) {
length_error = length < FT_IPv4_LEN ? TRUE : FALSE ;
report_type_length_mismatch ( tree , " an IPv4 address " , length , length_error ) ;
}
2005-09-10 19:43:41 +00:00
value = tvb_get_ipv4 ( tvb , start ) ;
2010-05-24 06:06:17 +00:00
/*
* NOTE : to support code written when
* proto_tree_add_item ( ) took a gboolean as its
* last argument , with FALSE meaning " big-endian "
* and TRUE meaning " little-endian " , we treat any
* non - zero value of " encoding " as meaning
* " little-endian " .
*/
proto_tree_set_ipv4 ( new_fi , encoding ? GUINT32_SWAP_LE_BE ( value ) : value ) ;
2000-05-31 05:09:07 +00:00
break ;
case FT_IPXNET :
2012-08-10 23:05:04 +00:00
if ( length ! = FT_IPXNET_LEN ) {
length_error = length < FT_IPXNET_LEN ? TRUE : FALSE ;
report_type_length_mismatch ( tree , " an IPXNET address " , length , length_error ) ;
}
Convert IPX-and-friend dissectors in packet-ipx.c to use
tvbuffs.
In doing so, I realied that my recommendation for using
tvb_new_subset(pi.compat_top_tvb, -1, -1) was incorrect, because
some dissectors (ethernet!) change pi.len and pi.cap_len. So, I have
to take those two variables into account instead of using -1 and -1.
So, I provide a macro called tvb_create_from_top(offset), where
offset is the name of your offset variable. It is a wrapper around
tvb_new_subset().
I converted the lines that followed my suggestion to use
tvb_create_from_top().
In proto.c I added
proto_tree_add_debug_text(proto_tree*, const char*, ...)
It's much like proto_tree_add_text(), except that it takes no offset
or length; it's soley for temporarily putting debug text into the
proto_tree while debugging a dissector. In making sure that its
use is temporary, the funciton also prints the debug string to stdout
to remind the programmer that the debug code needs to be removed
before shipping the code.
svn path=/trunk/; revision=2068
2000-06-15 03:49:00 +00:00
proto_tree_set_ipxnet ( new_fi ,
2013-07-22 23:11:07 +00:00
get_uint_value ( tree , tvb , start , FT_IPXNET_LEN , ENC_BIG_ENDIAN ) ) ;
2000-05-31 05:09:07 +00:00
break ;
case FT_IPv6 :
2012-08-10 23:05:04 +00:00
if ( length ! = FT_IPv6_LEN ) {
length_error = length < FT_IPv6_LEN ? TRUE : FALSE ;
report_type_length_mismatch ( tree , " an IPv6 address " , length , length_error ) ;
}
2009-08-28 09:38:34 +00:00
proto_tree_set_ipv6_tvb ( new_fi , tvb , start , length ) ;
2000-05-31 05:09:07 +00:00
break ;
2014-12-24 05:06:35 +00:00
case FT_FCWWN :
if ( length ! = FT_FCWWN_LEN ) {
length_error = length < FT_FCWWN_LEN ? TRUE : FALSE ;
report_type_length_mismatch ( tree , " an FCWWN address " , length , length_error ) ;
}
proto_tree_set_fcwwn_tvb ( new_fi , tvb , start , length ) ;
break ;
2012-08-02 16:54:43 +00:00
case FT_AX25 :
2012-08-10 23:05:04 +00:00
if ( length ! = 7 ) {
length_error = length < 7 ? TRUE : FALSE ;
2013-07-15 18:06:29 +00:00
report_type_length_mismatch ( tree , " an AX.25 address " , length , length_error ) ;
2012-08-10 23:05:04 +00:00
}
2012-08-02 16:54:43 +00:00
proto_tree_set_ax25_tvb ( new_fi , tvb , start ) ;
break ;
2013-07-28 00:07:49 +00:00
case FT_VINES :
if ( length ! = VINES_ADDR_LEN ) {
length_error = length < VINES_ADDR_LEN ? TRUE : FALSE ;
report_type_length_mismatch ( tree , " a Vines address " , length , length_error ) ;
}
proto_tree_set_vines_tvb ( new_fi , tvb , start ) ;
break ;
2000-05-31 05:09:07 +00:00
case FT_ETHER :
2012-08-10 23:05:04 +00:00
if ( length ! = FT_ETHER_LEN ) {
length_error = length < FT_ETHER_LEN ? TRUE : FALSE ;
2014-06-01 21:28:11 +00:00
report_type_length_mismatch ( tree , " a MAC address " , length , length_error ) ;
2012-08-10 23:05:04 +00:00
}
2000-05-31 05:09:07 +00:00
proto_tree_set_ether_tvb ( new_fi , tvb , start ) ;
break ;
2011-05-08 10:23:53 +00:00
case FT_EUI64 :
/*
* Map all non - zero values to little - endian for
* backwards compatibility .
*/
if ( encoding )
encoding = ENC_LITTLE_ENDIAN ;
2012-08-10 23:05:04 +00:00
if ( length ! = FT_EUI64_LEN ) {
length_error = length < FT_EUI64_LEN ? TRUE : FALSE ;
report_type_length_mismatch ( tree , " an EUI-64 address " , length , length_error ) ;
}
2011-05-08 10:23:53 +00:00
proto_tree_set_eui64_tvb ( new_fi , tvb , start , encoding ) ;
break ;
2005-07-04 13:04:53 +00:00
case FT_GUID :
2011-02-07 08:18:12 +00:00
/*
* Map all non - zero values to little - endian for
* backwards compatibility .
*/
if ( encoding )
encoding = ENC_LITTLE_ENDIAN ;
2012-08-10 23:05:04 +00:00
if ( length ! = FT_GUID_LEN ) {
length_error = length < FT_GUID_LEN ? TRUE : FALSE ;
report_type_length_mismatch ( tree , " a GUID " , length , length_error ) ;
}
2010-05-24 06:06:17 +00:00
proto_tree_set_guid_tvb ( new_fi , tvb , start , encoding ) ;
2005-07-04 13:04:53 +00:00
break ;
2005-12-02 13:16:58 +00:00
case FT_OID :
2013-10-06 02:31:10 +00:00
case FT_REL_OID :
2005-12-02 13:16:58 +00:00
proto_tree_set_oid_tvb ( new_fi , tvb , start , length ) ;
break ;
2013-12-23 15:18:48 +00:00
case FT_SYSTEM_ID :
proto_tree_set_system_id_tvb ( new_fi , tvb , start , length ) ;
break ;
2004-08-10 21:23:34 +00:00
case FT_FLOAT :
2010-05-24 06:06:17 +00:00
/*
* NOTE : to support code written when
* proto_tree_add_item ( ) took a gboolean as its
* last argument , with FALSE meaning " big-endian "
* and TRUE meaning " little-endian " , we treat any
* non - zero value of " encoding " as meaning
* " little-endian " .
*
* At some point in the future , we might
* support non - IEEE - binary floating - point
* formats in the encoding as well
* ( IEEE decimal , System / 3 x0 , VAX ) .
*/
2011-02-07 08:18:12 +00:00
if ( encoding )
encoding = ENC_LITTLE_ENDIAN ;
2012-08-10 23:05:04 +00:00
if ( length ! = 4 ) {
length_error = length < 4 ? TRUE : FALSE ;
report_type_length_mismatch ( tree , " a single-precision floating point number " , length , length_error ) ;
}
2010-05-24 06:06:17 +00:00
if ( encoding )
2004-08-10 21:23:34 +00:00
floatval = tvb_get_letohieee_float ( tvb , start ) ;
else
floatval = tvb_get_ntohieee_float ( tvb , start ) ;
proto_tree_set_float ( new_fi , floatval ) ;
break ;
case FT_DOUBLE :
2010-05-24 06:06:17 +00:00
/*
* NOTE : to support code written when
* proto_tree_add_item ( ) took a gboolean as its
* last argument , with FALSE meaning " big-endian "
* and TRUE meaning " little-endian " , we treat any
* non - zero value of " encoding " as meaning
* " little-endian " .
*
* At some point in the future , we might
* support non - IEEE - binary floating - point
* formats in the encoding as well
* ( IEEE decimal , System / 3 x0 , VAX ) .
*/
2011-02-07 08:18:12 +00:00
if ( encoding = = TRUE )
encoding = ENC_LITTLE_ENDIAN ;
2012-08-12 15:48:36 +00:00
if ( length ! = 8 ) {
2012-08-10 23:05:04 +00:00
length_error = length < 8 ? TRUE : FALSE ;
report_type_length_mismatch ( tree , " a double-precision floating point number " , length , length_error ) ;
}
2010-05-24 06:06:17 +00:00
if ( encoding )
2004-08-10 21:23:34 +00:00
doubleval = tvb_get_letohieee_double ( tvb , start ) ;
else
doubleval = tvb_get_ntohieee_double ( tvb , start ) ;
proto_tree_set_double ( new_fi , doubleval ) ;
break ;
2000-05-31 05:09:07 +00:00
case FT_STRING :
2016-02-02 04:56:56 +00:00
stringval = get_string_value ( wmem_packet_scope ( ) ,
tvb , start , length , & length , encoding ) ;
proto_tree_set_string ( new_fi , stringval ) ;
/* Instead of calling proto_item_set_len(), since we
* don ' t yet have a proto_item , we set the
* field_info ' s length ourselves .
*
* XXX - our caller can ' t use that length to
* advance an offset unless they arrange that
* there always be a protocol tree into which
* we ' re putting this item .
*/
new_fi - > length = length ;
2000-05-31 05:09:07 +00:00
break ;
2000-08-30 02:50:18 +00:00
case FT_STRINGZ :
2016-02-02 04:56:56 +00:00
stringval = get_stringz_value ( wmem_packet_scope ( ) ,
tree , tvb , start , length , & length , encoding ) ;
proto_tree_set_string ( new_fi , stringval ) ;
2005-06-15 15:10:02 +00:00
/* Instead of calling proto_item_set_len(),
* since we don ' t yet have a proto_item , we
* set the field_info ' s length ourselves .
*
* XXX - our caller can ' t use that length to
* advance an offset unless they arrange that
* there always be a protocol tree into which
* we ' re putting this item .
*/
new_fi - > length = length ;
2000-08-30 02:50:18 +00:00
break ;
2000-08-22 06:38:32 +00:00
case FT_UINT_STRING :
2011-02-07 08:18:12 +00:00
/*
* NOTE : to support code written when
* proto_tree_add_item ( ) took a gboolean as its
* last argument , with FALSE meaning " big-endian "
2012-05-11 23:55:54 +00:00
* and TRUE meaning " little-endian " , if the
* encoding value is TRUE , treat that as
* ASCII with a little - endian length .
2011-02-07 08:18:12 +00:00
*
2012-05-11 23:55:54 +00:00
* This won ' t work for code that passes
* arbitrary non - zero values ; that code
* will need to be fixed .
2011-02-07 08:18:12 +00:00
*/
2012-05-11 23:55:54 +00:00
if ( encoding = = TRUE )
encoding = ENC_ASCII | ENC_LITTLE_ENDIAN ;
2016-02-02 04:56:56 +00:00
stringval = get_uint_string_value ( wmem_packet_scope ( ) ,
tree , tvb , start , length , & length , encoding ) ;
proto_tree_set_string ( new_fi , stringval ) ;
2000-08-22 06:38:32 +00:00
When "proto_tree_add_item()" is used with an FT_STRINGZ and given a
length (rather than being given -1), the length is, in most cases, the
maximum length of a null-*padded* string, rather than the actual length
of a null-*terminated* string. Treat it as such - allocate a buffer one
larger than the length (to leave room for a terminating '\0'), and pass
the size of that buffer to "tvb_get_nstringz0()". (Otherwise, in those
cases, the last character of the string is chopped off.)
Allow "proto_tree_add_string()" to add FT_STRINGZ items to the protocol
tree, as well as FT_STRING items.
In "alloc_field_info()", if we're passed a length of -1 and the field is
an FT_STRINGZ, don't make the length be the length remaining in the
tvbuff; that way, you *can* use a length of -1 in
"proto_tree_add_item()" for an FT_STRINGZ item, and have it get the
actual length by looking for the terminating '\0'.
(We might want to distinguish between null-terminated and null-padded
strings, e.g. with an FT_STRINGZPAD type. Null-terminated strings
rarely, if ever, have a specified length; the length is found by
scanning for the terminating '\0'. Null-padded strings presumably
always have a specified length, which is the length to which the string
is padded.)
svn path=/trunk/; revision=7784
2003-06-04 21:51:54 +00:00
/* Instead of calling proto_item_set_len(), since we
* don ' t yet have a proto_item , we set the
* field_info ' s length ourselves .
*
* XXX - our caller can ' t use that length to
* advance an offset unless they arrange that
* there always be a protocol tree into which
* we ' re putting this item .
*/
2016-02-02 04:56:56 +00:00
new_fi - > length = length ;
2000-07-27 06:41:59 +00:00
break ;
When "proto_tree_add_item()" is used with an FT_STRINGZ and given a
length (rather than being given -1), the length is, in most cases, the
maximum length of a null-*padded* string, rather than the actual length
of a null-*terminated* string. Treat it as such - allocate a buffer one
larger than the length (to leave room for a terminating '\0'), and pass
the size of that buffer to "tvb_get_nstringz0()". (Otherwise, in those
cases, the last character of the string is chopped off.)
Allow "proto_tree_add_string()" to add FT_STRINGZ items to the protocol
tree, as well as FT_STRING items.
In "alloc_field_info()", if we're passed a length of -1 and the field is
an FT_STRINGZ, don't make the length be the length remaining in the
tvbuff; that way, you *can* use a length of -1 in
"proto_tree_add_item()" for an FT_STRINGZ item, and have it get the
actual length by looking for the terminating '\0'.
(We might want to distinguish between null-terminated and null-padded
strings, e.g. with an FT_STRINGZPAD type. Null-terminated strings
rarely, if ever, have a specified length; the length is found by
scanning for the terminating '\0'. Null-padded strings presumably
always have a specified length, which is the length to which the string
is padded.)
svn path=/trunk/; revision=7784
2003-06-04 21:51:54 +00:00
2014-04-12 22:26:34 +00:00
case FT_STRINGZPAD :
2016-02-02 04:56:56 +00:00
stringval = get_stringzpad_value ( wmem_packet_scope ( ) ,
tvb , start , length , & length , encoding ) ;
proto_tree_set_string ( new_fi , stringval ) ;
/* Instead of calling proto_item_set_len(), since we
* don ' t yet have a proto_item , we set the
* field_info ' s length ourselves .
*
* XXX - our caller can ' t use that length to
* advance an offset unless they arrange that
* there always be a protocol tree into which
* we ' re putting this item .
2014-04-12 22:26:34 +00:00
*/
2016-02-02 04:56:56 +00:00
new_fi - > length = length ;
2014-04-12 22:26:34 +00:00
break ;
2010-05-10 06:32:31 +00:00
case FT_ABSOLUTE_TIME :
2011-02-07 08:18:12 +00:00
/*
* Absolute times can be in any of a number of
* formats , and they can be big - endian or
* little - endian .
*
* Historically FT_TIMEs were only timespecs ;
* the only question was whether they were stored
* in big - or little - endian format .
*
* For backwards compatibility , we interpret an
* encoding of 1 as meaning " little-endian timespec " ,
* so that passing TRUE is interpreted as that .
2010-05-24 06:06:17 +00:00
*/
2011-02-07 08:18:12 +00:00
if ( encoding = = TRUE )
encoding = ENC_TIME_TIMESPEC | ENC_LITTLE_ENDIAN ;
2011-02-08 02:38:51 +00:00
2012-08-10 23:05:04 +00:00
if ( length ! = 8 & & length ! = 4 ) {
length_error = length < 4 ? TRUE : FALSE ;
report_type_length_mismatch ( tree , " an absolute time value " , length , length_error ) ;
}
2014-04-12 04:32:20 +00:00
get_time_value ( tvb , start , length , encoding , & time_stamp , FALSE ) ;
2011-02-07 08:18:12 +00:00
proto_tree_set_time ( new_fi , & time_stamp ) ;
break ;
case FT_RELATIVE_TIME :
/*
* Relative times can be in any of a number of
* formats , and they can be big - endian or
* little - endian .
*
* Historically FT_TIMEs were only timespecs ;
* the only question was whether they were stored
* in big - or little - endian format .
*
* For backwards compatibility , we interpret an
* encoding of 1 as meaning " little-endian timespec " ,
* so that passing TRUE is interpreted as that .
*/
if ( encoding = = TRUE )
encoding = ENC_TIME_TIMESPEC | ENC_LITTLE_ENDIAN ;
2012-08-10 23:05:04 +00:00
if ( length ! = 8 & & length ! = 4 ) {
length_error = length < 4 ? TRUE : FALSE ;
report_type_length_mismatch ( tree , " a relative time value " , length , length_error ) ;
}
2014-04-12 04:32:20 +00:00
get_time_value ( tvb , start , length , encoding , & time_stamp , TRUE ) ;
2011-02-07 08:18:12 +00:00
2010-05-10 06:32:31 +00:00
proto_tree_set_time ( new_fi , & time_stamp ) ;
break ;
2015-09-06 17:01:47 +00:00
case FT_IEEE_11073_SFLOAT :
if ( encoding )
encoding = ENC_LITTLE_ENDIAN ;
if ( length ! = 2 ) {
length_error = length < 2 ? TRUE : FALSE ;
report_type_length_mismatch ( tree , " a IEEE 11073 SFLOAT " , length , length_error ) ;
}
fvalue_set_uinteger ( & new_fi - > value , tvb_get_guint16 ( tvb , start , encoding ) ) ;
2010-05-10 06:32:31 +00:00
2015-09-06 17:01:47 +00:00
break ;
case FT_IEEE_11073_FLOAT :
if ( encoding )
encoding = ENC_LITTLE_ENDIAN ;
if ( length ! = 4 ) {
length_error = length < 4 ? TRUE : FALSE ;
report_type_length_mismatch ( tree , " a IEEE 11073 FLOAT " , length , length_error ) ;
}
break ;
2000-05-31 05:09:07 +00:00
default :
2003-12-03 09:28:26 +00:00
g_error ( " new_fi->hfinfo->type %d (%s) not handled \n " ,
new_fi - > hfinfo - > type ,
ftype_name ( new_fi - > hfinfo - > type ) ) ;
2005-03-23 00:09:12 +00:00
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
2001-05-09 01:22:46 +00:00
break ;
2000-05-31 05:09:07 +00:00
}
2011-02-07 08:18:12 +00:00
FI_SET_FLAG ( new_fi , ( encoding & ENC_LITTLE_ENDIAN ) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN ) ;
2000-05-31 05:09:07 +00:00
tvb_get_nstringz() needs to terminate a string with a NUL if the
end of the tvbuff is reached before the maximum_length passed by the
caller is reached and before a terminating NUL is found. In this case,
tvb_get_nstringz() returns a -1, but if the string is not artificially
terminated with a NUL by tvb_get_nstringz(), the
caller has no idea where the string should end because 1) the
return value "-1" gives the impression that the string ends
at the end of the buffer but 2) the string does
not end at the end of the buffer, but somewhere in the middle, due
to the packet being shorter than expected.
tvb_get_nstringz() and tvb_get_nstringz0() were both modified.
The FT_STRINGZ case in proto_tree_add_item() is made simpler.
During regression testing, when investigating a regression that I later
corrected, I discovered that strings added through proto_tree_add_item
(FT_STRING, FT_STRINGZ, and FT_UINT_STRING) leaked memory due to double
allocation of the string. The proto_tree_add_string*() functions do
not leak memory, since they only copy the string once. The memory
leak was fixed by adding another argument to the static function
proto_tree_set_string() to let the string ftype code know to g_strdup()
the string or not.
svn path=/trunk/; revision=4891
2002-03-06 19:17:06 +00:00
/* Don't add new node to proto_tree until now so that any exceptions
2000-07-27 06:41:59 +00:00
* raised by a tvbuff access method doesn ' t leave junk in the proto_tree . */
2012-09-03 12:00:08 +00:00
/* XXX. wouldn't be better to add this item to tree, with some special flag (FI_EXCEPTION?)
* to know which item caused exception ? */
2000-07-27 06:41:59 +00:00
pi = proto_tree_add_node ( tree , new_fi ) ;
2000-05-31 05:09:07 +00:00
return pi ;
}
2015-02-13 08:34:16 +00:00
proto_item *
proto_tree_add_item_ret_int ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
2016-01-20 20:36:54 +00:00
const gint start , gint length ,
const guint encoding , gint32 * retval )
2015-02-13 08:34:16 +00:00
{
header_field_info * hfinfo = proto_registrar_get_nth ( hfindex ) ;
field_info * new_fi ;
2015-04-09 16:28:27 +00:00
gint32 value ;
2015-02-13 08:34:16 +00:00
2015-06-23 17:58:38 +00:00
DISSECTOR_ASSERT_HINT ( hfinfo ! = NULL , " Not passed hfi! " ) ;
2015-02-13 08:34:16 +00:00
switch ( hfinfo - > type ) {
case FT_INT8 :
case FT_INT16 :
case FT_INT24 :
case FT_INT32 :
break ;
default :
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
}
2015-04-09 16:28:27 +00:00
/* length validation for native number encoding caught by get_uint_value() */
/* length has to be -1 or > 0 regardless of encoding */
if ( length < - 1 | | length = = 0 )
REPORT_DISSECTOR_BUG ( wmem_strdup_printf ( wmem_packet_scope ( ) ,
" Invalid length %d passed to proto_tree_add_item_ret_int " ,
length ) ) ;
if ( encoding & ENC_STRING ) {
REPORT_DISSECTOR_BUG ( " wrong encoding " ) ;
}
/* I believe it's ok if this is called with a NULL tree */
value = get_int_value ( tree , tvb , start , length , encoding ) ;
if ( retval )
* retval = value ;
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2015-04-09 16:28:27 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfinfo - > id , hfinfo ) ;
new_fi = new_field_info ( tree , hfinfo , tvb , start , length ) ;
proto_tree_set_int ( new_fi , value ) ;
2016-01-20 20:36:54 +00:00
new_fi - > flags | = ( encoding & ENC_LITTLE_ENDIAN ) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN ;
2015-04-09 16:28:27 +00:00
return proto_tree_add_node ( tree , new_fi ) ;
2015-02-13 08:34:16 +00:00
}
proto_item *
proto_tree_add_item_ret_uint ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
2016-01-09 02:25:26 +00:00
const gint start , gint length ,
const guint encoding , guint32 * retval )
2015-02-13 08:34:16 +00:00
{
header_field_info * hfinfo = proto_registrar_get_nth ( hfindex ) ;
field_info * new_fi ;
guint32 value ;
2015-06-23 17:58:38 +00:00
DISSECTOR_ASSERT_HINT ( hfinfo ! = NULL , " Not passed hfi! " ) ;
2015-02-13 08:34:16 +00:00
switch ( hfinfo - > type ) {
case FT_UINT8 :
case FT_UINT16 :
case FT_UINT24 :
case FT_UINT32 :
break ;
default :
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
}
2015-04-09 16:28:27 +00:00
/* length validation for native number encoding caught by get_uint_value() */
/* length has to be -1 or > 0 regardless of encoding */
if ( length < - 1 | | length = = 0 )
REPORT_DISSECTOR_BUG ( wmem_strdup_printf ( wmem_packet_scope ( ) ,
" Invalid length %d passed to proto_tree_add_item_ret_uint " ,
length ) ) ;
if ( encoding & ENC_STRING ) {
REPORT_DISSECTOR_BUG ( " wrong encoding " ) ;
}
/* I believe it's ok if this is called with a NULL tree */
value = get_uint_value ( tree , tvb , start , length , encoding ) ;
if ( retval )
* retval = value ;
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2015-04-09 16:28:27 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfinfo - > id , hfinfo ) ;
new_fi = new_field_info ( tree , hfinfo , tvb , start , length ) ;
proto_tree_set_uint ( new_fi , value ) ;
2016-01-20 20:36:54 +00:00
new_fi - > flags | = ( encoding & ENC_LITTLE_ENDIAN ) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN ;
2015-04-09 16:28:27 +00:00
return proto_tree_add_node ( tree , new_fi ) ;
2015-02-13 08:34:16 +00:00
}
2016-02-02 04:56:56 +00:00
proto_item *
proto_tree_add_item_ret_string ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
const gint start , gint length ,
const guint encoding , wmem_allocator_t * scope ,
const guint8 * * retval )
{
header_field_info * hfinfo = proto_registrar_get_nth ( hfindex ) ;
field_info * new_fi ;
const guint8 * value ;
DISSECTOR_ASSERT_HINT ( hfinfo ! = NULL , " Not passed hfi! " ) ;
switch ( hfinfo - > type ) {
case FT_STRING :
value = get_string_value ( scope , tvb , start , length , & length , encoding ) ;
break ;
case FT_STRINGZ :
value = get_stringz_value ( scope , tree , tvb , start , length , & length , encoding ) ;
break ;
case FT_UINT_STRING :
value = get_uint_string_value ( scope , tree , tvb , start , length , & length , encoding ) ;
break ;
case FT_STRINGZPAD :
value = get_stringzpad_value ( scope , tvb , start , length , & length , encoding ) ;
break ;
default :
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
}
if ( retval )
* retval = value ;
CHECK_FOR_NULL_TREE ( tree ) ;
TRY_TO_FAKE_THIS_ITEM ( tree , hfinfo - > id , hfinfo ) ;
new_fi = new_field_info ( tree , hfinfo , tvb , start , length ) ;
proto_tree_set_string ( new_fi , value ) ;
new_fi - > flags | = ( encoding & ENC_LITTLE_ENDIAN ) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN ;
return proto_tree_add_node ( tree , new_fi ) ;
}
2015-07-16 03:10:16 +00:00
/*
* Validates that field length bytes are available starting from
* start ( pos / neg ) . Throws an exception if they aren ' t .
*/
static void
test_length ( header_field_info * hfinfo , tvbuff_t * tvb ,
gint start , gint length )
{
gint size = length ;
if ( ! tvb )
return ;
if ( hfinfo - > type = = FT_STRINGZ ) {
/* If we're fetching until the end of the TVB, only validate
* that the offset is within range .
*/
if ( length = = - 1 )
size = 0 ;
}
tvb_ensure_bytes_exist ( tvb , start , size ) ;
}
2005-10-22 05:43:09 +00:00
/* Gets data from tvbuff, adds it to proto_tree, increments offset,
and returns proto_item * */
2010-04-26 20:48:13 +00:00
proto_item *
2005-10-22 05:43:09 +00:00
ptvcursor_add ( ptvcursor_t * ptvc , int hfindex , gint length ,
2010-05-24 06:06:17 +00:00
const guint encoding )
2005-10-22 05:43:09 +00:00
{
2012-03-14 17:11:39 +00:00
field_info * new_fi ;
header_field_info * hfinfo ;
gint item_length ;
int offset ;
2005-10-22 05:43:09 +00:00
offset = ptvc - > offset ;
2013-06-18 20:52:31 +00:00
PROTO_REGISTRAR_GET_NTH ( hfindex , hfinfo ) ;
2013-07-11 15:03:43 +00:00
get_hfi_length ( hfinfo , ptvc - > tvb , offset , & length , & item_length ) ;
2016-04-26 00:32:57 +00:00
test_length ( hfinfo , ptvc - > tvb , offset , item_length ) ;
2016-01-09 02:25:26 +00:00
2016-01-09 02:27:22 +00:00
ptvc - > offset + = get_full_length ( hfinfo , ptvc - > tvb , offset , length ,
2016-01-09 02:25:26 +00:00
item_length , encoding ) ;
2016-04-26 00:41:49 +00:00
CHECK_FOR_NULL_TREE ( ptvc - > tree ) ;
2009-08-21 17:11:02 +00:00
/* Coast clear. Try and fake it */
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( ptvc - > tree , hfindex , hfinfo ) ;
2005-10-22 05:43:09 +00:00
2009-09-06 07:33:07 +00:00
new_fi = new_field_info ( ptvc - > tree , hfinfo , ptvc - > tvb , offset , item_length ) ;
2005-10-22 05:43:09 +00:00
2009-07-18 20:10:14 +00:00
return proto_tree_new_item ( new_fi , ptvc - > tree , ptvc - > tvb ,
2010-05-24 06:06:17 +00:00
offset , length , encoding ) ;
2005-10-22 05:43:09 +00:00
}
/* Add an item to a proto_tree, using the text label registered to that item;
the item is extracted from the tvbuff handed to it . */
proto_item *
2013-08-17 07:16:12 +00:00
proto_tree_add_item_new ( proto_tree * tree , header_field_info * hfinfo , tvbuff_t * tvb ,
2016-01-09 02:25:26 +00:00
const gint start , gint length , const guint encoding )
2005-10-22 05:43:09 +00:00
{
2012-03-14 17:11:39 +00:00
field_info * new_fi ;
2013-05-31 01:46:28 +00:00
gint item_length ;
2013-08-16 21:21:52 +00:00
DISSECTOR_ASSERT_HINT ( hfinfo ! = NULL , " Not passed hfi! " ) ;
2013-10-17 12:24:25 +00:00
get_hfi_length ( hfinfo , tvb , start , & length , & item_length ) ;
2013-10-22 16:02:13 +00:00
test_length ( hfinfo , tvb , start , item_length ) ;
2005-10-22 05:43:09 +00:00
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfinfo - > id , hfinfo ) ;
2005-10-22 05:43:09 +00:00
2013-05-31 01:46:28 +00:00
new_fi = new_field_info ( tree , hfinfo , tvb , start , item_length ) ;
2005-10-22 05:43:09 +00:00
2013-05-31 01:46:28 +00:00
return proto_tree_new_item ( new_fi , tree , tvb , start , length , encoding ) ;
2005-10-22 05:43:09 +00:00
}
2013-08-16 21:21:52 +00:00
proto_item *
2013-08-17 07:16:12 +00:00
proto_tree_add_item ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
2013-08-16 21:21:52 +00:00
const gint start , gint length , const guint encoding )
{
2014-04-24 15:26:22 +00:00
register header_field_info * hfinfo ;
PROTO_REGISTRAR_GET_NTH ( hfindex , hfinfo ) ;
return proto_tree_add_item_new ( tree , hfinfo , tvb , start , length , encoding ) ;
2013-08-16 21:21:52 +00:00
}
2016-01-09 02:25:26 +00:00
/* Add an item to a proto_tree, using the text label registered to that item;
the item is extracted from the tvbuff handed to it .
Return the length of the item through the pointer . */
proto_item *
proto_tree_add_item_new_ret_length ( proto_tree * tree , header_field_info * hfinfo ,
tvbuff_t * tvb , const gint start ,
gint length , const guint encoding ,
gint * retval )
{
field_info * new_fi ;
gint item_length ;
proto_item * item ;
DISSECTOR_ASSERT_HINT ( hfinfo ! = NULL , " Not passed hfi! " ) ;
get_hfi_length ( hfinfo , tvb , start , & length , & item_length ) ;
test_length ( hfinfo , tvb , start , item_length ) ;
if ( ! tree ) {
/*
* We need to get the correct item length here .
* That ' s normally done by proto_tree_new_item ( ) ,
* but we won ' t be calling it .
*/
* retval = get_full_length ( hfinfo , tvb , start , length ,
item_length , encoding ) ;
return NULL ;
}
TRY_TO_FAKE_THIS_ITEM ( tree , hfinfo - > id , hfinfo ) ;
new_fi = new_field_info ( tree , hfinfo , tvb , start , item_length ) ;
item = proto_tree_new_item ( new_fi , tree , tvb , start , length , encoding ) ;
* retval = new_fi - > length ;
return item ;
}
proto_item *
proto_tree_add_item_ret_length ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
const gint start , gint length ,
const guint encoding , gint * retval )
{
register header_field_info * hfinfo ;
PROTO_REGISTRAR_GET_NTH ( hfindex , hfinfo ) ;
return proto_tree_add_item_new_ret_length ( tree , hfinfo , tvb , start , length , encoding , retval ) ;
}
2014-04-13 03:20:15 +00:00
/* which FT_ types can use proto_tree_add_bytes_item() */
static inline gboolean
validate_proto_tree_add_bytes_ftype ( const enum ftenum type )
{
return ( type = = FT_BYTES | |
type = = FT_UINT_BYTES | |
type = = FT_OID | |
type = = FT_REL_OID | |
type = = FT_SYSTEM_ID ) ;
}
/* Note: this does no validation that the byte array of an FT_OID or
FT_REL_OID is actually valid ; and neither does proto_tree_add_item ( ) ,
so I think it ' s ok to continue not validating it ?
*/
proto_item *
proto_tree_add_bytes_item ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
const gint start , gint length , const guint encoding ,
GByteArray * retval , gint * endoff , gint * err )
{
field_info * new_fi ;
GByteArray * bytes = retval ;
GByteArray * created_bytes = NULL ;
gint saved_err = 0 ;
guint32 n = 0 ;
2014-04-24 15:26:22 +00:00
header_field_info * hfinfo ;
2014-04-13 03:20:15 +00:00
gboolean generate = ( bytes | | tree ) ? TRUE : FALSE ;
2014-04-24 15:26:22 +00:00
PROTO_REGISTRAR_GET_NTH ( hfindex , hfinfo ) ;
2014-04-13 03:20:15 +00:00
DISSECTOR_ASSERT_HINT ( hfinfo ! = NULL , " Not passed hfi! " ) ;
DISSECTOR_ASSERT_HINT ( validate_proto_tree_add_bytes_ftype ( hfinfo - > type ) ,
" Called proto_tree_add_bytes_item but not a bytes-based FT_XXX type " ) ;
/* length has to be -1 or > 0 regardless of encoding */
/* invalid FT_UINT_BYTES length is caught in get_uint_value() */
if ( length < - 1 | | length = = 0 ) {
REPORT_DISSECTOR_BUG ( wmem_strdup_printf ( wmem_packet_scope ( ) ,
" Invalid length %d passed to proto_tree_add_bytes_item for %s " ,
length , ftype_name ( hfinfo - > type ) ) ) ;
}
if ( encoding & ENC_STR_NUM ) {
REPORT_DISSECTOR_BUG ( " Decoding number strings for byte arrays is not supported " ) ;
}
if ( generate & & ( encoding & ENC_STR_HEX ) ) {
if ( hfinfo - > type = = FT_UINT_BYTES ) {
/* can't decode FT_UINT_BYTES from strings */
REPORT_DISSECTOR_BUG ( " proto_tree_add_bytes_item called for "
" FT_UINT_BYTES type, but as ENC_STR_HEX " ) ;
}
if ( ! bytes ) {
/* caller doesn't care about return value, but we need it to
call tvb_get_string_bytes ( ) and set the tree later */
bytes = created_bytes = g_byte_array_new ( ) ;
}
/* bytes might be NULL after this, but can't add expert error until later */
bytes = tvb_get_string_bytes ( tvb , start , length , encoding , bytes , endoff ) ;
/* grab the errno now before it gets overwritten */
saved_err = errno ;
}
else if ( generate ) {
tvb_ensure_bytes_exist ( tvb , start , length ) ;
if ( ! bytes ) {
/* caller doesn't care about return value, but we need it to
call tvb_get_string_bytes ( ) and set the tree later */
bytes = created_bytes = g_byte_array_new ( ) ;
}
if ( hfinfo - > type = = FT_UINT_BYTES ) {
n = length ; /* n is now the "header" length */
length = get_uint_value ( tree , tvb , start , n , encoding ) ;
/* length is now the value's length; only store the value in the array */
g_byte_array_append ( bytes , tvb_get_ptr ( tvb , start + n , length ) , length ) ;
}
else if ( length > 0 ) {
g_byte_array_append ( bytes , tvb_get_ptr ( tvb , start , length ) , length ) ;
}
if ( endoff )
* endoff = start + n + length ;
}
if ( err ) * err = saved_err ;
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE_AND_FREE ( tree ,
{
if ( created_bytes )
g_byte_array_free ( created_bytes , TRUE ) ;
created_bytes = NULL ;
bytes = NULL ;
} ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM_OR_FREE ( tree , hfinfo - > id , hfinfo ,
2014-04-13 03:20:15 +00:00
{
if ( created_bytes )
g_byte_array_free ( created_bytes , TRUE ) ;
created_bytes = NULL ;
bytes = NULL ;
} ) ;
/* n will be zero except when it's a FT_UINT_BYTES */
new_fi = new_field_info ( tree , hfinfo , tvb , start , n + length ) ;
if ( encoding & ENC_STRING ) {
if ( saved_err = = ERANGE )
expert_add_info ( NULL , tree , & ei_number_string_decoding_erange_error ) ;
else if ( ! bytes | | saved_err ! = 0 )
expert_add_info ( NULL , tree , & ei_number_string_decoding_failed_error ) ;
if ( bytes )
proto_tree_set_bytes_gbytearray ( new_fi , bytes ) ;
2015-06-25 01:04:13 +00:00
else
proto_tree_set_bytes ( new_fi , NULL , 0 ) ;
2014-04-13 03:20:15 +00:00
if ( created_bytes )
g_byte_array_free ( created_bytes , TRUE ) ;
}
else {
/* n will be zero except when it's a FT_UINT_BYTES */
proto_tree_set_bytes_tvb ( new_fi , tvb , start + n , length ) ;
FI_SET_FLAG ( new_fi ,
( encoding & ENC_LITTLE_ENDIAN ) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN ) ;
}
return proto_tree_add_node ( tree , new_fi ) ;
}
2014-04-12 04:32:20 +00:00
proto_item *
proto_tree_add_time_item ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
const gint start , gint length , const guint encoding ,
nstime_t * retval , gint * endoff , gint * err )
{
field_info * new_fi ;
nstime_t time_stamp ;
gint saved_err = 0 ;
2014-04-24 15:26:22 +00:00
header_field_info * hfinfo ;
PROTO_REGISTRAR_GET_NTH ( hfindex , hfinfo ) ;
2014-04-12 04:32:20 +00:00
DISSECTOR_ASSERT_HINT ( hfinfo ! = NULL , " Not passed hfi! " ) ;
2014-12-21 23:17:13 +00:00
DISSECTOR_ASSERT_FIELD_TYPE_IS_TIME ( hfinfo ) ;
2014-04-12 04:32:20 +00:00
/* length has to be -1 or > 0 regardless of encoding */
if ( length < - 1 | | length = = 0 ) {
REPORT_DISSECTOR_BUG ( wmem_strdup_printf ( wmem_packet_scope ( ) ,
" Invalid length %d passed to proto_tree_add_time_item " , length ) ) ;
}
time_stamp . secs = 0 ;
time_stamp . nsecs = 0 ;
if ( encoding & ENC_STR_TIME_MASK ) {
tvb_get_string_time ( tvb , start , length , encoding , & time_stamp , endoff ) ;
/* grab the errno now before it gets overwritten */
saved_err = errno ;
}
else {
const gboolean is_relative = ( hfinfo - > type = = FT_RELATIVE_TIME ) ? TRUE : FALSE ;
if ( length ! = 8 & & length ! = 4 ) {
const gboolean length_error = length < 4 ? TRUE : FALSE ;
if ( is_relative )
report_type_length_mismatch ( tree , " a relative time value " , length , length_error ) ;
else
report_type_length_mismatch ( tree , " an absolute time value " , length , length_error ) ;
}
tvb_ensure_bytes_exist ( tvb , start , length ) ;
get_time_value ( tvb , start , length , encoding , & time_stamp , is_relative ) ;
if ( endoff ) * endoff = length ;
}
if ( err ) * err = saved_err ;
if ( retval ) {
retval - > secs = time_stamp . secs ;
retval - > nsecs = time_stamp . nsecs ;
}
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfinfo - > id , hfinfo ) ;
2014-04-12 04:32:20 +00:00
new_fi = new_field_info ( tree , hfinfo , tvb , start , length ) ;
proto_tree_set_time ( new_fi , & time_stamp ) ;
if ( encoding & ENC_STRING ) {
if ( saved_err = = ERANGE )
expert_add_info ( NULL , tree , & ei_number_string_decoding_erange_error ) ;
else if ( saved_err = = EDOM )
expert_add_info ( NULL , tree , & ei_number_string_decoding_failed_error ) ;
}
else {
FI_SET_FLAG ( new_fi ,
( encoding & ENC_LITTLE_ENDIAN ) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN ) ;
}
return proto_tree_add_node ( tree , new_fi ) ;
}
2000-03-12 04:48:32 +00:00
/* Add a FT_NONE to a proto_tree */
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_none_format ( proto_tree * tree , const int hfindex , tvbuff_t * tvb ,
const gint start , gint length , const char * format ,
. . . )
2000-03-12 04:48:32 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
header_field_info * hfinfo ;
2000-03-12 04:48:32 +00:00
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hfinfo ) ;
2009-08-11 18:08:03 +00:00
2014-12-21 23:17:13 +00:00
DISSECTOR_ASSERT_FIELD_TYPE ( hfinfo , FT_NONE ) ;
2000-03-12 04:48:32 +00:00
2013-08-22 21:20:50 +00:00
pi = proto_tree_add_pi ( tree , hfinfo , tvb , start , & length ) ;
2000-05-31 05:09:07 +00:00
2013-07-02 20:51:58 +00:00
TRY_TO_FAKE_THIS_REPR ( pi ) ;
2009-09-06 07:33:07 +00:00
2000-03-12 04:48:32 +00:00
va_start ( ap , format ) ;
2000-05-31 05:09:07 +00:00
proto_tree_set_representation ( pi , format , ap ) ;
2000-03-12 04:48:32 +00:00
va_end ( ap ) ;
2000-05-31 05:09:07 +00:00
/* no value to set for FT_NONE */
2001-02-01 20:21:25 +00:00
return pi ;
}
2005-10-22 05:43:09 +00:00
/* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
* offset , and returns proto_item * */
2010-04-26 20:48:13 +00:00
proto_item *
2005-10-22 05:43:09 +00:00
ptvcursor_add_no_advance ( ptvcursor_t * ptvc , int hf , gint length ,
2010-05-24 06:06:17 +00:00
const guint encoding )
2005-10-22 05:43:09 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * item ;
2005-10-22 05:43:09 +00:00
2013-08-17 07:16:12 +00:00
item = proto_tree_add_item ( ptvc - > tree , hf , ptvc - > tvb , ptvc - > offset ,
2010-05-24 06:06:17 +00:00
length , encoding ) ;
2005-10-22 05:43:09 +00:00
return item ;
}
/* Advance the ptvcursor's offset within its tvbuff without
* adding anything to the proto_tree . */
void
ptvcursor_advance ( ptvcursor_t * ptvc , gint length )
{
ptvc - > offset + = length ;
}
2002-08-28 20:41:00 +00:00
2001-02-01 20:21:25 +00:00
static void
proto_tree_set_protocol_tvb ( field_info * fi , tvbuff_t * tvb )
{
2014-01-15 01:05:03 +00:00
fvalue_set_tvbuff ( & fi - > value , tvb ) ;
2001-02-01 20:21:25 +00:00
}
/* Add a FT_PROTOCOL to a proto_tree */
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_protocol_format ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
gint start , gint length , const char * format , . . . )
2001-02-01 20:21:25 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
header_field_info * hfinfo ;
2001-02-01 20:21:25 +00:00
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hfinfo ) ;
2009-08-11 18:08:03 +00:00
2014-12-21 23:17:13 +00:00
DISSECTOR_ASSERT_FIELD_TYPE ( hfinfo , FT_PROTOCOL ) ;
2001-02-01 20:21:25 +00:00
2013-08-22 21:20:50 +00:00
pi = proto_tree_add_pi ( tree , hfinfo , tvb , start , & length ) ;
2001-02-01 20:21:25 +00:00
2014-09-16 21:30:16 +00:00
proto_tree_set_protocol_tvb ( PNODE_FINFO ( pi ) , ( start = = 0 ? tvb : tvb_new_subset_length ( tvb , start , length ) ) ) ;
2009-09-06 07:33:07 +00:00
2013-07-02 20:51:58 +00:00
TRY_TO_FAKE_THIS_REPR ( pi ) ;
2009-09-06 07:33:07 +00:00
2001-02-01 20:21:25 +00:00
va_start ( ap , format ) ;
proto_tree_set_representation ( pi , format , ap ) ;
va_end ( ap ) ;
2000-03-12 04:48:32 +00:00
return pi ;
}
2015-01-06 09:46:17 +00:00
/* Add a FT_BYTES to a proto_tree */
proto_item *
2015-02-09 07:56:28 +00:00
proto_tree_add_bytes ( proto_tree * tree , int hfindex , tvbuff_t * tvb , gint start ,
gint length , const guint8 * start_ptr )
2015-01-06 09:46:17 +00:00
{
2015-02-09 07:56:28 +00:00
proto_item * pi ;
header_field_info * hfinfo ;
gint item_length ;
2015-01-06 09:46:17 +00:00
2015-02-09 07:56:28 +00:00
PROTO_REGISTRAR_GET_NTH ( hfindex , hfinfo ) ;
get_hfi_length ( hfinfo , tvb , start , & length , & item_length ) ;
test_length ( hfinfo , tvb , start , item_length ) ;
2015-01-06 09:46:17 +00:00
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2015-02-09 07:56:28 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hfinfo ) ;
2015-01-06 09:46:17 +00:00
2015-02-09 07:56:28 +00:00
DISSECTOR_ASSERT_FIELD_TYPE ( hfinfo , FT_BYTES ) ;
2015-01-06 09:46:17 +00:00
2015-02-09 07:56:28 +00:00
pi = proto_tree_add_pi ( tree , hfinfo , tvb , start , & length ) ;
proto_tree_set_bytes ( PNODE_FINFO ( pi ) , start_ptr , length ) ;
2015-01-06 09:46:17 +00:00
2015-02-09 07:56:28 +00:00
return pi ;
2015-01-06 09:46:17 +00:00
}
2001-02-01 20:21:25 +00:00
2000-03-12 04:48:32 +00:00
/* Add a FT_BYTES to a proto_tree */
proto_item *
2015-02-09 07:56:28 +00:00
proto_tree_add_bytes_with_length ( proto_tree * tree , int hfindex , tvbuff_t * tvb , gint start ,
2015-02-12 10:25:31 +00:00
gint tvbuff_length , const guint8 * start_ptr , gint ptr_length )
2000-03-12 04:48:32 +00:00
{
2015-02-09 07:56:28 +00:00
proto_item * pi ;
2012-03-14 17:11:39 +00:00
header_field_info * hfinfo ;
2015-02-09 07:56:28 +00:00
gint item_length ;
2014-04-20 02:20:26 +00:00
PROTO_REGISTRAR_GET_NTH ( hfindex , hfinfo ) ;
2015-02-12 10:25:31 +00:00
get_hfi_length ( hfinfo , tvb , start , & tvbuff_length , & item_length ) ;
2014-04-20 02:20:26 +00:00
test_length ( hfinfo , tvb , start , item_length ) ;
2000-03-12 04:48:32 +00:00
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hfinfo ) ;
2005-04-11 08:43:51 +00:00
2014-12-21 23:17:13 +00:00
DISSECTOR_ASSERT_FIELD_TYPE ( hfinfo , FT_BYTES ) ;
2000-03-12 04:48:32 +00:00
2015-02-12 10:25:31 +00:00
pi = proto_tree_add_pi ( tree , hfinfo , tvb , start , & tvbuff_length ) ;
2015-02-09 07:56:28 +00:00
proto_tree_set_bytes ( PNODE_FINFO ( pi ) , start_ptr , ptr_length ) ;
2000-05-31 05:09:07 +00:00
return pi ;
}
2006-02-09 04:18:23 +00:00
proto_item *
proto_tree_add_bytes_format_value ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
2010-04-26 20:48:13 +00:00
gint start , gint length ,
const guint8 * start_ptr ,
const char * format , . . . )
2006-02-09 04:18:23 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
header_field_info * hfinfo ;
2014-04-20 02:20:26 +00:00
gint item_length ;
PROTO_REGISTRAR_GET_NTH ( hfindex , hfinfo ) ;
get_hfi_length ( hfinfo , tvb , start , & length , & item_length ) ;
test_length ( hfinfo , tvb , start , item_length ) ;
2009-08-19 19:08:34 +00:00
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hfinfo ) ;
2006-02-09 04:18:23 +00:00
Modify proto_tree_add_bytes_format() and proto_tree_add_bytes_format_value()
so that if the start_ptr is NULL the bytes are extracted from the given TVB
using the given offset and length.
Replace a bunch of:
proto_tree_add_bytes_format*(tree, hf, tvb, offset, length, tvb_get_ptr(tvb, offset, length), [...])
with:
proto_tree_add_bytes_format*(tree, hf, tvb, offset, length, NULL, [...])
svn path=/trunk/; revision=35896
2011-02-10 16:31:00 +00:00
if ( start_ptr )
pi = proto_tree_add_bytes ( tree , hfindex , tvb , start , length ,
start_ptr ) ;
else
pi = proto_tree_add_bytes ( tree , hfindex , tvb , start , length ,
tvb_get_ptr ( tvb , start , length ) ) ;
2006-02-09 04:18:23 +00:00
va_start ( ap , format ) ;
proto_tree_set_representation_value ( pi , format , ap ) ;
va_end ( ap ) ;
return pi ;
}
2000-05-31 05:09:07 +00:00
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_bytes_format ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
gint start , gint length , const guint8 * start_ptr ,
const char * format , . . . )
2000-05-31 05:09:07 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
header_field_info * hfinfo ;
2014-04-20 02:20:26 +00:00
gint item_length ;
PROTO_REGISTRAR_GET_NTH ( hfindex , hfinfo ) ;
get_hfi_length ( hfinfo , tvb , start , & length , & item_length ) ;
test_length ( hfinfo , tvb , start , item_length ) ;
2009-08-19 19:08:34 +00:00
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hfinfo ) ;
2000-05-31 05:09:07 +00:00
Modify proto_tree_add_bytes_format() and proto_tree_add_bytes_format_value()
so that if the start_ptr is NULL the bytes are extracted from the given TVB
using the given offset and length.
Replace a bunch of:
proto_tree_add_bytes_format*(tree, hf, tvb, offset, length, tvb_get_ptr(tvb, offset, length), [...])
with:
proto_tree_add_bytes_format*(tree, hf, tvb, offset, length, NULL, [...])
svn path=/trunk/; revision=35896
2011-02-10 16:31:00 +00:00
if ( start_ptr )
pi = proto_tree_add_bytes ( tree , hfindex , tvb , start , length ,
start_ptr ) ;
else
pi = proto_tree_add_bytes ( tree , hfindex , tvb , start , length ,
tvb_get_ptr ( tvb , start , length ) ) ;
2013-07-02 20:51:58 +00:00
TRY_TO_FAKE_THIS_REPR ( pi ) ;
2009-09-06 07:33:07 +00:00
2000-05-31 05:09:07 +00:00
va_start ( ap , format ) ;
proto_tree_set_representation ( pi , format , ap ) ;
2000-03-12 04:48:32 +00:00
va_end ( ap ) ;
return pi ;
}
static void
2000-03-14 06:03:26 +00:00
proto_tree_set_bytes ( field_info * fi , const guint8 * start_ptr , gint length )
2000-03-12 04:48:32 +00:00
{
2012-03-14 17:11:39 +00:00
GByteArray * bytes ;
2000-05-19 04:54:36 +00:00
2013-10-01 22:50:29 +00:00
DISSECTOR_ASSERT ( start_ptr ! = NULL | | length = = 0 ) ;
2001-02-01 20:21:25 +00:00
bytes = g_byte_array_new ( ) ;
2000-05-19 04:54:36 +00:00
if ( length > 0 ) {
2001-02-01 20:21:25 +00:00
g_byte_array_append ( bytes , start_ptr , length ) ;
2000-05-19 04:54:36 +00:00
}
2014-01-15 01:05:03 +00:00
fvalue_set_byte_array ( & fi - > value , bytes ) ;
2000-03-12 04:48:32 +00:00
}
2001-02-01 20:21:25 +00:00
2000-05-31 05:09:07 +00:00
static void
proto_tree_set_bytes_tvb ( field_info * fi , tvbuff_t * tvb , gint offset , gint length )
{
2001-02-01 20:21:25 +00:00
proto_tree_set_bytes ( fi , tvb_get_ptr ( tvb , offset , length ) , length ) ;
2000-05-31 05:09:07 +00:00
}
2014-04-13 03:20:15 +00:00
static void
proto_tree_set_bytes_gbytearray ( field_info * fi , const GByteArray * value )
{
GByteArray * bytes ;
DISSECTOR_ASSERT ( value ! = NULL ) ;
bytes = byte_array_dup ( value ) ;
fvalue_set_byte_array ( & fi - > value , bytes ) ;
}
2000-03-12 04:48:32 +00:00
/* Add a FT_*TIME to a proto_tree */
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_time ( proto_tree * tree , int hfindex , tvbuff_t * tvb , gint start ,
2014-01-15 01:05:03 +00:00
gint length , const nstime_t * value_ptr )
2000-03-12 04:48:32 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
header_field_info * hfinfo ;
2000-03-12 04:48:32 +00:00
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hfinfo ) ;
2005-04-11 08:43:51 +00:00
2014-12-21 23:17:13 +00:00
DISSECTOR_ASSERT_FIELD_TYPE_IS_TIME ( hfinfo ) ;
2000-03-12 04:48:32 +00:00
2013-08-22 21:20:50 +00:00
pi = proto_tree_add_pi ( tree , hfinfo , tvb , start , & length ) ;
proto_tree_set_time ( PNODE_FINFO ( pi ) , value_ptr ) ;
2000-05-31 05:09:07 +00:00
return pi ;
}
2006-02-09 04:18:23 +00:00
proto_item *
proto_tree_add_time_format_value ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
2010-04-26 20:48:13 +00:00
gint start , gint length , nstime_t * value_ptr ,
const char * format , . . . )
2006-02-09 04:18:23 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2006-02-09 04:18:23 +00:00
pi = proto_tree_add_time ( tree , hfindex , tvb , start , length , value_ptr ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
va_start ( ap , format ) ;
proto_tree_set_representation_value ( pi , format , ap ) ;
va_end ( ap ) ;
}
2006-02-09 04:18:23 +00:00
return pi ;
}
2000-05-31 05:09:07 +00:00
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_time_format ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
gint start , gint length , nstime_t * value_ptr ,
const char * format , . . . )
2000-05-31 05:09:07 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2000-05-31 05:09:07 +00:00
pi = proto_tree_add_time ( tree , hfindex , tvb , start , length , value_ptr ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
2013-07-02 20:51:58 +00:00
TRY_TO_FAKE_THIS_REPR ( pi ) ;
2000-05-31 05:09:07 +00:00
2013-07-02 18:36:00 +00:00
va_start ( ap , format ) ;
proto_tree_set_representation ( pi , format , ap ) ;
va_end ( ap ) ;
}
2000-03-12 04:48:32 +00:00
return pi ;
}
/* Set the FT_*TIME value */
static void
2014-01-15 01:05:03 +00:00
proto_tree_set_time ( field_info * fi , const nstime_t * value_ptr )
2000-03-12 04:48:32 +00:00
{
2005-08-16 16:04:30 +00:00
DISSECTOR_ASSERT ( value_ptr ! = NULL ) ;
2008-02-22 12:28:41 +00:00
2014-01-15 01:05:03 +00:00
fvalue_set_time ( & fi - > value , value_ptr ) ;
2000-03-12 04:48:32 +00:00
}
/* Add a FT_IPXNET to a proto_tree */
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_ipxnet ( proto_tree * tree , int hfindex , tvbuff_t * tvb , gint start ,
gint length , guint32 value )
2000-03-12 04:48:32 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
header_field_info * hfinfo ;
2000-03-12 04:48:32 +00:00
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hfinfo ) ;
2005-04-11 08:43:51 +00:00
2014-12-21 23:17:13 +00:00
DISSECTOR_ASSERT_FIELD_TYPE ( hfinfo , FT_IPXNET ) ;
2000-03-12 04:48:32 +00:00
2013-08-22 21:20:50 +00:00
pi = proto_tree_add_pi ( tree , hfinfo , tvb , start , & length ) ;
proto_tree_set_ipxnet ( PNODE_FINFO ( pi ) , value ) ;
2000-05-31 05:09:07 +00:00
return pi ;
}
2006-02-09 04:18:23 +00:00
proto_item *
proto_tree_add_ipxnet_format_value ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
2010-04-26 20:48:13 +00:00
gint start , gint length , guint32 value ,
const char * format , . . . )
2006-02-09 04:18:23 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2006-02-09 04:18:23 +00:00
pi = proto_tree_add_ipxnet ( tree , hfindex , tvb , start , length , value ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
va_start ( ap , format ) ;
proto_tree_set_representation_value ( pi , format , ap ) ;
va_end ( ap ) ;
}
2006-02-09 04:18:23 +00:00
return pi ;
}
2000-05-31 05:09:07 +00:00
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_ipxnet_format ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
gint start , gint length , guint32 value ,
const char * format , . . . )
2000-05-31 05:09:07 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2000-05-31 05:09:07 +00:00
pi = proto_tree_add_ipxnet ( tree , hfindex , tvb , start , length , value ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
2013-07-02 20:51:58 +00:00
TRY_TO_FAKE_THIS_REPR ( pi ) ;
2000-05-31 05:09:07 +00:00
2013-07-02 18:36:00 +00:00
va_start ( ap , format ) ;
proto_tree_set_representation ( pi , format , ap ) ;
va_end ( ap ) ;
}
2000-03-12 04:48:32 +00:00
return pi ;
}
/* Set the FT_IPXNET value */
static void
proto_tree_set_ipxnet ( field_info * fi , guint32 value )
{
2007-01-18 11:02:26 +00:00
fvalue_set_uinteger ( & fi - > value , value ) ;
2000-03-12 04:48:32 +00:00
}
/* Add a FT_IPv4 to a proto_tree */
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_ipv4 ( proto_tree * tree , int hfindex , tvbuff_t * tvb , gint start ,
gint length , guint32 value )
2000-03-12 04:48:32 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
header_field_info * hfinfo ;
2000-03-12 04:48:32 +00:00
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hfinfo ) ;
2005-04-11 08:43:51 +00:00
2014-12-21 23:17:13 +00:00
DISSECTOR_ASSERT_FIELD_TYPE ( hfinfo , FT_IPv4 ) ;
2000-03-12 04:48:32 +00:00
2013-08-22 21:20:50 +00:00
pi = proto_tree_add_pi ( tree , hfinfo , tvb , start , & length ) ;
proto_tree_set_ipv4 ( PNODE_FINFO ( pi ) , value ) ;
2000-05-31 05:09:07 +00:00
return pi ;
}
2006-02-09 04:18:23 +00:00
proto_item *
proto_tree_add_ipv4_format_value ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
2010-04-26 20:48:13 +00:00
gint start , gint length , guint32 value ,
const char * format , . . . )
2006-02-09 04:18:23 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2006-02-09 04:18:23 +00:00
pi = proto_tree_add_ipv4 ( tree , hfindex , tvb , start , length , value ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
va_start ( ap , format ) ;
proto_tree_set_representation_value ( pi , format , ap ) ;
va_end ( ap ) ;
}
2006-02-09 04:18:23 +00:00
return pi ;
}
2000-05-31 05:09:07 +00:00
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_ipv4_format ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
gint start , gint length , guint32 value ,
const char * format , . . . )
2000-05-31 05:09:07 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2000-05-31 05:09:07 +00:00
pi = proto_tree_add_ipv4 ( tree , hfindex , tvb , start , length , value ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
2013-07-02 20:51:58 +00:00
TRY_TO_FAKE_THIS_REPR ( pi ) ;
2000-05-31 05:09:07 +00:00
2013-07-02 18:36:00 +00:00
va_start ( ap , format ) ;
proto_tree_set_representation ( pi , format , ap ) ;
va_end ( ap ) ;
}
2000-03-12 04:48:32 +00:00
return pi ;
}
/* Set the FT_IPv4 value */
static void
proto_tree_set_ipv4 ( field_info * fi , guint32 value )
{
2007-01-18 11:02:26 +00:00
fvalue_set_uinteger ( & fi - > value , value ) ;
2000-03-12 04:48:32 +00:00
}
/* Add a FT_IPv6 to a proto_tree */
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_ipv6 ( proto_tree * tree , int hfindex , tvbuff_t * tvb , gint start ,
2015-10-05 21:43:46 +00:00
gint length , const struct e_in6_addr * value_ptr )
2000-03-12 04:48:32 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
header_field_info * hfinfo ;
2000-03-12 04:48:32 +00:00
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hfinfo ) ;
2005-04-11 08:43:51 +00:00
2014-12-21 23:17:13 +00:00
DISSECTOR_ASSERT_FIELD_TYPE ( hfinfo , FT_IPv6 ) ;
2000-03-12 04:48:32 +00:00
2013-08-22 21:20:50 +00:00
pi = proto_tree_add_pi ( tree , hfinfo , tvb , start , & length ) ;
2015-10-05 21:43:46 +00:00
proto_tree_set_ipv6 ( PNODE_FINFO ( pi ) , value_ptr - > bytes ) ;
2000-05-31 05:09:07 +00:00
return pi ;
}
2006-02-09 04:18:23 +00:00
proto_item *
proto_tree_add_ipv6_format_value ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
2010-04-26 20:48:13 +00:00
gint start , gint length ,
2015-10-05 21:43:46 +00:00
const struct e_in6_addr * value_ptr ,
2010-04-26 20:48:13 +00:00
const char * format , . . . )
2006-02-09 04:18:23 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2006-02-09 04:18:23 +00:00
pi = proto_tree_add_ipv6 ( tree , hfindex , tvb , start , length , value_ptr ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
va_start ( ap , format ) ;
proto_tree_set_representation_value ( pi , format , ap ) ;
va_end ( ap ) ;
}
2006-02-09 04:18:23 +00:00
return pi ;
}
2000-05-31 05:09:07 +00:00
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_ipv6_format ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
2015-10-05 21:43:46 +00:00
gint start , gint length ,
const struct e_in6_addr * value_ptr ,
2010-04-26 20:48:13 +00:00
const char * format , . . . )
2000-05-31 05:09:07 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2000-05-31 05:09:07 +00:00
pi = proto_tree_add_ipv6 ( tree , hfindex , tvb , start , length , value_ptr ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
2013-07-02 20:51:58 +00:00
TRY_TO_FAKE_THIS_REPR ( pi ) ;
2000-05-31 05:09:07 +00:00
2013-07-02 18:36:00 +00:00
va_start ( ap , format ) ;
proto_tree_set_representation ( pi , format , ap ) ;
va_end ( ap ) ;
}
2000-03-12 04:48:32 +00:00
return pi ;
}
2000-05-31 05:09:07 +00:00
/* Set the FT_IPv6 value */
2000-03-12 04:48:32 +00:00
static void
2000-05-31 05:09:07 +00:00
proto_tree_set_ipv6 ( field_info * fi , const guint8 * value_ptr )
2000-03-12 04:48:32 +00:00
{
2005-08-16 16:04:30 +00:00
DISSECTOR_ASSERT ( value_ptr ! = NULL ) ;
2014-01-15 01:05:03 +00:00
fvalue_set_bytes ( & fi - > value , value_ptr ) ;
2000-03-12 04:48:32 +00:00
}
2000-05-31 05:09:07 +00:00
static void
2009-08-28 09:38:34 +00:00
proto_tree_set_ipv6_tvb ( field_info * fi , tvbuff_t * tvb , gint start , gint length )
2000-05-31 05:09:07 +00:00
{
2009-08-28 09:38:34 +00:00
proto_tree_set_ipv6 ( fi , tvb_get_ptr ( tvb , start , length ) ) ;
2000-05-31 05:09:07 +00:00
}
2014-12-24 05:06:35 +00:00
/* Set the FT_FCWWN value */
static void
proto_tree_set_fcwwn ( field_info * fi , const guint8 * value_ptr )
{
DISSECTOR_ASSERT ( value_ptr ! = NULL ) ;
fvalue_set_bytes ( & fi - > value , value_ptr ) ;
}
static void
proto_tree_set_fcwwn_tvb ( field_info * fi , tvbuff_t * tvb , gint start , gint length )
{
proto_tree_set_fcwwn ( fi , tvb_get_ptr ( tvb , start , length ) ) ;
}
2005-07-04 13:04:53 +00:00
/* Add a FT_GUID to a proto_tree */
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_guid ( proto_tree * tree , int hfindex , tvbuff_t * tvb , gint start ,
gint length , const e_guid_t * value_ptr )
2005-07-04 13:04:53 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
header_field_info * hfinfo ;
2005-07-04 13:04:53 +00:00
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hfinfo ) ;
2005-07-04 13:04:53 +00:00
2014-12-21 23:17:13 +00:00
DISSECTOR_ASSERT_FIELD_TYPE ( hfinfo , FT_GUID ) ;
2005-07-04 13:04:53 +00:00
2013-08-22 21:20:50 +00:00
pi = proto_tree_add_pi ( tree , hfinfo , tvb , start , & length ) ;
proto_tree_set_guid ( PNODE_FINFO ( pi ) , value_ptr ) ;
2005-07-04 13:04:53 +00:00
return pi ;
}
2006-02-09 04:18:23 +00:00
proto_item *
proto_tree_add_guid_format_value ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
2010-04-26 20:48:13 +00:00
gint start , gint length ,
const e_guid_t * value_ptr ,
const char * format , . . . )
2006-02-09 04:18:23 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2006-02-09 04:18:23 +00:00
pi = proto_tree_add_guid ( tree , hfindex , tvb , start , length , value_ptr ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
va_start ( ap , format ) ;
proto_tree_set_representation_value ( pi , format , ap ) ;
va_end ( ap ) ;
}
2006-02-09 04:18:23 +00:00
return pi ;
}
2005-07-04 13:04:53 +00:00
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_guid_format ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
gint start , gint length , const e_guid_t * value_ptr ,
const char * format , . . . )
2005-07-04 13:04:53 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2005-07-04 13:04:53 +00:00
pi = proto_tree_add_guid ( tree , hfindex , tvb , start , length , value_ptr ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
2013-07-02 20:51:58 +00:00
TRY_TO_FAKE_THIS_REPR ( pi ) ;
2005-07-04 13:04:53 +00:00
2013-07-02 18:36:00 +00:00
va_start ( ap , format ) ;
proto_tree_set_representation ( pi , format , ap ) ;
va_end ( ap ) ;
}
2005-07-04 13:04:53 +00:00
return pi ;
}
/* Set the FT_GUID value */
static void
2006-03-10 11:58:22 +00:00
proto_tree_set_guid ( field_info * fi , const e_guid_t * value_ptr )
2005-07-04 13:04:53 +00:00
{
2005-08-16 16:04:30 +00:00
DISSECTOR_ASSERT ( value_ptr ! = NULL ) ;
2014-01-15 01:05:03 +00:00
fvalue_set_guid ( & fi - > value , value_ptr ) ;
2005-07-04 13:04:53 +00:00
}
static void
2010-04-26 20:48:13 +00:00
proto_tree_set_guid_tvb ( field_info * fi , tvbuff_t * tvb , gint start ,
2010-05-24 06:06:17 +00:00
const guint encoding )
2005-07-04 13:04:53 +00:00
{
2006-03-10 11:58:22 +00:00
e_guid_t guid ;
2006-07-20 21:29:45 +00:00
2010-05-24 06:06:17 +00:00
tvb_get_guid ( tvb , start , & guid , encoding ) ;
2006-03-10 11:58:22 +00:00
proto_tree_set_guid ( fi , & guid ) ;
2005-07-04 13:04:53 +00:00
}
2005-12-02 13:16:58 +00:00
/* Add a FT_OID to a proto_tree */
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_oid ( proto_tree * tree , int hfindex , tvbuff_t * tvb , gint start ,
gint length , const guint8 * value_ptr )
2005-12-02 13:16:58 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
header_field_info * hfinfo ;
2005-12-02 13:16:58 +00:00
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hfinfo ) ;
2005-12-02 13:16:58 +00:00
2014-12-21 23:17:13 +00:00
DISSECTOR_ASSERT_FIELD_TYPE ( hfinfo , FT_OID ) ;
2005-12-02 13:16:58 +00:00
2013-08-22 21:20:50 +00:00
pi = proto_tree_add_pi ( tree , hfinfo , tvb , start , & length ) ;
proto_tree_set_oid ( PNODE_FINFO ( pi ) , value_ptr , length ) ;
2005-12-02 13:16:58 +00:00
return pi ;
}
2006-02-09 04:18:23 +00:00
proto_item *
proto_tree_add_oid_format_value ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
2010-04-26 20:48:13 +00:00
gint start , gint length ,
const guint8 * value_ptr ,
const char * format , . . . )
2006-02-09 04:18:23 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2006-02-09 04:18:23 +00:00
pi = proto_tree_add_oid ( tree , hfindex , tvb , start , length , value_ptr ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
va_start ( ap , format ) ;
proto_tree_set_representation_value ( pi , format , ap ) ;
va_end ( ap ) ;
}
2006-02-09 04:18:23 +00:00
return pi ;
}
2005-12-02 13:16:58 +00:00
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_oid_format ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
gint start , gint length , const guint8 * value_ptr ,
const char * format , . . . )
2005-12-02 13:16:58 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2005-12-02 13:16:58 +00:00
pi = proto_tree_add_oid ( tree , hfindex , tvb , start , length , value_ptr ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
2013-07-02 20:51:58 +00:00
TRY_TO_FAKE_THIS_REPR ( pi ) ;
2005-12-02 13:16:58 +00:00
2013-07-02 18:36:00 +00:00
va_start ( ap , format ) ;
proto_tree_set_representation ( pi , format , ap ) ;
va_end ( ap ) ;
}
2005-12-02 13:16:58 +00:00
return pi ;
}
/* Set the FT_OID value */
static void
proto_tree_set_oid ( field_info * fi , const guint8 * value_ptr , gint length )
{
2012-03-14 17:11:39 +00:00
GByteArray * bytes ;
2005-12-02 13:16:58 +00:00
2013-09-23 12:09:20 +00:00
DISSECTOR_ASSERT ( value_ptr ! = NULL | | length = = 0 ) ;
2005-12-02 13:16:58 +00:00
bytes = g_byte_array_new ( ) ;
if ( length > 0 ) {
g_byte_array_append ( bytes , value_ptr , length ) ;
}
2014-01-15 01:05:03 +00:00
fvalue_set_byte_array ( & fi - > value , bytes ) ;
2005-12-02 13:16:58 +00:00
}
static void
proto_tree_set_oid_tvb ( field_info * fi , tvbuff_t * tvb , gint start , gint length )
{
proto_tree_set_oid ( fi , tvb_get_ptr ( tvb , start , length ) , length ) ;
}
2013-12-23 15:18:48 +00:00
/* Set the FT_SYSTEM_ID value */
static void
proto_tree_set_system_id ( field_info * fi , const guint8 * value_ptr , gint length )
{
GByteArray * bytes ;
DISSECTOR_ASSERT ( value_ptr ! = NULL | | length = = 0 ) ;
bytes = g_byte_array_new ( ) ;
if ( length > 0 ) {
g_byte_array_append ( bytes , value_ptr , length ) ;
}
2014-01-15 01:05:03 +00:00
fvalue_set_byte_array ( & fi - > value , bytes ) ;
2013-12-23 15:18:48 +00:00
}
static void
proto_tree_set_system_id_tvb ( field_info * fi , tvbuff_t * tvb , gint start , gint length )
{
proto_tree_set_system_id ( fi , tvb_get_ptr ( tvb , start , length ) , length ) ;
}
2014-04-12 22:26:34 +00:00
/* Add a FT_STRING, FT_STRINGZ, or FT_STRINGZPAD to a proto_tree. Creates
* own copy of string , and frees it when the proto_tree is destroyed . */
2000-03-12 04:48:32 +00:00
proto_item *
2000-05-31 05:09:07 +00:00
proto_tree_add_string ( proto_tree * tree , int hfindex , tvbuff_t * tvb , gint start ,
2010-04-26 20:48:13 +00:00
gint length , const char * value )
2000-03-12 04:48:32 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
header_field_info * hfinfo ;
2000-03-12 04:48:32 +00:00
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hfinfo ) ;
2005-04-11 08:43:51 +00:00
2014-12-21 23:17:13 +00:00
DISSECTOR_ASSERT_FIELD_TYPE_IS_STRING ( hfinfo ) ;
2000-03-12 04:48:32 +00:00
2013-12-07 15:48:35 +00:00
if ( hfinfo - > display = = STR_UNICODE ) {
DISSECTOR_ASSERT ( g_utf8_validate ( value , - 1 , NULL ) ) ;
}
2013-08-22 21:20:50 +00:00
pi = proto_tree_add_pi ( tree , hfinfo , tvb , start , & length ) ;
2005-03-23 00:09:12 +00:00
DISSECTOR_ASSERT ( length > = 0 ) ;
2013-10-29 21:18:22 +00:00
proto_tree_set_string ( PNODE_FINFO ( pi ) , value ) ;
2000-05-31 05:09:07 +00:00
return pi ;
}
2006-02-09 04:18:23 +00:00
proto_item *
proto_tree_add_string_format_value ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
2010-04-26 20:48:13 +00:00
gint start , gint length , const char * value ,
const char * format ,
. . . )
2006-02-09 04:18:23 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2006-02-09 04:18:23 +00:00
pi = proto_tree_add_string ( tree , hfindex , tvb , start , length , value ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
va_start ( ap , format ) ;
proto_tree_set_representation_value ( pi , format , ap ) ;
va_end ( ap ) ;
}
2006-02-09 04:18:23 +00:00
return pi ;
}
2000-05-31 05:09:07 +00:00
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_string_format ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
gint start , gint length , const char * value ,
const char * format , . . . )
2000-05-31 05:09:07 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2000-05-31 05:09:07 +00:00
pi = proto_tree_add_string ( tree , hfindex , tvb , start , length , value ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
2013-07-02 20:51:58 +00:00
TRY_TO_FAKE_THIS_REPR ( pi ) ;
2000-05-31 05:09:07 +00:00
2013-07-02 18:36:00 +00:00
va_start ( ap , format ) ;
proto_tree_set_representation ( pi , format , ap ) ;
va_end ( ap ) ;
}
2000-03-12 04:48:32 +00:00
return pi ;
}
2014-04-12 22:26:34 +00:00
/* Appends string data to a FT_STRING, FT_STRINGZ, or FT_STRINGZPAD,
* allowing progressive field info update instead of only updating the
* representation as does proto_item_append_text ( )
2003-10-29 23:48:14 +00:00
*/
2012-09-19 16:56:59 +00:00
/* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
* speed optimization .
* Currently only WSP use this function so it is not that bad but try to
* avoid using this one if possible .
* IF you must use this function you MUST also disable the
* TRY_TO_FAKE_THIS_ITEM ( ) optimization for your dissector / function
* using proto_item_append_string ( ) .
* Do that by faking that the tree is visible by calling
* proto_tree_set_visible ( tree , TRUE ) ( see packet - wsp . c )
* BEFORE you create the item you are later going to use
* proto_item_append_string ( ) on .
*/
2003-10-29 23:48:14 +00:00
void
proto_item_append_string ( proto_item * pi , const char * str )
{
2012-09-19 16:56:59 +00:00
field_info * fi ;
header_field_info * hfinfo ;
2013-07-25 17:19:17 +00:00
const gchar * old_str , * new_str ;
2003-10-29 23:48:14 +00:00
2012-09-19 16:56:59 +00:00
if ( ! pi )
2003-10-29 23:48:14 +00:00
return ;
2012-09-19 16:56:59 +00:00
if ( ! * str )
2005-09-28 07:08:57 +00:00
return ;
2012-09-19 11:58:32 +00:00
2012-09-19 16:56:59 +00:00
fi = PITEM_FINFO ( pi ) ;
DISSECTOR_ASSERT_HINT ( fi , " proto_tree_set_visible(tree, TRUE) should have been called previously " ) ;
2012-09-19 11:58:32 +00:00
2012-09-19 16:56:59 +00:00
hfinfo = fi - > hfinfo ;
if ( hfinfo - > type = = FT_PROTOCOL ) {
/* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
return ;
2012-09-19 11:58:32 +00:00
}
2014-12-21 23:17:13 +00:00
DISSECTOR_ASSERT_FIELD_TYPE_IS_STRING ( hfinfo ) ;
2013-03-02 12:10:56 +00:00
old_str = ( guint8 * ) fvalue_get ( & fi - > value ) ;
2013-07-25 17:19:17 +00:00
if ( old_str & & old_str [ 0 ] )
2015-01-11 00:04:06 +00:00
new_str = wmem_strconcat ( wmem_packet_scope ( ) , old_str , str , NULL ) ;
2013-07-25 17:19:17 +00:00
else
new_str = str ;
2014-01-15 01:05:03 +00:00
fvalue_set_string ( & fi - > value , new_str ) ;
2003-10-29 23:48:14 +00:00
}
2000-03-12 04:48:32 +00:00
/* Set the FT_STRING value */
static void
2013-10-29 21:18:22 +00:00
proto_tree_set_string ( field_info * fi , const char * value )
2000-03-12 04:48:32 +00:00
{
2008-02-13 05:05:33 +00:00
if ( value ) {
2014-01-15 01:05:03 +00:00
fvalue_set_string ( & fi - > value , value ) ;
2008-02-13 05:05:33 +00:00
} else {
2014-01-15 01:05:03 +00:00
fvalue_set_string ( & fi - > value , " [ Null ] " ) ;
2008-02-13 05:05:33 +00:00
}
2000-03-12 04:48:32 +00:00
}
2012-08-02 16:54:43 +00:00
/* Set the FT_AX25 value */
static void
proto_tree_set_ax25 ( field_info * fi , const guint8 * value )
{
2014-01-15 01:05:03 +00:00
fvalue_set_bytes ( & fi - > value , value ) ;
2012-08-02 16:54:43 +00:00
}
static void
proto_tree_set_ax25_tvb ( field_info * fi , tvbuff_t * tvb , gint start )
{
proto_tree_set_ax25 ( fi , tvb_get_ptr ( tvb , start , 7 ) ) ;
}
2013-07-28 00:07:49 +00:00
/* Set the FT_VINES value */
static void
proto_tree_set_vines ( field_info * fi , const guint8 * value )
{
2014-01-15 01:05:03 +00:00
fvalue_set_bytes ( & fi - > value , value ) ;
2013-07-28 00:07:49 +00:00
}
static void
proto_tree_set_vines_tvb ( field_info * fi , tvbuff_t * tvb , gint start )
{
proto_tree_set_vines ( fi , tvb_get_ptr ( tvb , start , FT_VINES_ADDR_LEN ) ) ;
}
2012-08-02 16:54:43 +00:00
2000-03-12 04:48:32 +00:00
/* Add a FT_ETHER to a proto_tree */
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_ether ( proto_tree * tree , int hfindex , tvbuff_t * tvb , gint start ,
gint length , const guint8 * value )
2000-03-12 04:48:32 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
header_field_info * hfinfo ;
2000-03-12 04:48:32 +00:00
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hfinfo ) ;
2005-04-11 08:43:51 +00:00
2014-12-21 23:17:13 +00:00
DISSECTOR_ASSERT_FIELD_TYPE ( hfinfo , FT_ETHER ) ;
2000-03-12 04:48:32 +00:00
2013-08-22 21:20:50 +00:00
pi = proto_tree_add_pi ( tree , hfinfo , tvb , start , & length ) ;
proto_tree_set_ether ( PNODE_FINFO ( pi ) , value ) ;
2000-05-31 05:09:07 +00:00
return pi ;
}
2006-02-09 04:18:23 +00:00
proto_item *
proto_tree_add_ether_format_value ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
2010-04-26 20:48:13 +00:00
gint start , gint length , const guint8 * value ,
const char * format , . . . )
2006-02-09 04:18:23 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2006-02-09 04:18:23 +00:00
pi = proto_tree_add_ether ( tree , hfindex , tvb , start , length , value ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
va_start ( ap , format ) ;
proto_tree_set_representation_value ( pi , format , ap ) ;
va_end ( ap ) ;
}
2006-02-09 04:18:23 +00:00
return pi ;
}
2000-05-31 05:09:07 +00:00
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_ether_format ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
gint start , gint length , const guint8 * value ,
const char * format , . . . )
2000-05-31 05:09:07 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2000-05-31 05:09:07 +00:00
pi = proto_tree_add_ether ( tree , hfindex , tvb , start , length , value ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
2013-07-02 20:51:58 +00:00
TRY_TO_FAKE_THIS_REPR ( pi ) ;
2000-05-31 05:09:07 +00:00
2013-07-02 18:36:00 +00:00
va_start ( ap , format ) ;
proto_tree_set_representation ( pi , format , ap ) ;
va_end ( ap ) ;
}
2000-03-12 04:48:32 +00:00
return pi ;
}
/* Set the FT_ETHER value */
static void
2000-05-31 05:09:07 +00:00
proto_tree_set_ether ( field_info * fi , const guint8 * value )
2000-03-12 04:48:32 +00:00
{
2014-01-15 01:05:03 +00:00
fvalue_set_bytes ( & fi - > value , value ) ;
2000-03-12 04:48:32 +00:00
}
2000-05-31 05:09:07 +00:00
static void
proto_tree_set_ether_tvb ( field_info * fi , tvbuff_t * tvb , gint start )
{
2009-09-10 18:22:33 +00:00
proto_tree_set_ether ( fi , tvb_get_ptr ( tvb , start , FT_ETHER_LEN ) ) ;
2000-05-31 05:09:07 +00:00
}
2000-03-12 04:48:32 +00:00
/* Add a FT_BOOLEAN to a proto_tree */
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_boolean ( proto_tree * tree , int hfindex , tvbuff_t * tvb , gint start ,
gint length , guint32 value )
2000-03-12 04:48:32 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
header_field_info * hfinfo ;
2000-03-12 04:48:32 +00:00
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hfinfo ) ;
2005-04-11 08:43:51 +00:00
2014-12-21 23:17:13 +00:00
DISSECTOR_ASSERT_FIELD_TYPE ( hfinfo , FT_BOOLEAN ) ;
2000-03-12 04:48:32 +00:00
2013-08-22 21:20:50 +00:00
pi = proto_tree_add_pi ( tree , hfinfo , tvb , start , & length ) ;
proto_tree_set_boolean ( PNODE_FINFO ( pi ) , value ) ;
2000-05-31 05:09:07 +00:00
return pi ;
}
2006-02-09 04:18:23 +00:00
proto_item *
proto_tree_add_boolean_format_value ( proto_tree * tree , int hfindex ,
2010-04-26 20:48:13 +00:00
tvbuff_t * tvb , gint start , gint length ,
guint32 value , const char * format , . . . )
2006-02-09 04:18:23 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2006-02-09 04:18:23 +00:00
pi = proto_tree_add_boolean ( tree , hfindex , tvb , start , length , value ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
va_start ( ap , format ) ;
proto_tree_set_representation_value ( pi , format , ap ) ;
va_end ( ap ) ;
}
2006-02-09 04:18:23 +00:00
return pi ;
}
2000-05-31 05:09:07 +00:00
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_boolean_format ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
gint start , gint length , guint32 value ,
const char * format , . . . )
2000-05-31 05:09:07 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2000-05-31 05:09:07 +00:00
pi = proto_tree_add_boolean ( tree , hfindex , tvb , start , length , value ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
2013-07-02 20:51:58 +00:00
TRY_TO_FAKE_THIS_REPR ( pi ) ;
2000-05-31 05:09:07 +00:00
2013-07-02 18:36:00 +00:00
va_start ( ap , format ) ;
proto_tree_set_representation ( pi , format , ap ) ;
va_end ( ap ) ;
}
2000-03-12 04:48:32 +00:00
return pi ;
}
2015-04-20 07:05:13 +00:00
static proto_item *
proto_tree_add_boolean64 ( proto_tree * tree , int hfindex , tvbuff_t * tvb , gint start ,
gint length , guint64 value )
{
proto_item * pi ;
header_field_info * hfinfo ;
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2015-04-20 07:05:13 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hfinfo ) ;
DISSECTOR_ASSERT_FIELD_TYPE ( hfinfo , FT_BOOLEAN ) ;
pi = proto_tree_add_pi ( tree , hfinfo , tvb , start , & length ) ;
proto_tree_set_boolean ( PNODE_FINFO ( pi ) , value ) ;
return pi ;
}
2000-03-12 04:48:32 +00:00
/* Set the FT_BOOLEAN value */
static void
2014-09-17 16:39:22 +00:00
proto_tree_set_boolean ( field_info * fi , guint64 value )
2000-03-12 04:48:32 +00:00
{
2014-09-17 16:39:22 +00:00
proto_tree_set_uint64 ( fi , value ) ;
2000-03-12 04:48:32 +00:00
}
2015-09-11 23:38:05 +00:00
/* Generate, into "buf", a string showing the bits of a bitfield.
Return a pointer to the character after that string . */
/*XXX this needs a buf_len check */
static char *
other_decode_bitfield_value ( char * buf , const guint64 val , const guint64 mask , const int width )
{
int i ;
guint64 bit ;
char * p ;
i = 0 ;
p = buf ;
bit = G_GUINT64_CONSTANT ( 1 ) < < ( width - 1 ) ;
for ( ; ; ) {
if ( mask & bit ) {
/* This bit is part of the field. Show its value. */
if ( val & bit )
* p + + = ' 1 ' ;
else
* p + + = ' 0 ' ;
} else {
/* This bit is not part of the field. */
* p + + = ' . ' ;
}
bit > > = 1 ;
i + + ;
if ( i > = width )
break ;
if ( i % 4 = = 0 )
* p + + = ' ' ;
}
* p = ' \0 ' ;
return p ;
}
2015-03-18 13:22:46 +00:00
static char *
decode_bitfield_value ( char * buf , const guint64 val , const guint64 mask , const int width )
{
char * p ;
p = other_decode_bitfield_value ( buf , val , mask , width ) ;
p = g_stpcpy ( p , " = " ) ;
return p ;
}
2002-08-24 19:45:28 +00:00
/* Add a FT_FLOAT to a proto_tree */
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_float ( proto_tree * tree , int hfindex , tvbuff_t * tvb , gint start ,
gint length , float value )
2002-08-24 19:45:28 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
header_field_info * hfinfo ;
2002-08-24 19:45:28 +00:00
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hfinfo ) ;
2005-04-11 08:43:51 +00:00
2014-12-21 23:17:13 +00:00
DISSECTOR_ASSERT_FIELD_TYPE ( hfinfo , FT_FLOAT ) ;
2002-08-24 19:45:28 +00:00
2013-08-22 21:20:50 +00:00
pi = proto_tree_add_pi ( tree , hfinfo , tvb , start , & length ) ;
proto_tree_set_float ( PNODE_FINFO ( pi ) , value ) ;
2002-08-24 19:45:28 +00:00
return pi ;
}
2006-02-09 04:18:23 +00:00
proto_item *
proto_tree_add_float_format_value ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
2010-04-26 20:48:13 +00:00
gint start , gint length , float value ,
const char * format , . . . )
2006-02-09 04:18:23 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2006-02-09 04:18:23 +00:00
pi = proto_tree_add_float ( tree , hfindex , tvb , start , length , value ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
va_start ( ap , format ) ;
proto_tree_set_representation_value ( pi , format , ap ) ;
va_end ( ap ) ;
}
2006-02-09 04:18:23 +00:00
return pi ;
}
2002-08-24 19:45:28 +00:00
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_float_format ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
gint start , gint length , float value ,
const char * format , . . . )
2002-08-24 19:45:28 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2002-08-24 19:45:28 +00:00
pi = proto_tree_add_float ( tree , hfindex , tvb , start , length , value ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
2013-07-02 20:51:58 +00:00
TRY_TO_FAKE_THIS_REPR ( pi ) ;
2002-08-24 19:45:28 +00:00
2013-07-02 18:36:00 +00:00
va_start ( ap , format ) ;
proto_tree_set_representation ( pi , format , ap ) ;
va_end ( ap ) ;
}
2002-08-24 19:45:28 +00:00
return pi ;
}
/* Set the FT_FLOAT value */
static void
proto_tree_set_float ( field_info * fi , float value )
{
2003-12-02 21:15:49 +00:00
fvalue_set_floating ( & fi - > value , value ) ;
2002-08-24 19:45:28 +00:00
}
2000-03-12 04:48:32 +00:00
/* Add a FT_DOUBLE to a proto_tree */
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_double ( proto_tree * tree , int hfindex , tvbuff_t * tvb , gint start ,
gint length , double value )
2000-03-12 04:48:32 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
header_field_info * hfinfo ;
2000-03-12 04:48:32 +00:00
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hfinfo ) ;
2005-04-11 08:43:51 +00:00
2014-12-21 23:17:13 +00:00
DISSECTOR_ASSERT_FIELD_TYPE ( hfinfo , FT_DOUBLE ) ;
2000-03-12 04:48:32 +00:00
2013-08-22 21:20:50 +00:00
pi = proto_tree_add_pi ( tree , hfinfo , tvb , start , & length ) ;
proto_tree_set_double ( PNODE_FINFO ( pi ) , value ) ;
2000-05-31 05:09:07 +00:00
return pi ;
}
2006-02-09 04:18:23 +00:00
proto_item *
proto_tree_add_double_format_value ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
2010-04-26 20:48:13 +00:00
gint start , gint length , double value ,
const char * format , . . . )
2006-02-09 04:18:23 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2006-02-09 04:18:23 +00:00
pi = proto_tree_add_double ( tree , hfindex , tvb , start , length , value ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
va_start ( ap , format ) ;
proto_tree_set_representation_value ( pi , format , ap ) ;
va_end ( ap ) ;
}
2006-02-09 04:18:23 +00:00
return pi ;
}
2000-05-31 05:09:07 +00:00
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_double_format ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
gint start , gint length , double value ,
const char * format , . . . )
2000-05-31 05:09:07 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2000-05-31 05:09:07 +00:00
pi = proto_tree_add_double ( tree , hfindex , tvb , start , length , value ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
2013-07-02 20:51:58 +00:00
TRY_TO_FAKE_THIS_REPR ( pi ) ;
2000-05-31 05:09:07 +00:00
2013-07-02 18:36:00 +00:00
va_start ( ap , format ) ;
proto_tree_set_representation ( pi , format , ap ) ;
va_end ( ap ) ;
}
2000-03-12 04:48:32 +00:00
return pi ;
}
/* Set the FT_DOUBLE value */
static void
proto_tree_set_double ( field_info * fi , double value )
{
2003-12-02 21:15:49 +00:00
fvalue_set_floating ( & fi - > value , value ) ;
2000-03-12 04:48:32 +00:00
}
2004-08-22 00:31:58 +00:00
/* Add FT_UINT{8,16,24,32} to a proto_tree */
2000-03-12 04:48:32 +00:00
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_uint ( proto_tree * tree , int hfindex , tvbuff_t * tvb , gint start ,
gint length , guint32 value )
2000-03-12 04:48:32 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi = NULL ;
header_field_info * hfinfo ;
2000-03-12 04:48:32 +00:00
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hfinfo ) ;
2005-04-11 08:43:51 +00:00
2012-03-14 17:11:39 +00:00
switch ( hfinfo - > type ) {
2000-03-12 04:48:32 +00:00
case FT_UINT8 :
case FT_UINT16 :
case FT_UINT24 :
case FT_UINT32 :
2002-12-19 02:58:53 +00:00
case FT_FRAMENUM :
2013-08-22 21:20:50 +00:00
pi = proto_tree_add_pi ( tree , hfinfo , tvb , start , & length ) ;
proto_tree_set_uint ( PNODE_FINFO ( pi ) , value ) ;
2000-03-12 04:48:32 +00:00
break ;
default :
2005-03-23 00:09:12 +00:00
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
2000-03-12 04:48:32 +00:00
}
return pi ;
}
2006-02-09 04:18:23 +00:00
proto_item *
proto_tree_add_uint_format_value ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
2010-04-26 20:48:13 +00:00
gint start , gint length , guint32 value ,
const char * format , . . . )
2006-02-09 04:18:23 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2006-02-09 04:18:23 +00:00
pi = proto_tree_add_uint ( tree , hfindex , tvb , start , length , value ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
va_start ( ap , format ) ;
proto_tree_set_representation_value ( pi , format , ap ) ;
va_end ( ap ) ;
}
2006-02-09 04:18:23 +00:00
return pi ;
}
2000-05-31 05:09:07 +00:00
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_uint_format ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
gint start , gint length , guint32 value ,
const char * format , . . . )
2000-05-31 05:09:07 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2000-05-31 05:09:07 +00:00
pi = proto_tree_add_uint ( tree , hfindex , tvb , start , length , value ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
2013-07-02 20:51:58 +00:00
TRY_TO_FAKE_THIS_REPR ( pi ) ;
2000-05-31 05:09:07 +00:00
2013-07-02 18:36:00 +00:00
va_start ( ap , format ) ;
proto_tree_set_representation ( pi , format , ap ) ;
va_end ( ap ) ;
}
2000-05-31 05:09:07 +00:00
return pi ;
}
2004-08-22 00:31:58 +00:00
/* Set the FT_UINT{8,16,24,32} value */
2000-03-12 04:48:32 +00:00
static void
proto_tree_set_uint ( field_info * fi , guint32 value )
{
2012-03-14 17:11:39 +00:00
header_field_info * hfinfo ;
guint32 integer ;
2000-03-12 04:48:32 +00:00
2003-12-03 09:28:26 +00:00
hfinfo = fi - > hfinfo ;
2001-02-01 20:21:25 +00:00
integer = value ;
2000-03-12 04:48:32 +00:00
if ( hfinfo - > bitmask ) {
/* Mask out irrelevant portions */
2014-10-13 12:17:35 +00:00
integer & = ( guint32 ) ( hfinfo - > bitmask ) ;
2000-03-12 04:48:32 +00:00
/* Shift bits */
2013-08-06 20:10:59 +00:00
integer > > = hfinfo_bitshift ( hfinfo ) ;
2000-03-12 04:48:32 +00:00
}
2008-02-22 11:32:36 +00:00
2007-01-18 11:02:26 +00:00
fvalue_set_uinteger ( & fi - > value , integer ) ;
2000-03-12 04:48:32 +00:00
}
2014-12-17 20:19:20 +00:00
/* Add FT_UINT{40,48,56,64} to a proto_tree */
2004-08-22 00:31:58 +00:00
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_uint64 ( proto_tree * tree , int hfindex , tvbuff_t * tvb , gint start ,
gint length , guint64 value )
2004-08-22 00:31:58 +00:00
{
2014-12-17 20:19:20 +00:00
proto_item * pi = NULL ;
2012-03-14 17:11:39 +00:00
header_field_info * hfinfo ;
2004-08-22 00:31:58 +00:00
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hfinfo ) ;
2005-04-11 08:43:51 +00:00
2014-12-17 20:19:20 +00:00
switch ( hfinfo - > type ) {
case FT_UINT40 :
case FT_UINT48 :
case FT_UINT56 :
case FT_UINT64 :
case FT_FRAMENUM :
pi = proto_tree_add_pi ( tree , hfinfo , tvb , start , & length ) ;
proto_tree_set_uint64 ( PNODE_FINFO ( pi ) , value ) ;
break ;
2004-08-22 00:31:58 +00:00
2014-12-17 20:19:20 +00:00
default :
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
}
2004-08-22 00:31:58 +00:00
return pi ;
}
2006-02-09 04:18:23 +00:00
proto_item *
proto_tree_add_uint64_format_value ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
2010-04-26 20:48:13 +00:00
gint start , gint length , guint64 value ,
const char * format , . . . )
2006-02-09 04:18:23 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2006-02-09 04:18:23 +00:00
pi = proto_tree_add_uint64 ( tree , hfindex , tvb , start , length , value ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
va_start ( ap , format ) ;
proto_tree_set_representation_value ( pi , format , ap ) ;
va_end ( ap ) ;
}
2006-02-09 04:18:23 +00:00
return pi ;
}
2004-08-22 00:31:58 +00:00
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_uint64_format ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
gint start , gint length , guint64 value ,
const char * format , . . . )
2004-08-22 00:31:58 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2004-08-22 00:31:58 +00:00
pi = proto_tree_add_uint64 ( tree , hfindex , tvb , start , length , value ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
2013-07-02 20:51:58 +00:00
TRY_TO_FAKE_THIS_REPR ( pi ) ;
2004-08-22 00:31:58 +00:00
2013-07-02 18:36:00 +00:00
va_start ( ap , format ) ;
proto_tree_set_representation ( pi , format , ap ) ;
va_end ( ap ) ;
}
2004-08-22 00:31:58 +00:00
return pi ;
}
2014-12-17 20:19:20 +00:00
/* Set the FT_UINT{40,48,56,64} value */
static void
proto_tree_set_uint64 ( field_info * fi , guint64 value )
{
header_field_info * hfinfo ;
guint64 integer ;
gint no_of_bits ;
hfinfo = fi - > hfinfo ;
integer = value ;
if ( hfinfo - > bitmask ) {
/* Mask out irrelevant portions */
integer & = hfinfo - > bitmask ;
/* Shift bits */
integer > > = hfinfo_bitshift ( hfinfo ) ;
no_of_bits = ws_count_ones ( hfinfo - > bitmask ) ;
integer = ws_sign_ext64 ( integer , no_of_bits ) ;
}
fvalue_set_uinteger64 ( & fi - > value , integer ) ;
}
2004-08-22 00:31:58 +00:00
/* Add FT_INT{8,16,24,32} to a proto_tree */
2000-04-25 21:43:50 +00:00
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_int ( proto_tree * tree , int hfindex , tvbuff_t * tvb , gint start ,
gint length , gint32 value )
2000-04-25 21:43:50 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi = NULL ;
header_field_info * hfinfo ;
2000-04-25 21:43:50 +00:00
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hfinfo ) ;
2005-04-11 08:43:51 +00:00
2012-03-14 17:11:39 +00:00
switch ( hfinfo - > type ) {
2000-04-25 21:43:50 +00:00
case FT_INT8 :
case FT_INT16 :
case FT_INT24 :
case FT_INT32 :
2013-08-22 21:20:50 +00:00
pi = proto_tree_add_pi ( tree , hfinfo , tvb , start , & length ) ;
proto_tree_set_int ( PNODE_FINFO ( pi ) , value ) ;
2000-04-25 21:43:50 +00:00
break ;
default :
2005-03-23 00:09:12 +00:00
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
2000-04-25 21:43:50 +00:00
}
2000-05-31 05:09:07 +00:00
return pi ;
}
2006-02-09 04:18:23 +00:00
proto_item *
proto_tree_add_int_format_value ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
2010-04-26 20:48:13 +00:00
gint start , gint length , gint32 value ,
const char * format , . . . )
2006-02-09 04:18:23 +00:00
{
2013-07-02 18:36:00 +00:00
proto_item * pi ;
va_list ap ;
2006-02-09 04:18:23 +00:00
pi = proto_tree_add_int ( tree , hfindex , tvb , start , length , value ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
va_start ( ap , format ) ;
proto_tree_set_representation_value ( pi , format , ap ) ;
va_end ( ap ) ;
}
2006-02-09 04:18:23 +00:00
return pi ;
}
2000-05-31 05:09:07 +00:00
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_int_format ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
gint start , gint length , gint32 value ,
const char * format , . . . )
2000-05-31 05:09:07 +00:00
{
2013-07-02 18:36:00 +00:00
proto_item * pi ;
va_list ap ;
2000-05-31 05:09:07 +00:00
pi = proto_tree_add_int ( tree , hfindex , tvb , start , length , value ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
2013-07-02 20:51:58 +00:00
TRY_TO_FAKE_THIS_REPR ( pi ) ;
2000-05-31 05:09:07 +00:00
2013-07-02 18:36:00 +00:00
va_start ( ap , format ) ;
proto_tree_set_representation ( pi , format , ap ) ;
va_end ( ap ) ;
}
2000-05-31 05:09:07 +00:00
return pi ;
}
2004-08-22 00:31:58 +00:00
/* Set the FT_INT{8,16,24,32} value */
2000-04-25 21:43:50 +00:00
static void
proto_tree_set_int ( field_info * fi , gint32 value )
{
2012-03-14 17:11:39 +00:00
header_field_info * hfinfo ;
guint32 integer ;
2013-08-26 16:23:55 +00:00
gint no_of_bits ;
2000-04-25 21:43:50 +00:00
2003-12-03 09:28:26 +00:00
hfinfo = fi - > hfinfo ;
2001-02-01 20:21:25 +00:00
integer = ( guint32 ) value ;
2000-04-25 21:43:50 +00:00
if ( hfinfo - > bitmask ) {
/* Mask out irrelevant portions */
2014-10-13 12:17:35 +00:00
integer & = ( guint32 ) ( hfinfo - > bitmask ) ;
2000-04-25 21:43:50 +00:00
/* Shift bits */
2013-08-06 20:10:59 +00:00
integer > > = hfinfo_bitshift ( hfinfo ) ;
2013-08-26 16:23:55 +00:00
2013-11-09 04:47:08 +00:00
no_of_bits = ws_count_ones ( hfinfo - > bitmask ) ;
2013-12-17 21:36:33 +00:00
integer = ws_sign_ext32 ( integer , no_of_bits ) ;
2000-04-25 21:43:50 +00:00
}
2008-02-13 05:05:33 +00:00
2007-01-18 11:02:26 +00:00
fvalue_set_sinteger ( & fi - > value , integer ) ;
2000-04-25 21:43:50 +00:00
}
2000-03-12 04:48:32 +00:00
2014-12-17 20:19:20 +00:00
/* Add FT_INT{40,48,56,64} to a proto_tree */
2004-08-22 00:31:58 +00:00
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_int64 ( proto_tree * tree , int hfindex , tvbuff_t * tvb , gint start ,
gint length , gint64 value )
2004-08-22 00:31:58 +00:00
{
2014-12-17 20:19:20 +00:00
proto_item * pi = NULL ;
2012-03-14 17:11:39 +00:00
header_field_info * hfinfo ;
2004-08-22 00:31:58 +00:00
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hfinfo ) ;
2005-04-11 08:43:51 +00:00
2014-12-17 20:19:20 +00:00
switch ( hfinfo - > type ) {
case FT_INT40 :
case FT_INT48 :
case FT_INT56 :
case FT_INT64 :
pi = proto_tree_add_pi ( tree , hfinfo , tvb , start , & length ) ;
proto_tree_set_int64 ( PNODE_FINFO ( pi ) , value ) ;
break ;
2004-08-22 00:31:58 +00:00
2014-12-17 20:19:20 +00:00
default :
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
}
2004-08-22 00:31:58 +00:00
return pi ;
}
2006-02-09 04:18:23 +00:00
proto_item *
proto_tree_add_int64_format_value ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
2010-04-26 20:48:13 +00:00
gint start , gint length , gint64 value ,
const char * format , . . . )
2006-02-09 04:18:23 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2006-02-09 04:18:23 +00:00
pi = proto_tree_add_int64 ( tree , hfindex , tvb , start , length , value ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
va_start ( ap , format ) ;
proto_tree_set_representation_value ( pi , format , ap ) ;
va_end ( ap ) ;
}
2006-02-09 04:18:23 +00:00
return pi ;
}
2014-12-17 20:19:20 +00:00
/* Set the FT_INT{40,48,56,64} value */
static void
proto_tree_set_int64 ( field_info * fi , gint64 value )
{
header_field_info * hfinfo ;
guint64 integer ;
gint no_of_bits ;
hfinfo = fi - > hfinfo ;
integer = value ;
if ( hfinfo - > bitmask ) {
/* Mask out irrelevant portions */
integer & = hfinfo - > bitmask ;
/* Shift bits */
integer > > = hfinfo_bitshift ( hfinfo ) ;
no_of_bits = ws_count_ones ( hfinfo - > bitmask ) ;
integer = ws_sign_ext64 ( integer , no_of_bits ) ;
}
fvalue_set_sinteger64 ( & fi - > value , integer ) ;
}
2004-08-22 00:31:58 +00:00
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_int64_format ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
gint start , gint length , gint64 value ,
const char * format , . . . )
2004-08-22 00:31:58 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2004-08-22 00:31:58 +00:00
pi = proto_tree_add_int64 ( tree , hfindex , tvb , start , length , value ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
2013-07-02 20:51:58 +00:00
TRY_TO_FAKE_THIS_REPR ( pi ) ;
2004-08-22 00:31:58 +00:00
2013-07-02 18:36:00 +00:00
va_start ( ap , format ) ;
proto_tree_set_representation ( pi , format , ap ) ;
va_end ( ap ) ;
}
2004-08-22 00:31:58 +00:00
return pi ;
}
2014-12-17 20:19:20 +00:00
2011-05-08 10:23:53 +00:00
/* Add a FT_EUI64 to a proto_tree */
proto_item *
proto_tree_add_eui64 ( proto_tree * tree , int hfindex , tvbuff_t * tvb , gint start ,
gint length , const guint64 value )
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
header_field_info * hfinfo ;
2011-05-08 10:23:53 +00:00
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hfinfo ) ;
2011-05-08 10:23:53 +00:00
2014-12-21 23:17:13 +00:00
DISSECTOR_ASSERT_FIELD_TYPE ( hfinfo , FT_EUI64 ) ;
2011-05-08 10:23:53 +00:00
2013-08-22 21:20:50 +00:00
pi = proto_tree_add_pi ( tree , hfinfo , tvb , start , & length ) ;
proto_tree_set_eui64 ( PNODE_FINFO ( pi ) , value ) ;
2011-05-08 10:23:53 +00:00
return pi ;
}
proto_item *
proto_tree_add_eui64_format_value ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
gint start , gint length , const guint64 value ,
const char * format , . . . )
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2011-05-08 10:23:53 +00:00
pi = proto_tree_add_eui64 ( tree , hfindex , tvb , start , length , value ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
va_start ( ap , format ) ;
proto_tree_set_representation_value ( pi , format , ap ) ;
va_end ( ap ) ;
}
2011-05-08 10:23:53 +00:00
return pi ;
}
proto_item *
proto_tree_add_eui64_format ( proto_tree * tree , int hfindex , tvbuff_t * tvb ,
gint start , gint length , const guint64 value ,
const char * format , . . . )
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
va_list ap ;
2011-05-08 10:23:53 +00:00
pi = proto_tree_add_eui64 ( tree , hfindex , tvb , start , length , value ) ;
2013-07-02 18:36:00 +00:00
if ( pi ! = tree ) {
2013-07-02 20:51:58 +00:00
TRY_TO_FAKE_THIS_REPR ( pi ) ;
2011-05-08 10:23:53 +00:00
2013-07-02 18:36:00 +00:00
va_start ( ap , format ) ;
proto_tree_set_representation ( pi , format , ap ) ;
va_end ( ap ) ;
}
2011-05-08 10:23:53 +00:00
return pi ;
}
/* Set the FT_EUI64 value */
static void
proto_tree_set_eui64 ( field_info * fi , const guint64 value )
{
2014-12-17 20:19:20 +00:00
fvalue_set_uinteger64 ( & fi - > value , value ) ;
2011-05-08 10:23:53 +00:00
}
static void
proto_tree_set_eui64_tvb ( field_info * fi , tvbuff_t * tvb , gint start , const guint encoding )
{
2012-03-14 17:11:39 +00:00
if ( encoding )
2011-05-08 10:23:53 +00:00
{
proto_tree_set_eui64 ( fi , tvb_get_letoh64 ( tvb , start ) ) ;
2012-03-14 17:11:39 +00:00
} else {
2011-05-08 10:23:53 +00:00
proto_tree_set_eui64 ( fi , tvb_get_ntoh64 ( tvb , start ) ) ;
}
}
2004-08-22 00:31:58 +00:00
2003-12-04 10:59:34 +00:00
/* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
2000-03-12 04:48:32 +00:00
static proto_item *
proto_tree_add_node ( proto_tree * tree , field_info * fi )
{
2003-12-04 10:59:34 +00:00
proto_node * pnode , * tnode , * sibling ;
2002-04-04 20:23:50 +00:00
field_info * tfi ;
2016-04-11 22:38:14 +00:00
int depth = 1 ;
/*
* Restrict our depth . proto_tree_traverse_pre_order and
* proto_tree_traverse_post_order ( and possibly others ) are recursive
* so we need to be mindful of our stack size .
*/
if ( tree - > first_child = = NULL ) {
for ( tnode = tree ; tnode ! = NULL ; tnode = tnode - > parent ) {
depth + + ;
if ( G_UNLIKELY ( depth > MAX_TREE_LEVELS ) ) {
THROW_MESSAGE ( DissectorError , wmem_strdup_printf ( wmem_packet_scope ( ) ,
" Maximum tree depth %d exceeded for \" %s \" - \" %s \" (%s:%u) " ,
MAX_TREE_LEVELS ,
fi - > hfinfo - > name , fi - > hfinfo - > abbrev , G_STRFUNC , __LINE__ ) ) ;
}
}
}
2002-04-04 20:23:50 +00:00
/*
* Make sure " tree " is ready to have subtrees under it , by
* checking whether it ' s been given an ett_ value .
*
2009-08-09 17:57:31 +00:00
* " PNODE_FINFO(tnode) " may be null ; that ' s the case for the root
2002-04-04 20:23:50 +00:00
* node of the protocol tree . That node is not displayed ,
* so it doesn ' t need an ett_ value to remember whether it
* was expanded .
*/
2003-12-04 10:59:34 +00:00
tnode = tree ;
2009-08-09 17:57:31 +00:00
tfi = PNODE_FINFO ( tnode ) ;
2005-01-26 23:17:00 +00:00
if ( tfi ! = NULL & & ( tfi - > tree_type < 0 | | tfi - > tree_type > = num_tree_types ) ) {
2015-01-18 17:15:26 +00:00
REPORT_DISSECTOR_BUG ( wmem_strdup_printf ( wmem_packet_scope ( ) ,
" \" %s \" - \" %s \" tfi->tree_type: %u invalid (%s:%u) " ,
2010-04-26 20:48:13 +00:00
fi - > hfinfo - > name , fi - > hfinfo - > abbrev , tfi - > tree_type , __FILE__ , __LINE__ ) ) ;
2005-09-28 16:16:37 +00:00
/* XXX - is it safe to continue here? */
}
2005-01-26 23:17:00 +00:00
2013-10-20 10:03:32 +00:00
pnode = wmem_new ( PNODE_POOL ( tree ) , proto_node ) ;
PROTO_NODE_INIT ( pnode ) ;
2003-12-04 19:53:54 +00:00
pnode - > parent = tnode ;
2009-08-09 17:57:31 +00:00
PNODE_FINFO ( pnode ) = fi ;
2002-01-07 01:05:33 +00:00
pnode - > tree_data = PTREE_DATA ( tree ) ;
1999-07-07 22:52:57 +00:00
2003-12-04 10:59:34 +00:00
if ( tnode - > last_child ! = NULL ) {
sibling = tnode - > last_child ;
2005-03-23 00:09:12 +00:00
DISSECTOR_ASSERT ( sibling - > next = = NULL ) ;
2003-12-04 10:59:34 +00:00
sibling - > next = pnode ;
} else
tnode - > first_child = pnode ;
tnode - > last_child = pnode ;
2001-12-18 19:09:08 +00:00
2013-07-02 21:26:14 +00:00
tree_data_add_maybe_interesting_field ( pnode - > tree_data , fi ) ;
2013-07-02 19:23:10 +00:00
2012-03-14 17:11:39 +00:00
return ( proto_item * ) pnode ;
2000-03-12 04:48:32 +00:00
}
2000-05-31 05:09:07 +00:00
/* Generic way to allocate field_info and add to proto_tree.
2013-07-02 18:56:48 +00:00
* Sets * pfi to address of newly - allocated field_info struct */
2000-03-12 04:48:32 +00:00
static proto_item *
2013-06-18 20:52:31 +00:00
proto_tree_add_pi ( proto_tree * tree , header_field_info * hfinfo , tvbuff_t * tvb , gint start ,
2013-08-22 21:20:50 +00:00
gint * length )
2000-03-12 04:48:32 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * pi ;
field_info * fi ;
2014-04-25 13:29:29 +00:00
gint item_length ;
2000-03-12 04:48:32 +00:00
2014-04-25 13:29:29 +00:00
get_hfi_length ( hfinfo , tvb , start , length , & item_length ) ;
fi = new_field_info ( tree , hfinfo , tvb , start , item_length ) ;
2000-07-27 06:41:59 +00:00
pi = proto_tree_add_node ( tree , fi ) ;
return pi ;
}
2005-10-22 05:43:09 +00:00
2013-06-18 20:52:31 +00:00
static void
2013-07-11 15:03:43 +00:00
get_hfi_length ( header_field_info * hfinfo , tvbuff_t * tvb , const gint start , gint * length ,
2010-04-26 20:48:13 +00:00
gint * item_length )
2000-07-27 06:41:59 +00:00
{
2013-07-11 15:03:43 +00:00
gint length_remaining ;
2001-11-20 09:07:34 +00:00
/*
* We only allow a null tvbuff if the item has a zero length ,
* i . e . if there ' s no data backing it .
*/
2005-03-23 00:09:12 +00:00
DISSECTOR_ASSERT ( tvb ! = NULL | | * length = = 0 ) ;
Allow a length of -1 to be specified when adding FT_NONE and FT_PROTOCOL
items to the protocol tree; it's interpreted as "the rest of the data in
the tvbuff". This can be used if
1) the item covers the entire packet or the remaining payload in
the packet
or
2) the item's length won't be known until it's dissected, and
will be then set with "proto_item_set_len()" - if an
exception is thrown in the dissection, it means the item ran
*past* the end of the tvbuff, so saying it runs to the end of
the tvbuff is reasonable.
Convert a number of "proto_tree_add_XXX()" calls using
"tvb_length_remaining()", values derived from the result of
"tvb_length()", or 0 (in the case of items whose length is unknown) to
use -1 instead (using 0 means that if an exception is thrown, selecting
the item highlights nothing; using -1 means it highlights all the data
for that item that's available).
In some places where "tvb_length()" or "tvb_length_remaining()" was used
to determine how large a packet is, use "tvb_reported_length()" or
"tvb_reported_length_remaining()", instead - the first two calls
indicate how much captured data was in the packet, the latter two calls
indicate how large the packet actually was (and the fact that using the
latter could cause BoundsError exceptions to be thrown is a feature - if
such an exception is thrown, the frame really *was* short, and it should
be tagged as such).
Replace some "proto_tree_add_XXX()" calls with equivalent
"proto_tree_add_item()" calls.
Fix some indentation.
svn path=/trunk/; revision=4578
2002-01-20 22:12:39 +00:00
2005-03-26 03:27:22 +00:00
/*
* XXX - in some protocols , there are 32 - bit unsigned length
* fields , so lengths in protocol tree and tvbuff routines
* should really be unsigned . We should have , for those
* field types for which " to the end of the tvbuff " makes sense ,
* additional routines that take no length argument and
* add fields that run to the end of the tvbuff .
*/
2005-04-28 03:30:07 +00:00
if ( * length = = - 1 ) {
Allow a length of -1 to be specified when adding FT_NONE and FT_PROTOCOL
items to the protocol tree; it's interpreted as "the rest of the data in
the tvbuff". This can be used if
1) the item covers the entire packet or the remaining payload in
the packet
or
2) the item's length won't be known until it's dissected, and
will be then set with "proto_item_set_len()" - if an
exception is thrown in the dissection, it means the item ran
*past* the end of the tvbuff, so saying it runs to the end of
the tvbuff is reasonable.
Convert a number of "proto_tree_add_XXX()" calls using
"tvb_length_remaining()", values derived from the result of
"tvb_length()", or 0 (in the case of items whose length is unknown) to
use -1 instead (using 0 means that if an exception is thrown, selecting
the item highlights nothing; using -1 means it highlights all the data
for that item that's available).
In some places where "tvb_length()" or "tvb_length_remaining()" was used
to determine how large a packet is, use "tvb_reported_length()" or
"tvb_reported_length_remaining()", instead - the first two calls
indicate how much captured data was in the packet, the latter two calls
indicate how large the packet actually was (and the fact that using the
latter could cause BoundsError exceptions to be thrown is a feature - if
such an exception is thrown, the frame really *was* short, and it should
be tagged as such).
Replace some "proto_tree_add_XXX()" calls with equivalent
"proto_tree_add_item()" calls.
Fix some indentation.
svn path=/trunk/; revision=4578
2002-01-20 22:12:39 +00:00
/*
2014-04-12 22:26:34 +00:00
* For FT_NONE , FT_PROTOCOL , FT_BYTES , FT_STRING , and
* FT_STRINGZPAD fields , a length of - 1 means " set the
* length to what remains in the tvbuff " .
2002-02-18 22:26:29 +00:00
*
* The assumption is either that
*
* 1 ) the length of the item can only be determined
* by dissection ( typically true of items with
* subitems , which are probably FT_NONE or
* FT_PROTOCOL )
*
* or
*
* 2 ) if the tvbuff is " short " ( either due to a short
* snapshot length or due to lack of reassembly of
* fragments / segments / whatever ) , we want to display
* what ' s available in the field ( probably FT_BYTES
* or FT_STRING ) and then throw an exception later
*
* or
*
* 3 ) the field is defined to be " what's left in the
* packet "
*
* so we set the length to what remains in the tvbuff so
* that , if we throw an exception while dissecting , it
* has what is probably the right value .
Allow a length of -1 to be specified when adding FT_NONE and FT_PROTOCOL
items to the protocol tree; it's interpreted as "the rest of the data in
the tvbuff". This can be used if
1) the item covers the entire packet or the remaining payload in
the packet
or
2) the item's length won't be known until it's dissected, and
will be then set with "proto_item_set_len()" - if an
exception is thrown in the dissection, it means the item ran
*past* the end of the tvbuff, so saying it runs to the end of
the tvbuff is reasonable.
Convert a number of "proto_tree_add_XXX()" calls using
"tvb_length_remaining()", values derived from the result of
"tvb_length()", or 0 (in the case of items whose length is unknown) to
use -1 instead (using 0 means that if an exception is thrown, selecting
the item highlights nothing; using -1 means it highlights all the data
for that item that's available).
In some places where "tvb_length()" or "tvb_length_remaining()" was used
to determine how large a packet is, use "tvb_reported_length()" or
"tvb_reported_length_remaining()", instead - the first two calls
indicate how much captured data was in the packet, the latter two calls
indicate how large the packet actually was (and the fact that using the
latter could cause BoundsError exceptions to be thrown is a feature - if
such an exception is thrown, the frame really *was* short, and it should
be tagged as such).
Replace some "proto_tree_add_XXX()" calls with equivalent
"proto_tree_add_item()" calls.
Fix some indentation.
svn path=/trunk/; revision=4578
2002-01-20 22:12:39 +00:00
*
When "proto_tree_add_item()" is used with an FT_STRINGZ and given a
length (rather than being given -1), the length is, in most cases, the
maximum length of a null-*padded* string, rather than the actual length
of a null-*terminated* string. Treat it as such - allocate a buffer one
larger than the length (to leave room for a terminating '\0'), and pass
the size of that buffer to "tvb_get_nstringz0()". (Otherwise, in those
cases, the last character of the string is chopped off.)
Allow "proto_tree_add_string()" to add FT_STRINGZ items to the protocol
tree, as well as FT_STRING items.
In "alloc_field_info()", if we're passed a length of -1 and the field is
an FT_STRINGZ, don't make the length be the length remaining in the
tvbuff; that way, you *can* use a length of -1 in
"proto_tree_add_item()" for an FT_STRINGZ item, and have it get the
actual length by looking for the terminating '\0'.
(We might want to distinguish between null-terminated and null-padded
strings, e.g. with an FT_STRINGZPAD type. Null-terminated strings
rarely, if ever, have a specified length; the length is found by
scanning for the terminating '\0'. Null-padded strings presumably
always have a specified length, which is the length to which the string
is padded.)
svn path=/trunk/; revision=7784
2003-06-04 21:51:54 +00:00
* For FT_STRINGZ , it means " the string is null-terminated,
* not null - padded ; set the length to the actual length
* of the string " , and if the tvbuff if short, we just
* throw an exception .
*
2014-09-12 16:59:34 +00:00
* It ' s not valid for any other type of field . For those
* fields , we treat - 1 the same way we treat other
* negative values - we assume the length is a Really
* Big Positive Number , and throw a ReportedBoundsError
* exception , under the assumption that the Really Big
* Length would run past the end of the packet .
Allow a length of -1 to be specified when adding FT_NONE and FT_PROTOCOL
items to the protocol tree; it's interpreted as "the rest of the data in
the tvbuff". This can be used if
1) the item covers the entire packet or the remaining payload in
the packet
or
2) the item's length won't be known until it's dissected, and
will be then set with "proto_item_set_len()" - if an
exception is thrown in the dissection, it means the item ran
*past* the end of the tvbuff, so saying it runs to the end of
the tvbuff is reasonable.
Convert a number of "proto_tree_add_XXX()" calls using
"tvb_length_remaining()", values derived from the result of
"tvb_length()", or 0 (in the case of items whose length is unknown) to
use -1 instead (using 0 means that if an exception is thrown, selecting
the item highlights nothing; using -1 means it highlights all the data
for that item that's available).
In some places where "tvb_length()" or "tvb_length_remaining()" was used
to determine how large a packet is, use "tvb_reported_length()" or
"tvb_reported_length_remaining()", instead - the first two calls
indicate how much captured data was in the packet, the latter two calls
indicate how large the packet actually was (and the fact that using the
latter could cause BoundsError exceptions to be thrown is a feature - if
such an exception is thrown, the frame really *was* short, and it should
be tagged as such).
Replace some "proto_tree_add_XXX()" calls with equivalent
"proto_tree_add_item()" calls.
Fix some indentation.
svn path=/trunk/; revision=4578
2002-01-20 22:12:39 +00:00
*/
When "proto_tree_add_item()" is used with an FT_STRINGZ and given a
length (rather than being given -1), the length is, in most cases, the
maximum length of a null-*padded* string, rather than the actual length
of a null-*terminated* string. Treat it as such - allocate a buffer one
larger than the length (to leave room for a terminating '\0'), and pass
the size of that buffer to "tvb_get_nstringz0()". (Otherwise, in those
cases, the last character of the string is chopped off.)
Allow "proto_tree_add_string()" to add FT_STRINGZ items to the protocol
tree, as well as FT_STRING items.
In "alloc_field_info()", if we're passed a length of -1 and the field is
an FT_STRINGZ, don't make the length be the length remaining in the
tvbuff; that way, you *can* use a length of -1 in
"proto_tree_add_item()" for an FT_STRINGZ item, and have it get the
actual length by looking for the terminating '\0'.
(We might want to distinguish between null-terminated and null-padded
strings, e.g. with an FT_STRINGZPAD type. Null-terminated strings
rarely, if ever, have a specified length; the length is found by
scanning for the terminating '\0'. Null-padded strings presumably
always have a specified length, which is the length to which the string
is padded.)
svn path=/trunk/; revision=7784
2003-06-04 21:51:54 +00:00
switch ( hfinfo - > type ) {
case FT_PROTOCOL :
2014-04-23 02:14:56 +00:00
case FT_NONE :
case FT_BYTES :
case FT_STRING :
case FT_STRINGZPAD :
2003-12-24 23:37:28 +00:00
/*
2014-04-23 02:14:56 +00:00
* We allow FT_PROTOCOLs to be zero - length -
* for example , an ONC RPC NULL procedure has
2003-12-24 23:37:28 +00:00
* neither arguments nor reply , so the
* payload for that protocol is empty .
*
2014-04-23 02:14:56 +00:00
* We also allow the others to be zero - length -
* because that ' s the way the code has been for a
* long , long time .
*
* However , we want to ensure that the start
* offset is not * past * the byte past the end
* of the tvbuff : we throw an exception in that
* case .
2003-12-24 23:37:28 +00:00
*/
2014-05-14 17:00:37 +00:00
* length = tvb_ensure_captured_length_remaining ( tvb , start ) ;
2005-03-23 00:09:12 +00:00
DISSECTOR_ASSERT ( * length > = 0 ) ;
When "proto_tree_add_item()" is used with an FT_STRINGZ and given a
length (rather than being given -1), the length is, in most cases, the
maximum length of a null-*padded* string, rather than the actual length
of a null-*terminated* string. Treat it as such - allocate a buffer one
larger than the length (to leave room for a terminating '\0'), and pass
the size of that buffer to "tvb_get_nstringz0()". (Otherwise, in those
cases, the last character of the string is chopped off.)
Allow "proto_tree_add_string()" to add FT_STRINGZ items to the protocol
tree, as well as FT_STRING items.
In "alloc_field_info()", if we're passed a length of -1 and the field is
an FT_STRINGZ, don't make the length be the length remaining in the
tvbuff; that way, you *can* use a length of -1 in
"proto_tree_add_item()" for an FT_STRINGZ item, and have it get the
actual length by looking for the terminating '\0'.
(We might want to distinguish between null-terminated and null-padded
strings, e.g. with an FT_STRINGZPAD type. Null-terminated strings
rarely, if ever, have a specified length; the length is found by
scanning for the terminating '\0'. Null-padded strings presumably
always have a specified length, which is the length to which the string
is padded.)
svn path=/trunk/; revision=7784
2003-06-04 21:51:54 +00:00
break ;
case FT_STRINGZ :
/*
* Leave the length as - 1 , so our caller knows
* it was - 1.
*/
break ;
default :
2014-09-12 16:59:34 +00:00
THROW ( ReportedBoundsError ) ;
2005-03-23 00:09:12 +00:00
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
When "proto_tree_add_item()" is used with an FT_STRINGZ and given a
length (rather than being given -1), the length is, in most cases, the
maximum length of a null-*padded* string, rather than the actual length
of a null-*terminated* string. Treat it as such - allocate a buffer one
larger than the length (to leave room for a terminating '\0'), and pass
the size of that buffer to "tvb_get_nstringz0()". (Otherwise, in those
cases, the last character of the string is chopped off.)
Allow "proto_tree_add_string()" to add FT_STRINGZ items to the protocol
tree, as well as FT_STRING items.
In "alloc_field_info()", if we're passed a length of -1 and the field is
an FT_STRINGZ, don't make the length be the length remaining in the
tvbuff; that way, you *can* use a length of -1 in
"proto_tree_add_item()" for an FT_STRINGZ item, and have it get the
actual length by looking for the terminating '\0'.
(We might want to distinguish between null-terminated and null-padded
strings, e.g. with an FT_STRINGZPAD type. Null-terminated strings
rarely, if ever, have a specified length; the length is found by
scanning for the terminating '\0'. Null-padded strings presumably
always have a specified length, which is the length to which the string
is padded.)
svn path=/trunk/; revision=7784
2003-06-04 21:51:54 +00:00
}
2005-10-22 05:43:09 +00:00
* item_length = * length ;
2005-01-17 00:56:56 +00:00
} else {
2005-10-22 05:43:09 +00:00
* item_length = * length ;
2005-03-26 03:27:22 +00:00
if ( hfinfo - > type = = FT_PROTOCOL | | hfinfo - > type = = FT_NONE ) {
/*
* These types are for interior nodes of the
* tree , and don ' t have data associated with
* them ; if the length is negative ( XXX - see
* above ) or goes past the end of the tvbuff ,
* cut it short at the end of the tvbuff .
* That way , if this field is selected in
2006-05-28 19:49:07 +00:00
* Wireshark , we don ' t highlight stuff past
2005-03-26 03:27:22 +00:00
* the end of the data .
*/
2005-10-22 05:43:09 +00:00
/* XXX - what to do, if we don't have a tvb? */
if ( tvb ) {
2014-04-01 04:20:07 +00:00
length_remaining = tvb_captured_length_remaining ( tvb , start ) ;
2005-10-22 05:43:09 +00:00
if ( * item_length < 0 | |
2009-09-23 16:27:37 +00:00
( * item_length > 0 & &
( length_remaining < * item_length ) ) )
2005-10-22 05:43:09 +00:00
* item_length = length_remaining ;
}
2005-03-26 03:27:22 +00:00
}
2005-10-22 05:43:09 +00:00
if ( * item_length < 0 ) {
2005-04-28 04:03:30 +00:00
THROW ( ReportedBoundsError ) ;
}
2005-01-17 00:56:56 +00:00
}
2005-10-22 05:43:09 +00:00
}
2016-01-09 02:25:26 +00:00
static gint
get_full_length ( header_field_info * hfinfo , tvbuff_t * tvb , const gint start ,
gint length , guint item_length , const gint encoding )
{
guint32 n ;
/*
* We need to get the correct item length here .
* That ' s normally done by proto_tree_new_item ( ) ,
* but we won ' t be calling it .
*/
switch ( hfinfo - > type ) {
case FT_NONE :
case FT_PROTOCOL :
case FT_BYTES :
/*
* The length is the specified length .
*/
break ;
case FT_UINT_BYTES :
/*
* Map all non - zero values to little - endian for
* backwards compatibility .
*/
n = get_uint_value ( NULL , tvb , start , length ,
encoding ? ENC_LITTLE_ENDIAN : ENC_BIG_ENDIAN ) ;
item_length + = n ;
break ;
case FT_BOOLEAN :
/* XXX - make these just FT_UINT? */
case FT_UINT8 :
case FT_UINT16 :
case FT_UINT24 :
case FT_UINT32 :
case FT_UINT40 :
case FT_UINT48 :
case FT_UINT56 :
case FT_UINT64 :
/* XXX - make these just FT_INT? */
case FT_INT8 :
case FT_INT16 :
case FT_INT24 :
case FT_INT32 :
case FT_INT40 :
case FT_INT48 :
case FT_INT56 :
case FT_INT64 :
case FT_IPv4 :
case FT_IPXNET :
case FT_IPv6 :
case FT_FCWWN :
case FT_AX25 :
case FT_VINES :
case FT_ETHER :
case FT_EUI64 :
case FT_GUID :
case FT_OID :
case FT_REL_OID :
case FT_SYSTEM_ID :
case FT_FLOAT :
case FT_DOUBLE :
case FT_STRING :
/*
* The length is the specified length .
*/
break ;
case FT_STRINGZ :
if ( length < - 1 ) {
report_type_length_mismatch ( NULL , " a string " , length , TRUE ) ;
}
if ( length = = - 1 ) {
/* This can throw an exception */
/* XXX - do this without fetching the string? */
tvb_get_stringz_enc ( wmem_packet_scope ( ) , tvb , start , & length , encoding ) ;
}
item_length = length ;
break ;
case FT_UINT_STRING :
n = get_uint_value ( NULL , tvb , start , length , encoding & ~ ENC_CHARENCODING_MASK ) ;
item_length + = n ;
break ;
case FT_STRINGZPAD :
case FT_ABSOLUTE_TIME :
case FT_RELATIVE_TIME :
case FT_IEEE_11073_SFLOAT :
case FT_IEEE_11073_FLOAT :
/*
* The length is the specified length .
*/
break ;
default :
g_error ( " hfinfo->type %d (%s) not handled \n " ,
hfinfo - > type ,
ftype_name ( hfinfo - > type ) ) ;
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
break ;
}
return item_length ;
}
2005-10-22 05:43:09 +00:00
static field_info *
new_field_info ( proto_tree * tree , header_field_info * hfinfo , tvbuff_t * tvb ,
2010-04-26 20:48:13 +00:00
const gint start , const gint item_length )
2005-10-22 05:43:09 +00:00
{
2012-03-14 17:11:39 +00:00
field_info * fi ;
2005-10-22 05:43:09 +00:00
2013-10-12 21:01:17 +00:00
FIELD_INFO_NEW ( PNODE_POOL ( tree ) , fi ) ;
2003-11-24 21:12:10 +00:00
2012-03-14 17:11:39 +00:00
fi - > hfinfo = hfinfo ;
fi - > start = start ;
fi - > start + = ( tvb ) ? tvb_raw_offset ( tvb ) : 0 ;
fi - > length = item_length ;
fi - > tree_type = - 1 ;
fi - > flags = 0 ;
2004-10-27 10:02:45 +00:00
if ( ! PTREE_DATA ( tree ) - > visible )
FI_SET_FLAG ( fi , FI_HIDDEN ) ;
2003-12-03 09:28:26 +00:00
fvalue_init ( & fi - > value , fi - > hfinfo - > type ) ;
2012-03-14 17:11:39 +00:00
fi - > rep = NULL ;
2000-03-12 04:48:32 +00:00
2002-02-18 01:08:44 +00:00
/* add the data source tvbuff */
2012-03-14 17:11:39 +00:00
fi - > ds_tvb = tvb ? tvb_get_ds_tvb ( tvb ) : NULL ;
2001-03-23 14:44:04 +00:00
2012-03-14 17:11:39 +00:00
fi - > appendix_start = 0 ;
2007-09-17 12:12:02 +00:00
fi - > appendix_length = 0 ;
2000-07-27 06:41:59 +00:00
return fi ;
1999-07-07 22:52:57 +00:00
}
2006-02-09 04:18:23 +00:00
/* If the protocol tree is to be visible, set the representation of a
proto_tree entry with the name of the field for the item and with
the value formatted with the supplied printf - style format and
argument list . */
static void
proto_tree_set_representation_value ( proto_item * pi , const char * format , va_list ap )
{
2013-07-02 16:09:56 +00:00
g_assert ( pi ) ;
/* If the tree (GUI) or item isn't visible it's pointless for us to generate the protocol
* items string representation */
if ( PTREE_DATA ( pi ) - > visible & & ! PROTO_ITEM_IS_HIDDEN ( pi ) ) {
2013-07-02 17:09:38 +00:00
int ret = 0 ;
2013-07-02 16:09:56 +00:00
field_info * fi = PITEM_FINFO ( pi ) ;
header_field_info * hf ;
2009-08-21 11:03:30 +00:00
2013-07-02 16:09:56 +00:00
DISSECTOR_ASSERT ( fi ) ;
2009-08-21 11:03:30 +00:00
2013-07-02 16:09:56 +00:00
hf = fi - > hfinfo ;
2006-02-09 04:18:23 +00:00
2013-10-12 21:01:17 +00:00
ITEM_LABEL_NEW ( PNODE_POOL ( pi ) , fi - > rep ) ;
2008-08-01 10:16:52 +00:00
if ( hf - > bitmask & & ( hf - > type = = FT_BOOLEAN | | IS_FT_UINT ( hf - > type ) ) ) {
2014-09-17 16:39:22 +00:00
guint64 val ;
2013-07-02 17:09:38 +00:00
char * p ;
2008-03-09 14:50:14 +00:00
2014-09-17 16:39:22 +00:00
if ( IS_FT_UINT ( hf - > type ) )
val = fvalue_get_uinteger ( & fi - > value ) ;
else
2014-12-17 20:19:20 +00:00
val = fvalue_get_uinteger64 ( & fi - > value ) ;
2014-09-17 16:39:22 +00:00
2013-08-06 20:10:59 +00:00
val < < = hfinfo_bitshift ( hf ) ;
2013-07-02 17:09:38 +00:00
2016-01-12 11:20:46 +00:00
p = decode_bitfield_value ( fi - > rep - > representation , val , hf - > bitmask , hfinfo_container_bitwidth ( hf ) ) ;
2013-07-02 17:09:38 +00:00
ret = ( int ) ( p - fi - > rep - > representation ) ;
2008-08-01 10:16:52 +00:00
}
2008-03-09 14:50:14 +00:00
2013-07-02 17:09:38 +00:00
/* put in the hf name */
ret + = g_snprintf ( fi - > rep - > representation + ret , ITEM_LABEL_LENGTH - ret , " %s: " , hf - > name ) ;
2009-03-22 15:31:44 +00:00
/* If possible, Put in the value of the string */
if ( ret < ITEM_LABEL_LENGTH ) {
ret + = g_vsnprintf ( fi - > rep - > representation + ret ,
ITEM_LABEL_LENGTH - ret , format , ap ) ;
}
if ( ret > = ITEM_LABEL_LENGTH ) {
2008-03-09 14:50:14 +00:00
/* Uh oh, we don't have enough room. Tell the user
* that the field is truncated .
*/
2014-03-01 21:08:42 +00:00
LABEL_MARK_TRUNCATED_START ( fi - > rep - > representation ) ;
2008-03-09 14:50:14 +00:00
}
2006-02-09 04:18:23 +00:00
}
}
/* If the protocol tree is to be visible, set the representation of a
proto_tree entry with the representation formatted with the supplied
printf - style format and argument list . */
2000-05-31 05:09:07 +00:00
static void
proto_tree_set_representation ( proto_item * pi , const char * format , va_list ap )
{
2012-03-14 17:11:39 +00:00
int ret ; /*tmp return value */
2001-12-18 19:09:08 +00:00
field_info * fi = PITEM_FINFO ( pi ) ;
2000-05-31 05:09:07 +00:00
2009-08-21 11:03:30 +00:00
DISSECTOR_ASSERT ( fi ) ;
2004-05-01 15:15:08 +00:00
if ( ! PROTO_ITEM_IS_HIDDEN ( pi ) ) {
2013-10-12 21:01:17 +00:00
ITEM_LABEL_NEW ( PNODE_POOL ( pi ) , fi - > rep ) ;
2008-03-09 14:50:14 +00:00
ret = g_vsnprintf ( fi - > rep - > representation , ITEM_LABEL_LENGTH ,
format , ap ) ;
2009-03-22 15:31:44 +00:00
if ( ret > = ITEM_LABEL_LENGTH ) {
2008-03-09 14:50:14 +00:00
/* Uh oh, we don't have enough room. Tell the user
* that the field is truncated .
*/
2014-03-01 21:08:42 +00:00
LABEL_MARK_TRUNCATED_START ( fi - > rep - > representation ) ;
2008-03-09 14:50:14 +00:00
}
2000-05-31 05:09:07 +00:00
}
}
2000-03-12 04:48:32 +00:00
2013-12-07 11:50:43 +00:00
static const char *
hfinfo_format_text ( const header_field_info * hfinfo , const guchar * string )
{
switch ( hfinfo - > display ) {
case STR_ASCII :
return format_text ( string , strlen ( string ) ) ;
/*
case STR_ASCII_WSP
return format_text_wsp ( string , strlen ( string ) ) ;
*/
case STR_UNICODE :
/* XXX, format_unicode_text() */
return string ;
}
return format_text ( string , strlen ( string ) ) ;
}
2012-05-17 10:18:53 +00:00
static int
protoo_strlcpy ( gchar * dest , const gchar * src , gsize dest_size )
{
gsize res = g_strlcpy ( dest , src , dest_size ) ;
if ( res > dest_size )
res = dest_size ;
return ( int ) res ;
}
2013-08-06 20:53:47 +00:00
static header_field_info *
hfinfo_same_name_get_prev ( const header_field_info * hfinfo )
{
2014-04-24 15:26:22 +00:00
header_field_info * dup_hfinfo ;
2013-08-06 20:53:47 +00:00
if ( hfinfo - > same_name_prev_id = = - 1 )
return NULL ;
2014-04-24 15:26:22 +00:00
PROTO_REGISTRAR_GET_NTH ( hfinfo - > same_name_prev_id , dup_hfinfo ) ;
return dup_hfinfo ;
2013-08-06 20:53:47 +00:00
}
2015-08-23 18:11:06 +00:00
static void
2015-08-24 09:52:29 +00:00
hfinfo_remove_from_gpa_name_map ( const header_field_info * hfinfo )
2015-08-23 18:11:06 +00:00
{
2016-02-01 20:50:07 +00:00
g_free ( last_field_name ) ;
last_field_name = NULL ;
2015-08-27 00:14:39 +00:00
2016-02-01 20:50:07 +00:00
if ( ! hfinfo - > same_name_next & & hfinfo - > same_name_prev_id = = - 1 ) {
/* No hfinfo with the same name */
g_hash_table_steal ( gpa_name_map , hfinfo - > abbrev ) ;
return ;
}
2015-08-23 18:11:06 +00:00
2016-02-01 20:50:07 +00:00
if ( hfinfo - > same_name_next ) {
hfinfo - > same_name_next - > same_name_prev_id = hfinfo - > same_name_prev_id ;
}
2015-08-23 18:11:06 +00:00
2016-02-01 20:50:07 +00:00
if ( hfinfo - > same_name_prev_id ! = - 1 ) {
header_field_info * same_name_prev = hfinfo_same_name_get_prev ( hfinfo ) ;
same_name_prev - > same_name_next = hfinfo - > same_name_next ;
if ( ! hfinfo - > same_name_next ) {
/* It's always the latest added hfinfo which is stored in gpa_name_map */
g_hash_table_insert ( gpa_name_map , ( gpointer ) ( same_name_prev - > abbrev ) , same_name_prev ) ;
}
}
2015-08-23 18:11:06 +00:00
}
2009-08-25 21:10:35 +00:00
/* -------------------------- */
const gchar *
2014-12-17 10:38:49 +00:00
proto_custom_set ( proto_tree * tree , GSList * field_ids , gint occurrence ,
2012-03-14 17:11:39 +00:00
gchar * result , gchar * expr , const int size )
2009-08-25 21:10:35 +00:00
{
2016-01-03 23:05:13 +00:00
guint32 number ;
guint64 number64 ;
guint8 * bytes ;
ipv4_addr_and_mask * ipv4 ;
struct e_in6_addr * ipv6 ;
address addr ;
guint32 n_addr ; /* network-order IPv4 address */
2009-08-25 21:10:35 +00:00
const true_false_string * tfstring ;
2012-03-14 17:11:39 +00:00
int len , prev_len = 0 , last , i , offset_r = 0 , offset_e = 0 ;
GPtrArray * finfos ;
field_info * finfo = NULL ;
header_field_info * hfinfo ;
const gchar * abbrev = NULL ;
2009-09-06 07:24:54 +00:00
2013-07-13 09:14:25 +00:00
const char * hf_str_val ;
2015-02-23 15:50:18 +00:00
char number_buf [ 48 ] ;
2013-07-01 09:46:50 +00:00
const char * number_out ;
2015-01-09 17:51:15 +00:00
char * tmpbuf , * str ;
2014-12-17 10:38:49 +00:00
int * field_idx ;
int field_id ;
int ii = 0 ;
2013-07-01 09:46:50 +00:00
2014-12-17 10:38:49 +00:00
g_assert ( field_ids ! = NULL ) ;
while ( ( field_idx = ( int * ) g_slist_nth_data ( field_ids , ii + + ) ) ) {
field_id = * field_idx ;
PROTO_REGISTRAR_GET_NTH ( ( guint ) field_id , hfinfo ) ;
2009-08-25 21:10:35 +00:00
2014-12-17 10:38:49 +00:00
/* do we need to rewind ? */
if ( ! hfinfo )
return " " ;
2009-08-25 21:10:35 +00:00
2014-12-17 10:38:49 +00:00
if ( occurrence < 0 ) {
/* Search other direction */
while ( hfinfo - > same_name_prev_id ! = - 1 ) {
PROTO_REGISTRAR_GET_NTH ( hfinfo - > same_name_prev_id , hfinfo ) ;
}
2010-10-14 13:11:03 +00:00
}
2014-12-17 10:38:49 +00:00
while ( hfinfo ) {
finfos = proto_get_finfo_ptr_array ( tree , hfinfo - > id ) ;
2009-08-25 21:10:35 +00:00
2014-12-17 10:38:49 +00:00
if ( ! finfos | | ! ( len = g_ptr_array_len ( finfos ) ) ) {
if ( occurrence < 0 ) {
hfinfo = hfinfo - > same_name_next ;
} else {
hfinfo = hfinfo_same_name_get_prev ( hfinfo ) ;
}
continue ;
}
/* Are there enough occurrences of the field? */
if ( ( ( occurrence - prev_len ) > len ) | | ( ( occurrence + prev_len ) < - len ) ) {
if ( occurrence < 0 ) {
hfinfo = hfinfo - > same_name_next ;
} else {
hfinfo = hfinfo_same_name_get_prev ( hfinfo ) ;
}
prev_len + = len ;
continue ;
2010-10-14 13:11:03 +00:00
}
2009-08-25 21:10:35 +00:00
2014-12-17 10:38:49 +00:00
/* Calculate single index or set outer bounderies */
2012-03-14 17:11:39 +00:00
if ( occurrence < 0 ) {
2014-12-17 10:38:49 +00:00
i = occurrence + len + prev_len ;
last = i ;
} else if ( occurrence > 0 ) {
i = occurrence - 1 - prev_len ;
last = i ;
2012-03-14 17:11:39 +00:00
} else {
2014-12-17 10:38:49 +00:00
i = 0 ;
last = len - 1 ;
2012-03-14 17:11:39 +00:00
}
2014-12-17 10:38:49 +00:00
prev_len + = len ; /* Count handled occurrences */
while ( i < = last ) {
finfo = ( field_info * ) g_ptr_array_index ( finfos , i ) ;
if ( offset_r & & ( offset_r < ( size - 2 ) ) )
result [ offset_r + + ] = ' , ' ;
if ( offset_e & & ( offset_e < ( size - 2 ) ) )
expr [ offset_e + + ] = ' , ' ;
switch ( hfinfo - > type ) {
2014-12-17 20:19:20 +00:00
case FT_NONE : /* Nothing to add */
if ( offset_r = = 0 ) {
result [ 0 ] = ' \0 ' ;
} else if ( result [ offset_r - 1 ] = = ' , ' ) {
result [ offset_r - 1 ] = ' \0 ' ;
}
break ;
2014-12-17 10:38:49 +00:00
2014-12-17 20:19:20 +00:00
case FT_PROTOCOL :
/* prevent multiple "yes" entries by setting result directly */
g_strlcpy ( result , " Yes " , size ) ;
break ;
2014-12-17 10:38:49 +00:00
2014-12-17 20:19:20 +00:00
case FT_UINT_BYTES :
case FT_BYTES :
bytes = ( guint8 * ) fvalue_get ( & finfo - > value ) ;
if ( bytes ) {
switch ( hfinfo - > display )
2015-01-04 16:17:53 +00:00
{
2014-12-17 20:19:20 +00:00
case SEP_DOT :
2015-11-30 06:51:01 +00:00
str = bytestring_to_str ( NULL , bytes , fvalue_length ( & finfo - > value ) , ' . ' ) ;
2014-12-17 20:19:20 +00:00
break ;
case SEP_DASH :
2015-11-30 06:51:01 +00:00
str = bytestring_to_str ( NULL , bytes , fvalue_length ( & finfo - > value ) , ' - ' ) ;
2014-12-17 20:19:20 +00:00
break ;
case SEP_COLON :
2015-11-30 06:51:01 +00:00
str = bytestring_to_str ( NULL , bytes , fvalue_length ( & finfo - > value ) , ' : ' ) ;
2014-12-17 20:19:20 +00:00
break ;
case SEP_SPACE :
2015-11-30 06:51:01 +00:00
str = bytestring_to_str ( NULL , bytes , fvalue_length ( & finfo - > value ) , ' ' ) ;
2014-12-17 20:19:20 +00:00
break ;
case BASE_NONE :
default :
if ( prefs . display_byte_fields_with_spaces )
{
2015-11-30 06:51:01 +00:00
str = bytestring_to_str ( NULL , bytes , fvalue_length ( & finfo - > value ) , ' ' ) ;
2014-12-17 20:19:20 +00:00
}
else
{
2015-11-30 06:51:01 +00:00
str = bytes_to_str ( NULL , bytes , fvalue_length ( & finfo - > value ) ) ;
2014-12-17 20:19:20 +00:00
}
break ;
2015-01-04 16:17:53 +00:00
}
2014-12-17 20:19:20 +00:00
offset_r + = protoo_strlcpy ( result + offset_r , str , size - offset_r ) ;
wmem_free ( NULL , str ) ;
2015-01-07 14:36:06 +00:00
}
2014-12-17 20:19:20 +00:00
else {
2015-11-29 00:13:59 +00:00
if ( hfinfo - > display & BASE_ALLOW_ZERO ) {
offset_r + = protoo_strlcpy ( result + offset_r , " <none> " , size - offset_r ) ;
} else {
offset_r + = protoo_strlcpy ( result + offset_r , " <MISSING> " , size - offset_r ) ;
}
2014-12-17 20:19:20 +00:00
}
break ;
2014-12-17 10:38:49 +00:00
2014-12-17 20:19:20 +00:00
case FT_ABSOLUTE_TIME :
tmpbuf = abs_time_to_str ( NULL , ( const nstime_t * ) fvalue_get ( & finfo - > value ) , ( absolute_time_display_e ) hfinfo - > display , TRUE ) ;
offset_r + = protoo_strlcpy ( result + offset_r ,
2014-12-17 10:38:49 +00:00
tmpbuf ,
size - offset_r ) ;
2014-12-17 20:19:20 +00:00
wmem_free ( NULL , tmpbuf ) ;
break ;
2014-12-17 10:38:49 +00:00
2014-12-17 20:19:20 +00:00
case FT_RELATIVE_TIME :
tmpbuf = rel_time_to_secs_str ( NULL , ( const nstime_t * ) fvalue_get ( & finfo - > value ) ) ;
offset_r + = protoo_strlcpy ( result + offset_r ,
2014-12-17 10:38:49 +00:00
tmpbuf ,
size - offset_r ) ;
2014-12-17 20:19:20 +00:00
wmem_free ( NULL , tmpbuf ) ;
break ;
2014-12-17 10:38:49 +00:00
2014-12-17 20:19:20 +00:00
case FT_BOOLEAN :
2016-03-15 23:08:06 +00:00
number64 = fvalue_get_uinteger64 ( & finfo - > value ) ;
2014-12-17 20:19:20 +00:00
tfstring = ( const true_false_string * ) & tfs_true_false ;
if ( hfinfo - > strings ) {
tfstring = ( const struct true_false_string * ) hfinfo - > strings ;
}
offset_r + = protoo_strlcpy ( result + offset_r ,
2016-03-15 23:08:06 +00:00
number64 ?
2014-12-17 20:19:20 +00:00
tfstring - > true_string :
tfstring - > false_string , size - offset_r ) ;
2014-12-17 10:38:49 +00:00
2014-12-17 20:19:20 +00:00
offset_e + = protoo_strlcpy ( expr + offset_e ,
2016-03-15 23:08:06 +00:00
number64 ? " 1 " : " 0 " , size - offset_e ) ;
2014-12-17 20:19:20 +00:00
break ;
2014-12-17 10:38:49 +00:00
2014-12-17 20:19:20 +00:00
/* XXX - make these just FT_NUMBER? */
case FT_INT8 :
case FT_INT16 :
case FT_INT24 :
case FT_INT32 :
case FT_UINT8 :
case FT_UINT16 :
case FT_UINT24 :
case FT_UINT32 :
case FT_FRAMENUM :
hf_str_val = NULL ;
number = IS_FT_INT ( hfinfo - > type ) ?
2014-12-17 10:38:49 +00:00
( guint32 ) fvalue_get_sinteger ( & finfo - > value ) :
fvalue_get_uinteger ( & finfo - > value ) ;
2014-12-17 20:19:20 +00:00
if ( ( hfinfo - > display & FIELD_DISPLAY_E_MASK ) = = BASE_CUSTOM ) {
gchar tmp [ ITEM_LABEL_LENGTH ] ;
custom_fmt_func_t fmtfunc = ( custom_fmt_func_t ) hfinfo - > strings ;
2014-12-17 10:38:49 +00:00
2014-12-17 20:19:20 +00:00
DISSECTOR_ASSERT ( fmtfunc ) ;
fmtfunc ( tmp , number ) ;
2014-12-17 10:38:49 +00:00
2014-12-17 20:19:20 +00:00
offset_r + = protoo_strlcpy ( result + offset_r , tmp , size - offset_r ) ;
2014-12-17 10:38:49 +00:00
2015-07-02 08:48:58 +00:00
} else if ( hfinfo - > strings & & hfinfo - > type ! = FT_FRAMENUM ) {
2014-12-17 20:19:20 +00:00
number_out = hf_str_val = hf_try_val_to_str ( number , hfinfo ) ;
2014-12-17 10:38:49 +00:00
2014-12-17 20:19:20 +00:00
if ( ! number_out )
number_out = hfinfo_number_value_format_display ( hfinfo , BASE_DEC , number_buf , number ) ;
2014-12-17 10:38:49 +00:00
2014-12-17 20:19:20 +00:00
offset_r + = protoo_strlcpy ( result + offset_r , number_out , size - offset_r ) ;
2014-12-17 10:38:49 +00:00
2014-12-17 20:19:20 +00:00
} else {
number_out = hfinfo_number_value_format ( hfinfo , number_buf , number ) ;
2014-12-17 10:38:49 +00:00
2014-12-17 20:19:20 +00:00
offset_r + = protoo_strlcpy ( result + offset_r , number_out , size - offset_r ) ;
}
2014-12-17 10:38:49 +00:00
2014-12-17 20:19:20 +00:00
if ( hf_str_val & & ( hfinfo - > display & FIELD_DISPLAY_E_MASK ) = = BASE_NONE ) {
g_snprintf ( expr + offset_e , size - offset_e , " \" %s \" " , hf_str_val ) ;
} else {
number_out = hfinfo_numeric_value_format ( hfinfo , number_buf , number ) ;
2014-12-17 10:38:49 +00:00
2014-12-17 20:19:20 +00:00
g_strlcpy ( expr + offset_e , number_out , size - offset_e ) ;
}
2014-12-17 10:38:49 +00:00
2014-12-17 20:19:20 +00:00
offset_e = ( int ) strlen ( expr ) ;
break ;
2014-12-17 10:38:49 +00:00
2014-12-17 20:19:20 +00:00
case FT_INT40 :
case FT_INT48 :
case FT_INT56 :
case FT_INT64 :
case FT_UINT40 :
case FT_UINT48 :
case FT_UINT56 :
case FT_UINT64 :
hf_str_val = NULL ;
number64 = IS_FT_INT ( hfinfo - > type ) ?
( guint64 ) fvalue_get_sinteger64 ( & finfo - > value ) :
fvalue_get_uinteger64 ( & finfo - > value ) ;
if ( ( hfinfo - > display & FIELD_DISPLAY_E_MASK ) = = BASE_CUSTOM ) {
gchar tmp [ ITEM_LABEL_LENGTH ] ;
custom_fmt_func_64_t fmtfunc64 = ( custom_fmt_func_64_t ) hfinfo - > strings ;
DISSECTOR_ASSERT ( fmtfunc64 ) ;
fmtfunc64 ( tmp , number64 ) ;
offset_r + = protoo_strlcpy ( result + offset_r , tmp , size - offset_r ) ;
} else if ( hfinfo - > strings ) {
number_out = hf_str_val = hf_try_val64_to_str ( number64 , hfinfo ) ;
if ( ! number_out )
number_out = hfinfo_number_value_format_display64 ( hfinfo , BASE_DEC , number_buf , number64 ) ;
offset_r + = protoo_strlcpy ( result + offset_r , number_out , size - offset_r ) ;
} else {
number_out = hfinfo_number_value_format64 ( hfinfo , number_buf , number64 ) ;
offset_r + = protoo_strlcpy ( result + offset_r , number_out , size - offset_r ) ;
}
2014-12-17 10:38:49 +00:00
2014-12-17 20:19:20 +00:00
if ( hf_str_val & & ( hfinfo - > display & FIELD_DISPLAY_E_MASK ) = = BASE_NONE ) {
g_snprintf ( expr + offset_e , size - offset_e , " \" %s \" " , hf_str_val ) ;
} else {
number_out = hfinfo_numeric_value_format64 ( hfinfo , number_buf , number64 ) ;
2014-12-17 10:38:49 +00:00
2014-12-17 20:19:20 +00:00
g_strlcpy ( expr + offset_e , number_out , size - offset_e ) ;
}
2014-12-17 10:38:49 +00:00
2014-12-17 20:19:20 +00:00
offset_e = ( int ) strlen ( expr ) ;
break ;
2014-12-24 05:06:35 +00:00
2014-12-17 20:19:20 +00:00
case FT_EUI64 :
str = eui64_to_str ( NULL , fvalue_get_uinteger64 ( & finfo - > value ) ) ;
offset_r + = protoo_strlcpy ( result + offset_r , str , size - offset_r ) ;
wmem_free ( NULL , str ) ;
break ;
2014-12-17 10:38:49 +00:00
2014-12-17 20:19:20 +00:00
case FT_IPv4 :
2016-01-03 23:05:13 +00:00
ipv4 = ( ipv4_addr_and_mask * ) fvalue_get ( & finfo - > value ) ;
2014-12-17 20:19:20 +00:00
n_addr = ipv4_get_net_order_addr ( ipv4 ) ;
2015-10-21 19:04:16 +00:00
set_address ( & addr , AT_IPv4 , 4 , & n_addr ) ;
2014-12-17 20:19:20 +00:00
address_to_str_buf ( & addr , result + offset_r , size - offset_r ) ;
offset_r = ( int ) strlen ( result ) ;
break ;
2014-12-17 10:38:49 +00:00
2014-12-17 20:19:20 +00:00
case FT_IPv6 :
ipv6 = ( struct e_in6_addr * ) fvalue_get ( & finfo - > value ) ;
2015-10-21 19:04:16 +00:00
set_address ( & addr , AT_IPv6 , sizeof ( struct e_in6_addr ) , ipv6 ) ;
2014-12-17 20:19:20 +00:00
address_to_str_buf ( & addr , result + offset_r , size - offset_r ) ;
offset_r = ( int ) strlen ( result ) ;
break ;
2014-12-17 10:38:49 +00:00
2014-12-17 20:19:20 +00:00
case FT_FCWWN :
2015-10-21 19:04:16 +00:00
set_address ( & addr , AT_FCWWN , FCWWN_ADDR_LEN , fvalue_get ( & finfo - > value ) ) ;
2014-12-17 20:19:20 +00:00
address_to_str_buf ( & addr , result + offset_r , size - offset_r ) ;
offset_r = ( int ) strlen ( result ) ;
break ;
2014-12-17 10:38:49 +00:00
2014-12-17 20:19:20 +00:00
case FT_ETHER :
2015-10-21 19:04:16 +00:00
set_address ( & addr , AT_ETHER , FT_ETHER_LEN , fvalue_get ( & finfo - > value ) ) ;
2014-12-17 20:19:20 +00:00
address_to_str_buf ( & addr , result + offset_r , size - offset_r ) ;
offset_r = ( int ) strlen ( result ) ;
break ;
2014-12-17 10:38:49 +00:00
2014-12-17 20:19:20 +00:00
case FT_GUID :
str = guid_to_str ( NULL , ( e_guid_t * ) fvalue_get ( & finfo - > value ) ) ;
offset_r + = protoo_strlcpy ( result + offset_r , str , size - offset_r ) ;
wmem_free ( NULL , str ) ;
break ;
2014-12-17 10:38:49 +00:00
2014-12-17 20:19:20 +00:00
case FT_REL_OID :
bytes = ( guint8 * ) fvalue_get ( & finfo - > value ) ;
str = rel_oid_resolved_from_encoded ( NULL , bytes , fvalue_length ( & finfo - > value ) ) ;
offset_r + = protoo_strlcpy ( result + offset_r , str , size - offset_r ) ;
wmem_free ( NULL , str ) ;
str = rel_oid_encoded2string ( NULL , bytes , fvalue_length ( & finfo - > value ) ) ;
offset_e + = protoo_strlcpy ( expr + offset_e , str , size - offset_e ) ;
wmem_free ( NULL , str ) ;
break ;
case FT_OID :
bytes = ( guint8 * ) fvalue_get ( & finfo - > value ) ;
str = oid_resolved_from_encoded ( NULL , bytes , fvalue_length ( & finfo - > value ) ) ;
offset_r + = protoo_strlcpy ( result + offset_r , str , size - offset_r ) ;
wmem_free ( NULL , str ) ;
str = oid_encoded2string ( NULL , bytes , fvalue_length ( & finfo - > value ) ) ;
offset_e + = protoo_strlcpy ( expr + offset_e , str , size - offset_e ) ;
wmem_free ( NULL , str ) ;
break ;
case FT_SYSTEM_ID :
bytes = ( guint8 * ) fvalue_get ( & finfo - > value ) ;
str = print_system_id ( NULL , bytes , fvalue_length ( & finfo - > value ) ) ;
offset_r + = protoo_strlcpy ( result + offset_r , str , size - offset_r ) ;
offset_e + = protoo_strlcpy ( expr + offset_e , str , size - offset_e ) ;
wmem_free ( NULL , str ) ;
break ;
case FT_FLOAT :
g_snprintf ( result + offset_r , size - offset_r ,
" %. " G_STRINGIFY ( FLT_DIG ) " g " , fvalue_get_floating ( & finfo - > value ) ) ;
offset_r = ( int ) strlen ( result ) ;
break ;
2014-12-17 10:38:49 +00:00
2014-12-17 20:19:20 +00:00
case FT_DOUBLE :
g_snprintf ( result + offset_r , size - offset_r ,
" %. " G_STRINGIFY ( DBL_DIG ) " g " , fvalue_get_floating ( & finfo - > value ) ) ;
offset_r = ( int ) strlen ( result ) ;
break ;
case FT_STRING :
case FT_STRINGZ :
case FT_UINT_STRING :
case FT_STRINGZPAD :
bytes = ( guint8 * ) fvalue_get ( & finfo - > value ) ;
offset_r + = protoo_strlcpy ( result + offset_r ,
2014-12-17 10:38:49 +00:00
hfinfo_format_text ( hfinfo , bytes ) ,
size - offset_r ) ;
2014-12-17 20:19:20 +00:00
break ;
2014-12-17 10:38:49 +00:00
2015-09-06 17:01:47 +00:00
case FT_IEEE_11073_SFLOAT :
{
guint8 buf [ 240 ] ;
fvalue_to_string_repr ( & finfo - > value , FTREPR_DISPLAY , hfinfo - > display , buf ) ;
g_snprintf ( result + offset_r , size - offset_r ,
" %s: %s " ,
hfinfo - > name , buf ) ;
}
offset_r = ( int ) strlen ( result ) ;
break ;
2016-02-01 20:50:07 +00:00
case FT_IEEE_11073_FLOAT :
2015-09-06 17:01:47 +00:00
{
guint8 buf [ 240 ] ;
fvalue_to_string_repr ( & finfo - > value , FTREPR_DISPLAY , hfinfo - > display , buf ) ;
g_snprintf ( result + offset_r , size - offset_r ,
" %s: %s " ,
hfinfo - > name , buf ) ;
}
offset_r = ( int ) strlen ( result ) ;
break ;
2014-12-17 20:19:20 +00:00
case FT_IPXNET : /*XXX really No column custom ?*/
case FT_PCRE :
default :
g_error ( " hfinfo->type %d (%s) not handled \n " ,
hfinfo - > type ,
ftype_name ( hfinfo - > type ) ) ;
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
break ;
2012-03-14 17:11:39 +00:00
}
2014-12-17 10:38:49 +00:00
i + + ;
}
2012-03-14 17:11:39 +00:00
2014-12-17 10:38:49 +00:00
switch ( hfinfo - > type ) {
2012-03-14 17:11:39 +00:00
2014-12-17 20:19:20 +00:00
case FT_BOOLEAN :
case FT_UINT8 :
case FT_UINT16 :
case FT_UINT24 :
case FT_UINT32 :
case FT_UINT40 :
case FT_UINT48 :
case FT_UINT56 :
case FT_UINT64 :
case FT_FRAMENUM :
case FT_INT8 :
case FT_INT16 :
case FT_INT24 :
case FT_INT32 :
case FT_INT40 :
case FT_INT48 :
case FT_INT56 :
case FT_INT64 :
case FT_OID :
case FT_REL_OID :
case FT_SYSTEM_ID :
/* for these types, "expr" is filled in the loop above */
break ;
2012-03-14 17:11:39 +00:00
2014-12-17 20:19:20 +00:00
default :
/* for all others, just copy "result" to "expr" */
g_strlcpy ( expr , result , size ) ;
break ;
2012-03-14 17:11:39 +00:00
}
2014-12-17 10:38:49 +00:00
if ( ! abbrev ) {
/* Store abbrev for return value */
abbrev = hfinfo - > abbrev ;
}
2012-03-14 17:11:39 +00:00
2014-12-17 10:38:49 +00:00
if ( occurrence = = 0 ) {
/* Fetch next hfinfo with same name (abbrev) */
hfinfo = hfinfo_same_name_get_prev ( hfinfo ) ;
} else {
hfinfo = NULL ;
}
2012-03-14 17:11:39 +00:00
}
}
return abbrev ? abbrev : " " ;
2009-08-25 21:10:35 +00:00
}
2001-08-29 00:51:10 +00:00
/* Set text of proto_item after having already been created. */
2000-01-22 04:59:55 +00:00
void
2000-03-07 05:54:52 +00:00
proto_item_set_text ( proto_item * pi , const char * format , . . . )
2000-01-22 04:59:55 +00:00
{
2001-11-03 11:42:50 +00:00
field_info * fi = NULL ;
2012-03-14 17:11:39 +00:00
va_list ap ;
2000-01-22 04:59:55 +00:00
2014-09-12 21:21:53 +00:00
TRY_TO_FAKE_THIS_REPR_VOID ( pi ) ;
2001-11-03 11:42:50 +00:00
2001-12-18 19:09:08 +00:00
fi = PITEM_FINFO ( pi ) ;
2012-03-14 17:11:39 +00:00
if ( fi = = NULL )
2009-08-21 11:03:30 +00:00
return ;
2001-11-03 11:42:50 +00:00
2012-03-14 17:11:39 +00:00
if ( fi - > rep ) {
2013-10-12 21:01:17 +00:00
ITEM_LABEL_FREE ( PNODE_POOL ( pi ) , fi - > rep ) ;
2013-01-14 22:29:23 +00:00
fi - > rep = NULL ;
2006-12-22 09:01:12 +00:00
}
2000-03-07 05:54:52 +00:00
va_start ( ap , format ) ;
2000-05-31 05:09:07 +00:00
proto_tree_set_representation ( pi , format , ap ) ;
2000-01-22 04:59:55 +00:00
va_end ( ap ) ;
}
2001-08-29 00:51:10 +00:00
/* Append to text of proto_item after having already been created. */
void
proto_item_append_text ( proto_item * pi , const char * format , . . . )
{
2001-11-03 11:42:50 +00:00
field_info * fi = NULL ;
2012-03-14 17:11:39 +00:00
size_t curlen ;
va_list ap ;
2001-08-29 00:51:10 +00:00
2014-09-12 21:21:53 +00:00
TRY_TO_FAKE_THIS_REPR_VOID ( pi ) ;
2001-11-03 11:42:50 +00:00
2001-12-18 19:09:08 +00:00
fi = PITEM_FINFO ( pi ) ;
2012-03-14 17:11:39 +00:00
if ( fi = = NULL ) {
2007-01-17 21:05:44 +00:00
return ;
}
2001-11-03 11:42:50 +00:00
2006-02-09 04:18:23 +00:00
if ( ! PROTO_ITEM_IS_HIDDEN ( pi ) ) {
2001-08-29 00:51:10 +00:00
/*
2002-03-19 08:42:16 +00:00
* If we don ' t already have a representation ,
* generate the default representation .
2001-08-29 00:51:10 +00:00
*/
2003-11-25 14:07:45 +00:00
if ( fi - > rep = = NULL ) {
2013-10-12 21:01:17 +00:00
ITEM_LABEL_NEW ( PNODE_POOL ( pi ) , fi - > rep ) ;
2003-11-25 14:07:45 +00:00
proto_item_fill_label ( fi , fi - > rep - > representation ) ;
2002-03-19 08:42:16 +00:00
}
2003-11-25 14:07:45 +00:00
curlen = strlen ( fi - > rep - > representation ) ;
2002-12-31 21:37:29 +00:00
if ( ITEM_LABEL_LENGTH > curlen ) {
2010-05-26 02:25:13 +00:00
va_start ( ap , format ) ;
2009-03-22 15:31:44 +00:00
g_vsnprintf ( fi - > rep - > representation + curlen ,
2009-09-23 16:27:37 +00:00
ITEM_LABEL_LENGTH - ( gulong ) curlen , format , ap ) ;
2010-05-26 02:25:13 +00:00
va_end ( ap ) ;
2002-12-31 21:37:29 +00:00
}
2001-08-29 00:51:10 +00:00
}
}
2010-08-14 17:24:21 +00:00
/* Prepend to text of proto_item after having already been created. */
void
proto_item_prepend_text ( proto_item * pi , const char * format , . . . )
{
field_info * fi = NULL ;
2012-03-14 17:11:39 +00:00
char representation [ ITEM_LABEL_LENGTH ] ;
va_list ap ;
2010-08-14 17:24:21 +00:00
2014-09-12 21:21:53 +00:00
TRY_TO_FAKE_THIS_REPR_VOID ( pi ) ;
2010-08-14 17:24:21 +00:00
fi = PITEM_FINFO ( pi ) ;
2012-03-14 17:11:39 +00:00
if ( fi = = NULL ) {
2010-08-14 17:24:21 +00:00
return ;
}
if ( ! PROTO_ITEM_IS_HIDDEN ( pi ) ) {
/*
* If we don ' t already have a representation ,
* generate the default representation .
*/
if ( fi - > rep = = NULL ) {
2013-10-12 21:01:17 +00:00
ITEM_LABEL_NEW ( PNODE_POOL ( pi ) , fi - > rep ) ;
2013-07-03 17:44:46 +00:00
proto_item_fill_label ( fi , representation ) ;
} else
g_strlcpy ( representation , fi - > rep - > representation , ITEM_LABEL_LENGTH ) ;
2010-08-14 17:24:21 +00:00
va_start ( ap , format ) ;
g_vsnprintf ( fi - > rep - > representation ,
ITEM_LABEL_LENGTH , format , ap ) ;
va_end ( ap ) ;
2011-03-28 16:42:25 +00:00
g_strlcat ( fi - > rep - > representation , representation , ITEM_LABEL_LENGTH ) ;
2010-08-14 17:24:21 +00:00
}
}
1999-07-07 22:52:57 +00:00
void
2010-04-03 18:18:50 +00:00
proto_item_set_len ( proto_item * pi , const gint length )
1999-07-07 22:52:57 +00:00
{
2001-05-07 21:06:59 +00:00
field_info * fi ;
2002-08-28 20:41:00 +00:00
2014-09-12 21:21:53 +00:00
TRY_TO_FAKE_THIS_REPR_VOID ( pi ) ;
2009-08-21 11:03:30 +00:00
2001-12-18 19:09:08 +00:00
fi = PITEM_FINFO ( pi ) ;
2009-08-21 11:03:30 +00:00
if ( fi = = NULL )
return ;
2005-03-23 00:09:12 +00:00
DISSECTOR_ASSERT ( length > = 0 ) ;
1999-07-07 22:52:57 +00:00
fi - > length = length ;
2007-10-23 11:02:08 +00:00
2011-05-18 07:20:45 +00:00
/*
* You cannot just make the " len " field of a GByteArray
* larger , if there ' s no data to back that length ;
* you can only make it smaller .
*/
2011-06-25 14:58:06 +00:00
if ( fi - > value . ftype - > ftype = = FT_BYTES & & length < = ( gint ) fi - > value . value . bytes - > len )
2007-10-23 11:02:08 +00:00
fi - > value . value . bytes - > len = length ;
1999-07-07 22:52:57 +00:00
}
2003-04-29 21:27:19 +00:00
/*
* Sets the length of the item based on its start and on the specified
* offset , which is the offset past the end of the item ; as the start
* in the item is relative to the beginning of the data source tvbuff ,
* we need to pass in a tvbuff - the end offset is relative to the beginning
* of that tvbuff .
*/
void
proto_item_set_end ( proto_item * pi , tvbuff_t * tvb , gint end )
{
field_info * fi ;
2014-09-12 21:21:53 +00:00
TRY_TO_FAKE_THIS_REPR_VOID ( pi ) ;
2009-08-21 11:03:30 +00:00
2003-04-29 21:27:19 +00:00
fi = PITEM_FINFO ( pi ) ;
2009-08-21 11:03:30 +00:00
if ( fi = = NULL )
return ;
2011-05-27 03:06:50 +00:00
end + = tvb_raw_offset ( tvb ) ;
2005-03-23 00:09:12 +00:00
DISSECTOR_ASSERT ( end > = fi - > start ) ;
2003-04-29 21:27:19 +00:00
fi - > length = end - fi - > start ;
}
2000-07-27 06:41:59 +00:00
int
2010-04-03 18:18:50 +00:00
proto_item_get_len ( const proto_item * pi )
2000-07-27 06:41:59 +00:00
{
2001-12-18 19:09:08 +00:00
field_info * fi = PITEM_FINFO ( pi ) ;
2009-08-21 11:03:30 +00:00
return fi ? fi - > length : - 1 ;
2000-07-27 06:41:59 +00:00
}
2010-04-26 20:48:13 +00:00
proto_tree *
2012-08-10 20:33:01 +00:00
proto_tree_create_root ( packet_info * pinfo )
1999-07-07 22:52:57 +00:00
{
2012-03-14 17:11:39 +00:00
proto_node * pnode ;
2001-12-18 19:09:08 +00:00
2002-04-04 20:23:50 +00:00
/* Initialize the proto_node */
2013-10-20 10:21:25 +00:00
pnode = g_slice_new ( proto_tree ) ;
2013-10-20 10:03:32 +00:00
PROTO_NODE_INIT ( pnode ) ;
2003-12-04 19:53:54 +00:00
pnode - > parent = NULL ;
2009-08-09 17:57:31 +00:00
PNODE_FINFO ( pnode ) = NULL ;
2013-10-20 10:21:25 +00:00
pnode - > tree_data = g_slice_new ( tree_data_t ) ;
2002-04-04 20:23:50 +00:00
2012-08-10 20:33:01 +00:00
/* Make sure we can access pinfo everywhere */
pnode - > tree_data - > pinfo = pinfo ;
2009-07-18 20:10:14 +00:00
/* Don't initialize the tree_data_t. Wait until we know we need it */
pnode - > tree_data - > interesting_hfids = NULL ;
2002-04-04 20:23:50 +00:00
/* Set the default to FALSE so it's easier to
* find errors ; if we expect to see the protocol tree
* but for some reason the default ' visible ' is not
* changed , then we ' ll find out very quickly . */
pnode - > tree_data - > visible = FALSE ;
2006-11-01 20:32:23 +00:00
2009-08-11 18:08:03 +00:00
/* Make sure that we fake protocols (if possible) */
pnode - > tree_data - > fake_protocols = TRUE ;
2006-09-22 21:14:54 +00:00
/* Keep track of the number of children */
pnode - > tree_data - > count = 0 ;
2001-12-18 19:09:08 +00:00
2012-03-14 17:11:39 +00:00
return ( proto_tree * ) pnode ;
2001-12-18 19:09:08 +00:00
}
2002-08-28 20:41:00 +00:00
2002-05-09 23:50:34 +00:00
/* "prime" a proto_tree with a single hfid that a dfilter
* is interested in . */
2001-12-18 19:09:08 +00:00
void
2010-04-03 18:18:50 +00:00
proto_tree_prime_hfid ( proto_tree * tree _U_ , const gint hfid )
2001-12-18 19:09:08 +00:00
{
2005-04-11 08:43:51 +00:00
header_field_info * hfinfo ;
PROTO_REGISTRAR_GET_NTH ( hfid , hfinfo ) ;
/* this field is referenced by a filter so increase the refcount.
also increase the refcount for the parent , i . e the protocol .
*/
2009-09-30 14:02:49 +00:00
hfinfo - > ref_type = HF_REF_TYPE_DIRECT ;
2005-04-11 08:43:51 +00:00
/* only increase the refcount if there is a parent.
if this is a protocol and not a field then parent will be - 1
and there is no parent to add any refcounting for .
*/
if ( hfinfo - > parent ! = - 1 ) {
header_field_info * parent_hfinfo ;
PROTO_REGISTRAR_GET_NTH ( hfinfo - > parent , parent_hfinfo ) ;
2009-07-18 20:10:14 +00:00
/* Mark parent as indirectly referenced unless it is already directly
* referenced , i . e . the user has specified the parent in a filter .
*/
2009-09-30 14:02:49 +00:00
if ( parent_hfinfo - > ref_type ! = HF_REF_TYPE_DIRECT )
parent_hfinfo - > ref_type = HF_REF_TYPE_INDIRECT ;
2005-04-11 08:43:51 +00:00
}
}
2002-05-09 23:50:34 +00:00
2010-04-26 20:48:13 +00:00
proto_tree *
2010-04-03 18:18:50 +00:00
proto_item_add_subtree ( proto_item * pi , const gint idx ) {
2001-03-26 17:58:33 +00:00
field_info * fi ;
if ( ! pi )
2012-03-14 17:11:39 +00:00
return NULL ;
2001-03-26 17:58:33 +00:00
2005-03-23 00:09:12 +00:00
DISSECTOR_ASSERT ( idx > = 0 & & idx < num_tree_types ) ;
2009-08-21 11:03:30 +00:00
fi = PITEM_FINFO ( pi ) ;
if ( ! fi )
2012-03-14 17:11:39 +00:00
return ( proto_tree * ) pi ;
2009-08-21 11:03:30 +00:00
1999-07-07 22:52:57 +00:00
fi - > tree_type = idx ;
2005-04-11 08:43:51 +00:00
2012-03-14 17:11:39 +00:00
return ( proto_tree * ) pi ;
1999-07-07 22:52:57 +00:00
}
2010-04-26 20:48:13 +00:00
proto_tree *
2014-01-15 01:05:03 +00:00
proto_item_get_subtree ( proto_item * pi ) {
2004-03-25 09:18:03 +00:00
field_info * fi ;
if ( ! pi )
2012-03-14 17:11:39 +00:00
return NULL ;
2004-03-25 09:18:03 +00:00
fi = PITEM_FINFO ( pi ) ;
2005-04-19 11:59:40 +00:00
if ( ( ! fi ) | | ( fi - > tree_type = = - 1 ) )
2012-03-14 17:11:39 +00:00
return NULL ;
return ( proto_tree * ) pi ;
2004-03-25 09:18:03 +00:00
}
2010-04-26 20:48:13 +00:00
proto_item *
2010-04-03 18:18:50 +00:00
proto_item_get_parent ( const proto_item * ti ) {
2007-01-12 10:21:02 +00:00
if ( ! ti )
2012-03-14 17:11:39 +00:00
return NULL ;
2004-03-25 23:55:21 +00:00
return ti - > parent ;
}
2010-04-26 20:48:13 +00:00
proto_item *
2004-03-25 23:55:21 +00:00
proto_item_get_parent_nth ( proto_item * ti , int gen ) {
2007-01-12 10:21:02 +00:00
if ( ! ti )
2012-03-14 17:11:39 +00:00
return NULL ;
2004-03-25 23:55:21 +00:00
while ( gen - - ) {
ti = ti - > parent ;
if ( ! ti )
2012-03-14 17:11:39 +00:00
return NULL ;
2004-03-25 23:55:21 +00:00
}
return ti ;
}
2010-04-26 20:48:13 +00:00
proto_item *
2014-01-15 01:05:03 +00:00
proto_tree_get_parent ( proto_tree * tree ) {
2007-01-12 10:21:02 +00:00
if ( ! tree )
2012-03-14 17:11:39 +00:00
return NULL ;
return ( proto_item * ) tree ;
2004-03-25 09:18:03 +00:00
}
2014-08-28 16:24:19 +00:00
proto_tree *
proto_tree_get_parent_tree ( proto_tree * tree ) {
if ( ! tree )
return NULL ;
/* we're the root tree, there's no parent
return ourselves so the caller has at least a tree to attach to */
if ( ! tree - > parent )
return tree ;
return ( proto_tree * ) tree - > parent ;
}
2010-04-26 20:48:13 +00:00
proto_tree *
2006-08-28 07:05:02 +00:00
proto_tree_get_root ( proto_tree * tree ) {
2007-01-12 10:21:02 +00:00
if ( ! tree )
2012-03-14 17:11:39 +00:00
return NULL ;
2006-08-28 07:05:02 +00:00
while ( tree - > parent ) {
tree = tree - > parent ;
}
return tree ;
}
1999-07-07 22:52:57 +00:00
2005-06-02 18:35:20 +00:00
void
2010-04-26 20:48:13 +00:00
proto_tree_move_item ( proto_tree * tree , proto_item * fixed_item ,
proto_item * item_to_move )
2005-06-02 18:35:20 +00:00
{
2011-02-04 12:16:26 +00:00
2015-04-02 19:10:36 +00:00
/* Revert part of: https://code.wireshark.org/review/gitweb?p=wireshark.git;a=commit;h=00c05ed3fdfa9287422e6e1fc9bd6ea8b31ca4ee
2011-02-04 12:16:26 +00:00
* See https : //bugs.wireshark.org/bugzilla/show_bug.cgi?id=5500
*/
/* This function doesn't generate any values. It only reorganizes the prococol tree
* so we can bail out immediately if it isn ' t visible . */
if ( ! tree | | ! PTREE_DATA ( tree ) - > visible )
return ;
2009-09-23 16:27:37 +00:00
DISSECTOR_ASSERT ( item_to_move - > parent = = tree ) ;
DISSECTOR_ASSERT ( fixed_item - > parent = = tree ) ;
2005-06-02 18:35:20 +00:00
2009-09-23 16:27:37 +00:00
/*** cut item_to_move out ***/
2005-06-02 18:35:20 +00:00
2009-09-23 16:27:37 +00:00
/* is item_to_move the first? */
2012-03-14 17:11:39 +00:00
if ( tree - > first_child = = item_to_move ) {
2009-09-23 16:27:37 +00:00
/* simply change first child to next */
tree - > first_child = item_to_move - > next ;
2008-10-15 20:02:15 +00:00
2009-09-23 16:27:37 +00:00
DISSECTOR_ASSERT ( tree - > last_child ! = item_to_move ) ;
} else {
proto_item * curr_item ;
/* find previous and change it's next */
for ( curr_item = tree - > first_child ; curr_item ! = NULL ; curr_item = curr_item - > next ) {
2012-03-14 17:11:39 +00:00
if ( curr_item - > next = = item_to_move ) {
2009-09-23 16:27:37 +00:00
break ;
}
}
2005-06-02 18:35:20 +00:00
2009-09-23 16:27:37 +00:00
DISSECTOR_ASSERT ( curr_item ) ;
2005-06-02 18:35:20 +00:00
2009-09-23 16:27:37 +00:00
curr_item - > next = item_to_move - > next ;
2005-06-02 18:35:20 +00:00
2009-09-23 16:27:37 +00:00
/* fix last_child if required */
2012-03-14 17:11:39 +00:00
if ( tree - > last_child = = item_to_move ) {
2009-09-23 16:27:37 +00:00
tree - > last_child = curr_item ;
}
}
2005-06-02 18:35:20 +00:00
2009-09-23 16:27:37 +00:00
/*** insert to_move after fixed ***/
item_to_move - > next = fixed_item - > next ;
fixed_item - > next = item_to_move ;
2012-03-14 17:11:39 +00:00
if ( tree - > last_child = = fixed_item ) {
2009-09-23 16:27:37 +00:00
tree - > last_child = item_to_move ;
}
2005-06-02 18:35:20 +00:00
}
2007-09-17 12:12:02 +00:00
void
2010-04-26 20:48:13 +00:00
proto_tree_set_appendix ( proto_tree * tree , tvbuff_t * tvb , gint start ,
const gint length )
2007-09-17 12:12:02 +00:00
{
field_info * fi ;
if ( tree = = NULL )
return ;
2009-08-09 17:57:31 +00:00
fi = PTREE_FINFO ( tree ) ;
2009-08-21 11:03:30 +00:00
if ( fi = = NULL )
return ;
2011-05-27 03:06:50 +00:00
start + = tvb_raw_offset ( tvb ) ;
2007-09-17 12:12:02 +00:00
DISSECTOR_ASSERT ( start > = 0 ) ;
DISSECTOR_ASSERT ( length > = 0 ) ;
fi - > appendix_start = start ;
fi - > appendix_length = length ;
}
2005-06-02 18:35:20 +00:00
1999-07-07 22:52:57 +00:00
int
2010-04-26 20:48:13 +00:00
proto_register_protocol ( const char * name , const char * short_name ,
const char * filter_name )
1999-07-07 22:52:57 +00:00
{
2014-01-15 01:05:03 +00:00
protocol_t * protocol ;
const protocol_t * existing_protocol = NULL ;
2009-09-23 16:27:37 +00:00
header_field_info * hfinfo ;
int proto_id ;
2014-01-15 01:05:03 +00:00
const char * existing_name ;
2009-09-23 16:27:37 +00:00
gint * key ;
guint i ;
2014-10-17 23:10:53 +00:00
gchar c ;
2009-09-23 16:27:37 +00:00
gboolean found_invalid ;
/*
* Make sure there ' s not already a protocol with any of those
* names . Crash if there is , as that ' s an error in the code
* or an inappropriate plugin .
* This situation has to be fixed to not register more than one
* protocol with the same name .
*
2012-03-15 14:15:48 +00:00
* This is done by reducing the number of strcmp ( and alike ) calls
* as much as possible , as this significally slows down startup time .
2009-09-23 16:27:37 +00:00
*
* Drawback : As a hash value is used to reduce insert time ,
* this might lead to a hash collision .
2012-03-15 14:15:48 +00:00
* However , although we have somewhat over 1000 protocols , we ' re using
* a 32 bit int so this is very , very unlikely .
2009-09-23 16:27:37 +00:00
*/
2013-03-02 12:10:56 +00:00
key = ( gint * ) g_malloc ( sizeof ( gint ) ) ;
2009-09-23 16:27:37 +00:00
* key = wrs_str_hash ( name ) ;
2012-03-15 14:15:48 +00:00
2014-01-15 01:05:03 +00:00
existing_name = ( const char * ) g_hash_table_lookup ( proto_names , key ) ;
2009-09-23 16:27:37 +00:00
if ( existing_name ! = NULL ) {
/* g_error will terminate the program */
g_error ( " Duplicate protocol name \" %s \" ! "
" This might be caused by an inappropriate plugin or a development error. " , name ) ;
}
g_hash_table_insert ( proto_names , key , ( gpointer ) name ) ;
2015-12-28 21:00:39 +00:00
existing_protocol = ( const protocol_t * ) g_hash_table_lookup ( proto_short_names , short_name ) ;
2014-07-23 17:38:55 +00:00
if ( existing_protocol ! = NULL ) {
2009-09-23 16:27:37 +00:00
g_error ( " Duplicate protocol short_name \" %s \" ! "
" This might be caused by an inappropriate plugin or a development error. " , short_name ) ;
}
found_invalid = FALSE ;
2012-05-28 15:59:00 +00:00
for ( i = 0 ; filter_name [ i ] ; i + + ) {
2009-09-23 16:27:37 +00:00
c = filter_name [ i ] ;
2014-10-17 23:10:53 +00:00
if ( ! ( g_ascii_islower ( c ) | | g_ascii_isdigit ( c ) | | c = = ' - ' | | c = = ' _ ' | | c = = ' . ' ) ) {
2009-09-23 16:27:37 +00:00
found_invalid = TRUE ;
}
}
if ( found_invalid ) {
g_error ( " Protocol filter name \" %s \" has one or more invalid characters. "
" Allowed are lower characters, digits, '-', '_' and '.'. "
" This might be caused by an inappropriate plugin or a development error. " , filter_name ) ;
}
2015-12-28 21:00:39 +00:00
existing_protocol = ( const protocol_t * ) g_hash_table_lookup ( proto_filter_names , filter_name ) ;
2013-10-29 22:17:18 +00:00
if ( existing_protocol ! = NULL ) {
2009-09-23 16:27:37 +00:00
g_error ( " Duplicate protocol filter_name \" %s \" ! "
" This might be caused by an inappropriate plugin or a development error. " , filter_name ) ;
}
/* Add this protocol to the list of known protocols; the list
is sorted by protocol short name . */
2009-10-11 09:18:51 +00:00
protocol = g_new ( protocol_t , 1 ) ;
2009-09-23 16:27:37 +00:00
protocol - > name = name ;
protocol - > short_name = short_name ;
protocol - > filter_name = filter_name ;
2014-04-20 21:27:18 +00:00
protocol - > fields = g_ptr_array_new ( ) ;
2009-09-23 16:27:37 +00:00
protocol - > is_enabled = TRUE ; /* protocol is enabled by default */
protocol - > can_toggle = TRUE ;
2015-07-21 17:32:42 +00:00
protocol - > heur_list = NULL ;
2009-09-23 16:27:37 +00:00
/* list will be sorted later by name, when all protocols completed registering */
protocols = g_list_prepend ( protocols , protocol ) ;
2013-10-29 22:17:18 +00:00
g_hash_table_insert ( proto_filter_names , ( gpointer ) filter_name , protocol ) ;
2014-07-23 17:38:55 +00:00
g_hash_table_insert ( proto_short_names , ( gpointer ) short_name , protocol ) ;
2009-09-23 16:27:37 +00:00
2012-06-10 15:10:11 +00:00
/* Here we allocate a new header_field_info struct */
2009-10-11 08:52:34 +00:00
hfinfo = g_slice_new ( header_field_info ) ;
2009-09-23 16:27:37 +00:00
hfinfo - > name = name ;
hfinfo - > abbrev = filter_name ;
hfinfo - > type = FT_PROTOCOL ;
hfinfo - > display = BASE_NONE ;
hfinfo - > strings = protocol ;
hfinfo - > bitmask = 0 ;
2009-09-30 14:02:49 +00:00
hfinfo - > ref_type = HF_REF_TYPE_NONE ;
2009-09-23 16:27:37 +00:00
hfinfo - > blurb = NULL ;
hfinfo - > parent = - 1 ; /* this field differentiates protos and fields */
proto_id = proto_register_field_init ( hfinfo , hfinfo - > parent ) ;
protocol - > proto_id = proto_id ;
return proto_id ;
1999-07-07 22:52:57 +00:00
}
2015-08-11 12:08:08 +00:00
gboolean
proto_deregister_protocol ( const char * short_name )
{
2016-02-01 20:50:07 +00:00
protocol_t * protocol ;
header_field_info * hfinfo ;
int proto_id ;
gint key ;
guint i ;
2015-08-11 12:08:08 +00:00
2016-02-01 20:50:07 +00:00
proto_id = proto_get_id_by_short_name ( short_name ) ;
protocol = find_protocol_by_id ( proto_id ) ;
if ( protocol = = NULL )
return FALSE ;
2015-08-11 12:08:08 +00:00
2016-02-01 20:50:07 +00:00
key = wrs_str_hash ( protocol - > name ) ;
g_hash_table_remove ( proto_names , & key ) ;
2015-08-11 12:08:08 +00:00
2016-02-01 20:50:07 +00:00
g_hash_table_remove ( proto_short_names , ( gpointer ) short_name ) ;
g_hash_table_remove ( proto_filter_names , ( gpointer ) protocol - > filter_name ) ;
2015-08-11 12:08:08 +00:00
2016-02-01 20:50:07 +00:00
for ( i = 0 ; i < protocol - > fields - > len ; i + + ) {
hfinfo = ( header_field_info * ) g_ptr_array_index ( protocol - > fields , i ) ;
hfinfo_remove_from_gpa_name_map ( hfinfo ) ;
expert_deregister_expertinfo ( hfinfo - > abbrev ) ;
g_ptr_array_add ( deregistered_fields , gpa_hfinfo . hfi [ hfinfo - > id ] ) ;
}
g_ptr_array_free ( protocol - > fields , TRUE ) ;
protocol - > fields = NULL ;
2015-08-11 12:08:08 +00:00
2016-02-01 20:50:07 +00:00
/* Remove this protocol from the list of known protocols */
protocols = g_list_remove ( protocols , protocol ) ;
2015-08-11 12:08:08 +00:00
2016-02-01 20:50:07 +00:00
g_ptr_array_add ( deregistered_fields , gpa_hfinfo . hfi [ proto_id ] ) ;
g_hash_table_steal ( gpa_name_map , protocol - > filter_name ) ;
2015-08-11 12:08:08 +00:00
2016-02-01 20:50:07 +00:00
g_free ( last_field_name ) ;
last_field_name = NULL ;
2015-08-27 00:14:39 +00:00
2016-02-01 20:50:07 +00:00
return TRUE ;
2015-08-11 12:08:08 +00:00
}
2001-01-03 06:56:03 +00:00
/*
* Routines to use to iterate over the protocols .
* The argument passed to the iterator routines is an opaque cookie to
* their callers ; it ' s the GList pointer for the current element in
* the list .
* The ID of the protocol is returned , or - 1 if there is no protocol .
*/
int
proto_get_first_protocol ( void * * cookie )
{
protocol_t * protocol ;
if ( protocols = = NULL )
return - 1 ;
* cookie = protocols ;
2013-03-02 12:10:56 +00:00
protocol = ( protocol_t * ) protocols - > data ;
2001-01-03 06:56:03 +00:00
return protocol - > proto_id ;
}
2012-05-04 04:44:23 +00:00
int
proto_get_data_protocol ( void * cookie )
{
2013-03-02 12:10:56 +00:00
GList * list_item = ( GList * ) cookie ;
2012-05-04 04:44:23 +00:00
2013-03-02 12:10:56 +00:00
protocol_t * protocol = ( protocol_t * ) list_item - > data ;
2012-05-04 04:44:23 +00:00
return protocol - > proto_id ;
}
2001-01-03 06:56:03 +00:00
int
proto_get_next_protocol ( void * * cookie )
{
2013-03-02 12:10:56 +00:00
GList * list_item = ( GList * ) * cookie ;
2001-01-03 06:56:03 +00:00
protocol_t * protocol ;
list_item = g_list_next ( list_item ) ;
if ( list_item = = NULL )
return - 1 ;
* cookie = list_item ;
2013-03-02 12:10:56 +00:00
protocol = ( protocol_t * ) list_item - > data ;
2001-01-03 06:56:03 +00:00
return protocol - > proto_id ;
}
Add the "Edit:Protocols..." feature which currently only implements
the following:
It is now possible to enable/disable a particular protocol decoding
(i.e. the protocol dissector is void or not). When a protocol
is disabled, it is displayed as Data and of course, all linked
sub-protocols are disabled as well.
Disabling a protocol could be interesting:
- in case of buggy dissectors
- in case of wrong heuristics
- for performance reasons
- to decode the data as another protocol (TODO)
Currently (if I am not wrong), all dissectors but NFS can be disabled
(and dissectors that do not register protocols :-)
I do not like the way the RPC sub-dissectors are disabled (in the
sub-dissectors) since this could be done in the RPC dissector itself,
knowing the sub-protocol hfinfo entry (this is why, I've not modified
the NFS one yet).
Two functions are added in proto.c :
gboolean proto_is_protocol_enabled(int n);
void proto_set_decoding(int n, gboolean enabled);
and two MACROs which can be used in dissectors:
OLD_CHECK_DISPLAY_AS_DATA(index, pd, offset, fd, tree)
CHECK_DISPLAY_AS_DATA(index, tvb, pinfo, tree)
See also the XXX in proto_dlg.c and proto.c around the new functions.
svn path=/trunk/; revision=2267
2000-08-13 14:09:15 +00:00
2014-06-30 05:48:16 +00:00
/* XXX: Unfortunately certain functions in proto_hier_tree_model.c
assume that the cookie stored by
proto_get_ ( first | next ) _protocol_field ( ) will never have a
value of NULL . So , to preserve this semantic , the cookie value
below is adjusted so that the cookie value stored is 1 + the
current ( zero - based ) array index .
*/
2003-08-25 00:15:02 +00:00
header_field_info *
2010-04-03 18:18:50 +00:00
proto_get_first_protocol_field ( const int proto_id , void * * cookie )
2003-08-25 00:15:02 +00:00
{
2014-04-20 21:27:18 +00:00
protocol_t * protocol = find_protocol_by_id ( proto_id ) ;
2003-08-25 00:15:02 +00:00
2014-04-20 21:27:18 +00:00
if ( ( protocol = = NULL ) | | ( protocol - > fields - > len = = 0 ) )
2003-08-25 00:15:02 +00:00
return NULL ;
2014-06-30 05:48:16 +00:00
* cookie = GUINT_TO_POINTER ( 0 + 1 ) ;
2014-04-20 21:27:18 +00:00
return ( header_field_info * ) g_ptr_array_index ( protocol - > fields , 0 ) ;
2003-08-25 00:15:02 +00:00
}
header_field_info *
2014-04-20 21:27:18 +00:00
proto_get_next_protocol_field ( const int proto_id , void * * cookie )
2003-08-25 00:15:02 +00:00
{
2014-04-20 21:27:18 +00:00
protocol_t * protocol = find_protocol_by_id ( proto_id ) ;
2014-06-30 05:48:16 +00:00
guint i = GPOINTER_TO_UINT ( * cookie ) - 1 ;
2003-08-25 00:15:02 +00:00
2014-04-21 15:57:06 +00:00
i + + ;
2014-04-20 21:27:18 +00:00
2014-04-21 15:57:06 +00:00
if ( i > = protocol - > fields - > len )
2003-08-25 00:15:02 +00:00
return NULL ;
2014-06-30 05:48:16 +00:00
* cookie = GUINT_TO_POINTER ( i + 1 ) ;
2014-04-21 15:57:06 +00:00
return ( header_field_info * ) g_ptr_array_index ( protocol - > fields , i ) ;
2003-08-25 00:15:02 +00:00
}
2003-11-16 23:17:27 +00:00
protocol_t *
2010-04-03 18:18:50 +00:00
find_protocol_by_id ( const int proto_id )
Add the "Edit:Protocols..." feature which currently only implements
the following:
It is now possible to enable/disable a particular protocol decoding
(i.e. the protocol dissector is void or not). When a protocol
is disabled, it is displayed as Data and of course, all linked
sub-protocols are disabled as well.
Disabling a protocol could be interesting:
- in case of buggy dissectors
- in case of wrong heuristics
- for performance reasons
- to decode the data as another protocol (TODO)
Currently (if I am not wrong), all dissectors but NFS can be disabled
(and dissectors that do not register protocols :-)
I do not like the way the RPC sub-dissectors are disabled (in the
sub-dissectors) since this could be done in the RPC dissector itself,
knowing the sub-protocol hfinfo entry (this is why, I've not modified
the NFS one yet).
Two functions are added in proto.c :
gboolean proto_is_protocol_enabled(int n);
void proto_set_decoding(int n, gboolean enabled);
and two MACROs which can be used in dissectors:
OLD_CHECK_DISPLAY_AS_DATA(index, pd, offset, fd, tree)
CHECK_DISPLAY_AS_DATA(index, tvb, pinfo, tree)
See also the XXX in proto_dlg.c and proto.c around the new functions.
svn path=/trunk/; revision=2267
2000-08-13 14:09:15 +00:00
{
2005-04-07 12:00:03 +00:00
header_field_info * hfinfo ;
2002-08-28 20:41:00 +00:00
2012-03-14 17:11:39 +00:00
if ( proto_id < 0 )
2001-01-03 06:56:03 +00:00
return NULL ;
2005-04-07 12:00:03 +00:00
PROTO_REGISTRAR_GET_NTH ( proto_id , hfinfo ) ;
2014-12-21 23:17:13 +00:00
DISSECTOR_ASSERT_FIELD_TYPE ( hfinfo , FT_PROTOCOL ) ;
2005-04-07 12:00:03 +00:00
return ( protocol_t * ) hfinfo - > strings ;
2001-01-03 06:56:03 +00:00
}
Add the "Edit:Protocols..." feature which currently only implements
the following:
It is now possible to enable/disable a particular protocol decoding
(i.e. the protocol dissector is void or not). When a protocol
is disabled, it is displayed as Data and of course, all linked
sub-protocols are disabled as well.
Disabling a protocol could be interesting:
- in case of buggy dissectors
- in case of wrong heuristics
- for performance reasons
- to decode the data as another protocol (TODO)
Currently (if I am not wrong), all dissectors but NFS can be disabled
(and dissectors that do not register protocols :-)
I do not like the way the RPC sub-dissectors are disabled (in the
sub-dissectors) since this could be done in the RPC dissector itself,
knowing the sub-protocol hfinfo entry (this is why, I've not modified
the NFS one yet).
Two functions are added in proto.c :
gboolean proto_is_protocol_enabled(int n);
void proto_set_decoding(int n, gboolean enabled);
and two MACROs which can be used in dissectors:
OLD_CHECK_DISPLAY_AS_DATA(index, pd, offset, fd, tree)
CHECK_DISPLAY_AS_DATA(index, tvb, pinfo, tree)
See also the XXX in proto_dlg.c and proto.c around the new functions.
svn path=/trunk/; revision=2267
2000-08-13 14:09:15 +00:00
2003-11-16 23:17:27 +00:00
int
2010-04-03 18:18:50 +00:00
proto_get_id ( const protocol_t * protocol )
2003-11-16 23:17:27 +00:00
{
return protocol - > proto_id ;
}
2015-11-20 17:56:45 +00:00
gboolean
proto_name_already_registered ( const gchar * name )
{
gint key ;
DISSECTOR_ASSERT_HINT ( name , " No name present " ) ;
key = wrs_str_hash ( name ) ;
if ( g_hash_table_lookup ( proto_names , & key ) ! = NULL )
return TRUE ;
return FALSE ;
}
2014-09-15 18:28:07 +00:00
int
proto_get_id_by_filter_name ( const gchar * filter_name )
2001-04-01 22:50:08 +00:00
{
2014-01-15 01:05:03 +00:00
const protocol_t * protocol = NULL ;
2002-04-20 08:07:56 +00:00
2014-09-15 18:28:07 +00:00
DISSECTOR_ASSERT_HINT ( filter_name , " No filter name present " ) ;
2012-11-18 18:12:50 +00:00
2015-12-28 21:00:39 +00:00
protocol = ( const protocol_t * ) g_hash_table_lookup ( proto_filter_names , filter_name ) ;
2008-04-07 05:22:54 +00:00
2013-10-29 22:17:18 +00:00
if ( protocol = = NULL )
2002-04-20 08:07:56 +00:00
return - 1 ;
return protocol - > proto_id ;
2001-04-01 22:50:08 +00:00
}
2014-09-15 18:28:07 +00:00
int
proto_get_id_by_short_name ( const gchar * short_name )
2014-07-23 17:38:55 +00:00
{
const protocol_t * protocol = NULL ;
2014-09-15 18:28:07 +00:00
DISSECTOR_ASSERT_HINT ( short_name , " No short name present " ) ;
2014-07-23 17:38:55 +00:00
2015-12-28 21:00:39 +00:00
protocol = ( const protocol_t * ) g_hash_table_lookup ( proto_short_names , short_name ) ;
2014-07-23 17:38:55 +00:00
if ( protocol = = NULL )
return - 1 ;
return protocol - > proto_id ;
}
2005-07-24 19:01:28 +00:00
const char *
2010-04-03 18:18:50 +00:00
proto_get_protocol_name ( const int proto_id )
2001-01-03 06:56:03 +00:00
{
protocol_t * protocol ;
Add the "Edit:Protocols..." feature which currently only implements
the following:
It is now possible to enable/disable a particular protocol decoding
(i.e. the protocol dissector is void or not). When a protocol
is disabled, it is displayed as Data and of course, all linked
sub-protocols are disabled as well.
Disabling a protocol could be interesting:
- in case of buggy dissectors
- in case of wrong heuristics
- for performance reasons
- to decode the data as another protocol (TODO)
Currently (if I am not wrong), all dissectors but NFS can be disabled
(and dissectors that do not register protocols :-)
I do not like the way the RPC sub-dissectors are disabled (in the
sub-dissectors) since this could be done in the RPC dissector itself,
knowing the sub-protocol hfinfo entry (this is why, I've not modified
the NFS one yet).
Two functions are added in proto.c :
gboolean proto_is_protocol_enabled(int n);
void proto_set_decoding(int n, gboolean enabled);
and two MACROs which can be used in dissectors:
OLD_CHECK_DISPLAY_AS_DATA(index, pd, offset, fd, tree)
CHECK_DISPLAY_AS_DATA(index, tvb, pinfo, tree)
See also the XXX in proto_dlg.c and proto.c around the new functions.
svn path=/trunk/; revision=2267
2000-08-13 14:09:15 +00:00
2001-01-03 06:56:03 +00:00
protocol = find_protocol_by_id ( proto_id ) ;
2011-03-29 11:09:59 +00:00
if ( protocol = = NULL )
return NULL ;
2001-01-03 06:56:03 +00:00
return protocol - > name ;
}
2005-07-24 19:01:28 +00:00
const char *
2010-04-03 18:18:50 +00:00
proto_get_protocol_short_name ( const protocol_t * protocol )
2001-01-03 06:56:03 +00:00
{
2003-11-16 23:17:27 +00:00
if ( protocol = = NULL )
2001-02-01 07:34:33 +00:00
return " (none) " ;
2001-01-03 06:56:03 +00:00
return protocol - > short_name ;
}
2008-10-24 07:48:09 +00:00
const char *
2010-04-03 18:18:50 +00:00
proto_get_protocol_long_name ( const protocol_t * protocol )
2008-10-24 07:48:09 +00:00
{
if ( protocol = = NULL )
return " (none) " ;
return protocol - > name ;
}
2005-07-24 19:01:28 +00:00
const char *
2010-04-03 18:18:50 +00:00
proto_get_protocol_filter_name ( const int proto_id )
2001-01-03 06:56:03 +00:00
{
protocol_t * protocol ;
protocol = find_protocol_by_id ( proto_id ) ;
2007-12-07 18:50:41 +00:00
if ( protocol = = NULL )
return " (none) " ;
2001-01-03 06:56:03 +00:00
return protocol - > filter_name ;
}
2015-07-21 17:32:42 +00:00
void proto_add_heuristic_dissector ( protocol_t * protocol , const char * short_name )
{
heur_dtbl_entry_t * heuristic_dissector ;
if ( protocol = = NULL )
return ;
heuristic_dissector = find_heur_dissector_by_unique_short_name ( short_name ) ;
if ( heuristic_dissector ! = NULL )
{
protocol - > heur_list = g_list_append ( protocol - > heur_list , heuristic_dissector ) ;
}
}
void proto_heuristic_dissector_foreach ( const protocol_t * protocol , GFunc func , gpointer user_data )
{
if ( protocol = = NULL )
return ;
g_list_foreach ( protocol - > heur_list , func , user_data ) ;
}
2013-12-23 17:20:07 +00:00
void
2014-09-15 18:28:07 +00:00
proto_get_frame_protocols ( const wmem_list_t * layers , gboolean * is_ip ,
gboolean * is_tcp , gboolean * is_udp ,
2015-02-02 17:01:29 +00:00
gboolean * is_sctp , gboolean * is_ssl ,
2015-10-20 14:07:10 +00:00
gboolean * is_rtp ,
gboolean * is_lte_rlc )
2014-09-15 18:28:07 +00:00
{
2013-12-23 17:20:07 +00:00
wmem_list_frame_t * protos = wmem_list_head ( layers ) ;
int proto_id ;
const char * proto_name ;
/* Walk the list of a available protocols in the packet and
find " major " ones . */
/* It might make more sense to assemble and return a bitfield. */
while ( protos ! = NULL )
{
proto_id = GPOINTER_TO_INT ( wmem_list_frame_data ( protos ) ) ;
proto_name = proto_get_protocol_filter_name ( proto_id ) ;
if ( is_ip & & ( ( ! strcmp ( proto_name , " ip " ) ) | |
( ! strcmp ( proto_name , " ipv6 " ) ) ) ) {
* is_ip = TRUE ;
} else if ( is_tcp & & ! strcmp ( proto_name , " tcp " ) ) {
* is_tcp = TRUE ;
} else if ( is_udp & & ! strcmp ( proto_name , " udp " ) ) {
* is_udp = TRUE ;
} else if ( is_sctp & & ! strcmp ( proto_name , " sctp " ) ) {
* is_sctp = TRUE ;
2013-12-24 13:44:00 +00:00
} else if ( is_ssl & & ! strcmp ( proto_name , " ssl " ) ) {
* is_ssl = TRUE ;
2015-02-02 17:01:29 +00:00
} else if ( is_rtp & & ! strcmp ( proto_name , " rtp " ) ) {
* is_rtp = TRUE ;
2015-10-20 14:07:10 +00:00
} else if ( is_lte_rlc & & ! strcmp ( proto_name , " rlc-lte " ) ) {
* is_lte_rlc = TRUE ;
2016-02-01 20:50:07 +00:00
}
2013-12-23 17:20:07 +00:00
protos = wmem_list_frame_next ( protos ) ;
}
2013-11-23 01:06:30 +00:00
}
2014-12-09 02:40:24 +00:00
gboolean
proto_is_frame_protocol ( const wmem_list_t * layers , const char * proto_name )
{
wmem_list_frame_t * protos = wmem_list_head ( layers ) ;
int proto_id ;
const char * name ;
/* Walk the list of a available protocols in the packet and
find " major " ones . */
/* It might make more sense to assemble and return a bitfield. */
while ( protos ! = NULL )
{
proto_id = GPOINTER_TO_INT ( wmem_list_frame_data ( protos ) ) ;
name = proto_get_protocol_filter_name ( proto_id ) ;
if ( ! strcmp ( name , proto_name ) )
{
return TRUE ;
}
protos = wmem_list_frame_next ( protos ) ;
}
2015-06-30 18:46:05 +00:00
return FALSE ;
2014-12-09 02:40:24 +00:00
}
2001-01-03 06:56:03 +00:00
gboolean
2010-04-03 18:18:50 +00:00
proto_is_protocol_enabled ( const protocol_t * protocol )
2001-01-03 06:56:03 +00:00
{
return protocol - > is_enabled ;
}
gboolean
2010-04-03 18:18:50 +00:00
proto_can_toggle_protocol ( const int proto_id )
2001-01-03 06:56:03 +00:00
{
protocol_t * protocol ;
protocol = find_protocol_by_id ( proto_id ) ;
2004-01-03 18:40:08 +00:00
return protocol - > can_toggle ;
Add the "Edit:Protocols..." feature which currently only implements
the following:
It is now possible to enable/disable a particular protocol decoding
(i.e. the protocol dissector is void or not). When a protocol
is disabled, it is displayed as Data and of course, all linked
sub-protocols are disabled as well.
Disabling a protocol could be interesting:
- in case of buggy dissectors
- in case of wrong heuristics
- for performance reasons
- to decode the data as another protocol (TODO)
Currently (if I am not wrong), all dissectors but NFS can be disabled
(and dissectors that do not register protocols :-)
I do not like the way the RPC sub-dissectors are disabled (in the
sub-dissectors) since this could be done in the RPC dissector itself,
knowing the sub-protocol hfinfo entry (this is why, I've not modified
the NFS one yet).
Two functions are added in proto.c :
gboolean proto_is_protocol_enabled(int n);
void proto_set_decoding(int n, gboolean enabled);
and two MACROs which can be used in dissectors:
OLD_CHECK_DISPLAY_AS_DATA(index, pd, offset, fd, tree)
CHECK_DISPLAY_AS_DATA(index, tvb, pinfo, tree)
See also the XXX in proto_dlg.c and proto.c around the new functions.
svn path=/trunk/; revision=2267
2000-08-13 14:09:15 +00:00
}
2002-08-28 20:41:00 +00:00
void
2010-04-03 18:18:50 +00:00
proto_set_decoding ( const int proto_id , const gboolean enabled )
Add the "Edit:Protocols..." feature which currently only implements
the following:
It is now possible to enable/disable a particular protocol decoding
(i.e. the protocol dissector is void or not). When a protocol
is disabled, it is displayed as Data and of course, all linked
sub-protocols are disabled as well.
Disabling a protocol could be interesting:
- in case of buggy dissectors
- in case of wrong heuristics
- for performance reasons
- to decode the data as another protocol (TODO)
Currently (if I am not wrong), all dissectors but NFS can be disabled
(and dissectors that do not register protocols :-)
I do not like the way the RPC sub-dissectors are disabled (in the
sub-dissectors) since this could be done in the RPC dissector itself,
knowing the sub-protocol hfinfo entry (this is why, I've not modified
the NFS one yet).
Two functions are added in proto.c :
gboolean proto_is_protocol_enabled(int n);
void proto_set_decoding(int n, gboolean enabled);
and two MACROs which can be used in dissectors:
OLD_CHECK_DISPLAY_AS_DATA(index, pd, offset, fd, tree)
CHECK_DISPLAY_AS_DATA(index, tvb, pinfo, tree)
See also the XXX in proto_dlg.c and proto.c around the new functions.
svn path=/trunk/; revision=2267
2000-08-13 14:09:15 +00:00
{
2001-01-03 06:56:03 +00:00
protocol_t * protocol ;
Add the "Edit:Protocols..." feature which currently only implements
the following:
It is now possible to enable/disable a particular protocol decoding
(i.e. the protocol dissector is void or not). When a protocol
is disabled, it is displayed as Data and of course, all linked
sub-protocols are disabled as well.
Disabling a protocol could be interesting:
- in case of buggy dissectors
- in case of wrong heuristics
- for performance reasons
- to decode the data as another protocol (TODO)
Currently (if I am not wrong), all dissectors but NFS can be disabled
(and dissectors that do not register protocols :-)
I do not like the way the RPC sub-dissectors are disabled (in the
sub-dissectors) since this could be done in the RPC dissector itself,
knowing the sub-protocol hfinfo entry (this is why, I've not modified
the NFS one yet).
Two functions are added in proto.c :
gboolean proto_is_protocol_enabled(int n);
void proto_set_decoding(int n, gboolean enabled);
and two MACROs which can be used in dissectors:
OLD_CHECK_DISPLAY_AS_DATA(index, pd, offset, fd, tree)
CHECK_DISPLAY_AS_DATA(index, tvb, pinfo, tree)
See also the XXX in proto_dlg.c and proto.c around the new functions.
svn path=/trunk/; revision=2267
2000-08-13 14:09:15 +00:00
2001-01-03 06:56:03 +00:00
protocol = find_protocol_by_id ( proto_id ) ;
2005-03-23 00:09:12 +00:00
DISSECTOR_ASSERT ( protocol - > can_toggle ) ;
2001-01-03 06:56:03 +00:00
protocol - > is_enabled = enabled ;
}
2008-01-14 16:40:23 +00:00
void
proto_enable_all ( void )
{
protocol_t * protocol ;
2012-03-14 17:11:39 +00:00
GList * list_item = protocols ;
2008-01-14 16:40:23 +00:00
if ( protocols = = NULL )
return ;
while ( list_item ) {
2013-03-02 12:10:56 +00:00
protocol = ( protocol_t * ) list_item - > data ;
2008-01-14 16:40:23 +00:00
if ( protocol - > can_toggle )
protocol - > is_enabled = TRUE ;
list_item = g_list_next ( list_item ) ;
}
}
2002-08-28 20:41:00 +00:00
void
2010-04-03 18:18:50 +00:00
proto_set_cant_toggle ( const int proto_id )
2001-01-03 06:56:03 +00:00
{
protocol_t * protocol ;
protocol = find_protocol_by_id ( proto_id ) ;
2004-01-03 18:40:08 +00:00
protocol - > can_toggle = FALSE ;
Add the "Edit:Protocols..." feature which currently only implements
the following:
It is now possible to enable/disable a particular protocol decoding
(i.e. the protocol dissector is void or not). When a protocol
is disabled, it is displayed as Data and of course, all linked
sub-protocols are disabled as well.
Disabling a protocol could be interesting:
- in case of buggy dissectors
- in case of wrong heuristics
- for performance reasons
- to decode the data as another protocol (TODO)
Currently (if I am not wrong), all dissectors but NFS can be disabled
(and dissectors that do not register protocols :-)
I do not like the way the RPC sub-dissectors are disabled (in the
sub-dissectors) since this could be done in the RPC dissector itself,
knowing the sub-protocol hfinfo entry (this is why, I've not modified
the NFS one yet).
Two functions are added in proto.c :
gboolean proto_is_protocol_enabled(int n);
void proto_set_decoding(int n, gboolean enabled);
and two MACROs which can be used in dissectors:
OLD_CHECK_DISPLAY_AS_DATA(index, pd, offset, fd, tree)
CHECK_DISPLAY_AS_DATA(index, tvb, pinfo, tree)
See also the XXX in proto_dlg.c and proto.c around the new functions.
svn path=/trunk/; revision=2267
2000-08-13 14:09:15 +00:00
}
2013-11-07 20:14:18 +00:00
static int
proto_register_field_common ( protocol_t * proto , header_field_info * hfi , const int parent )
{
if ( proto ! = NULL ) {
2014-04-20 21:27:18 +00:00
g_ptr_array_add ( proto - > fields , hfi ) ;
2013-11-07 20:14:18 +00:00
}
return proto_register_field_init ( hfi , parent ) ;
}
1999-07-15 15:33:52 +00:00
/* for use with static arrays only, since we don't allocate our own copies
2003-01-21 19:20:49 +00:00
of the header_field_info struct contained within the hf_register_info struct */
1999-07-07 22:52:57 +00:00
void
2010-04-03 18:18:50 +00:00
proto_register_field_array ( const int parent , hf_register_info * hf , const int num_records )
1999-07-07 22:52:57 +00:00
{
2012-03-14 17:11:39 +00:00
hf_register_info * ptr = hf ;
protocol_t * proto ;
2013-11-07 20:14:18 +00:00
int i ;
1999-07-07 22:52:57 +00:00
2001-01-03 06:56:03 +00:00
proto = find_protocol_by_id ( parent ) ;
1999-07-07 22:52:57 +00:00
for ( i = 0 ; i < num_records ; i + + , ptr + + ) {
2003-10-06 20:46:52 +00:00
/*
2004-09-21 23:15:59 +00:00
* Make sure we haven ' t registered this yet .
2003-10-06 20:46:52 +00:00
* Most fields have variables associated with them
* that are initialized to - 1 ; some have array elements ,
* or possibly uninitialized variables , so we also allow
* 0 ( which is unlikely to be the field ID we get back
* from " proto_register_field_init() " ) .
*/
2005-10-10 18:06:50 +00:00
if ( * ptr - > p_id ! = - 1 & & * ptr - > p_id ! = 0 ) {
fprintf ( stderr ,
2009-09-23 16:27:37 +00:00
" Duplicate field detected in call to proto_register_field_array: %s is already registered \n " ,
ptr - > hfinfo . abbrev ) ;
2005-10-10 18:06:50 +00:00
return ;
}
2003-10-06 20:46:52 +00:00
2013-11-07 20:14:18 +00:00
* ptr - > p_id = proto_register_field_common ( proto , & ptr - > hfinfo , parent ) ;
}
}
void
proto_register_fields_section ( const int parent , header_field_info * hfi , const int num_records )
{
int i ;
protocol_t * proto ;
proto = find_protocol_by_id ( parent ) ;
for ( i = 0 ; i < num_records ; i + + ) {
/*
* Make sure we haven ' t registered this yet .
*/
if ( hfi [ i ] . id ! = - 1 ) {
fprintf ( stderr ,
" Duplicate field detected in call to proto_register_fields: %s is already registered \n " ,
hfi [ i ] . abbrev ) ;
return ;
2001-01-03 06:56:03 +00:00
}
2013-11-07 20:14:18 +00:00
proto_register_field_common ( proto , & hfi [ i ] , parent ) ;
1999-07-07 22:52:57 +00:00
}
}
2013-08-16 21:21:52 +00:00
void
2013-11-07 20:14:18 +00:00
proto_register_fields_manual ( const int parent , header_field_info * * hfi , const int num_records )
2013-08-16 21:21:52 +00:00
{
int i ;
protocol_t * proto ;
proto = find_protocol_by_id ( parent ) ;
for ( i = 0 ; i < num_records ; i + + ) {
/*
* Make sure we haven ' t registered this yet .
*/
if ( hfi [ i ] - > id ! = - 1 ) {
fprintf ( stderr ,
2013-11-07 20:14:18 +00:00
" Duplicate field detected in call to proto_register_fields: %s is already registered \n " ,
2013-08-16 21:21:52 +00:00
hfi [ i ] - > abbrev ) ;
return ;
}
2013-11-07 20:14:18 +00:00
proto_register_field_common ( proto , hfi [ i ] , parent ) ;
2013-08-16 21:21:52 +00:00
}
}
2015-08-11 12:08:08 +00:00
/* deregister already registered fields */
2011-10-04 10:12:55 +00:00
void
2015-08-11 12:08:08 +00:00
proto_deregister_field ( const int parent , gint hf_id )
2011-10-04 10:12:55 +00:00
{
2014-10-20 20:44:25 +00:00
header_field_info * hfi ;
2012-03-14 17:11:39 +00:00
protocol_t * proto ;
2014-04-20 21:27:18 +00:00
guint i ;
2011-10-04 10:12:55 +00:00
2015-08-27 00:14:39 +00:00
g_free ( last_field_name ) ;
last_field_name = NULL ;
2011-10-04 10:12:55 +00:00
if ( hf_id = = - 1 | | hf_id = = 0 )
return ;
proto = find_protocol_by_id ( parent ) ;
2014-04-20 21:27:18 +00:00
if ( ! proto | | proto - > fields - > len = = 0 ) {
2011-10-04 10:12:55 +00:00
return ;
}
2014-04-20 21:27:18 +00:00
for ( i = 0 ; i < proto - > fields - > len ; i + + ) {
2014-10-20 20:44:25 +00:00
hfi = ( header_field_info * ) g_ptr_array_index ( proto - > fields , i ) ;
if ( hfi - > id = = hf_id ) {
2011-10-04 10:12:55 +00:00
/* Found the hf_id in this protocol */
2014-10-20 20:44:25 +00:00
g_hash_table_steal ( gpa_name_map , hfi - > abbrev ) ;
2014-04-20 21:27:18 +00:00
g_ptr_array_remove_index_fast ( proto - > fields , i ) ;
2014-11-06 10:19:25 +00:00
g_ptr_array_add ( deregistered_fields , gpa_hfinfo . hfi [ hf_id ] ) ;
2014-04-20 21:27:18 +00:00
return ;
2011-10-04 10:12:55 +00:00
}
}
}
2014-11-06 10:19:25 +00:00
void
proto_add_deregistered_data ( void * data )
{
2016-02-01 20:50:07 +00:00
g_ptr_array_add ( deregistered_data , data ) ;
2014-11-06 10:19:25 +00:00
}
static void
free_deregistered_field ( gpointer data , gpointer user_data _U_ )
{
2016-02-01 20:50:07 +00:00
header_field_info * hfi = ( header_field_info * ) data ;
gint hf_id = hfi - > id ;
g_free ( ( char * ) hfi - > name ) ;
g_free ( ( char * ) hfi - > abbrev ) ;
g_free ( ( char * ) hfi - > blurb ) ;
if ( hfi - > strings ) {
switch ( hfi - > type ) {
case FT_FRAMENUM :
/* This is just an integer represented as a pointer */
break ;
case FT_PROTOCOL : {
protocol_t * protocol = ( protocol_t * ) hfi - > strings ;
g_free ( ( gchar * ) protocol - > short_name ) ;
break ;
}
case FT_BOOLEAN : {
true_false_string * tf = ( true_false_string * ) hfi - > strings ;
g_free ( ( gchar * ) tf - > true_string ) ;
g_free ( ( gchar * ) tf - > false_string ) ;
break ;
}
case FT_UINT64 :
case FT_INT64 : {
val64_string * vs64 = ( val64_string * ) hfi - > strings ;
while ( vs64 - > strptr ) {
g_free ( ( gchar * ) vs64 - > strptr ) ;
vs64 + + ;
}
break ;
}
default : {
/* Other Integer types */
value_string * vs = ( value_string * ) hfi - > strings ;
while ( vs - > strptr ) {
g_free ( ( gchar * ) vs - > strptr ) ;
vs + + ;
}
break ;
}
}
if ( hfi - > type ! = FT_FRAMENUM ) {
g_free ( ( void * ) hfi - > strings ) ;
}
}
if ( hfi - > parent = = - 1 )
g_slice_free ( header_field_info , hfi ) ;
gpa_hfinfo . hfi [ hf_id ] = NULL ; /* Invalidate this hf_id / proto_id */
2014-11-06 10:19:25 +00:00
}
static void
free_deregistered_data ( gpointer data , gpointer user_data _U_ )
{
2016-02-01 20:50:07 +00:00
g_free ( data ) ;
2014-11-06 10:19:25 +00:00
}
/* free deregistered fields and data */
void
proto_free_deregistered_fields ( void )
{
2016-02-01 20:50:07 +00:00
expert_free_deregistered_expertinfos ( ) ;
2015-12-10 13:10:17 +00:00
2016-02-01 20:50:07 +00:00
g_ptr_array_foreach ( deregistered_fields , free_deregistered_field , NULL ) ;
g_ptr_array_free ( deregistered_fields , TRUE ) ;
deregistered_fields = g_ptr_array_new ( ) ;
2014-11-06 10:19:25 +00:00
2016-02-01 20:50:07 +00:00
g_ptr_array_foreach ( deregistered_data , free_deregistered_data , NULL ) ;
g_ptr_array_free ( deregistered_data , TRUE ) ;
deregistered_data = g_ptr_array_new ( ) ;
2014-11-06 10:19:25 +00:00
}
2007-11-28 10:18:16 +00:00
/* chars allowed in field abbrev */
2007-12-07 18:50:41 +00:00
static
2014-10-28 18:36:38 +00:00
const guint8 fld_abbrev_chars [ 256 ] = {
2012-03-14 17:11:39 +00:00
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 0x00-0x0F */
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 0x10-0x1F */
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , /* 0x20-0x2F '-', '.' */
1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , /* 0x30-0x3F '0'-'9' */
0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , /* 0x40-0x4F 'A'-'O' */
1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , /* 0x50-0x5F 'P'-'Z', '_' */
0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , /* 0x60-0x6F 'a'-'o' */
1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , /* 0x70-0x7F 'p'-'z' */
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 0x80-0x8F */
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 0x90-0x9F */
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 0xA0-0xAF */
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 0xB0-0xBF */
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 0xC0-0xCF */
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 0xD0-0xDF */
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 0xE0-0xEF */
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* 0xF0-0xFF */
2007-12-07 18:50:41 +00:00
} ;
2007-11-28 10:18:16 +00:00
2012-06-20 17:25:53 +00:00
static const value_string hf_display [ ] = {
{ BASE_NONE , " BASE_NONE " } ,
{ BASE_DEC , " BASE_DEC " } ,
{ BASE_HEX , " BASE_HEX " } ,
{ BASE_OCT , " BASE_OCT " } ,
{ BASE_DEC_HEX , " BASE_DEC_HEX " } ,
{ BASE_HEX_DEC , " BASE_HEX_DEC " } ,
{ BASE_CUSTOM , " BASE_CUSTOM " } ,
{ BASE_NONE | BASE_RANGE_STRING , " BASE_NONE|BASE_RANGE_STRING " } ,
{ BASE_DEC | BASE_RANGE_STRING , " BASE_DEC|BASE_RANGE_STRING " } ,
{ BASE_HEX | BASE_RANGE_STRING , " BASE_HEX|BASE_RANGE_STRING " } ,
{ BASE_OCT | BASE_RANGE_STRING , " BASE_OCT|BASE_RANGE_STRING " } ,
{ BASE_DEC_HEX | BASE_RANGE_STRING , " BASE_DEC_HEX|BASE_RANGE_STRING " } ,
{ BASE_HEX_DEC | BASE_RANGE_STRING , " BASE_HEX_DEC|BASE_RANGE_STRING " } ,
{ BASE_CUSTOM | BASE_RANGE_STRING , " BASE_CUSTOM|BASE_RANGE_STRING " } ,
2013-07-26 23:51:00 +00:00
{ BASE_NONE | BASE_VAL64_STRING , " BASE_NONE|BASE_VAL64_STRING " } ,
{ BASE_DEC | BASE_VAL64_STRING , " BASE_DEC|BASE_VAL64_STRING " } ,
{ BASE_HEX | BASE_VAL64_STRING , " BASE_HEX|BASE_VAL64_STRING " } ,
{ BASE_OCT | BASE_VAL64_STRING , " BASE_OCT|BASE_VAL64_STRING " } ,
{ BASE_DEC_HEX | BASE_VAL64_STRING , " BASE_DEC_HEX|BASE_VAL64_STRING " } ,
{ BASE_HEX_DEC | BASE_VAL64_STRING , " BASE_HEX_DEC|BASE_VAL64_STRING " } ,
{ BASE_CUSTOM | BASE_VAL64_STRING , " BASE_CUSTOM|BASE_VAL64_STRING " } ,
2015-09-06 17:01:47 +00:00
/* Alias: BASE_NONE { BASE_FLOAT, "BASE_FLOAT" }, */
/* Alias: BASE_NONE { STR_ASCII, "STR_ASCII" }, */
2013-12-07 11:50:43 +00:00
{ STR_UNICODE , " STR_UNICODE " } ,
2012-06-20 17:25:53 +00:00
{ ABSOLUTE_TIME_LOCAL , " ABSOLUTE_TIME_LOCAL " } ,
{ ABSOLUTE_TIME_UTC , " ABSOLUTE_TIME_UTC " } ,
{ ABSOLUTE_TIME_DOY_UTC , " ABSOLUTE_TIME_DOY_UTC " } ,
2015-10-05 10:53:07 +00:00
{ BASE_PT_UDP , " BASE_PT_UDP " } ,
{ BASE_PT_TCP , " BASE_PT_TCP " } ,
{ BASE_PT_DCCP , " BASE_PT_DCCP " } ,
{ BASE_PT_SCTP , " BASE_PT_SCTP " } ,
2012-06-20 17:25:53 +00:00
{ 0 , NULL } } ;
2015-10-05 10:53:07 +00:00
static inline port_type
display_to_port_type ( field_display_e e )
{
switch ( e ) {
case BASE_PT_UDP :
return PT_UDP ;
case BASE_PT_TCP :
return PT_TCP ;
case BASE_PT_DCCP :
return PT_DCCP ;
case BASE_PT_SCTP :
return PT_SCTP ;
default :
break ;
}
return PT_NONE ;
}
2007-11-28 10:18:16 +00:00
/* temporary function containing assert part for easier profiling */
2012-03-01 22:00:33 +00:00
static void
2012-06-20 17:25:53 +00:00
tmp_fld_check_assert ( header_field_info * hfinfo )
{
2015-02-04 04:27:01 +00:00
gchar * tmp_str ;
2010-04-24 03:08:08 +00:00
2007-03-11 06:16:00 +00:00
/* The field must have a name (with length > 0) */
2010-04-24 03:08:08 +00:00
if ( ! hfinfo - > name | | ! hfinfo - > name [ 0 ] ) {
if ( hfinfo - > abbrev )
/* Try to identify the field */
2010-04-24 19:07:21 +00:00
g_error ( " Field (abbrev='%s') does not have a name \n " ,
hfinfo - > abbrev ) ;
2010-04-24 03:08:08 +00:00
else
/* Hum, no luck */
g_error ( " Field does not have a name (nor an abbreviation) \n " ) ;
}
2007-03-11 06:16:00 +00:00
/* fields with an empty string for an abbreviation aren't filterable */
2012-03-01 22:00:33 +00:00
if ( ! hfinfo - > abbrev | | ! hfinfo - > abbrev [ 0 ] )
2010-04-24 03:08:08 +00:00
g_error ( " Field '%s' does not have an abbreviation \n " , hfinfo - > name ) ;
2003-08-25 00:15:02 +00:00
2010-04-24 19:07:21 +00:00
/* These types of fields are allowed to have value_strings,
* true_false_strings or a protocol_t struct
*/
2010-04-24 03:08:08 +00:00
if ( hfinfo - > strings ! = NULL & & ! (
2012-03-14 17:11:39 +00:00
( hfinfo - > type = = FT_UINT8 ) | |
( hfinfo - > type = = FT_UINT16 ) | |
( hfinfo - > type = = FT_UINT24 ) | |
( hfinfo - > type = = FT_UINT32 ) | |
2014-12-17 20:19:20 +00:00
( hfinfo - > type = = FT_UINT40 ) | |
( hfinfo - > type = = FT_UINT48 ) | |
( hfinfo - > type = = FT_UINT56 ) | |
2013-05-17 00:06:26 +00:00
( hfinfo - > type = = FT_UINT64 ) | |
2012-03-14 17:11:39 +00:00
( hfinfo - > type = = FT_INT8 ) | |
( hfinfo - > type = = FT_INT16 ) | |
( hfinfo - > type = = FT_INT24 ) | |
( hfinfo - > type = = FT_INT32 ) | |
2014-12-17 20:19:20 +00:00
( hfinfo - > type = = FT_INT40 ) | |
( hfinfo - > type = = FT_INT48 ) | |
( hfinfo - > type = = FT_INT56 ) | |
2013-05-17 00:06:26 +00:00
( hfinfo - > type = = FT_INT64 ) | |
2012-03-14 17:11:39 +00:00
( hfinfo - > type = = FT_BOOLEAN ) | |
2016-02-01 20:50:07 +00:00
( hfinfo - > type = = FT_PROTOCOL ) | |
( hfinfo - > type = = FT_FRAMENUM ) ) )
g_error ( " Field '%s' (%s) has a 'strings' value but is of type %s "
2012-03-14 17:11:39 +00:00
" (which is not allowed to have strings) \n " ,
2014-04-12 22:39:20 +00:00
hfinfo - > name , hfinfo - > abbrev , ftype_name ( hfinfo - > type ) ) ;
1999-10-12 06:21:15 +00:00
2011-05-19 01:21:48 +00:00
/* TODO: This check may slow down startup, and output quite a few warnings.
It would be good to be able to enable this ( and possibly other checks ? )
in non - release builds . */
#if 0
/* Check for duplicate value_string values.
There are lots that have the same value * and * string , so for now only
report those that have same value but different string . */
2012-06-10 15:10:11 +00:00
if ( ( hfinfo - > strings ! = NULL ) & &
2012-03-14 17:11:39 +00:00
! ( hfinfo - > display & BASE_RANGE_STRING ) & &
2013-12-07 10:41:42 +00:00
! ( ( hfinfo - > display & FIELD_DISPLAY_E_MASK ) = = BASE_CUSTOM ) & &
2012-03-14 17:11:39 +00:00
(
( hfinfo - > type = = FT_UINT8 ) | |
( hfinfo - > type = = FT_UINT16 ) | |
( hfinfo - > type = = FT_UINT24 ) | |
( hfinfo - > type = = FT_UINT32 ) | |
( hfinfo - > type = = FT_INT8 ) | |
( hfinfo - > type = = FT_INT16 ) | |
( hfinfo - > type = = FT_INT24 ) | |
( hfinfo - > type = = FT_INT32 ) | |
( hfinfo - > type = = FT_FRAMENUM ) ) ) {
2011-05-19 01:21:48 +00:00
int n , m ;
2012-04-26 15:33:46 +00:00
const value_string * start_values ;
const value_string * current ;
2012-06-10 15:10:11 +00:00
2014-04-09 22:58:59 +00:00
if ( hfinfo - > display & BASE_EXT_STRING )
2012-04-26 15:33:46 +00:00
start_values = VALUE_STRING_EXT_VS_P ( ( ( const value_string_ext * ) hfinfo - > strings ) ) ;
2012-06-10 15:10:11 +00:00
else
2012-04-26 15:33:46 +00:00
start_values = ( const value_string * ) hfinfo - > strings ;
current = start_values ;
2011-05-19 01:21:48 +00:00
for ( n = 0 ; current ; n + + , current + + ) {
/* Drop out if we reached the end. */
if ( ( current - > value = = 0 ) & & ( current - > strptr = = NULL ) ) {
break ;
}
/* Check value against all previous */
for ( m = 0 ; m < n ; m + + ) {
/* There are lots of duplicates with the same string,
so only report if different . . . */
if ( ( start_values [ m ] . value = = current - > value ) & &
2012-03-14 17:11:39 +00:00
( strcmp ( start_values [ m ] . strptr , current - > strptr ) ! = 0 ) ) {
g_warning ( " Field '%s' (%s) has a conflicting entry in its "
2012-06-20 17:25:53 +00:00
" value_string: %u is at indices %u (%s) and %u (%s)) \n " ,
2012-03-14 17:11:39 +00:00
hfinfo - > name , hfinfo - > abbrev ,
current - > value , m , start_values [ m ] . strptr , n , current - > strptr ) ;
2011-05-19 01:21:48 +00:00
}
}
}
}
# endif
2001-04-23 01:19:39 +00:00
switch ( hfinfo - > type ) {
2012-03-14 17:11:39 +00:00
case FT_INT8 :
case FT_INT16 :
case FT_INT24 :
case FT_INT32 :
2014-12-17 20:19:20 +00:00
case FT_INT40 :
case FT_INT48 :
case FT_INT56 :
2012-03-14 17:11:39 +00:00
case FT_INT64 :
/* Hexadecimal and octal are, in printf() and everywhere
* else , unsigned so don ' t allow dissectors to register a
* signed field to be displayed unsigned . ( Else how would
* we display negative values ? )
*/
2013-12-07 10:41:42 +00:00
switch ( hfinfo - > display & FIELD_DISPLAY_E_MASK ) {
2013-07-08 05:59:07 +00:00
case BASE_HEX :
case BASE_OCT :
case BASE_DEC_HEX :
case BASE_HEX_DEC :
2015-02-04 04:27:01 +00:00
tmp_str = val_to_str_wmem ( NULL , hfinfo - > display , hf_display , " (Bit count: %d) " ) ;
2013-07-08 05:59:07 +00:00
g_error ( " Field '%s' (%s) is signed (%s) but is being displayed unsigned (%s) \n " ,
hfinfo - > name , hfinfo - > abbrev ,
2015-02-04 04:27:01 +00:00
ftype_name ( hfinfo - > type ) , tmp_str ) ;
wmem_free ( NULL , tmp_str ) ;
2013-07-08 05:59:07 +00:00
}
2012-03-14 17:11:39 +00:00
/* FALL THROUGH */
case FT_UINT8 :
case FT_UINT16 :
case FT_UINT24 :
case FT_UINT32 :
2014-12-17 20:19:20 +00:00
case FT_UINT40 :
case FT_UINT48 :
case FT_UINT56 :
2012-03-14 17:11:39 +00:00
case FT_UINT64 :
2015-10-05 10:53:07 +00:00
if ( IS_BASE_PORT ( hfinfo - > display ) ) {
tmp_str = val_to_str_wmem ( NULL , hfinfo - > display , hf_display , " (Unknown: 0x%x) " ) ;
if ( hfinfo - > type ! = FT_UINT16 ) {
g_error ( " Field '%s' (%s) has 'display' value %s but it can only be used with FT_UINT16, not %s \n " ,
hfinfo - > name , hfinfo - > abbrev ,
tmp_str , ftype_name ( hfinfo - > type ) ) ;
}
if ( hfinfo - > strings ! = NULL ) {
g_error ( " Field '%s' (%s) is an %s (%s) but has a strings value \n " ,
hfinfo - > name , hfinfo - > abbrev ,
ftype_name ( hfinfo - > type ) , tmp_str ) ;
}
if ( hfinfo - > bitmask ! = 0 ) {
g_error ( " Field '%s' (%s) is an %s (%s) but has a bitmask \n " ,
hfinfo - > name , hfinfo - > abbrev ,
ftype_name ( hfinfo - > type ) , tmp_str ) ;
}
wmem_free ( NULL , tmp_str ) ;
break ;
}
2012-06-20 17:25:53 +00:00
/* Require integral types (other than frame number,
* which is always displayed in decimal ) to have a
* number base .
* If there is a strings value then this base is not
* normally used except when constructing a display
* filter for a value not found in the strings lookup .
*/
2013-12-07 10:41:42 +00:00
switch ( hfinfo - > display & FIELD_DISPLAY_E_MASK ) {
2012-06-20 17:25:53 +00:00
case BASE_DEC :
case BASE_HEX :
case BASE_OCT :
case BASE_DEC_HEX :
case BASE_HEX_DEC :
case BASE_CUSTOM : /* hfinfo_numeric_value_format() treats this as decimal */
break ;
default :
2015-02-04 04:27:01 +00:00
tmp_str = val_to_str_wmem ( NULL , hfinfo - > display , hf_display , " (Unknown: 0x%x) " ) ;
2012-03-14 17:11:39 +00:00
g_error ( " Field '%s' (%s) is an integral value (%s) "
2012-06-20 17:25:53 +00:00
" but is being displayed as %s \n " ,
2012-03-14 17:11:39 +00:00
hfinfo - > name , hfinfo - > abbrev ,
2015-02-04 04:27:01 +00:00
ftype_name ( hfinfo - > type ) , tmp_str ) ;
wmem_free ( NULL , tmp_str ) ;
2012-03-14 17:11:39 +00:00
}
break ;
2015-01-04 02:56:16 +00:00
case FT_BYTES :
/* Require bytes to have a "display type" that could
* add a character between displayed bytes .
*/
switch ( hfinfo - > display & FIELD_DISPLAY_E_MASK ) {
case BASE_NONE :
2015-01-11 00:26:46 +00:00
case SEP_DOT :
case SEP_DASH :
case SEP_COLON :
case SEP_SPACE :
2015-01-04 02:56:16 +00:00
break ;
default :
2015-02-04 04:27:01 +00:00
tmp_str = val_to_str_wmem ( NULL , hfinfo - > display , hf_display , " (Bit count: %d) " ) ;
g_error ( " Field '%s' (%s) is an byte array but is being displayed as %s instead of BASE_NONE, SEP_DOT, SEP_DASH, SEP_COLON, or SEP_SPACE \n " ,
hfinfo - > name , hfinfo - > abbrev , tmp_str ) ;
wmem_free ( NULL , tmp_str ) ;
2015-01-04 02:56:16 +00:00
}
if ( hfinfo - > bitmask ! = 0 )
g_error ( " Field '%s' (%s) is an %s but has a bitmask \n " ,
hfinfo - > name , hfinfo - > abbrev ,
ftype_name ( hfinfo - > type ) ) ;
if ( hfinfo - > strings ! = NULL )
g_error ( " Field '%s' (%s) is an %s but has a strings value \n " ,
hfinfo - > name , hfinfo - > abbrev ,
ftype_name ( hfinfo - > type ) ) ;
break ;
2001-04-23 01:19:39 +00:00
2012-03-14 17:11:39 +00:00
case FT_PROTOCOL :
case FT_FRAMENUM :
2015-02-04 04:27:01 +00:00
if ( hfinfo - > display ! = BASE_NONE ) {
tmp_str = val_to_str_wmem ( NULL , hfinfo - > display , hf_display , " (Bit count: %d) " ) ;
2012-03-14 17:11:39 +00:00
g_error ( " Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE \n " ,
hfinfo - > name , hfinfo - > abbrev ,
2015-02-04 04:27:01 +00:00
ftype_name ( hfinfo - > type ) , tmp_str ) ;
wmem_free ( NULL , tmp_str ) ;
}
2012-03-14 17:11:39 +00:00
if ( hfinfo - > bitmask ! = 0 )
g_error ( " Field '%s' (%s) is an %s but has a bitmask \n " ,
hfinfo - > name , hfinfo - > abbrev ,
2014-04-12 22:39:20 +00:00
ftype_name ( hfinfo - > type ) ) ;
2012-03-14 17:11:39 +00:00
break ;
2009-10-08 21:26:26 +00:00
2012-03-14 17:11:39 +00:00
case FT_BOOLEAN :
break ;
2002-12-19 02:58:53 +00:00
2012-03-14 17:11:39 +00:00
case FT_ABSOLUTE_TIME :
if ( ! ( hfinfo - > display = = ABSOLUTE_TIME_LOCAL | |
hfinfo - > display = = ABSOLUTE_TIME_UTC | |
2015-02-04 04:27:01 +00:00
hfinfo - > display = = ABSOLUTE_TIME_DOY_UTC ) ) {
tmp_str = val_to_str_wmem ( NULL , hfinfo - > display , hf_display , " (Bit count: %d) " ) ;
2012-03-14 17:11:39 +00:00
g_error ( " Field '%s' (%s) is a %s but is being displayed as %s instead of as a time \n " ,
2015-02-04 04:27:01 +00:00
hfinfo - > name , hfinfo - > abbrev , ftype_name ( hfinfo - > type ) , tmp_str ) ;
wmem_free ( NULL , tmp_str ) ;
}
2012-03-14 17:11:39 +00:00
if ( hfinfo - > bitmask ! = 0 )
g_error ( " Field '%s' (%s) is an %s but has a bitmask \n " ,
hfinfo - > name , hfinfo - > abbrev ,
2014-04-12 22:39:20 +00:00
ftype_name ( hfinfo - > type ) ) ;
2012-03-14 17:11:39 +00:00
break ;
2009-12-19 03:17:44 +00:00
2013-12-07 11:50:43 +00:00
case FT_STRING :
case FT_STRINGZ :
case FT_UINT_STRING :
2014-04-12 22:26:34 +00:00
case FT_STRINGZPAD :
2013-12-07 11:50:43 +00:00
switch ( hfinfo - > display ) {
case STR_ASCII :
case STR_UNICODE :
break ;
default :
2015-02-04 04:27:01 +00:00
tmp_str = val_to_str_wmem ( NULL , hfinfo - > display , hf_display , " (Unknown: 0x%x) " ) ;
2013-12-07 11:50:43 +00:00
g_error ( " Field '%s' (%s) is an string value (%s) "
" but is being displayed as %s \n " ,
hfinfo - > name , hfinfo - > abbrev ,
2015-02-04 04:27:01 +00:00
ftype_name ( hfinfo - > type ) , tmp_str ) ;
wmem_free ( NULL , tmp_str ) ;
2013-12-07 11:50:43 +00:00
}
if ( hfinfo - > bitmask ! = 0 )
g_error ( " Field '%s' (%s) is an %s but has a bitmask \n " ,
hfinfo - > name , hfinfo - > abbrev ,
2014-04-12 22:39:20 +00:00
ftype_name ( hfinfo - > type ) ) ;
2013-12-07 11:50:43 +00:00
if ( hfinfo - > strings ! = NULL )
g_error ( " Field '%s' (%s) is an %s but has a strings value \n " ,
hfinfo - > name , hfinfo - > abbrev ,
2014-04-12 22:39:20 +00:00
ftype_name ( hfinfo - > type ) ) ;
2013-12-07 11:50:43 +00:00
break ;
2015-09-07 01:56:30 +00:00
case FT_IPv4 :
switch ( hfinfo - > display ) {
case BASE_NONE :
case BASE_NETMASK :
break ;
default :
tmp_str = val_to_str_wmem ( NULL , hfinfo - > display , hf_display , " (Unknown: 0x%x) " ) ;
g_error ( " Field '%s' (%s) is an IPv4 value (%s) "
" but is being displayed as %s \n " ,
hfinfo - > name , hfinfo - > abbrev ,
ftype_name ( hfinfo - > type ) , tmp_str ) ;
wmem_free ( NULL , tmp_str ) ;
break ;
}
break ;
2012-03-14 17:11:39 +00:00
default :
2015-02-04 04:27:01 +00:00
if ( hfinfo - > display ! = BASE_NONE ) {
tmp_str = val_to_str_wmem ( NULL , hfinfo - > display , hf_display , " (Bit count: %d) " ) ;
2012-03-14 17:11:39 +00:00
g_error ( " Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE \n " ,
hfinfo - > name , hfinfo - > abbrev ,
2014-04-12 22:39:20 +00:00
ftype_name ( hfinfo - > type ) ,
2015-02-04 04:27:01 +00:00
tmp_str ) ;
wmem_free ( NULL , tmp_str ) ;
}
2012-03-14 17:11:39 +00:00
if ( hfinfo - > bitmask ! = 0 )
g_error ( " Field '%s' (%s) is an %s but has a bitmask \n " ,
hfinfo - > name , hfinfo - > abbrev ,
2014-04-12 22:39:20 +00:00
ftype_name ( hfinfo - > type ) ) ;
2012-03-14 17:11:39 +00:00
if ( hfinfo - > strings ! = NULL )
g_error ( " Field '%s' (%s) is an %s but has a strings value \n " ,
hfinfo - > name , hfinfo - > abbrev ,
2014-04-12 22:39:20 +00:00
ftype_name ( hfinfo - > type ) ) ;
2012-03-14 17:11:39 +00:00
break ;
2001-04-23 01:19:39 +00:00
}
2007-11-28 10:18:16 +00:00
}
2016-02-01 20:33:33 +00:00
# ifdef ENABLE_CHECK_FILTER
static enum ftenum
_ftype_common ( enum ftenum type )
{
switch ( type ) {
case FT_INT8 :
case FT_INT16 :
case FT_INT24 :
case FT_INT32 :
return FT_INT32 ;
case FT_UINT8 :
case FT_UINT16 :
case FT_UINT24 :
case FT_UINT32 :
case FT_IPXNET :
case FT_FRAMENUM :
return FT_UINT32 ;
case FT_UINT64 :
case FT_EUI64 :
return FT_UINT64 ;
case FT_STRING :
case FT_STRINGZ :
case FT_UINT_STRING :
return FT_STRING ;
case FT_FLOAT :
case FT_DOUBLE :
return FT_DOUBLE ;
case FT_BYTES :
case FT_UINT_BYTES :
case FT_ETHER :
case FT_OID :
return FT_BYTES ;
case FT_ABSOLUTE_TIME :
case FT_RELATIVE_TIME :
return FT_ABSOLUTE_TIME ;
default :
return type ;
}
}
# endif
2013-10-03 01:54:02 +00:00
static void
register_type_length_mismatch ( void )
{
static ei_register_info ei [ ] = {
2013-10-09 12:56:19 +00:00
{ & ei_type_length_mismatch_error , { " _ws.type_length.mismatch " , PI_MALFORMED , PI_ERROR , " Trying to fetch X with length Y " , EXPFILL } } ,
{ & ei_type_length_mismatch_warn , { " _ws.type_length.mismatch " , PI_MALFORMED , PI_WARN , " Trying to fetch X with length Y " , EXPFILL } } ,
2013-10-03 01:54:02 +00:00
} ;
expert_module_t * expert_type_length_mismatch ;
2013-10-09 12:56:19 +00:00
proto_type_length_mismatch = proto_register_protocol ( " Type Length Mismatch " , " Type length mismatch " , " _ws.type_length " ) ;
2013-10-03 01:54:02 +00:00
expert_type_length_mismatch = expert_register_protocol ( proto_type_length_mismatch ) ;
expert_register_field_array ( expert_type_length_mismatch , ei , array_length ( ei ) ) ;
/* "Type Length Mismatch" isn't really a protocol, it's an error indication;
disabling them makes no sense . */
proto_set_cant_toggle ( proto_type_length_mismatch ) ;
}
2014-04-12 04:32:20 +00:00
static void
register_number_string_decoding_error ( void )
{
static ei_register_info ei [ ] = {
{ & ei_number_string_decoding_failed_error ,
{ " _ws.number_string.decoding_error.failed " , PI_MALFORMED , PI_ERROR ,
" Failed to decode number from string " , EXPFILL
}
} ,
{ & ei_number_string_decoding_erange_error ,
{ " _ws.number_string.decoding_error.erange " , PI_MALFORMED , PI_ERROR ,
" Decoded number from string is out of valid range " , EXPFILL
}
} ,
} ;
expert_module_t * expert_number_string_decoding_error ;
proto_number_string_decoding_error =
proto_register_protocol ( " Number-String Decoding Error " ,
" Number-string decoding error " ,
" _ws.number_string.decoding_error " ) ;
expert_number_string_decoding_error =
expert_register_protocol ( proto_number_string_decoding_error ) ;
expert_register_field_array ( expert_number_string_decoding_error , ei , array_length ( ei ) ) ;
/* "Number-String Decoding Error" isn't really a protocol, it's an error indication;
disabling them makes no sense . */
proto_set_cant_toggle ( proto_number_string_decoding_error ) ;
}
2016-04-01 20:52:52 +00:00
# define PROTO_PRE_ALLOC_HF_FIELDS_MEM (178000+PRE_ALLOC_EXPERT_FIELDS_MEM)
2007-11-28 10:18:16 +00:00
static int
2010-04-03 18:18:50 +00:00
proto_register_field_init ( header_field_info * hfinfo , const int parent )
2007-11-28 10:18:16 +00:00
{
tmp_fld_check_assert ( hfinfo ) ;
2012-03-14 17:11:39 +00:00
hfinfo - > parent = parent ;
2001-02-13 18:34:51 +00:00
hfinfo - > same_name_next = NULL ;
2013-08-06 20:53:47 +00:00
hfinfo - > same_name_prev_id = - 1 ;
1999-07-07 22:52:57 +00:00
/* if we always add and never delete, then id == len - 1 is correct */
2012-03-14 17:11:39 +00:00
if ( gpa_hfinfo . len > = gpa_hfinfo . allocated_len ) {
if ( ! gpa_hfinfo . hfi ) {
gpa_hfinfo . allocated_len = PROTO_PRE_ALLOC_HF_FIELDS_MEM ;
2013-03-02 12:10:56 +00:00
gpa_hfinfo . hfi = ( header_field_info * * ) g_malloc ( sizeof ( header_field_info * ) * PROTO_PRE_ALLOC_HF_FIELDS_MEM ) ;
2003-11-21 14:58:49 +00:00
} else {
2012-03-14 17:11:39 +00:00
gpa_hfinfo . allocated_len + = 1000 ;
2013-03-02 12:10:56 +00:00
gpa_hfinfo . hfi = ( header_field_info * * ) g_realloc ( gpa_hfinfo . hfi ,
2012-03-14 17:11:39 +00:00
sizeof ( header_field_info * ) * gpa_hfinfo . allocated_len ) ;
/*g_warning("gpa_hfinfo.allocated_len %u", gpa_hfinfo.allocated_len);*/
2003-11-21 14:58:49 +00:00
}
}
2012-03-14 17:11:39 +00:00
gpa_hfinfo . hfi [ gpa_hfinfo . len ] = hfinfo ;
2003-11-21 14:58:49 +00:00
gpa_hfinfo . len + + ;
hfinfo - > id = gpa_hfinfo . len - 1 ;
2003-08-25 00:15:02 +00:00
/* if we have real names, enter this field in the name tree */
if ( ( hfinfo - > name [ 0 ] ! = 0 ) & & ( hfinfo - > abbrev [ 0 ] ! = 0 ) ) {
2007-11-28 10:18:16 +00:00
header_field_info * same_name_next_hfinfo ;
2003-11-13 23:38:33 +00:00
guchar c ;
/* Check that the filter name (abbreviation) is legal;
* it must contain only alphanumerics , ' - ' , " _ " , and " . " . */
2007-11-28 10:18:16 +00:00
c = wrs_check_charset ( fld_abbrev_chars , hfinfo - > abbrev ) ;
if ( c ) {
2014-10-28 18:36:38 +00:00
if ( g_ascii_isprint ( c ) )
fprintf ( stderr , " Invalid character '%c' in filter name '%s' \n " , c , hfinfo - > abbrev ) ;
else
fprintf ( stderr , " Invalid byte \\ %03o in filter name '%s' \n " , c , hfinfo - > abbrev ) ;
2014-09-15 18:28:07 +00:00
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
2006-01-10 16:19:56 +00:00
}
2007-11-28 10:18:16 +00:00
2003-08-25 00:15:02 +00:00
/* We allow multiple hfinfo's to be registered under the same
* abbreviation . This was done for X .25 , as , depending
* on whether it ' s modulo - 8 or modulo - 128 operation ,
* some bitfield fields may be in different bits of
* a byte , and we want to be able to refer to that field
* with one name regardless of whether the packets
* are modulo - 8 or modulo - 128 packets . */
2008-04-07 05:22:54 +00:00
2007-11-28 10:18:16 +00:00
same_name_hfinfo = NULL ;
2008-04-07 05:22:54 +00:00
2014-04-20 20:45:57 +00:00
g_hash_table_insert ( gpa_name_map , ( gpointer ) ( hfinfo - > abbrev ) , hfinfo ) ;
2007-12-07 18:50:41 +00:00
/* GLIB 2.x - if it is already present
2009-06-11 10:10:42 +00:00
* the previous hfinfo with the same name is saved
* to same_name_hfinfo by value destroy callback */
2003-08-25 00:15:02 +00:00
if ( same_name_hfinfo ) {
/* There's already a field with this name.
2015-01-18 19:45:30 +00:00
* Put the current field * before * that field
* in the list of fields with this name , Thus ,
* we end up with an effectively
* doubly - linked - list of same - named hfinfo ' s ,
* with the head of the list ( stored in the
* hash ) being the last seen hfinfo .
*/
2003-08-25 00:15:02 +00:00
same_name_next_hfinfo =
2009-09-23 16:27:37 +00:00
same_name_hfinfo - > same_name_next ;
2003-08-25 00:15:02 +00:00
hfinfo - > same_name_next = same_name_next_hfinfo ;
if ( same_name_next_hfinfo )
2013-08-06 20:53:47 +00:00
same_name_next_hfinfo - > same_name_prev_id = hfinfo - > id ;
2003-08-25 00:15:02 +00:00
same_name_hfinfo - > same_name_next = hfinfo ;
2013-08-06 20:53:47 +00:00
hfinfo - > same_name_prev_id = same_name_hfinfo - > id ;
2016-02-01 20:33:33 +00:00
# ifdef ENABLE_CHECK_FILTER
while ( same_name_hfinfo ) {
if ( _ftype_common ( hfinfo - > type ) ! = _ftype_common ( same_name_hfinfo - > type ) )
fprintf ( stderr , " '%s' exists multiple times with NOT compatible types: %s and %s \n " , hfinfo - > abbrev , ftype_name ( hfinfo - > type ) , ftype_name ( same_name_hfinfo - > type ) ) ;
same_name_hfinfo = same_name_hfinfo - > same_name_next ;
}
# endif
2003-08-25 00:15:02 +00:00
}
}
1999-07-07 22:52:57 +00:00
return hfinfo - > id ;
}
1999-11-16 11:44:20 +00:00
void
2010-04-03 18:18:50 +00:00
proto_register_subtree_array ( gint * const * indices , const int num_indices )
1999-11-16 11:44:20 +00:00
{
int i ;
2005-01-07 12:56:21 +00:00
gint * const * ptr = indices ;
1999-11-16 11:44:20 +00:00
2002-04-18 00:50:45 +00:00
/*
2005-01-08 23:43:29 +00:00
* If we ' ve already allocated the array of tree types , expand
* it ; this lets plugins such as mate add tree types after
* the initial startup . ( If we haven ' t already allocated it ,
* we don ' t allocate it ; on the first pass , we just assign
* ett values and keep track of how many we ' ve assigned , and
* when we ' re finished registering all dissectors we allocate
* the array , so that we do only one allocation rather than
* wasting CPU time and memory by growing the array for each
* dissector that registers ett values . )
2002-04-18 00:50:45 +00:00
*/
2005-01-08 23:43:29 +00:00
if ( tree_is_expanded ! = NULL ) {
2013-07-07 21:32:12 +00:00
tree_is_expanded = ( guint32 * ) g_realloc ( tree_is_expanded , ( 1 + ( ( num_tree_types + num_indices ) / 32 ) ) * sizeof ( guint32 ) ) ;
2013-07-07 17:13:17 +00:00
/* set new items to 0 */
/* XXX, slow!!! optimize when needed (align 'i' to 32, and set rest of guint32 to 0) */
for ( i = num_tree_types ; i < num_tree_types + num_indices ; i + + )
2015-04-30 18:13:50 +00:00
tree_is_expanded [ i > > 5 ] & = ~ ( 1U < < ( i & 31 ) ) ;
2005-01-08 23:43:29 +00:00
}
2002-04-18 00:50:45 +00:00
1999-11-16 11:44:20 +00:00
/*
* Assign " num_indices " subtree numbers starting at " num_tree_types " ,
* returning the indices through the pointers in the array whose
2002-04-01 02:00:53 +00:00
* first element is pointed to by " indices " , and update
1999-11-16 11:44:20 +00:00
* " num_tree_types " appropriately .
*/
2009-08-09 15:49:02 +00:00
for ( i = 0 ; i < num_indices ; i + + , ptr + + , num_tree_types + + ) {
if ( * * ptr ! = - 1 ) {
/* g_error will terminate the program */
g_error ( " register_subtree_array: subtree item type (ett_...) not -1 ! "
" This is a development error: "
" Either the subtree item type has already been assigned or "
" was not initialized to -1. " ) ;
}
1999-11-16 11:44:20 +00:00
* * ptr = num_tree_types ;
2009-08-09 15:49:02 +00:00
}
1999-11-16 11:44:20 +00:00
}
2013-07-16 22:09:29 +00:00
static inline gsize
label_concat ( char * label_str , gsize pos , const char * str )
{
if ( pos < ITEM_LABEL_LENGTH )
pos + = g_strlcpy ( label_str + pos , str , ITEM_LABEL_LENGTH - pos ) ;
return pos ;
}
static void
label_mark_truncated ( char * label_str , gsize name_pos )
{
2014-03-01 10:25:47 +00:00
static const char trunc_str [ ] = " [truncated] " ;
const size_t trunc_len = sizeof ( trunc_str ) - 1 ;
gchar * last_char ;
2013-07-16 22:09:29 +00:00
/* ..... field_name: dataaaaaaaaaaaaa
* |
* ^ ^ ^ ^ ^ name_pos
*
2014-03-01 21:08:42 +00:00
* . . . . . field_name [ truncated ] : dataaaaaaaaaaaaa
*
* name_pos = = 0 means that we have only data or only a field_name
*/
2013-07-16 22:09:29 +00:00
if ( name_pos < ITEM_LABEL_LENGTH - trunc_len ) {
memmove ( label_str + name_pos + trunc_len , label_str + name_pos , ITEM_LABEL_LENGTH - name_pos - trunc_len ) ;
memcpy ( label_str + name_pos , trunc_str , trunc_len ) ;
2014-03-01 10:25:47 +00:00
/* in general, label_str is UTF-8
we can truncate it only at the beginning of a new character
2014-04-23 02:14:56 +00:00
we go backwards from the byte right after our buffer and
2014-03-01 10:25:47 +00:00
find the next starting byte of a UTF - 8 character , this is
where we cut
there ' s no need to use g_utf8_find_prev_char ( ) , the search
will always succeed since we copied trunc_str into the
buffer */
last_char = g_utf8_prev_char ( & label_str [ ITEM_LABEL_LENGTH ] ) ;
* last_char = ' \0 ' ;
2013-07-16 22:09:29 +00:00
} else if ( name_pos < ITEM_LABEL_LENGTH )
g_strlcpy ( label_str + name_pos , trunc_str , ITEM_LABEL_LENGTH - name_pos ) ;
}
static gsize
2013-07-16 22:21:10 +00:00
label_fill ( char * label_str , gsize pos , const header_field_info * hfinfo , const char * text )
2012-07-30 10:52:20 +00:00
{
2013-07-16 22:21:10 +00:00
gsize name_pos ;
2012-07-30 10:52:20 +00:00
2013-07-16 22:09:29 +00:00
/* "%s: %s", hfinfo->name, text */
name_pos = pos = label_concat ( label_str , pos , hfinfo - > name ) ;
pos = label_concat ( label_str , pos , " : " ) ;
pos = label_concat ( label_str , pos , text ? text : " (null) " ) ;
if ( pos > = ITEM_LABEL_LENGTH ) {
2012-07-30 10:52:20 +00:00
/* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
2013-07-16 22:09:29 +00:00
label_mark_truncated ( label_str , name_pos ) ;
2012-07-30 10:52:20 +00:00
}
2013-07-16 22:09:29 +00:00
return pos ;
2012-07-30 10:52:20 +00:00
}
2013-07-16 22:09:29 +00:00
static gsize
2013-07-16 22:21:10 +00:00
label_fill_descr ( char * label_str , gsize pos , const header_field_info * hfinfo , const char * text , const char * descr )
2012-07-30 10:52:20 +00:00
{
2013-07-16 22:21:10 +00:00
gsize name_pos ;
2013-07-16 22:09:29 +00:00
/* "%s: %s (%s)", hfinfo->name, text, descr */
name_pos = pos = label_concat ( label_str , pos , hfinfo - > name ) ;
pos = label_concat ( label_str , pos , " : " ) ;
pos = label_concat ( label_str , pos , text ? text : " (null) " ) ;
pos = label_concat ( label_str , pos , " ( " ) ;
pos = label_concat ( label_str , pos , descr ? descr : " (null) " ) ;
pos = label_concat ( label_str , pos , " ) " ) ;
2012-07-30 10:52:20 +00:00
2013-07-16 22:09:29 +00:00
if ( pos > = ITEM_LABEL_LENGTH ) {
2012-07-30 10:52:20 +00:00
/* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
2013-07-16 22:09:29 +00:00
label_mark_truncated ( label_str , name_pos ) ;
2012-07-30 10:52:20 +00:00
}
2013-07-16 22:09:29 +00:00
return pos ;
2012-07-30 10:52:20 +00:00
}
1999-07-07 22:52:57 +00:00
void
proto_item_fill_label ( field_info * fi , gchar * label_str )
{
2016-01-03 23:05:13 +00:00
header_field_info * hfinfo ;
guint8 * bytes ;
guint32 integer ;
guint64 integer64 ;
ipv4_addr_and_mask * ipv4 ;
e_guid_t * guid ;
guint32 n_addr ; /* network-order IPv4 address */
2016-02-01 20:50:07 +00:00
gchar * name ;
2016-01-03 23:05:13 +00:00
address addr ;
char * addr_str ;
2016-02-01 20:50:07 +00:00
char * tmp ;
1999-07-07 22:52:57 +00:00
2009-08-21 11:03:30 +00:00
if ( ! fi ) {
if ( label_str )
label_str [ 0 ] = ' \0 ' ;
/* XXX: Check validity of hfinfo->type */
return ;
}
2009-08-21 23:02:59 +00:00
hfinfo = fi - > hfinfo ;
2012-03-14 17:11:39 +00:00
switch ( hfinfo - > type ) {
1999-07-07 22:52:57 +00:00
case FT_NONE :
2001-02-01 20:21:25 +00:00
case FT_PROTOCOL :
2009-03-22 15:31:44 +00:00
g_strlcpy ( label_str , hfinfo - > name , ITEM_LABEL_LENGTH ) ;
1999-07-07 22:52:57 +00:00
break ;
case FT_BOOLEAN :
1999-10-12 06:21:15 +00:00
fill_label_boolean ( fi , label_str ) ;
1999-07-07 22:52:57 +00:00
break ;
1999-09-18 15:44:41 +00:00
case FT_BYTES :
2002-05-09 23:50:34 +00:00
case FT_UINT_BYTES :
2013-03-02 12:10:56 +00:00
bytes = ( guint8 * ) fvalue_get ( & fi - > value ) ;
2015-01-07 14:36:06 +00:00
if ( bytes ) {
char * str = NULL ;
switch ( hfinfo - > display )
{
2015-01-11 00:26:46 +00:00
case SEP_DOT :
2015-11-30 06:51:01 +00:00
str = bytestring_to_str ( NULL , bytes , fvalue_length ( & fi - > value ) , ' . ' ) ;
2015-01-07 14:36:06 +00:00
break ;
2015-01-11 00:26:46 +00:00
case SEP_DASH :
2015-11-30 06:51:01 +00:00
str = bytestring_to_str ( NULL , bytes , fvalue_length ( & fi - > value ) , ' - ' ) ;
2015-01-07 14:36:06 +00:00
break ;
2015-01-11 00:26:46 +00:00
case SEP_COLON :
2015-11-30 06:51:01 +00:00
str = bytestring_to_str ( NULL , bytes , fvalue_length ( & fi - > value ) , ' : ' ) ;
2015-01-07 14:36:06 +00:00
break ;
2015-01-11 00:26:46 +00:00
case SEP_SPACE :
2015-11-30 06:51:01 +00:00
str = bytestring_to_str ( NULL , bytes , fvalue_length ( & fi - > value ) , ' ' ) ;
2015-01-09 17:51:15 +00:00
break ;
2015-01-07 14:36:06 +00:00
case BASE_NONE :
default :
2015-01-04 16:17:53 +00:00
if ( prefs . display_byte_fields_with_spaces )
{
2015-11-30 06:51:01 +00:00
str = bytestring_to_str ( NULL , bytes , fvalue_length ( & fi - > value ) , ' ' ) ;
2015-01-04 16:17:53 +00:00
}
else
{
2015-11-30 06:51:01 +00:00
str = bytes_to_str ( NULL , bytes , fvalue_length ( & fi - > value ) ) ;
2015-01-04 16:17:53 +00:00
}
2015-01-07 14:36:06 +00:00
break ;
}
label_fill ( label_str , 0 , hfinfo , str ) ;
wmem_free ( NULL , str ) ;
} else {
2015-11-29 00:13:59 +00:00
if ( hfinfo - > display & BASE_ALLOW_ZERO ) {
label_fill ( label_str , 0 , hfinfo , " <none> " ) ;
} else {
label_fill ( label_str , 0 , hfinfo , " <MISSING> " ) ;
}
2015-01-04 02:56:16 +00:00
}
1999-09-18 15:44:41 +00:00
break ;
1999-10-12 06:21:15 +00:00
/* Four types of integers to take care of:
2009-09-23 16:27:37 +00:00
* Bitfield , with val_string
* Bitfield , w / o val_string
* Non - bitfield , with val_string
* Non - bitfield , w / o val_string
1999-10-12 06:21:15 +00:00
*/
1999-07-07 22:52:57 +00:00
case FT_UINT8 :
case FT_UINT16 :
1999-10-12 22:51:58 +00:00
case FT_UINT24 :
1999-07-07 22:52:57 +00:00
case FT_UINT32 :
1999-10-12 06:21:15 +00:00
if ( hfinfo - > bitmask ) {
2013-08-26 16:23:55 +00:00
fill_label_bitfield ( fi , label_str , FALSE ) ;
2008-07-30 12:30:02 +00:00
} else {
2013-06-28 21:46:41 +00:00
fill_label_number ( fi , label_str , FALSE ) ;
1999-10-12 06:21:15 +00:00
}
1999-07-07 22:52:57 +00:00
break ;
2009-07-15 08:56:12 +00:00
case FT_FRAMENUM :
2013-06-28 21:46:41 +00:00
fill_label_number ( fi , label_str , FALSE ) ;
2009-07-15 08:56:12 +00:00
break ;
2014-12-17 20:19:20 +00:00
case FT_UINT40 :
case FT_UINT48 :
case FT_UINT56 :
2001-10-29 21:13:13 +00:00
case FT_UINT64 :
2014-12-17 20:19:20 +00:00
if ( hfinfo - > bitmask ) {
fill_label_bitfield64 ( fi , label_str , FALSE ) ;
} else {
fill_label_number64 ( fi , label_str , FALSE ) ;
}
2001-10-29 21:13:13 +00:00
break ;
1999-10-13 03:07:30 +00:00
case FT_INT8 :
case FT_INT16 :
case FT_INT24 :
case FT_INT32 :
2013-08-26 16:23:55 +00:00
if ( hfinfo - > bitmask ) {
fill_label_bitfield ( fi , label_str , TRUE ) ;
} else {
fill_label_number ( fi , label_str , TRUE ) ;
}
1999-10-13 03:07:30 +00:00
break ;
2014-12-17 20:19:20 +00:00
case FT_INT40 :
case FT_INT48 :
case FT_INT56 :
2001-11-02 10:09:51 +00:00
case FT_INT64 :
2014-12-17 20:19:20 +00:00
if ( hfinfo - > bitmask ) {
fill_label_bitfield64 ( fi , label_str , TRUE ) ;
} else {
fill_label_number64 ( fi , label_str , TRUE ) ;
}
2001-11-02 10:09:51 +00:00
break ;
2002-08-24 19:45:28 +00:00
case FT_FLOAT :
2009-03-22 15:31:44 +00:00
g_snprintf ( label_str , ITEM_LABEL_LENGTH ,
2013-11-09 14:37:13 +00:00
" %s: %. " G_STRINGIFY ( FLT_DIG ) " g " ,
2010-04-26 20:48:13 +00:00
hfinfo - > name , fvalue_get_floating ( & fi - > value ) ) ;
2002-08-24 19:45:28 +00:00
break ;
1999-09-12 06:11:51 +00:00
case FT_DOUBLE :
2009-03-22 15:31:44 +00:00
g_snprintf ( label_str , ITEM_LABEL_LENGTH ,
2013-11-09 14:37:13 +00:00
" %s: %. " G_STRINGIFY ( DBL_DIG ) " g " ,
2010-04-26 20:48:13 +00:00
hfinfo - > name , fvalue_get_floating ( & fi - > value ) ) ;
1999-09-12 06:11:51 +00:00
break ;
1999-07-07 22:52:57 +00:00
case FT_ABSOLUTE_TIME :
2014-06-16 17:54:20 +00:00
tmp = abs_time_to_str ( NULL , ( const nstime_t * ) fvalue_get ( & fi - > value ) , ( absolute_time_display_e ) hfinfo - > display , TRUE ) ;
label_fill ( label_str , 0 , hfinfo , tmp ) ;
wmem_free ( NULL , tmp ) ;
1999-09-12 06:11:51 +00:00
break ;
case FT_RELATIVE_TIME :
2014-06-16 17:54:20 +00:00
tmp = rel_time_to_secs_str ( NULL , ( const nstime_t * ) fvalue_get ( & fi - > value ) ) ;
2009-03-22 15:31:44 +00:00
g_snprintf ( label_str , ITEM_LABEL_LENGTH ,
2014-06-16 17:54:20 +00:00
" %s: %s seconds " , hfinfo - > name , tmp ) ;
wmem_free ( NULL , tmp ) ;
1999-07-07 22:52:57 +00:00
break ;
Changed the display filter scanner from GLIB's GScanner to lex. The code
as it standed depends on your lex being flex, but that only matters if you're
a developer. The distribution will include the dfilter-scanner.c file, so
that if the user doesn't modify dfilter-scanner.l, he won't need flex to
re-create the *.c file.
The new lex scanner gives me better syntax checking for ether addresses. I
thought I could get by using GScanner, but it simply wasn't powerful enough.
All operands have English-like abbreviations and C-like syntax:
and, && ; or, || ; eq, == ; ne, != ; , etc.
I removed the ETHER_VENDOR type in favor of letting the user use the [x:y]
notation: ether.src[0:3] == 0:6:29 instead of ether.srcvendor == 00:06:29
I implemented the IPXNET field type; it had been there before, but was
not implemented. I chose to make it use integer values rather than byte
ranges, since an IPX Network is 4 bytes. So a display filter looks like this:
ipx.srcnet == 0xc0a82c00
rather than this:
ipx.srcnet == c0:a8:2c:00
I can supposrt the byte-range type IPXNET in the future, very trivially.
I still have more work to do on the parser though. It needs to check ranges
when extracting byte ranges ([x:y]) from packets. And I need to get rid
of those reduce/reduce errors from yacc!
svn path=/trunk/; revision=414
1999-08-01 04:28:20 +00:00
case FT_IPXNET :
2007-01-18 11:02:26 +00:00
integer = fvalue_get_uinteger ( & fi - > value ) ;
2015-11-30 07:14:44 +00:00
tmp = get_ipxnet_name ( NULL , integer ) ;
2009-03-22 15:31:44 +00:00
g_snprintf ( label_str , ITEM_LABEL_LENGTH ,
2010-04-26 20:48:13 +00:00
" %s: %s (0x%08X) " , hfinfo - > name ,
2015-01-08 17:13:18 +00:00
tmp , integer ) ;
wmem_free ( NULL , tmp ) ;
Changed the display filter scanner from GLIB's GScanner to lex. The code
as it standed depends on your lex being flex, but that only matters if you're
a developer. The distribution will include the dfilter-scanner.c file, so
that if the user doesn't modify dfilter-scanner.l, he won't need flex to
re-create the *.c file.
The new lex scanner gives me better syntax checking for ether addresses. I
thought I could get by using GScanner, but it simply wasn't powerful enough.
All operands have English-like abbreviations and C-like syntax:
and, && ; or, || ; eq, == ; ne, != ; , etc.
I removed the ETHER_VENDOR type in favor of letting the user use the [x:y]
notation: ether.src[0:3] == 0:6:29 instead of ether.srcvendor == 00:06:29
I implemented the IPXNET field type; it had been there before, but was
not implemented. I chose to make it use integer values rather than byte
ranges, since an IPX Network is 4 bytes. So a display filter looks like this:
ipx.srcnet == 0xc0a82c00
rather than this:
ipx.srcnet == c0:a8:2c:00
I can supposrt the byte-range type IPXNET in the future, very trivially.
I still have more work to do on the parser though. It needs to check ranges
when extracting byte ranges ([x:y]) from packets. And I need to get rid
of those reduce/reduce errors from yacc!
svn path=/trunk/; revision=414
1999-08-01 04:28:20 +00:00
break ;
2012-08-02 16:54:43 +00:00
case FT_AX25 :
2014-12-19 23:13:17 +00:00
addr . type = AT_AX25 ;
addr . len = AX25_ADDR_LEN ;
addr . data = ( guint8 * ) fvalue_get ( & fi - > value ) ;
2015-01-05 16:12:08 +00:00
addr_str = ( char * ) address_to_str ( NULL , & addr ) ;
2014-12-19 23:13:17 +00:00
g_snprintf ( label_str , ITEM_LABEL_LENGTH ,
2015-01-05 16:12:08 +00:00
" %s: %s " , hfinfo - > name , addr_str ) ;
wmem_free ( NULL , addr_str ) ;
2012-08-02 16:54:43 +00:00
break ;
2013-07-28 00:07:49 +00:00
case FT_VINES :
addr . type = AT_VINES ;
addr . len = VINES_ADDR_LEN ;
addr . data = ( guint8 * ) fvalue_get ( & fi - > value ) ;
2015-01-05 16:12:08 +00:00
addr_str = ( char * ) address_to_str ( NULL , & addr ) ;
2013-07-28 00:07:49 +00:00
g_snprintf ( label_str , ITEM_LABEL_LENGTH ,
2015-01-05 16:12:08 +00:00
" %s: %s " , hfinfo - > name , addr_str ) ;
wmem_free ( NULL , addr_str ) ;
2013-07-28 00:07:49 +00:00
break ;
1999-07-07 22:52:57 +00:00
case FT_ETHER :
2013-03-02 12:10:56 +00:00
bytes = ( guint8 * ) fvalue_get ( & fi - > value ) ;
2014-12-20 02:42:14 +00:00
addr . type = AT_ETHER ;
addr . len = 6 ;
addr . data = bytes ;
2015-02-12 17:03:49 +00:00
addr_str = ( char * ) address_with_resolution_to_str ( NULL , & addr ) ;
g_snprintf ( label_str , ITEM_LABEL_LENGTH ,
" %s: %s " , hfinfo - > name , addr_str ) ;
2015-01-05 16:12:08 +00:00
wmem_free ( NULL , addr_str ) ;
1999-07-07 22:52:57 +00:00
break ;
case FT_IPv4 :
2016-01-03 23:05:13 +00:00
ipv4 = ( ipv4_addr_and_mask * ) fvalue_get ( & fi - > value ) ;
2001-02-01 20:21:25 +00:00
n_addr = ipv4_get_net_order_addr ( ipv4 ) ;
2014-12-21 13:02:26 +00:00
addr . type = AT_IPv4 ;
addr . len = 4 ;
addr . data = & n_addr ;
2015-09-07 01:56:30 +00:00
if ( hfinfo - > display = = BASE_NETMASK )
{
addr_str = ( char * ) address_to_str ( NULL , & addr ) ;
}
else
{
addr_str = ( char * ) address_with_resolution_to_str ( NULL , & addr ) ;
}
2015-02-12 17:03:49 +00:00
g_snprintf ( label_str , ITEM_LABEL_LENGTH ,
" %s: %s " , hfinfo - > name , addr_str ) ;
2015-01-05 16:12:08 +00:00
wmem_free ( NULL , addr_str ) ;
1999-07-07 22:52:57 +00:00
break ;
1999-10-11 17:05:49 +00:00
case FT_IPv6 :
2013-03-02 12:10:56 +00:00
bytes = ( guint8 * ) fvalue_get ( & fi - > value ) ;
2014-12-21 17:38:13 +00:00
addr . type = AT_IPv6 ;
addr . len = 16 ;
addr . data = bytes ;
2015-02-12 17:03:49 +00:00
addr_str = ( char * ) address_with_resolution_to_str ( NULL , & addr ) ;
g_snprintf ( label_str , ITEM_LABEL_LENGTH ,
" %s: %s " , hfinfo - > name , addr_str ) ;
2015-01-05 16:12:08 +00:00
wmem_free ( NULL , addr_str ) ;
1999-10-11 17:05:49 +00:00
break ;
2002-08-28 20:41:00 +00:00
2014-12-24 05:06:35 +00:00
case FT_FCWWN :
addr . type = AT_FCWWN ;
addr . len = FCWWN_ADDR_LEN ;
addr . data = ( guint8 * ) fvalue_get ( & fi - > value ) ;
2015-02-12 17:03:49 +00:00
addr_str = ( char * ) address_with_resolution_to_str ( NULL , & addr ) ;
2014-12-24 05:06:35 +00:00
g_snprintf ( label_str , ITEM_LABEL_LENGTH ,
2015-01-05 16:12:08 +00:00
" %s: %s " , hfinfo - > name , addr_str ) ;
wmem_free ( NULL , addr_str ) ;
2014-12-24 05:06:35 +00:00
break ;
2005-07-04 13:04:53 +00:00
case FT_GUID :
2013-03-02 12:10:56 +00:00
guid = ( e_guid_t * ) fvalue_get ( & fi - > value ) ;
2015-01-08 00:24:52 +00:00
tmp = guid_to_str ( NULL , guid ) ;
label_fill ( label_str , 0 , hfinfo , tmp ) ;
wmem_free ( NULL , tmp ) ;
2005-07-04 13:04:53 +00:00
break ;
2005-12-02 13:16:58 +00:00
case FT_OID :
2013-03-02 12:10:56 +00:00
bytes = ( guint8 * ) fvalue_get ( & fi - > value ) ;
2015-01-17 19:11:29 +00:00
name = oid_resolved_from_encoded ( NULL , bytes , fvalue_length ( & fi - > value ) ) ;
tmp = oid_encoded2string ( NULL , bytes , fvalue_length ( & fi - > value ) ) ;
2005-12-06 11:45:55 +00:00
if ( name ) {
2015-01-17 19:11:29 +00:00
label_fill_descr ( label_str , 0 , hfinfo , tmp , name ) ;
wmem_free ( NULL , name ) ;
2005-12-06 11:45:55 +00:00
} else {
2015-01-17 19:11:29 +00:00
label_fill ( label_str , 0 , hfinfo , tmp ) ;
2005-12-06 11:45:55 +00:00
}
2015-01-17 19:11:29 +00:00
wmem_free ( NULL , tmp ) ;
2005-12-02 13:16:58 +00:00
break ;
2013-10-06 02:31:10 +00:00
case FT_REL_OID :
bytes = ( guint8 * ) fvalue_get ( & fi - > value ) ;
2015-01-17 19:11:29 +00:00
name = rel_oid_resolved_from_encoded ( NULL , bytes , fvalue_length ( & fi - > value ) ) ;
tmp = rel_oid_encoded2string ( NULL , bytes , fvalue_length ( & fi - > value ) ) ;
2013-10-06 02:31:10 +00:00
if ( name ) {
2015-01-17 19:11:29 +00:00
label_fill_descr ( label_str , 0 , hfinfo , tmp , name ) ;
wmem_free ( NULL , name ) ;
2013-10-06 02:31:10 +00:00
} else {
2015-01-17 19:11:29 +00:00
label_fill ( label_str , 0 , hfinfo , tmp ) ;
2013-10-06 02:31:10 +00:00
}
2015-01-17 19:11:29 +00:00
wmem_free ( NULL , tmp ) ;
2013-10-06 02:31:10 +00:00
break ;
2013-12-23 15:18:48 +00:00
case FT_SYSTEM_ID :
bytes = ( guint8 * ) fvalue_get ( & fi - > value ) ;
2015-01-17 21:55:46 +00:00
tmp = print_system_id ( NULL , bytes , fvalue_length ( & fi - > value ) ) ;
label_fill ( label_str , 0 , hfinfo , tmp ) ;
wmem_free ( NULL , tmp ) ;
2013-12-23 15:18:48 +00:00
break ;
2011-05-08 10:23:53 +00:00
case FT_EUI64 :
2014-12-17 20:19:20 +00:00
integer64 = fvalue_get_uinteger64 ( & fi - > value ) ;
2015-01-08 18:16:01 +00:00
addr_str = eui64_to_str ( NULL , integer64 ) ;
2015-01-17 19:11:29 +00:00
tmp = ( char * ) eui64_to_display ( NULL , integer64 ) ;
2015-01-08 18:16:01 +00:00
label_fill_descr ( label_str , 0 , hfinfo , tmp , addr_str ) ;
wmem_free ( NULL , tmp ) ;
wmem_free ( NULL , addr_str ) ;
2011-05-08 10:23:53 +00:00
break ;
1999-07-07 22:52:57 +00:00
case FT_STRING :
2000-08-30 02:50:18 +00:00
case FT_STRINGZ :
2000-08-22 06:38:32 +00:00
case FT_UINT_STRING :
2014-04-12 22:26:34 +00:00
case FT_STRINGZPAD :
2013-03-02 12:10:56 +00:00
bytes = ( guint8 * ) fvalue_get ( & fi - > value ) ;
2013-12-07 11:50:43 +00:00
label_fill ( label_str , 0 , hfinfo , hfinfo_format_text ( hfinfo , bytes ) ) ;
1999-07-07 22:52:57 +00:00
break ;
2015-09-06 17:01:47 +00:00
case FT_IEEE_11073_SFLOAT :
{
guint8 buf [ 240 ] ;
fvalue_to_string_repr ( & fi - > value , FTREPR_DISPLAY , hfinfo - > display , buf ) ;
g_snprintf ( label_str , ITEM_LABEL_LENGTH ,
" %s: %s " ,
hfinfo - > name , buf ) ;
}
break ;
case FT_IEEE_11073_FLOAT :
{
guint8 buf [ 240 ] ;
fvalue_to_string_repr ( & fi - > value , FTREPR_DISPLAY , hfinfo - > display , buf ) ;
g_snprintf ( label_str , ITEM_LABEL_LENGTH ,
" %s: %s " ,
hfinfo - > name , buf ) ;
}
break ;
1999-07-07 22:52:57 +00:00
default :
2001-05-09 01:22:46 +00:00
g_error ( " hfinfo->type %d (%s) not handled \n " ,
2010-04-26 20:48:13 +00:00
hfinfo - > type , ftype_name ( hfinfo - > type ) ) ;
2005-03-23 00:09:12 +00:00
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
2001-05-09 01:22:46 +00:00
break ;
1999-07-07 22:52:57 +00:00
}
}
1999-10-12 06:21:15 +00:00
static void
fill_label_boolean ( field_info * fi , gchar * label_str )
{
2012-03-14 17:11:39 +00:00
char * p = label_str ;
int bitfield_byte_length = 0 , bitwidth ;
2014-09-17 16:39:22 +00:00
guint64 unshifted_value ;
guint64 value ;
1999-10-12 06:21:15 +00:00
2012-03-14 17:11:39 +00:00
header_field_info * hfinfo = fi - > hfinfo ;
const true_false_string * tfstring = ( const true_false_string * ) & tfs_true_false ;
1999-10-12 06:21:15 +00:00
if ( hfinfo - > strings ) {
2002-11-28 01:46:14 +00:00
tfstring = ( const struct true_false_string * ) hfinfo - > strings ;
1999-10-12 06:21:15 +00:00
}
2014-12-17 20:19:20 +00:00
value = fvalue_get_uinteger64 ( & fi - > value ) ;
1999-10-12 06:21:15 +00:00
if ( hfinfo - > bitmask ) {
/* Figure out the bit width */
2016-01-12 11:20:46 +00:00
bitwidth = hfinfo_container_bitwidth ( hfinfo ) ;
1999-10-12 06:21:15 +00:00
/* Un-shift bits */
2001-02-01 20:21:25 +00:00
unshifted_value = value ;
2013-08-06 20:10:59 +00:00
unshifted_value < < = hfinfo_bitshift ( hfinfo ) ;
1999-10-12 06:21:15 +00:00
/* Create the bitfield first */
p = decode_bitfield_value ( label_str , unshifted_value , hfinfo - > bitmask , bitwidth ) ;
2009-04-08 16:50:20 +00:00
bitfield_byte_length = ( int ) ( p - label_str ) ;
1999-10-12 06:21:15 +00:00
}
/* Fill in the textual info */
2013-07-16 22:21:10 +00:00
label_fill ( label_str , bitfield_byte_length , hfinfo , value ? tfstring - > true_string : tfstring - > false_string ) ;
1999-10-12 06:21:15 +00:00
}
2013-06-27 17:26:23 +00:00
static const char *
hf_try_val_to_str ( guint32 value , const header_field_info * hfinfo )
{
if ( hfinfo - > display & BASE_RANGE_STRING )
return try_rval_to_str ( value , ( const range_string * ) hfinfo - > strings ) ;
if ( hfinfo - > display & BASE_EXT_STRING )
2014-07-25 16:29:04 +00:00
return try_val_to_str_ext ( value , ( value_string_ext * ) hfinfo - > strings ) ;
2013-06-27 17:26:23 +00:00
2013-07-26 21:51:39 +00:00
if ( hfinfo - > display & BASE_VAL64_STRING )
return try_val64_to_str ( value , ( const val64_string * ) hfinfo - > strings ) ;
2013-06-27 17:26:23 +00:00
return try_val_to_str ( value , ( const value_string * ) hfinfo - > strings ) ;
}
2013-07-26 21:51:39 +00:00
static const char *
hf_try_val64_to_str ( guint64 value , const header_field_info * hfinfo )
{
if ( hfinfo - > display & BASE_VAL64_STRING )
return try_val64_to_str ( value , ( const val64_string * ) hfinfo - > strings ) ;
/* If this is reached somebody registered a 64-bit field with a 32-bit
* value - string , which isn ' t right . */
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
2013-07-26 22:52:34 +00:00
/* This is necessary to squelch MSVC errors; is there
any way to tell it that DISSECTOR_ASSERT_NOT_REACHED ( )
never returns ? */
return NULL ;
2013-07-26 21:51:39 +00:00
}
2013-06-27 17:26:23 +00:00
static const char *
hf_try_val_to_str_const ( guint32 value , const header_field_info * hfinfo , const char * unknown_str )
{
const char * str = hf_try_val_to_str ( value , hfinfo ) ;
return ( str ) ? str : unknown_str ;
}
2013-07-26 21:51:39 +00:00
static const char *
hf_try_val64_to_str_const ( guint64 value , const header_field_info * hfinfo , const char * unknown_str )
{
const char * str = hf_try_val64_to_str ( value , hfinfo ) ;
return ( str ) ? str : unknown_str ;
}
1999-10-12 06:21:15 +00:00
/* Fills data for bitfield ints with val_strings */
static void
2013-08-26 16:23:55 +00:00
fill_label_bitfield ( field_info * fi , gchar * label_str , gboolean is_signed )
1999-10-12 06:21:15 +00:00
{
2012-03-14 17:11:39 +00:00
char * p ;
int bitfield_byte_length , bitwidth ;
guint32 unshifted_value ;
guint32 value ;
2013-06-28 19:34:48 +00:00
2013-06-27 19:17:22 +00:00
char buf [ 32 ] ;
2013-06-28 19:34:48 +00:00
const char * out ;
1999-10-12 06:21:15 +00:00
2012-03-14 17:11:39 +00:00
header_field_info * hfinfo = fi - > hfinfo ;
1999-10-12 06:21:15 +00:00
/* Figure out the bit width */
2016-01-12 11:20:46 +00:00
bitwidth = hfinfo_container_bitwidth ( hfinfo ) ;
1999-10-12 06:21:15 +00:00
/* Un-shift bits */
2013-08-26 16:23:55 +00:00
if ( is_signed )
2016-01-12 11:20:46 +00:00
value = fvalue_get_sinteger ( & fi - > value ) ;
2013-08-26 16:23:55 +00:00
else
2016-01-12 11:20:46 +00:00
value = fvalue_get_uinteger ( & fi - > value ) ;
2013-08-26 16:23:55 +00:00
2016-01-12 11:20:46 +00:00
unshifted_value = value ;
2013-08-06 20:10:59 +00:00
if ( hfinfo - > bitmask ) {
unshifted_value < < = hfinfo_bitshift ( hfinfo ) ;
1999-10-12 06:21:15 +00:00
}
/* Create the bitfield first */
p = decode_bitfield_value ( label_str , unshifted_value , hfinfo - > bitmask , bitwidth ) ;
2009-04-08 16:50:20 +00:00
bitfield_byte_length = ( int ) ( p - label_str ) ;
1999-10-12 06:21:15 +00:00
/* Fill in the textual info using stored (shifted) value */
2008-07-30 12:30:02 +00:00
if ( hfinfo - > display = = BASE_CUSTOM ) {
gchar tmp [ ITEM_LABEL_LENGTH ] ;
2013-03-24 10:53:31 +00:00
const custom_fmt_func_t fmtfunc = ( const custom_fmt_func_t ) hfinfo - > strings ;
1999-10-12 06:21:15 +00:00
2008-07-30 12:30:02 +00:00
DISSECTOR_ASSERT ( fmtfunc ) ;
fmtfunc ( tmp , value ) ;
2013-07-16 22:21:10 +00:00
label_fill ( label_str , bitfield_byte_length , hfinfo , tmp ) ;
2008-07-30 12:30:02 +00:00
}
else if ( hfinfo - > strings ) {
2013-06-27 19:17:22 +00:00
const char * val_str = hf_try_val_to_str_const ( value , hfinfo , " Unknown " ) ;
2013-06-28 19:54:04 +00:00
out = hfinfo_number_vals_format ( hfinfo , buf , value ) ;
2013-06-28 19:34:48 +00:00
if ( out = = NULL ) /* BASE_NONE so don't put integer in descr */
2013-07-16 22:21:10 +00:00
label_fill ( label_str , bitfield_byte_length , hfinfo , val_str ) ;
2013-06-27 19:17:22 +00:00
else
2013-07-16 22:21:10 +00:00
label_fill_descr ( label_str , bitfield_byte_length , hfinfo , val_str , out ) ;
2005-09-05 10:56:41 +00:00
}
2008-07-30 12:30:02 +00:00
else {
2013-06-28 21:46:41 +00:00
out = hfinfo_number_value_format ( hfinfo , buf , value ) ;
2013-06-27 18:40:08 +00:00
2013-07-16 22:21:10 +00:00
label_fill ( label_str , bitfield_byte_length , hfinfo , out ) ;
2007-02-14 00:39:48 +00:00
}
1999-10-12 06:21:15 +00:00
}
2014-12-17 20:19:20 +00:00
static void
fill_label_bitfield64 ( field_info * fi , gchar * label_str , gboolean is_signed )
{
char * p ;
int bitfield_byte_length , bitwidth ;
guint64 unshifted_value ;
guint64 value ;
2015-02-23 15:50:18 +00:00
char buf [ 48 ] ;
2014-12-17 20:19:20 +00:00
const char * out ;
header_field_info * hfinfo = fi - > hfinfo ;
/* Figure out the bit width */
2016-01-12 11:20:46 +00:00
bitwidth = hfinfo_container_bitwidth ( hfinfo ) ;
2014-12-17 20:19:20 +00:00
/* Un-shift bits */
if ( is_signed )
2016-01-12 11:20:46 +00:00
value = fvalue_get_sinteger64 ( & fi - > value ) ;
2014-12-17 20:19:20 +00:00
else
2016-01-12 11:20:46 +00:00
value = fvalue_get_uinteger64 ( & fi - > value ) ;
2014-12-17 20:19:20 +00:00
2016-01-12 11:20:46 +00:00
unshifted_value = value ;
2014-12-17 20:19:20 +00:00
if ( hfinfo - > bitmask ) {
2016-01-12 11:20:46 +00:00
unshifted_value < < = hfinfo_bitshift ( hfinfo ) ;
2014-12-17 20:19:20 +00:00
}
/* Create the bitfield first */
p = decode_bitfield_value ( label_str , unshifted_value , hfinfo - > bitmask , bitwidth ) ;
bitfield_byte_length = ( int ) ( p - label_str ) ;
/* Fill in the textual info using stored (shifted) value */
if ( hfinfo - > display = = BASE_CUSTOM ) {
gchar tmp [ ITEM_LABEL_LENGTH ] ;
const custom_fmt_func_64_t fmtfunc64 = ( const custom_fmt_func_64_t ) hfinfo - > strings ;
DISSECTOR_ASSERT ( fmtfunc64 ) ;
fmtfunc64 ( tmp , value ) ;
label_fill ( label_str , bitfield_byte_length , hfinfo , tmp ) ;
}
else if ( hfinfo - > strings ) {
const char * val_str = hf_try_val64_to_str_const ( value , hfinfo , " Unknown " ) ;
out = hfinfo_number_vals_format64 ( hfinfo , buf , value ) ;
if ( out = = NULL ) /* BASE_NONE so don't put integer in descr */
label_fill ( label_str , bitfield_byte_length , hfinfo , val_str ) ;
else
label_fill_descr ( label_str , bitfield_byte_length , hfinfo , val_str , out ) ;
}
else {
out = hfinfo_number_value_format64 ( hfinfo , buf , value ) ;
label_fill ( label_str , bitfield_byte_length , hfinfo , out ) ;
}
}
1999-10-13 03:07:30 +00:00
static void
2013-06-28 22:47:50 +00:00
fill_label_number ( field_info * fi , gchar * label_str , gboolean is_signed )
1999-10-13 03:07:30 +00:00
{
2012-03-14 17:11:39 +00:00
header_field_info * hfinfo = fi - > hfinfo ;
guint32 value ;
2013-06-28 19:34:48 +00:00
2013-06-27 19:17:22 +00:00
char buf [ 32 ] ;
2013-06-28 19:34:48 +00:00
const char * out ;
1999-10-13 03:07:30 +00:00
2013-06-28 22:47:50 +00:00
if ( is_signed )
value = fvalue_get_sinteger ( & fi - > value ) ;
else
value = fvalue_get_uinteger ( & fi - > value ) ;
1999-10-13 03:07:30 +00:00
/* Fill in the textual info */
2008-07-30 12:30:02 +00:00
if ( hfinfo - > display = = BASE_CUSTOM ) {
gchar tmp [ ITEM_LABEL_LENGTH ] ;
2013-03-24 10:53:31 +00:00
const custom_fmt_func_t fmtfunc = ( const custom_fmt_func_t ) hfinfo - > strings ;
2008-07-30 12:30:02 +00:00
DISSECTOR_ASSERT ( fmtfunc ) ;
fmtfunc ( tmp , value ) ;
2013-07-16 22:21:10 +00:00
label_fill ( label_str , 0 , hfinfo , tmp ) ;
2008-07-30 12:30:02 +00:00
}
2015-10-05 10:53:07 +00:00
else if ( hfinfo - > strings & & hfinfo - > type ! = FT_FRAMENUM ) { /* Add fill_label_framenum? */
2013-06-27 19:17:22 +00:00
const char * val_str = hf_try_val_to_str_const ( value , hfinfo , " Unknown " ) ;
2013-06-28 19:54:04 +00:00
out = hfinfo_number_vals_format ( hfinfo , buf , value ) ;
2013-06-28 19:34:48 +00:00
if ( out = = NULL ) /* BASE_NONE so don't put integer in descr */
2013-07-16 22:21:10 +00:00
label_fill ( label_str , 0 , hfinfo , val_str ) ;
2013-06-27 19:17:22 +00:00
else
2013-07-16 22:21:10 +00:00
label_fill_descr ( label_str , 0 , hfinfo , val_str , out ) ;
2008-07-30 12:30:02 +00:00
}
2015-10-05 10:53:07 +00:00
else if ( IS_BASE_PORT ( hfinfo - > display ) ) {
gchar tmp [ ITEM_LABEL_LENGTH ] ;
port_with_resolution_to_str_buf ( tmp , sizeof ( tmp ) ,
display_to_port_type ( ( field_display_e ) hfinfo - > display ) , value ) ;
label_fill ( label_str , 0 , hfinfo , tmp ) ;
}
2008-07-30 12:30:02 +00:00
else {
2013-06-28 21:46:41 +00:00
out = hfinfo_number_value_format ( hfinfo , buf , value ) ;
2013-06-27 18:40:08 +00:00
2013-07-16 22:21:10 +00:00
label_fill ( label_str , 0 , hfinfo , out ) ;
2005-09-05 10:56:41 +00:00
}
1999-10-13 03:07:30 +00:00
}
2004-08-22 00:31:58 +00:00
static void
2013-07-01 15:24:42 +00:00
fill_label_number64 ( field_info * fi , gchar * label_str , gboolean is_signed )
2004-08-22 00:31:58 +00:00
{
2012-03-14 17:11:39 +00:00
header_field_info * hfinfo = fi - > hfinfo ;
guint64 value ;
2004-08-22 00:31:58 +00:00
2015-02-23 15:50:18 +00:00
char buf [ 48 ] ;
2015-02-22 08:56:00 +00:00
const char * out ;
if ( is_signed )
2015-02-22 03:45:08 +00:00
value = fvalue_get_sinteger64 ( & fi - > value ) ;
2015-02-22 08:56:00 +00:00
else
2015-02-22 03:45:08 +00:00
value = fvalue_get_uinteger64 ( & fi - > value ) ;
2004-08-22 00:31:58 +00:00
2015-02-22 08:56:00 +00:00
/* Fill in the textual info */
if ( hfinfo - > display = = BASE_CUSTOM ) {
gchar tmp [ ITEM_LABEL_LENGTH ] ;
const custom_fmt_func_64_t fmtfunc64 = ( const custom_fmt_func_64_t ) hfinfo - > strings ;
2013-07-28 20:05:04 +00:00
2015-02-22 08:56:00 +00:00
DISSECTOR_ASSERT ( fmtfunc64 ) ;
fmtfunc64 ( tmp , value ) ;
label_fill ( label_str , 0 , hfinfo , tmp ) ;
}
else if ( hfinfo - > strings ) {
2013-07-26 21:51:39 +00:00
const char * val_str = hf_try_val64_to_str_const ( value , hfinfo , " Unknown " ) ;
2015-02-22 08:56:00 +00:00
out = hfinfo_number_vals_format64 ( hfinfo , buf , value ) ;
if ( out = = NULL ) /* BASE_NONE so don't put integer in descr */
2013-07-26 21:51:39 +00:00
label_fill ( label_str , 0 , hfinfo , val_str ) ;
2015-02-22 08:56:00 +00:00
else
label_fill_descr ( label_str , 0 , hfinfo , val_str , out ) ;
2013-07-26 21:51:39 +00:00
}
else {
2015-02-22 08:56:00 +00:00
out = hfinfo_number_value_format64 ( hfinfo , buf , value ) ;
label_fill ( label_str , 0 , hfinfo , out ) ;
2005-09-05 10:56:41 +00:00
}
2004-08-22 00:31:58 +00:00
}
2013-08-06 20:10:59 +00:00
int
hfinfo_bitshift ( const header_field_info * hfinfo )
{
2013-11-08 22:01:12 +00:00
return ws_ctz ( hfinfo - > bitmask ) ;
2013-08-06 20:10:59 +00:00
}
2016-01-12 11:20:46 +00:00
static int
hfinfo_mask_bitwidth ( const header_field_info * hfinfo )
1999-10-12 06:21:15 +00:00
{
2016-02-01 20:50:07 +00:00
if ( ! hfinfo - > bitmask ) {
return 0 ;
}
1999-10-12 06:21:15 +00:00
2016-02-01 20:50:07 +00:00
/* ilog2 = first set bit, ctz = last set bit */
return ws_ilog2 ( hfinfo - > bitmask ) - ws_ctz ( hfinfo - > bitmask ) + 1 ;
2016-01-12 11:20:46 +00:00
}
1999-10-12 06:21:15 +00:00
2016-01-12 11:20:46 +00:00
static int
hfinfo_type_bitwidth ( enum ftenum type )
{
int bitwidth = 0 ;
switch ( type ) {
1999-10-12 06:21:15 +00:00
case FT_UINT8 :
case FT_INT8 :
bitwidth = 8 ;
break ;
case FT_UINT16 :
case FT_INT16 :
bitwidth = 16 ;
break ;
case FT_UINT24 :
case FT_INT24 :
bitwidth = 24 ;
break ;
case FT_UINT32 :
case FT_INT32 :
bitwidth = 32 ;
break ;
2014-12-17 20:19:20 +00:00
case FT_UINT40 :
case FT_INT40 :
bitwidth = 40 ;
break ;
case FT_UINT48 :
case FT_INT48 :
bitwidth = 48 ;
break ;
case FT_UINT56 :
case FT_INT56 :
bitwidth = 56 ;
break ;
case FT_UINT64 :
case FT_INT64 :
bitwidth = 64 ;
break ;
1999-10-12 06:21:15 +00:00
default :
2005-03-23 00:09:12 +00:00
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
1999-10-12 06:21:15 +00:00
;
}
return bitwidth ;
}
2016-01-12 11:20:46 +00:00
2013-06-27 18:40:08 +00:00
static int
2016-01-12 11:20:46 +00:00
hfinfo_container_bitwidth ( const header_field_info * hfinfo )
1999-10-12 06:21:15 +00:00
{
2016-01-12 11:20:46 +00:00
if ( ! hfinfo - > bitmask ) {
return 0 ;
}
2014-12-17 20:19:20 +00:00
2016-01-12 11:20:46 +00:00
if ( hfinfo - > type = = FT_BOOLEAN ) {
return hfinfo - > display ; /* hacky? :) */
}
2014-12-17 20:19:20 +00:00
2016-01-12 11:20:46 +00:00
return hfinfo_type_bitwidth ( hfinfo - > type ) ;
}
2014-12-17 20:19:20 +00:00
2016-01-12 11:20:46 +00:00
static int
hfinfo_hex_digits ( const header_field_info * hfinfo )
{
int bitwidth ;
2014-12-17 20:19:20 +00:00
2016-01-12 11:20:46 +00:00
/* If we have a bitmask, hfinfo->type is the width of the container, so not
* appropriate to determine the number of hex digits for the field .
* So instead , we compute it from the bitmask .
*/
if ( hfinfo - > bitmask ! = 0 ) {
bitwidth = hfinfo_mask_bitwidth ( hfinfo ) ;
} else {
bitwidth = hfinfo_type_bitwidth ( hfinfo - > type ) ;
2013-06-28 19:34:48 +00:00
}
2016-01-12 11:20:46 +00:00
/* Divide by 4, rounding up, to get number of hex digits. */
return ( bitwidth + 3 ) / 4 ;
2013-06-28 19:34:48 +00:00
}
2013-06-27 18:40:08 +00:00
2013-06-28 19:34:48 +00:00
static const char *
2013-07-13 09:14:25 +00:00
hfinfo_number_value_format_display ( const header_field_info * hfinfo , int display , char buf [ 32 ] , guint32 value )
2013-06-28 19:34:48 +00:00
{
char * ptr = & buf [ 31 ] ;
2013-06-28 19:54:04 +00:00
gboolean isint = IS_FT_INT ( hfinfo - > type ) ;
2013-06-27 18:40:08 +00:00
2013-06-28 19:34:48 +00:00
* ptr = ' \0 ' ;
/* Properly format value */
2015-05-10 20:57:26 +00:00
switch ( display & FIELD_DISPLAY_E_MASK ) {
case BASE_DEC :
return isint ? int_to_str_back ( ptr , ( gint32 ) value ) : uint_to_str_back ( ptr , value ) ;
case BASE_DEC_HEX :
* ( - - ptr ) = ' ) ' ;
2016-01-12 11:20:46 +00:00
ptr = hex_to_str_back ( ptr , hfinfo_hex_digits ( hfinfo ) , value ) ;
2015-05-10 20:57:26 +00:00
* ( - - ptr ) = ' ( ' ;
* ( - - ptr ) = ' ' ;
ptr = isint ? int_to_str_back ( ptr , ( gint32 ) value ) : uint_to_str_back ( ptr , value ) ;
return ptr ;
case BASE_OCT :
return oct_to_str_back ( ptr , value ) ;
case BASE_HEX :
2016-01-12 11:20:46 +00:00
return hex_to_str_back ( ptr , hfinfo_hex_digits ( hfinfo ) , value ) ;
2015-05-10 20:57:26 +00:00
case BASE_HEX_DEC :
* ( - - ptr ) = ' ) ' ;
ptr = isint ? int_to_str_back ( ptr , ( gint32 ) value ) : uint_to_str_back ( ptr , value ) ;
* ( - - ptr ) = ' ( ' ;
* ( - - ptr ) = ' ' ;
2016-01-12 11:20:46 +00:00
ptr = hex_to_str_back ( ptr , hfinfo_hex_digits ( hfinfo ) , value ) ;
2015-05-10 20:57:26 +00:00
return ptr ;
2015-10-11 13:15:20 +00:00
case BASE_PT_UDP :
case BASE_PT_TCP :
case BASE_PT_DCCP :
case BASE_PT_SCTP :
port_with_resolution_to_str_buf ( buf , 32 ,
display_to_port_type ( ( field_display_e ) display ) , value ) ;
return buf ;
2015-05-10 20:57:26 +00:00
default :
g_assert_not_reached ( ) ;
}
2013-06-28 19:34:48 +00:00
return ptr ;
2008-02-22 13:27:46 +00:00
}
2014-12-17 20:19:20 +00:00
static const char *
2015-02-23 15:50:18 +00:00
hfinfo_number_value_format_display64 ( const header_field_info * hfinfo , int display , char buf [ 48 ] , guint64 value )
2014-12-17 20:19:20 +00:00
{
2015-02-23 15:50:18 +00:00
char * ptr = & buf [ 47 ] ;
2014-12-17 20:19:20 +00:00
gboolean isint = IS_FT_INT ( hfinfo - > type ) ;
* ptr = ' \0 ' ;
/* Properly format value */
switch ( display ) {
case BASE_DEC :
return isint ? int64_to_str_back ( ptr , ( gint64 ) value ) : uint64_to_str_back ( ptr , value ) ;
case BASE_DEC_HEX :
* ( - - ptr ) = ' ) ' ;
2016-01-12 11:20:46 +00:00
ptr = hex64_to_str_back ( ptr , hfinfo_hex_digits ( hfinfo ) , value ) ;
2014-12-17 20:19:20 +00:00
* ( - - ptr ) = ' ( ' ;
* ( - - ptr ) = ' ' ;
ptr = isint ? int64_to_str_back ( ptr , ( gint64 ) value ) : uint64_to_str_back ( ptr , value ) ;
return ptr ;
case BASE_OCT :
return oct64_to_str_back ( ptr , value ) ;
case BASE_HEX :
2016-01-12 11:20:46 +00:00
return hex64_to_str_back ( ptr , hfinfo_hex_digits ( hfinfo ) , value ) ;
2014-12-17 20:19:20 +00:00
case BASE_HEX_DEC :
* ( - - ptr ) = ' ) ' ;
ptr = isint ? int64_to_str_back ( ptr , ( gint64 ) value ) : uint64_to_str_back ( ptr , value ) ;
* ( - - ptr ) = ' ( ' ;
* ( - - ptr ) = ' ' ;
2016-01-12 11:20:46 +00:00
ptr = hex64_to_str_back ( ptr , hfinfo_hex_digits ( hfinfo ) , value ) ;
2014-12-17 20:19:20 +00:00
return ptr ;
default :
2015-02-22 08:56:00 +00:00
g_assert_not_reached ( ) ;
2014-12-17 20:19:20 +00:00
}
return ptr ;
}
2013-06-28 19:34:48 +00:00
static const char *
2013-06-28 21:46:41 +00:00
hfinfo_number_value_format ( const header_field_info * hfinfo , char buf [ 32 ] , guint32 value )
1999-10-13 03:07:30 +00:00
{
2013-07-01 09:46:50 +00:00
int display = hfinfo - > display ;
2013-06-27 19:17:22 +00:00
if ( hfinfo - > type = = FT_FRAMENUM ) {
2013-07-01 09:46:50 +00:00
/*
* Frame numbers are always displayed in decimal .
*/
display = BASE_DEC ;
}
2013-06-28 19:34:48 +00:00
2013-07-13 09:14:25 +00:00
return hfinfo_number_value_format_display ( hfinfo , display , buf , value ) ;
2013-07-01 09:46:50 +00:00
}
2014-12-17 20:19:20 +00:00
static const char *
2015-02-23 15:50:18 +00:00
hfinfo_number_value_format64 ( const header_field_info * hfinfo , char buf [ 64 ] , guint64 value )
2014-12-17 20:19:20 +00:00
{
int display = hfinfo - > display ;
if ( hfinfo - > type = = FT_FRAMENUM ) {
/*
* Frame numbers are always displayed in decimal .
*/
display = BASE_DEC ;
}
return hfinfo_number_value_format_display64 ( hfinfo , display , buf , value ) ;
}
2013-07-01 09:46:50 +00:00
static const char *
hfinfo_numeric_value_format ( const header_field_info * hfinfo , char buf [ 32 ] , guint32 value )
{
/* Get the underlying BASE_ value */
2013-12-07 10:41:42 +00:00
int display = hfinfo - > display & FIELD_DISPLAY_E_MASK ;
2013-07-01 09:46:50 +00:00
if ( hfinfo - > type = = FT_FRAMENUM ) {
2013-06-27 19:17:22 +00:00
/*
* Frame numbers are always displayed in decimal .
*/
2013-07-01 09:46:50 +00:00
display = BASE_DEC ;
}
2016-01-18 17:06:39 +00:00
if ( IS_BASE_PORT ( display ) ) {
display = BASE_DEC ;
}
2013-07-01 09:46:50 +00:00
switch ( display ) {
case BASE_NONE :
/* case BASE_DEC: */
case BASE_DEC_HEX :
case BASE_OCT : /* XXX, why we're changing BASE_OCT to BASE_DEC? */
case BASE_CUSTOM :
display = BASE_DEC ;
break ;
/* case BASE_HEX: */
case BASE_HEX_DEC :
display = BASE_HEX ;
break ;
2013-06-27 19:17:22 +00:00
}
1999-10-13 03:07:30 +00:00
2013-07-13 09:14:25 +00:00
return hfinfo_number_value_format_display ( hfinfo , display , buf , value ) ;
2013-06-27 19:17:22 +00:00
}
2014-12-17 20:19:20 +00:00
static const char *
2015-02-23 15:50:18 +00:00
hfinfo_numeric_value_format64 ( const header_field_info * hfinfo , char buf [ 64 ] , guint64 value )
2014-12-17 20:19:20 +00:00
{
/* Get the underlying BASE_ value */
int display = hfinfo - > display & FIELD_DISPLAY_E_MASK ;
if ( hfinfo - > type = = FT_FRAMENUM ) {
/*
* Frame numbers are always displayed in decimal .
*/
display = BASE_DEC ;
}
switch ( display ) {
case BASE_NONE :
/* case BASE_DEC: */
case BASE_DEC_HEX :
case BASE_OCT : /* XXX, why we're changing BASE_OCT to BASE_DEC? */
case BASE_CUSTOM :
display = BASE_DEC ;
break ;
/* case BASE_HEX: */
case BASE_HEX_DEC :
display = BASE_HEX ;
break ;
}
return hfinfo_number_value_format_display64 ( hfinfo , display , buf , value ) ;
}
2013-06-28 19:34:48 +00:00
static const char *
2013-06-28 19:54:04 +00:00
hfinfo_number_vals_format ( const header_field_info * hfinfo , char buf [ 32 ] , guint32 value )
2013-06-27 19:17:22 +00:00
{
2009-12-12 03:15:28 +00:00
/* Get the underlying BASE_ value */
2013-12-07 10:41:42 +00:00
int display = hfinfo - > display & FIELD_DISPLAY_E_MASK ;
2013-06-27 19:17:22 +00:00
if ( display = = BASE_NONE )
2013-06-28 19:34:48 +00:00
return NULL ;
2013-06-27 19:17:22 +00:00
if ( display = = BASE_DEC_HEX )
display = BASE_DEC ;
if ( display = = BASE_HEX_DEC )
display = BASE_HEX ;
2013-07-13 09:14:25 +00:00
return hfinfo_number_value_format_display ( hfinfo , display , buf , value ) ;
1999-10-13 03:07:30 +00:00
}
2014-12-17 20:19:20 +00:00
static const char *
2015-02-23 15:50:18 +00:00
hfinfo_number_vals_format64 ( const header_field_info * hfinfo , char buf [ 64 ] , guint64 value )
2014-12-17 20:19:20 +00:00
{
/* Get the underlying BASE_ value */
int display = hfinfo - > display & FIELD_DISPLAY_E_MASK ;
if ( display = = BASE_NONE )
return NULL ;
if ( display = = BASE_DEC_HEX )
display = BASE_DEC ;
if ( display = = BASE_HEX_DEC )
display = BASE_HEX ;
return hfinfo_number_value_format_display64 ( hfinfo , display , buf , value ) ;
}
2010-04-26 20:48:13 +00:00
const char *
2010-04-03 18:18:50 +00:00
proto_registrar_get_name ( const int n )
1999-11-11 16:20:25 +00:00
{
2001-05-09 01:22:46 +00:00
header_field_info * hfinfo ;
2003-11-22 04:41:31 +00:00
PROTO_REGISTRAR_GET_NTH ( n , hfinfo ) ;
return hfinfo - > name ;
1999-11-11 16:20:25 +00:00
}
2010-04-26 20:48:13 +00:00
const char *
2010-04-03 18:18:50 +00:00
proto_registrar_get_abbrev ( const int n )
1999-07-07 22:52:57 +00:00
{
2001-02-01 20:21:25 +00:00
header_field_info * hfinfo ;
1999-07-07 22:52:57 +00:00
2003-11-22 04:41:31 +00:00
PROTO_REGISTRAR_GET_NTH ( n , hfinfo ) ;
return hfinfo - > abbrev ;
1999-07-07 22:52:57 +00:00
}
2012-05-11 17:29:56 +00:00
enum ftenum
2010-04-03 18:18:50 +00:00
proto_registrar_get_ftype ( const int n )
1999-07-07 22:52:57 +00:00
{
2001-02-01 20:21:25 +00:00
header_field_info * hfinfo ;
1999-07-07 22:52:57 +00:00
2003-11-22 04:41:31 +00:00
PROTO_REGISTRAR_GET_NTH ( n , hfinfo ) ;
return hfinfo - > type ;
1999-07-07 22:52:57 +00:00
}
int
2010-04-03 18:18:50 +00:00
proto_registrar_get_parent ( const int n )
1999-07-07 22:52:57 +00:00
{
2001-02-01 20:21:25 +00:00
header_field_info * hfinfo ;
1999-07-07 22:52:57 +00:00
2003-11-22 04:41:31 +00:00
PROTO_REGISTRAR_GET_NTH ( n , hfinfo ) ;
return hfinfo - > parent ;
1999-07-07 22:52:57 +00:00
}
gboolean
2010-04-03 18:18:50 +00:00
proto_registrar_is_protocol ( const int n )
1999-07-07 22:52:57 +00:00
{
2001-02-01 20:21:25 +00:00
header_field_info * hfinfo ;
1999-07-07 22:52:57 +00:00
2003-11-22 04:41:31 +00:00
PROTO_REGISTRAR_GET_NTH ( n , hfinfo ) ;
2015-08-01 16:38:15 +00:00
return ( ( ( hfinfo - > id ! = hf_text_only ) & & ( hfinfo - > parent = = - 1 ) ) ? TRUE : FALSE ) ;
1999-07-07 22:52:57 +00:00
}
1999-11-15 06:32:38 +00:00
/* Returns length of field in packet (not necessarily the length
* in our internal representation , as in the case of IPv4 ) .
1999-10-12 04:21:13 +00:00
* 0 means undeterminable at time of registration
* - 1 means the field is not registered . */
gint
2010-04-03 18:18:50 +00:00
proto_registrar_get_length ( const int n )
1999-10-12 04:21:13 +00:00
{
2001-02-01 20:21:25 +00:00
header_field_info * hfinfo ;
1999-10-12 04:21:13 +00:00
2003-11-22 04:41:31 +00:00
PROTO_REGISTRAR_GET_NTH ( n , hfinfo ) ;
2001-02-01 20:21:25 +00:00
return ftype_length ( hfinfo - > type ) ;
1999-10-12 04:21:13 +00:00
}
1999-08-29 04:06:43 +00:00
/* Looks for a protocol or a field in a proto_tree. Returns TRUE if
* it exists anywhere , or FALSE if it exists nowhere . */
gboolean
2010-04-03 18:18:50 +00:00
proto_check_for_protocol_or_field ( const proto_tree * tree , const int id )
1999-07-07 22:52:57 +00:00
{
2002-04-20 08:07:56 +00:00
GPtrArray * ptrs = proto_get_finfo_ptr_array ( tree , id ) ;
1999-07-07 22:52:57 +00:00
2016-03-07 22:20:44 +00:00
if ( g_ptr_array_len ( ptrs ) > 0 ) {
2002-04-20 08:07:56 +00:00
return TRUE ;
}
else {
return FALSE ;
}
1999-07-07 22:52:57 +00:00
}
2001-12-18 19:09:08 +00:00
/* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
* This only works if the hfindex was " primed " before the dissection
* took place , as we just pass back the already - created GPtrArray * .
* The caller should * not * free the GPtrArray * ; proto_tree_free_node ( )
* handles that . */
2010-04-26 20:48:13 +00:00
GPtrArray *
2010-04-03 18:18:50 +00:00
proto_get_finfo_ptr_array ( const proto_tree * tree , const int id )
1999-07-07 22:52:57 +00:00
{
2009-10-12 08:16:50 +00:00
if ( ! tree )
return NULL ;
2009-07-18 20:10:14 +00:00
if ( PTREE_DATA ( tree ) - > interesting_hfids ! = NULL )
2013-03-02 12:10:56 +00:00
return ( GPtrArray * ) g_hash_table_lookup ( PTREE_DATA ( tree ) - > interesting_hfids ,
2010-04-26 20:48:13 +00:00
GINT_TO_POINTER ( id ) ) ;
2009-07-18 20:10:14 +00:00
else
return NULL ;
1999-07-07 22:52:57 +00:00
}
2001-03-02 23:10:12 +00:00
2009-07-18 20:10:14 +00:00
gboolean
2010-04-03 18:18:50 +00:00
proto_tracking_interesting_fields ( const proto_tree * tree )
2009-07-18 20:10:14 +00:00
{
2014-06-19 22:41:49 +00:00
GHashTable * interesting_hfids ;
2009-10-12 08:16:50 +00:00
if ( ! tree )
2009-10-12 08:19:30 +00:00
return FALSE ;
2009-10-12 08:16:50 +00:00
2014-06-19 22:41:49 +00:00
interesting_hfids = PTREE_DATA ( tree ) - > interesting_hfids ;
return ( interesting_hfids ! = NULL ) & & g_hash_table_size ( interesting_hfids ) ;
2009-07-18 20:10:14 +00:00
}
2001-03-02 23:10:12 +00:00
2009-09-23 16:27:37 +00:00
/* Helper struct for proto_find_info() and proto_all_finfos() */
2003-12-06 06:09:13 +00:00
typedef struct {
2012-03-14 17:11:39 +00:00
GPtrArray * array ;
int id ;
2003-12-06 06:09:13 +00:00
} ffdata_t ;
2006-03-27 19:28:02 +00:00
/* Helper function for proto_find_info() */
2003-12-06 06:09:13 +00:00
static gboolean
find_finfo ( proto_node * node , gpointer data )
{
2009-08-09 17:33:23 +00:00
field_info * fi = PNODE_FINFO ( node ) ;
2003-12-06 06:09:13 +00:00
if ( fi & & fi - > hfinfo ) {
if ( fi - > hfinfo - > id = = ( ( ffdata_t * ) data ) - > id ) {
g_ptr_array_add ( ( ( ffdata_t * ) data ) - > array , fi ) ;
}
}
2006-07-20 21:29:45 +00:00
2003-12-06 06:09:13 +00:00
/* Don't stop traversing. */
return FALSE ;
}
/* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
2006-03-27 19:28:02 +00:00
* This works on any proto_tree , primed or unprimed , but actually searches
* the tree , so it is slower than using proto_get_finfo_ptr_array on a primed tree .
* The caller does need to free the returned GPtrArray with
2009-09-01 17:09:36 +00:00
* g_ptr_array_free ( < array > , TRUE ) .
2006-03-27 19:28:02 +00:00
*/
2010-04-26 20:48:13 +00:00
GPtrArray *
2010-04-03 18:18:50 +00:00
proto_find_finfo ( proto_tree * tree , const int id )
2003-12-06 06:09:13 +00:00
{
2012-03-14 17:11:39 +00:00
ffdata_t ffdata ;
2006-07-20 21:29:45 +00:00
2003-12-06 06:09:13 +00:00
ffdata . array = g_ptr_array_new ( ) ;
ffdata . id = id ;
2006-07-20 21:29:45 +00:00
2003-12-06 06:09:13 +00:00
proto_tree_traverse_pre_order ( tree , find_finfo , & ffdata ) ;
2006-07-20 21:29:45 +00:00
2006-03-27 19:28:02 +00:00
return ffdata . array ;
2006-07-20 21:29:45 +00:00
}
2006-03-27 19:28:02 +00:00
/* Helper function for proto_all_finfos() */
static gboolean
every_finfo ( proto_node * node , gpointer data )
{
2009-08-09 17:33:23 +00:00
field_info * fi = PNODE_FINFO ( node ) ;
2006-03-27 19:28:02 +00:00
if ( fi & & fi - > hfinfo ) {
g_ptr_array_add ( ( ( ffdata_t * ) data ) - > array , fi ) ;
}
2006-07-20 21:29:45 +00:00
2006-03-27 19:28:02 +00:00
/* Don't stop traversing. */
return FALSE ;
}
2003-12-06 06:09:13 +00:00
2006-03-27 19:28:02 +00:00
/* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
2010-04-26 20:48:13 +00:00
GPtrArray *
2006-03-27 19:28:02 +00:00
proto_all_finfos ( proto_tree * tree )
{
2012-03-14 17:11:39 +00:00
ffdata_t ffdata ;
2006-07-20 21:29:45 +00:00
2006-03-27 19:28:02 +00:00
ffdata . array = g_ptr_array_new ( ) ;
ffdata . id = 0 ;
2006-07-20 21:29:45 +00:00
2006-03-27 19:28:02 +00:00
proto_tree_traverse_pre_order ( tree , every_finfo , & ffdata ) ;
2006-07-20 21:29:45 +00:00
2003-12-06 06:09:13 +00:00
return ffdata . array ;
2006-07-20 21:29:45 +00:00
}
2003-12-06 06:09:13 +00:00
2001-03-02 23:10:12 +00:00
typedef struct {
2012-03-14 17:11:39 +00:00
guint offset ;
field_info * finfo ;
tvbuff_t * tvb ;
2001-03-02 23:10:12 +00:00
} offset_search_t ;
static gboolean
2016-01-05 12:06:36 +00:00
check_for_offset ( proto_node * node , gpointer data )
2001-03-02 23:10:12 +00:00
{
2012-03-14 17:11:39 +00:00
field_info * fi = PNODE_FINFO ( node ) ;
2013-03-02 12:10:56 +00:00
offset_search_t * offsearch = ( offset_search_t * ) data ;
2001-03-02 23:10:12 +00:00
/* !fi == the top most container node which holds nothing */
2016-02-01 20:50:07 +00:00
if ( fi & & ! PROTO_ITEM_IS_HIDDEN ( node ) & & ! PROTO_ITEM_IS_GENERATED ( node ) & & fi - > ds_tvb & & offsearch - > tvb = = fi - > ds_tvb ) {
2001-10-26 17:29:12 +00:00
if ( offsearch - > offset > = ( guint ) fi - > start & &
offsearch - > offset < ( guint ) ( fi - > start + fi - > length ) ) {
2001-03-02 23:10:12 +00:00
offsearch - > finfo = fi ;
return FALSE ; /* keep traversing */
}
}
return FALSE ; /* keep traversing */
}
/* Search a proto_tree backwards (from leaves to root) looking for the field
* whose start / length occupies ' offset ' */
/* XXX - I couldn't find an easy way to search backwards, so I search
* forwards , w / o stopping . Therefore , the last finfo I find will the be
* the one I want to return to the user . This algorithm is inefficient
* and could be re - done , but I ' d have to handle all the children and
* siblings of each node myself . When I have more time I ' ll do that .
* ( yeah right ) */
2010-04-26 20:48:13 +00:00
field_info *
2002-02-18 01:08:44 +00:00
proto_find_field_from_offset ( proto_tree * tree , guint offset , tvbuff_t * tvb )
2001-03-02 23:10:12 +00:00
{
2012-03-14 17:11:39 +00:00
offset_search_t offsearch ;
2001-03-02 23:10:12 +00:00
offsearch . offset = offset ;
2012-03-14 17:11:39 +00:00
offsearch . finfo = NULL ;
offsearch . tvb = tvb ;
2001-03-02 23:10:12 +00:00
2003-12-04 10:59:34 +00:00
proto_tree_traverse_pre_order ( tree , check_for_offset , & offsearch ) ;
2001-03-02 23:10:12 +00:00
return offsearch . finfo ;
}
2015-02-04 09:25:16 +00:00
static gboolean
2016-01-05 12:06:36 +00:00
check_for_undecoded ( proto_node * node , gpointer data )
2015-02-04 09:25:16 +00:00
{
field_info * fi = PNODE_FINFO ( node ) ;
gchar * decoded = ( gchar * ) data ;
gint i ;
guint byte ;
guint bit ;
if ( fi & & fi - > hfinfo - > type ! = FT_PROTOCOL ) {
for ( i = fi - > start ; i < fi - > start + fi - > length ; i + + ) {
byte = i / 8 ;
bit = i % 8 ;
decoded [ byte ] | = ( 1 < < bit ) ;
}
}
return FALSE ;
}
gchar *
proto_find_undecoded_data ( proto_tree * tree , guint length )
{
gchar * decoded = ( gchar * ) wmem_alloc0 ( wmem_packet_scope ( ) , length / 8 + 1 ) ;
proto_tree_traverse_pre_order ( tree , check_for_undecoded , decoded ) ;
return decoded ;
}
2009-09-23 16:27:37 +00:00
/* Dumps the protocols in the registration database to stdout. An independent
2002-05-14 10:15:12 +00:00
* program can take this output and format it into nice tables or HTML or
* whatever .
*
* There is one record per line . The fields are tab - delimited .
*
* Field 1 = protocol name
* Field 2 = protocol short name
* Field 3 = protocol filter name
*/
void
proto_registrar_dump_protocols ( void )
{
2012-03-14 17:11:39 +00:00
protocol_t * protocol ;
int i ;
void * cookie = NULL ;
2001-03-02 23:10:12 +00:00
2012-05-19 16:07:50 +00:00
i = proto_get_first_protocol ( & cookie ) ;
while ( i ! = - 1 ) {
2002-05-14 10:15:12 +00:00
protocol = find_protocol_by_id ( i ) ;
printf ( " %s \t %s \t %s \n " , protocol - > name , protocol - > short_name ,
2009-09-23 16:27:37 +00:00
protocol - > filter_name ) ;
2012-05-19 16:07:50 +00:00
i = proto_get_next_protocol ( & cookie ) ;
2002-05-14 10:15:12 +00:00
}
}
2001-03-02 23:10:12 +00:00
2010-11-12 19:48:30 +00:00
/* Dumps the value_strings, extended value string headers, range_strings
* or true / false strings for fields that have them .
* There is one record per line . Fields are tab - delimited .
* There are four types of records : Value String , Extended Value String Header ,
* Range String and True / False String . The first field , ' V ' , ' E ' , ' R ' or ' T ' , indicates
2009-04-22 19:50:34 +00:00
* the type of record .
2004-09-10 15:21:20 +00:00
*
2010-11-12 19:48:30 +00:00
* Note that a record will be generated only if the value_string , . . . is referenced
* in a registered hfinfo entry .
*
*
2004-09-10 15:21:20 +00:00
* Value Strings
* - - - - - - - - - - - - -
* Field 1 = ' V '
2010-11-12 19:48:30 +00:00
* Field 2 = Field abbreviation to which this value string corresponds
2004-09-10 15:21:20 +00:00
* Field 3 = Integer value
* Field 4 = String
*
2010-11-12 19:48:30 +00:00
* Extended Value String Headers
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Field 1 = ' E '
* Field 2 = Field abbreviation to which this extended value string header corresponds
* Field 3 = Extended Value String " Name "
* Field 4 = Number of entries in the associated value_string array
* Field 5 = Access Type : " Linear Search " , " Binary Search " , " Direct (indexed) Access "
*
2009-04-22 19:50:34 +00:00
* Range Strings
* - - - - - - - - - - - - -
* Field 1 = ' R '
2010-11-12 19:48:30 +00:00
* Field 2 = Field abbreviation to which this range string corresponds
2009-04-22 19:50:34 +00:00
* Field 3 = Integer value : lower bound
* Field 4 = Integer value : upper bound
* Field 5 = String
*
2004-09-10 15:21:20 +00:00
* True / False Strings
* - - - - - - - - - - - - - - - - - -
* Field 1 = ' T '
2010-11-12 19:48:30 +00:00
* Field 2 = Field abbreviation to which this true / false string corresponds
2004-09-10 15:21:20 +00:00
* Field 3 = True String
* Field 4 = False String
*/
void
proto_registrar_dump_values ( void )
{
2011-06-07 22:28:55 +00:00
header_field_info * hfinfo ;
2004-09-10 15:21:20 +00:00
int i , len , vi ;
const value_string * vals ;
2013-07-26 21:51:39 +00:00
const val64_string * vals64 ;
2009-04-22 19:50:34 +00:00
const range_string * range ;
2004-09-10 15:21:20 +00:00
const true_false_string * tfs ;
len = gpa_hfinfo . len ;
for ( i = 0 ; i < len ; i + + ) {
2014-11-06 10:19:25 +00:00
if ( gpa_hfinfo . hfi [ i ] = = NULL )
continue ; /* This is a deregistered protocol or field */
2004-09-10 15:21:20 +00:00
PROTO_REGISTRAR_GET_NTH ( i , hfinfo ) ;
if ( hfinfo - > id = = hf_text_only ) {
continue ;
}
/* ignore protocols */
if ( proto_registrar_is_protocol ( i ) ) {
continue ;
}
/* process header fields */
2014-11-25 17:53:43 +00:00
#if 0 /* XXX: We apparently allow fields with the same name but with differing "strings" content */
/*
* If this field isn ' t at the head of the list of
* fields with this name , skip this field - all
* fields with the same name are really just versions
* of the same field stored in different bits , and
* should have the same type / radix / value list , and
* just differ in their bit masks . ( If a field isn ' t
* a bitfield , but can be , say , 1 or 2 bytes long ,
* it can just be made FT_UINT16 , meaning the
* * maximum * length is 2 bytes , and be used
* for all lengths . )
*/
if ( hfinfo - > same_name_prev_id ! = - 1 )
continue ;
# endif
vals = NULL ;
vals64 = NULL ;
range = NULL ;
tfs = NULL ;
if ( hfinfo - > strings ! = NULL ) {
if ( ( hfinfo - > display & FIELD_DISPLAY_E_MASK ) ! = BASE_CUSTOM & &
( hfinfo - > type = = FT_UINT8 | |
hfinfo - > type = = FT_UINT16 | |
hfinfo - > type = = FT_UINT24 | |
hfinfo - > type = = FT_UINT32 | |
2014-12-17 20:19:20 +00:00
hfinfo - > type = = FT_UINT40 | |
hfinfo - > type = = FT_UINT48 | |
hfinfo - > type = = FT_UINT56 | |
2014-11-25 17:53:43 +00:00
hfinfo - > type = = FT_UINT64 | |
hfinfo - > type = = FT_INT8 | |
hfinfo - > type = = FT_INT16 | |
hfinfo - > type = = FT_INT24 | |
hfinfo - > type = = FT_INT32 | |
2014-12-17 20:19:20 +00:00
hfinfo - > type = = FT_INT40 | |
hfinfo - > type = = FT_INT48 | |
hfinfo - > type = = FT_INT56 | |
2014-11-25 17:53:43 +00:00
hfinfo - > type = = FT_INT64 ) ) {
if ( hfinfo - > display & BASE_RANGE_STRING ) {
range = ( const range_string * ) hfinfo - > strings ;
} else if ( hfinfo - > display & BASE_EXT_STRING ) {
vals = VALUE_STRING_EXT_VS_P ( ( value_string_ext * ) hfinfo - > strings ) ;
} else if ( hfinfo - > display & BASE_VAL64_STRING ) {
vals64 = ( const val64_string * ) hfinfo - > strings ;
} else {
vals = ( const value_string * ) hfinfo - > strings ;
2009-04-22 19:50:34 +00:00
}
2004-09-10 15:21:20 +00:00
}
2014-11-25 17:53:43 +00:00
else if ( hfinfo - > type = = FT_BOOLEAN ) {
tfs = ( const struct true_false_string * ) hfinfo - > strings ;
}
}
2004-09-10 15:21:20 +00:00
2014-11-25 17:53:43 +00:00
/* Print value strings? */
if ( vals ) {
if ( hfinfo - > display & BASE_EXT_STRING ) {
value_string_ext * vse_p = ( value_string_ext * ) hfinfo - > strings ;
if ( ! value_string_ext_validate ( vse_p ) ) {
g_warning ( " Invalid value_string_ext ptr for: %s " , hfinfo - > abbrev ) ;
continue ;
}
try_val_to_str_ext ( 0 , vse_p ) ; /* "prime" the extended value_string */
2015-02-09 18:42:51 +00:00
printf ( " E \t %s \t %u \t %s \t %s \n " ,
2014-11-25 17:53:43 +00:00
hfinfo - > abbrev ,
VALUE_STRING_EXT_VS_NUM_ENTRIES ( vse_p ) ,
VALUE_STRING_EXT_VS_NAME ( vse_p ) ,
value_string_ext_match_type_str ( vse_p ) ) ;
}
vi = 0 ;
while ( vals [ vi ] . strptr ) {
/* Print in the proper base */
if ( hfinfo - > display = = BASE_HEX ) {
printf ( " V \t %s \t 0x%x \t %s \n " ,
2010-11-12 19:48:30 +00:00
hfinfo - > abbrev ,
2014-11-25 17:53:43 +00:00
vals [ vi ] . value ,
vals [ vi ] . strptr ) ;
2010-11-12 19:48:30 +00:00
}
2014-11-25 17:53:43 +00:00
else {
printf ( " V \t %s \t %u \t %s \n " ,
hfinfo - > abbrev ,
vals [ vi ] . value ,
vals [ vi ] . strptr ) ;
2004-09-10 15:21:20 +00:00
}
2014-11-25 17:53:43 +00:00
vi + + ;
2004-09-10 15:21:20 +00:00
}
2014-11-25 17:53:43 +00:00
}
else if ( vals64 ) {
vi = 0 ;
while ( vals64 [ vi ] . strptr ) {
printf ( " V64 \t %s \t % " G_GINT64_MODIFIER " u \t %s \n " ,
hfinfo - > abbrev ,
vals64 [ vi ] . value ,
vals64 [ vi ] . strptr ) ;
vi + + ;
2013-07-26 21:51:39 +00:00
}
2014-11-25 17:53:43 +00:00
}
2004-09-10 15:21:20 +00:00
2014-11-25 17:53:43 +00:00
/* print range strings? */
else if ( range ) {
vi = 0 ;
while ( range [ vi ] . strptr ) {
/* Print in the proper base */
if ( ( hfinfo - > display & FIELD_DISPLAY_E_MASK ) = = BASE_HEX ) {
printf ( " R \t %s \t 0x%x \t 0x%x \t %s \n " ,
hfinfo - > abbrev ,
range [ vi ] . value_min ,
range [ vi ] . value_max ,
range [ vi ] . strptr ) ;
}
else {
printf ( " R \t %s \t %u \t %u \t %s \n " ,
hfinfo - > abbrev ,
range [ vi ] . value_min ,
range [ vi ] . value_max ,
range [ vi ] . strptr ) ;
2009-04-22 19:50:34 +00:00
}
2014-11-25 17:53:43 +00:00
vi + + ;
2009-04-22 19:50:34 +00:00
}
2014-11-25 17:53:43 +00:00
}
2009-04-22 19:50:34 +00:00
2014-11-25 17:53:43 +00:00
/* Print true/false strings? */
else if ( tfs ) {
printf ( " T \t %s \t %s \t %s \n " , hfinfo - > abbrev ,
tfs - > true_string , tfs - > false_string ) ;
2004-09-10 15:21:20 +00:00
}
}
}
2015-09-21 19:00:35 +00:00
/* Prints the number of registered fields.
* Useful for determining an appropriate value for
* PROTO_PRE_ALLOC_HF_FIELDS_MEM .
2015-09-23 14:14:31 +00:00
*
* Returns FALSE if PROTO_PRE_ALLOC_HF_FIELDS_MEM is larger than or equal to
* the number of fields , TRUE otherwise .
2015-09-21 19:00:35 +00:00
*/
2015-09-23 14:14:31 +00:00
gboolean
2015-09-21 19:00:35 +00:00
proto_registrar_dump_fieldcount ( void )
{
guint32 i ;
header_field_info * hfinfo ;
guint32 deregistered_count = 0 ;
guint32 same_name_count = 0 ;
guint32 protocol_count = 0 ;
for ( i = 0 ; i < gpa_hfinfo . len ; i + + ) {
if ( gpa_hfinfo . hfi [ i ] = = NULL ) {
deregistered_count + + ;
continue ; /* This is a deregistered protocol or header field */
}
PROTO_REGISTRAR_GET_NTH ( i , hfinfo ) ;
if ( proto_registrar_is_protocol ( i ) )
protocol_count + + ;
if ( hfinfo - > same_name_prev_id ! = - 1 )
same_name_count + + ;
}
2015-09-23 14:14:31 +00:00
printf ( " There are %d header fields registered, of which: \n "
" \t %d are deregistered \n "
" \t %d are protocols \n "
" \t %d have the same name as another field \n \n " ,
2015-09-21 19:00:35 +00:00
gpa_hfinfo . len , deregistered_count , protocol_count ,
same_name_count ) ;
2015-09-23 14:14:31 +00:00
printf ( " %d fields were pre-allocated. \n %s " , PROTO_PRE_ALLOC_HF_FIELDS_MEM ,
( gpa_hfinfo . allocated_len > PROTO_PRE_ALLOC_HF_FIELDS_MEM ) ?
" * * Please increase PROTO_PRE_ALLOC_HF_FIELDS_MEM (in epan/proto.c)! * * \n \n " :
" \n " ) ;
printf ( " The header field table consumes %d KiB of memory. \n " ,
( int ) ( gpa_hfinfo . allocated_len * sizeof ( header_field_info * ) / 1024 ) ) ;
printf ( " The fields themselves consume %d KiB of memory. \n " ,
( int ) ( gpa_hfinfo . len * sizeof ( header_field_info ) / 1024 ) ) ;
return ( gpa_hfinfo . allocated_len > PROTO_PRE_ALLOC_HF_FIELDS_MEM ) ;
2015-09-21 19:00:35 +00:00
}
2008-12-15 17:05:41 +00:00
/* Dumps the contents of the registration database to stdout. An independent
2002-05-14 10:15:12 +00:00
* program can take this output and format it into nice tables or HTML or
* whatever .
1999-07-15 15:33:52 +00:00
*
* There is one record per line . Each record is either a protocol or a header
* field , differentiated by the first field . The fields are tab - delimited .
*
* Protocols
* - - - - - - - - -
* Field 1 = ' P '
2004-09-10 15:21:20 +00:00
* Field 2 = descriptive protocol name
1999-07-15 15:33:52 +00:00
* Field 3 = protocol abbreviation
*
* Header Fields
* - - - - - - - - - - - - -
* Field 1 = ' F '
2004-09-10 15:21:20 +00:00
* Field 2 = descriptive field name
1999-07-15 15:33:52 +00:00
* Field 3 = field abbreviation
* Field 4 = type ( textual representation of the the ftenum type )
* Field 5 = parent protocol abbreviation
2013-04-05 21:58:43 +00:00
* Field 6 = base for display ( for integer types ) ; " parent bitfield width " for FT_BOOLEAN
* Field 7 = bitmask : format : hex : 0 x . . . .
* Field 8 = blurb describing field
1999-07-15 15:33:52 +00:00
*/
void
2013-04-05 21:58:43 +00:00
proto_registrar_dump_fields ( void )
1999-07-15 15:33:52 +00:00
{
2012-03-14 17:11:39 +00:00
header_field_info * hfinfo , * parent_hfinfo ;
int i , len ;
const char * enum_name ;
const char * base_name ;
const char * blurb ;
char width [ 5 ] ;
1999-07-15 15:33:52 +00:00
2003-11-21 14:58:49 +00:00
len = gpa_hfinfo . len ;
1999-07-15 15:33:52 +00:00
for ( i = 0 ; i < len ; i + + ) {
2014-11-06 10:19:25 +00:00
if ( gpa_hfinfo . hfi [ i ] = = NULL )
continue ; /* This is a deregistered protocol or header field */
2003-11-22 04:41:31 +00:00
PROTO_REGISTRAR_GET_NTH ( i , hfinfo ) ;
1999-07-15 15:33:52 +00:00
2001-04-19 23:06:23 +00:00
/*
2006-10-31 22:00:41 +00:00
* Skip the pseudo - field for " proto_tree_add_text() " since
* we don ' t want it in the list of filterable fields .
2009-09-23 16:27:37 +00:00
*/
if ( hfinfo - > id = = hf_text_only )
2001-04-19 23:06:23 +00:00
continue ;
1999-07-15 15:33:52 +00:00
/* format for protocols */
if ( proto_registrar_is_protocol ( i ) ) {
printf ( " P \t %s \t %s \n " , hfinfo - > name , hfinfo - > abbrev ) ;
}
/* format for header fields */
else {
2001-02-12 10:06:51 +00:00
/*
2001-02-13 18:34:51 +00:00
* If this field isn ' t at the head of the list of
* fields with this name , skip this field - all
* fields with the same name are really just versions
* of the same field stored in different bits , and
* should have the same type / radix / value list , and
2009-09-23 16:27:37 +00:00
* just differ in their bit masks . ( If a field isn ' t
2001-02-12 10:06:51 +00:00
* a bitfield , but can be , say , 1 or 2 bytes long ,
* it can just be made FT_UINT16 , meaning the
* * maximum * length is 2 bytes , and be used
* for all lengths . )
*/
2013-08-06 20:53:47 +00:00
if ( hfinfo - > same_name_prev_id ! = - 1 )
2001-02-12 10:06:51 +00:00
continue ;
2003-11-22 04:41:31 +00:00
PROTO_REGISTRAR_GET_NTH ( hfinfo - > parent , parent_hfinfo ) ;
1999-07-15 15:33:52 +00:00
2001-02-01 20:21:25 +00:00
enum_name = ftype_name ( hfinfo - > type ) ;
2004-09-10 15:21:20 +00:00
base_name = " " ;
2013-04-05 21:58:43 +00:00
if ( hfinfo - > type = = FT_UINT8 | |
hfinfo - > type = = FT_UINT16 | |
hfinfo - > type = = FT_UINT24 | |
hfinfo - > type = = FT_UINT32 | |
2014-12-17 20:19:20 +00:00
hfinfo - > type = = FT_UINT40 | |
hfinfo - > type = = FT_UINT48 | |
hfinfo - > type = = FT_UINT56 | |
2013-04-05 21:58:43 +00:00
hfinfo - > type = = FT_UINT64 | |
hfinfo - > type = = FT_INT8 | |
hfinfo - > type = = FT_INT16 | |
hfinfo - > type = = FT_INT24 | |
hfinfo - > type = = FT_INT32 | |
2014-12-17 20:19:20 +00:00
hfinfo - > type = = FT_INT40 | |
hfinfo - > type = = FT_INT48 | |
hfinfo - > type = = FT_INT56 | |
2013-04-05 21:58:43 +00:00
hfinfo - > type = = FT_INT64 ) {
2015-10-11 16:51:40 +00:00
switch ( FIELD_DISPLAY ( hfinfo - > display ) ) {
2013-04-05 21:58:43 +00:00
case BASE_NONE :
case BASE_DEC :
case BASE_HEX :
case BASE_OCT :
case BASE_DEC_HEX :
case BASE_HEX_DEC :
case BASE_CUSTOM :
2015-10-11 16:51:40 +00:00
case BASE_PT_UDP :
case BASE_PT_TCP :
case BASE_PT_DCCP :
case BASE_PT_SCTP :
base_name = val_to_str_const ( FIELD_DISPLAY ( hfinfo - > display ) , hf_display , " ???? " ) ;
2013-04-05 21:58:43 +00:00
break ;
default :
base_name = " ???? " ;
break ;
2004-09-10 15:21:20 +00:00
}
2013-04-05 21:58:43 +00:00
} else if ( hfinfo - > type = = FT_BOOLEAN ) {
/* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
g_snprintf ( width , sizeof ( width ) , " %d " , hfinfo - > display ) ;
base_name = width ;
2004-09-10 15:21:20 +00:00
}
2005-12-04 04:22:43 +00:00
blurb = hfinfo - > blurb ;
if ( blurb = = NULL )
blurb = " " ;
2010-05-26 14:35:06 +00:00
else if ( strlen ( blurb ) = = 0 )
blurb = " \" \" " ;
2013-04-05 21:58:43 +00:00
2014-10-13 12:17:35 +00:00
printf ( " F \t %s \t %s \t %s \t %s \t %s \t 0x% " G_GINT64_MODIFIER " x \t %s \n " ,
2013-04-05 21:58:43 +00:00
hfinfo - > name , hfinfo - > abbrev , enum_name ,
2014-09-17 16:39:22 +00:00
parent_hfinfo - > abbrev , base_name ,
2014-10-13 12:17:35 +00:00
hfinfo - > bitmask , blurb ) ;
1999-07-15 15:33:52 +00:00
}
}
}
2000-08-30 02:50:18 +00:00
2011-12-27 20:35:41 +00:00
/* Dumps field types and descriptive names to stdout. An independent
* program can take this output and format it into nice tables or HTML or
* whatever .
*
* There is one record per line . The fields are tab - delimited .
*
* Field 1 = field type name , e . g . FT_UINT8
* Field 2 = descriptive name , e . g . " Unsigned, 1 byte "
*/
void
proto_registrar_dump_ftypes ( void )
{
2013-03-02 12:10:56 +00:00
int fte ;
2011-12-27 20:35:41 +00:00
for ( fte = 0 ; fte < FT_NUM_TYPES ; fte + + ) {
2013-03-02 12:10:56 +00:00
printf ( " %s \t %s \n " , ftype_name ( ( ftenum_t ) fte ) , ftype_pretty_name ( ( ftenum_t ) fte ) ) ;
2011-12-27 20:35:41 +00:00
}
}
2006-11-23 21:16:46 +00:00
/* This function indicates whether it's possible to construct a
* " match selected " display filter string for the specified field ,
* returns an indication of whether it ' s possible , and , if it ' s
* possible and " filter " is non - null , constructs the filter and
* sets " *filter " to point to it .
2006-07-20 21:29:45 +00:00
* You do not need to [ g_ ] free ( ) this string since it will be automatically
2005-09-01 09:03:29 +00:00
* freed once the next packet is dissected .
*/
2006-11-24 18:25:23 +00:00
static gboolean
construct_match_selected_string ( field_info * finfo , epan_dissect_t * edt ,
2010-04-26 20:48:13 +00:00
char * * filter )
2001-02-01 20:21:25 +00:00
{
2012-03-14 17:11:39 +00:00
header_field_info * hfinfo ;
int abbrev_len ;
char * ptr ;
int buf_len ;
int dfilter_len , i ;
gint start , length , length_remaining ;
guint8 c ;
gchar is_signed_num = FALSE ;
2013-12-23 17:20:07 +00:00
if ( ! finfo )
return FALSE ;
2012-12-07 20:08:00 +00:00
2012-03-14 17:11:39 +00:00
hfinfo = finfo - > hfinfo ;
2005-03-23 00:09:12 +00:00
DISSECTOR_ASSERT ( hfinfo ) ;
2009-04-08 16:50:20 +00:00
abbrev_len = ( int ) strlen ( hfinfo - > abbrev ) ;
2001-02-01 20:21:25 +00:00
2013-12-07 10:41:42 +00:00
if ( hfinfo - > strings & & ( hfinfo - > display & FIELD_DISPLAY_E_MASK ) = = BASE_NONE ) {
2009-03-09 00:24:21 +00:00
const gchar * str = NULL ;
2012-03-14 17:11:39 +00:00
switch ( hfinfo - > type ) {
2009-03-09 00:24:21 +00:00
case FT_INT8 :
case FT_INT16 :
case FT_INT24 :
case FT_INT32 :
2013-06-27 17:26:23 +00:00
str = hf_try_val_to_str ( fvalue_get_sinteger ( & finfo - > value ) , hfinfo ) ;
2009-03-09 00:24:21 +00:00
break ;
case FT_UINT8 :
case FT_UINT16 :
case FT_UINT24 :
case FT_UINT32 :
2013-06-27 17:26:23 +00:00
str = hf_try_val_to_str ( fvalue_get_uinteger ( & finfo - > value ) , hfinfo ) ;
2009-03-09 00:24:21 +00:00
break ;
default :
break ;
}
if ( str ! = NULL & & filter ! = NULL ) {
2015-01-17 02:47:48 +00:00
* filter = wmem_strdup_printf ( NULL , " %s == \" %s \" " , hfinfo - > abbrev , str ) ;
2009-03-09 00:24:21 +00:00
return TRUE ;
}
}
2003-05-03 01:11:29 +00:00
/*
2005-10-31 02:42:22 +00:00
* XXX - we can ' t use the " val_to_string_repr " and " string_repr_len "
* functions for FT_UINT and FT_INT types , as we choose the base in
* the string expression based on the display base of the field .
2003-05-03 01:11:29 +00:00
*
* Note that the base does matter , as this is also used for
* the protocolinfo tap .
*
2005-10-31 02:42:22 +00:00
* It might be nice to use them in " proto_item_fill_label() "
2003-05-03 01:11:29 +00:00
* as well , although , there , you ' d have to deal with the base
* * and * with resolved values for addresses .
*
* Perhaps we need two different val_to_string routines , one
* to generate items for display filters and one to generate
* strings for display , and pass to both of them the
* " display " and " strings " values in the header_field_info
* structure for the field , so they can get the base and ,
* if the field is Boolean or an enumerated integer type ,
* the tables used to generate human - readable values .
*/
2012-03-14 17:11:39 +00:00
switch ( hfinfo - > type ) {
2001-02-01 20:21:25 +00:00
2000-08-30 02:50:18 +00:00
case FT_INT8 :
case FT_INT16 :
case FT_INT24 :
case FT_INT32 :
2007-01-18 11:02:26 +00:00
is_signed_num = TRUE ;
2011-03-26 15:24:36 +00:00
/* FALLTHRU */
2007-01-18 11:02:26 +00:00
case FT_UINT8 :
case FT_UINT16 :
case FT_UINT24 :
case FT_UINT32 :
2009-07-15 08:56:12 +00:00
case FT_FRAMENUM :
if ( filter ! = NULL ) {
2013-07-01 09:46:50 +00:00
guint32 number ;
char buf [ 32 ] ;
const char * out ;
if ( is_signed_num )
number = fvalue_get_sinteger ( & finfo - > value ) ;
else
number = fvalue_get_uinteger ( & finfo - > value ) ;
out = hfinfo_numeric_value_format ( hfinfo , buf , number ) ;
2015-01-17 02:47:48 +00:00
* filter = wmem_strdup_printf ( NULL , " %s == %s " , hfinfo - > abbrev , out ) ;
2009-07-15 08:56:12 +00:00
}
break ;
2014-12-17 20:19:20 +00:00
case FT_INT40 :
case FT_INT48 :
case FT_INT56 :
2001-11-02 10:09:51 +00:00
case FT_INT64 :
2014-12-17 20:19:20 +00:00
is_signed_num = TRUE ;
/* FALLTHRU */
case FT_UINT40 :
case FT_UINT48 :
case FT_UINT56 :
2004-08-22 00:31:58 +00:00
case FT_UINT64 :
2006-11-23 21:16:46 +00:00
if ( filter ! = NULL ) {
2014-12-17 20:19:20 +00:00
guint64 number ;
2015-02-23 15:50:18 +00:00
char buf [ 48 ] ;
2014-12-17 20:19:20 +00:00
const char * out ;
if ( is_signed_num )
number = fvalue_get_sinteger64 ( & finfo - > value ) ;
else
number = fvalue_get_uinteger64 ( & finfo - > value ) ;
out = hfinfo_numeric_value_format64 ( hfinfo , buf , number ) ;
2013-07-01 09:46:50 +00:00
2014-12-17 20:19:20 +00:00
* filter = wmem_strdup_printf ( NULL , " %s == %s " , hfinfo - > abbrev , out ) ;
2006-11-23 21:16:46 +00:00
}
2001-11-02 10:09:51 +00:00
break ;
2003-06-11 21:24:54 +00:00
case FT_PROTOCOL :
2006-11-23 21:16:46 +00:00
if ( filter ! = NULL )
2015-01-17 02:47:48 +00:00
* filter = wmem_strdup ( NULL , finfo - > hfinfo - > abbrev ) ;
2003-06-11 21:48:39 +00:00
break ;
2003-06-11 21:24:54 +00:00
2006-11-22 22:11:38 +00:00
case FT_NONE :
2006-11-23 21:16:46 +00:00
/*
* If the length is 0 , just match the name of the
* field .
*
* ( Also check for negative values , just in case ,
* as we ' ll cast it to an unsigned value later . )
*/
length = finfo - > length ;
if ( length = = 0 ) {
if ( filter ! = NULL )
2015-01-17 02:47:48 +00:00
* filter = wmem_strdup ( NULL , finfo - > hfinfo - > abbrev ) ;
2006-11-23 21:16:46 +00:00
break ;
}
if ( length < 0 )
return FALSE ;
Rename "proto_alloc_dfilter_string()" to
"proto_construct_dfilter_string()", to more accurately reflect what it
does.
Give it, and "proto_can_match_selected()", an "epan_dissect_t *"
argument, which replaces the raw data pointer argument to
"proto_construct_dfilter_string()".
For fields that don't have a type we can directly filter on, we don't
support filtering on the field as raw data if:
the "epan_dissect_t *" argument is null;
the data source tvbuff for the field isn't the tvbuff for the
"epan_dissect_t" in question (i.e., it's in the result of a
reassembly, and "frame[N:M]" can't get at it).
Trim the length the raw data in the case of such a field to the length
of the tvbuff for the "epan_dissect_t" in question, so we don't go past
it. Fetch the raw data bytes to match from that tvbuff.
Have "proto_construct_dfilter_string()" return a null pointer if it
can't construct the filter string, and have "protocolinfo_packet()" in
the tap-protocolinfo tap ignore a field if
"proto_construct_dfilter_string()" can't construct a filter string for
it - and have it pass NULL as the "epan_dissect_t *", for now. If
somebody decides it makes sense to dump out a "frame[N:M] =" value for
non-registered fields, it can be changed to pass "edt".
svn path=/trunk/; revision=7635
2003-05-03 00:48:37 +00:00
/*
* This doesn ' t have a value , so we ' d match
* on the raw bytes at this address .
*
* Should we be allowed to access to the raw bytes ?
* If " edt " is NULL , the answer is " no " .
*/
if ( edt = = NULL )
2006-11-23 21:16:46 +00:00
return FALSE ;
Rename "proto_alloc_dfilter_string()" to
"proto_construct_dfilter_string()", to more accurately reflect what it
does.
Give it, and "proto_can_match_selected()", an "epan_dissect_t *"
argument, which replaces the raw data pointer argument to
"proto_construct_dfilter_string()".
For fields that don't have a type we can directly filter on, we don't
support filtering on the field as raw data if:
the "epan_dissect_t *" argument is null;
the data source tvbuff for the field isn't the tvbuff for the
"epan_dissect_t" in question (i.e., it's in the result of a
reassembly, and "frame[N:M]" can't get at it).
Trim the length the raw data in the case of such a field to the length
of the tvbuff for the "epan_dissect_t" in question, so we don't go past
it. Fetch the raw data bytes to match from that tvbuff.
Have "proto_construct_dfilter_string()" return a null pointer if it
can't construct the filter string, and have "protocolinfo_packet()" in
the tap-protocolinfo tap ignore a field if
"proto_construct_dfilter_string()" can't construct a filter string for
it - and have it pass NULL as the "epan_dissect_t *", for now. If
somebody decides it makes sense to dump out a "frame[N:M] =" value for
non-registered fields, it can be changed to pass "edt".
svn path=/trunk/; revision=7635
2003-05-03 00:48:37 +00:00
/*
* Is this field part of the raw frame tvbuff ?
* If not , we can ' t use " frame[N:M] " to match
* it .
*
* XXX - should this be frame - relative , or
* protocol - relative ?
*
* XXX - does this fallback for non - registered
* fields even make sense ?
*/
if ( finfo - > ds_tvb ! = edt - > tvb )
2006-11-23 21:16:46 +00:00
return FALSE ; /* you lose */
Rename "proto_alloc_dfilter_string()" to
"proto_construct_dfilter_string()", to more accurately reflect what it
does.
Give it, and "proto_can_match_selected()", an "epan_dissect_t *"
argument, which replaces the raw data pointer argument to
"proto_construct_dfilter_string()".
For fields that don't have a type we can directly filter on, we don't
support filtering on the field as raw data if:
the "epan_dissect_t *" argument is null;
the data source tvbuff for the field isn't the tvbuff for the
"epan_dissect_t" in question (i.e., it's in the result of a
reassembly, and "frame[N:M]" can't get at it).
Trim the length the raw data in the case of such a field to the length
of the tvbuff for the "epan_dissect_t" in question, so we don't go past
it. Fetch the raw data bytes to match from that tvbuff.
Have "proto_construct_dfilter_string()" return a null pointer if it
can't construct the filter string, and have "protocolinfo_packet()" in
the tap-protocolinfo tap ignore a field if
"proto_construct_dfilter_string()" can't construct a filter string for
it - and have it pass NULL as the "epan_dissect_t *", for now. If
somebody decides it makes sense to dump out a "frame[N:M] =" value for
non-registered fields, it can be changed to pass "edt".
svn path=/trunk/; revision=7635
2003-05-03 00:48:37 +00:00
/*
* Don ' t go past the end of that tvbuff .
*/
2014-04-01 04:20:07 +00:00
length_remaining = tvb_captured_length_remaining ( finfo - > ds_tvb , finfo - > start ) ;
2004-07-09 21:52:03 +00:00
if ( length > length_remaining )
length = length_remaining ;
Rename "proto_alloc_dfilter_string()" to
"proto_construct_dfilter_string()", to more accurately reflect what it
does.
Give it, and "proto_can_match_selected()", an "epan_dissect_t *"
argument, which replaces the raw data pointer argument to
"proto_construct_dfilter_string()".
For fields that don't have a type we can directly filter on, we don't
support filtering on the field as raw data if:
the "epan_dissect_t *" argument is null;
the data source tvbuff for the field isn't the tvbuff for the
"epan_dissect_t" in question (i.e., it's in the result of a
reassembly, and "frame[N:M]" can't get at it).
Trim the length the raw data in the case of such a field to the length
of the tvbuff for the "epan_dissect_t" in question, so we don't go past
it. Fetch the raw data bytes to match from that tvbuff.
Have "proto_construct_dfilter_string()" return a null pointer if it
can't construct the filter string, and have "protocolinfo_packet()" in
the tap-protocolinfo tap ignore a field if
"proto_construct_dfilter_string()" can't construct a filter string for
it - and have it pass NULL as the "epan_dissect_t *", for now. If
somebody decides it makes sense to dump out a "frame[N:M] =" value for
non-registered fields, it can be changed to pass "edt".
svn path=/trunk/; revision=7635
2003-05-03 00:48:37 +00:00
if ( length < = 0 )
2006-11-23 21:16:46 +00:00
return FALSE ;
if ( filter ! = NULL ) {
start = finfo - > start ;
buf_len = 32 + length * 3 ;
2015-01-17 02:47:48 +00:00
* filter = ( char * ) wmem_alloc0 ( NULL , buf_len ) ;
2006-11-23 21:16:46 +00:00
ptr = * filter ;
2009-04-08 16:50:20 +00:00
ptr + = g_snprintf ( ptr , ( gulong ) ( buf_len - ( ptr - * filter ) ) ,
2009-09-23 16:27:37 +00:00
" frame[%d:%d] == " , finfo - > start , length ) ;
2012-03-14 17:11:39 +00:00
for ( i = 0 ; i < length ; i + + ) {
2006-11-23 21:16:46 +00:00
c = tvb_get_guint8 ( finfo - > ds_tvb , start ) ;
start + + ;
if ( i = = 0 ) {
2009-04-08 16:50:20 +00:00
ptr + = g_snprintf ( ptr , ( gulong ) ( buf_len - ( ptr - * filter ) ) , " %02x " , c ) ;
2006-11-23 21:16:46 +00:00
}
else {
2009-04-08 16:50:20 +00:00
ptr + = g_snprintf ( ptr , ( gulong ) ( buf_len - ( ptr - * filter ) ) , " :%02x " , c ) ;
2006-11-23 21:16:46 +00:00
}
2001-02-01 20:21:25 +00:00
}
2001-05-09 01:22:46 +00:00
}
break ;
2006-11-22 22:11:38 +00:00
2009-08-12 18:24:49 +00:00
case FT_PCRE :
2009-09-06 07:24:54 +00:00
/* FT_PCRE never appears as a type for a registered field. It is
2009-08-12 18:24:49 +00:00
* only used internally . */
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
break ;
2006-11-22 22:11:38 +00:00
/* By default, use the fvalue's "to_string_repr" method. */
default :
/* Figure out the string length needed.
2009-09-23 16:27:37 +00:00
* The ft_repr length .
* 4 bytes for " == " .
* 1 byte for trailing NUL .
2006-11-22 22:11:38 +00:00
*/
2006-11-23 21:16:46 +00:00
if ( filter ! = NULL ) {
dfilter_len = fvalue_string_repr_len ( & finfo - > value ,
2015-01-04 02:56:16 +00:00
FTREPR_DFILTER , finfo - > hfinfo - > display ) ;
2006-11-23 21:16:46 +00:00
dfilter_len + = abbrev_len + 4 + 1 ;
2015-01-17 02:47:48 +00:00
* filter = ( char * ) wmem_alloc0 ( NULL , dfilter_len ) ;
2006-11-23 21:16:46 +00:00
/* Create the string */
g_snprintf ( * filter , dfilter_len , " %s == " ,
2009-09-23 16:27:37 +00:00
hfinfo - > abbrev ) ;
2006-11-23 21:16:46 +00:00
fvalue_to_string_repr ( & finfo - > value ,
2015-01-04 02:56:16 +00:00
FTREPR_DFILTER , finfo - > hfinfo - > display ,
2009-09-23 16:27:37 +00:00
& ( * filter ) [ abbrev_len + 4 ] ) ;
2006-11-23 21:16:46 +00:00
}
2006-11-22 22:11:38 +00:00
break ;
2000-08-30 02:50:18 +00:00
}
2001-02-01 20:21:25 +00:00
2006-11-23 21:16:46 +00:00
return TRUE ;
2000-08-30 02:50:18 +00:00
}
2006-11-24 18:25:23 +00:00
/*
* Returns TRUE if we can do a " match selected " on the field , FALSE
* otherwise .
*/
gboolean
proto_can_match_selected ( field_info * finfo , epan_dissect_t * edt )
{
return construct_match_selected_string ( finfo , edt , NULL ) ;
}
/* This function attempts to construct a "match selected" display filter
* string for the specified field ; if it can do so , it returns a pointer
* to the string , otherwise it returns NULL .
*
* The string is allocated with packet lifetime scope .
* You do not need to [ g_ ] free ( ) this string since it will be automatically
* freed once the next packet is dissected .
*/
2010-04-26 20:48:13 +00:00
char *
2006-11-24 18:25:23 +00:00
proto_construct_match_selected_string ( field_info * finfo , epan_dissect_t * edt )
{
2015-01-17 02:47:48 +00:00
char * filter = NULL ;
2006-11-24 18:25:23 +00:00
if ( ! construct_match_selected_string ( finfo , edt , & filter ) )
2015-01-17 02:47:48 +00:00
{
wmem_free ( NULL , filter ) ;
2006-11-24 18:25:23 +00:00
return NULL ;
2015-01-17 02:47:48 +00:00
}
2006-11-24 18:25:23 +00:00
return filter ;
}
2006-11-27 14:50:23 +00:00
2016-02-01 23:19:10 +00:00
/* This function is common code for all proto_tree_add_bitmask... functions.
2006-11-27 14:50:23 +00:00
*/
2011-10-24 19:52:43 +00:00
2008-08-04 20:41:43 +00:00
static gboolean
2010-04-26 20:48:13 +00:00
proto_item_add_bitmask_tree ( proto_item * item , tvbuff_t * tvb , const int offset ,
const int len , const gint ett , const int * * fields ,
2016-02-01 23:19:10 +00:00
const int flags , gboolean first ,
gboolean use_parent_tree ,
2015-04-12 23:12:35 +00:00
proto_tree * tree , guint64 value )
2006-11-27 14:50:23 +00:00
{
2016-02-01 23:19:10 +00:00
guint bitshift ;
2014-09-17 16:39:22 +00:00
guint64 available_bits = 0 ;
guint64 tmpval ;
2008-08-04 20:41:43 +00:00
header_field_info * hf ;
2006-11-27 14:50:23 +00:00
2016-02-01 23:19:10 +00:00
if ( len < = 0 | | len > 8 )
g_assert_not_reached ( ) ;
bitshift = ( 8 - ( guint ) len ) * 8 ;
available_bits = G_GUINT64_CONSTANT ( 0xFFFFFFFFFFFFFFFF ) > > bitshift ;
2006-11-27 14:50:23 +00:00
2015-04-12 23:12:35 +00:00
if ( use_parent_tree = = FALSE )
tree = proto_item_add_subtree ( item , ett ) ;
2008-08-04 20:41:43 +00:00
while ( * fields ) {
2014-09-17 16:39:22 +00:00
guint64 present_bits ;
2014-04-24 15:26:22 +00:00
PROTO_REGISTRAR_GET_NTH ( * * fields , hf ) ;
2014-12-18 16:53:03 +00:00
DISSECTOR_ASSERT_HINT ( hf - > bitmask ! = 0 , hf - > abbrev ) ;
2013-03-04 14:18:18 +00:00
/* Skip fields that aren't fully present */
present_bits = available_bits & hf - > bitmask ;
if ( present_bits ! = hf - > bitmask ) {
fields + + ;
continue ;
}
2016-02-01 23:19:10 +00:00
switch ( hf - > type ) {
case FT_INT8 :
case FT_UINT8 :
case FT_INT16 :
case FT_UINT16 :
case FT_INT24 :
case FT_UINT24 :
case FT_INT32 :
case FT_UINT32 :
proto_tree_add_uint ( tree , * * fields , tvb , offset , len , ( guint32 ) value ) ;
break ;
2015-04-19 21:26:54 +00:00
2016-02-01 23:19:10 +00:00
case FT_INT40 :
case FT_UINT40 :
case FT_INT48 :
case FT_UINT48 :
case FT_INT56 :
case FT_UINT56 :
case FT_INT64 :
case FT_UINT64 :
proto_tree_add_uint64 ( tree , * * fields , tvb , offset , len , value ) ;
break ;
2015-04-19 21:26:54 +00:00
2016-02-01 23:19:10 +00:00
case FT_BOOLEAN :
proto_tree_add_boolean64 ( tree , * * fields , tvb , offset , len , value ) ;
break ;
2015-04-19 21:26:54 +00:00
2016-02-01 23:19:10 +00:00
default :
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
break ;
2015-04-12 23:12:35 +00:00
}
2008-08-04 20:41:43 +00:00
if ( flags & BMT_NO_APPEND ) {
fields + + ;
continue ;
}
2013-08-06 20:10:59 +00:00
tmpval = ( value & hf - > bitmask ) > > hfinfo_bitshift ( hf ) ;
2006-11-27 14:50:23 +00:00
2008-08-04 20:41:43 +00:00
switch ( hf - > type ) {
2006-11-27 14:50:23 +00:00
case FT_INT8 :
case FT_UINT8 :
case FT_INT16 :
case FT_UINT16 :
case FT_INT24 :
case FT_UINT24 :
case FT_INT32 :
case FT_UINT32 :
2014-12-17 20:19:20 +00:00
case FT_INT40 :
case FT_UINT40 :
case FT_INT48 :
case FT_UINT48 :
case FT_INT56 :
case FT_UINT56 :
case FT_INT64 :
case FT_UINT64 :
2008-08-04 20:41:43 +00:00
if ( hf - > display = = BASE_CUSTOM ) {
gchar lbl [ ITEM_LABEL_LENGTH ] ;
2013-03-24 10:53:31 +00:00
const custom_fmt_func_t fmtfunc = ( const custom_fmt_func_t ) hf - > strings ;
2008-08-04 20:41:43 +00:00
DISSECTOR_ASSERT ( fmtfunc ) ;
2014-09-17 16:39:22 +00:00
fmtfunc ( lbl , ( guint32 ) tmpval ) ;
2008-08-04 20:41:43 +00:00
proto_item_append_text ( item , " %s%s: %s " , first ? " " : " , " ,
hf - > name , lbl ) ;
first = FALSE ;
2006-11-27 14:50:23 +00:00
}
2008-08-04 20:41:43 +00:00
else if ( hf - > strings ) {
2013-06-27 17:26:23 +00:00
proto_item_append_text ( item , " %s%s: %s " , first ? " " : " , " ,
2014-09-17 16:39:22 +00:00
hf - > name , hf_try_val_to_str_const ( ( guint32 ) tmpval , hf , " Unknown " ) ) ;
2008-08-04 20:41:43 +00:00
first = FALSE ;
}
else if ( ! ( flags & BMT_NO_INT ) ) {
2013-06-27 18:40:08 +00:00
char buf [ 32 ] ;
2013-06-28 19:34:48 +00:00
const char * out ;
2013-06-27 18:40:08 +00:00
2008-08-04 20:41:43 +00:00
if ( ! first ) {
proto_item_append_text ( item , " , " ) ;
}
2014-09-17 16:39:22 +00:00
out = hfinfo_number_value_format ( hf , buf , ( guint32 ) tmpval ) ;
2013-06-28 19:34:48 +00:00
proto_item_append_text ( item , " %s: %s " , hf - > name , out ) ;
2008-08-04 20:41:43 +00:00
first = FALSE ;
2006-11-27 14:50:23 +00:00
}
break ;
case FT_BOOLEAN :
2008-08-04 20:41:43 +00:00
if ( hf - > strings & & ! ( flags & BMT_NO_TFS ) ) {
/* If we have true/false strings, emit full - otherwise messages
might look weird */
const struct true_false_string * tfs =
( const struct true_false_string * ) hf - > strings ;
if ( tmpval ) {
proto_item_append_text ( item , " %s%s: %s " , first ? " " : " , " ,
hf - > name , tfs - > true_string ) ;
first = FALSE ;
} else if ( ! ( flags & BMT_NO_FALSE ) ) {
proto_item_append_text ( item , " %s%s: %s " , first ? " " : " , " ,
hf - > name , tfs - > false_string ) ;
first = FALSE ;
}
} else if ( hf - > bitmask & value ) {
/* If the flag is set, show the name */
proto_item_append_text ( item , " %s%s " , first ? " " : " , " , hf - > name ) ;
first = FALSE ;
2006-11-27 14:50:23 +00:00
}
break ;
default :
2015-04-19 21:26:54 +00:00
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
break ;
2006-11-27 14:50:23 +00:00
}
fields + + ;
}
2008-08-04 20:41:43 +00:00
return first ;
}
2016-02-01 23:19:10 +00:00
/* This function will dissect a sequence of bytes that describe a
* bitmask and supply the value of that sequence through a pointer .
* hf_hdr is a 8 / 16 / 24 / 32 / 40 / 48 / 56 / 64 bit integer that describes the bitmask
* to be dissected .
* This field will form an expansion under which the individual fields of the
* bitmask is dissected and displayed .
* This field must be of the type FT_ [ U ] INT { 8 | 16 | 24 | 32 | 40 | 48 | 56 | 64 } .
*
* fields is an array of pointers to int that lists all the fields of the
* bitmask . These fields can be either of the type FT_BOOLEAN for flags
* or another integer of the same type / size as hf_hdr with a mask specified .
* This array is terminated by a NULL entry .
*
* FT_BOOLEAN bits that are set to 1 will have the name added to the expansion .
* FT_integer fields that have a value_string attached will have the
* matched string displayed on the expansion line .
*/
proto_item *
proto_tree_add_bitmask_ret_uint64 ( proto_tree * parent_tree , tvbuff_t * tvb ,
const guint offset , const int hf_hdr ,
const gint ett , const int * * fields ,
const guint encoding , guint64 * retval )
{
return proto_tree_add_bitmask_with_flags_ret_uint64 ( parent_tree , tvb , offset , hf_hdr , ett , fields , encoding , BMT_NO_INT | BMT_NO_TFS , retval ) ;
}
2008-08-04 20:41:43 +00:00
/* This function will dissect a sequence of bytes that describe a
* bitmask .
2016-02-01 23:19:10 +00:00
* hf_hdr is a 8 / 16 / 24 / 32 / 40 / 48 / 56 / 64 bit integer that describes the bitmask
* to be dissected .
2008-08-04 20:41:43 +00:00
* This field will form an expansion under which the individual fields of the
* bitmask is dissected and displayed .
2016-02-01 23:19:10 +00:00
* This field must be of the type FT_ [ U ] INT { 8 | 16 | 24 | 32 | 40 | 48 | 56 | 64 } .
2008-08-04 20:41:43 +00:00
*
* fields is an array of pointers to int that lists all the fields of the
* bitmask . These fields can be either of the type FT_BOOLEAN for flags
* or another integer of the same type / size as hf_hdr with a mask specified .
* This array is terminated by a NULL entry .
*
* FT_BOOLEAN bits that are set to 1 will have the name added to the expansion .
2009-09-06 07:24:54 +00:00
* FT_integer fields that have a value_string attached will have the
2008-08-04 20:41:43 +00:00
* matched string displayed on the expansion line .
*/
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_bitmask ( proto_tree * parent_tree , tvbuff_t * tvb ,
const guint offset , const int hf_hdr ,
const gint ett , const int * * fields ,
2011-10-24 19:52:43 +00:00
const guint encoding )
2015-04-12 23:12:35 +00:00
{
return proto_tree_add_bitmask_with_flags ( parent_tree , tvb , offset , hf_hdr , ett , fields , encoding , BMT_NO_INT | BMT_NO_TFS ) ;
}
2016-02-01 23:19:10 +00:00
/* The same as proto_tree_add_bitmask_ret_uint64(), but uses user-supplied flags to determine
* what data is appended to the header .
*/
proto_item *
proto_tree_add_bitmask_with_flags_ret_uint64 ( proto_tree * parent_tree , tvbuff_t * tvb , const guint offset ,
const int hf_hdr , const gint ett , const int * * fields , const guint encoding , const int flags ,
guint64 * retval )
{
proto_item * item = NULL ;
header_field_info * hf ;
int len ;
guint64 value ;
PROTO_REGISTRAR_GET_NTH ( hf_hdr , hf ) ;
DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL ( hf ) ;
len = ftype_length ( hf - > type ) ;
value = get_uint64_value ( parent_tree , tvb , offset , len , encoding ) ;
if ( parent_tree ) {
item = proto_tree_add_item ( parent_tree , hf_hdr , tvb , offset , len , encoding ) ;
proto_item_add_bitmask_tree ( item , tvb , offset , len , ett , fields ,
flags , FALSE , FALSE , NULL , value ) ;
}
* retval = value ;
return item ;
}
/* The same as proto_tree_add_bitmask_ret_uint64(), but uses user-supplied flags to determine
2015-04-12 23:12:35 +00:00
* what data is appended to the header .
*/
proto_item *
proto_tree_add_bitmask_with_flags ( proto_tree * parent_tree , tvbuff_t * tvb , const guint offset ,
const int hf_hdr , const gint ett , const int * * fields , const guint encoding , const int flags )
2008-08-04 20:41:43 +00:00
{
2012-03-14 17:11:39 +00:00
proto_item * item = NULL ;
2008-08-04 20:41:43 +00:00
header_field_info * hf ;
2012-03-14 17:11:39 +00:00
int len ;
2016-02-01 23:19:10 +00:00
guint64 value ;
2008-08-04 20:41:43 +00:00
2014-04-24 15:26:22 +00:00
PROTO_REGISTRAR_GET_NTH ( hf_hdr , hf ) ;
2014-12-22 00:09:15 +00:00
DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL ( hf ) ;
2008-08-04 20:41:43 +00:00
if ( parent_tree ) {
2016-02-01 23:19:10 +00:00
len = ftype_length ( hf - > type ) ;
2013-08-17 07:16:12 +00:00
item = proto_tree_add_item ( parent_tree , hf_hdr , tvb , offset , len , encoding ) ;
2016-02-01 23:19:10 +00:00
value = get_uint64_value ( parent_tree , tvb , offset , len , encoding ) ;
proto_item_add_bitmask_tree ( item , tvb , offset , len , ett , fields ,
flags , FALSE , FALSE , NULL , value ) ;
2008-08-04 20:41:43 +00:00
}
return item ;
}
2015-04-12 23:12:35 +00:00
/* Similar to proto_tree_add_bitmask(), but with a passed in value (presumably because it
can ' t be retrieved directly from tvb ) */
2014-11-29 20:58:56 +00:00
proto_item *
2015-04-12 23:12:35 +00:00
proto_tree_add_bitmask_value ( proto_tree * parent_tree , tvbuff_t * tvb , const guint offset ,
const int hf_hdr , const gint ett , const int * * fields , const guint64 value )
{
return proto_tree_add_bitmask_value_with_flags ( parent_tree , tvb , offset ,
hf_hdr , ett , fields , value , BMT_NO_INT | BMT_NO_TFS ) ;
}
/* Similar to proto_tree_add_bitmask_value(), but with control of flag values */
WS_DLL_PUBLIC proto_item *
proto_tree_add_bitmask_value_with_flags ( proto_tree * parent_tree , tvbuff_t * tvb , const guint offset ,
const int hf_hdr , const gint ett , const int * * fields , const guint64 value , const int flags )
2014-11-29 20:58:56 +00:00
{
proto_item * item = NULL ;
header_field_info * hf ;
int len ;
PROTO_REGISTRAR_GET_NTH ( hf_hdr , hf ) ;
2014-12-22 00:09:15 +00:00
DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL ( hf ) ;
2014-11-29 20:58:56 +00:00
len = ftype_length ( hf - > type ) ;
if ( parent_tree ) {
2015-04-12 23:12:35 +00:00
if ( len < = 4 )
item = proto_tree_add_uint ( parent_tree , hf_hdr , tvb , offset , len , ( guint32 ) value ) ;
else
item = proto_tree_add_uint64 ( parent_tree , hf_hdr , tvb , offset , len , value ) ;
proto_item_add_bitmask_tree ( item , tvb , offset , len , ett , fields ,
2016-02-01 23:19:10 +00:00
flags , FALSE , FALSE , NULL , value ) ;
2014-11-29 20:58:56 +00:00
}
return item ;
}
2015-04-12 23:12:35 +00:00
/* Similar to proto_tree_add_bitmask(), but with no "header" item to group all of the fields */
void
proto_tree_add_bitmask_list ( proto_tree * tree , tvbuff_t * tvb , const guint offset ,
const int len , const int * * fields , const guint encoding )
{
2016-02-01 23:19:10 +00:00
guint64 value ;
if ( tree ) {
value = get_uint64_value ( tree , tvb , offset , len , encoding ) ;
2015-04-12 23:12:35 +00:00
proto_item_add_bitmask_tree ( NULL , tvb , offset , len , - 1 , fields ,
2016-02-01 23:19:10 +00:00
BMT_NO_APPEND , FALSE , TRUE , tree , value ) ;
}
2015-04-12 23:12:35 +00:00
}
2013-03-04 14:18:18 +00:00
/* The same as proto_tree_add_bitmask(), but using a caller-supplied length.
* This is intended to support bitmask fields whose lengths can vary , perhaps
* as the underlying standard evolves over time .
* With this API there is the possibility of being called to display more or
* less data than the dissector was coded to support .
* In such cases , it is assumed that bitmasks are extended on the MSb end .
* Thus when presented with " too much " or " too little " data , MSbits will be
* ignored or MSfields sacrificed .
*
* Only fields for which all defined bits are available are displayed .
*/
proto_item *
proto_tree_add_bitmask_len ( proto_tree * parent_tree , tvbuff_t * tvb ,
const guint offset , const guint len , const int hf_hdr ,
2013-10-03 01:54:02 +00:00
const gint ett , const int * * fields , struct expert_field * exp ,
2013-03-04 14:18:18 +00:00
const guint encoding )
{
proto_item * item = NULL ;
header_field_info * hf ;
2013-10-03 01:54:02 +00:00
guint decodable_len ;
guint decodable_offset ;
guint32 decodable_value ;
2016-02-01 23:19:10 +00:00
guint64 value ;
2013-03-04 14:18:18 +00:00
2014-04-24 15:26:22 +00:00
PROTO_REGISTRAR_GET_NTH ( hf_hdr , hf ) ;
2014-12-22 00:09:15 +00:00
DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL ( hf ) ;
2013-03-04 14:18:18 +00:00
2013-10-03 01:54:02 +00:00
decodable_offset = offset ;
decodable_len = MIN ( len , ( guint ) ftype_length ( hf - > type ) ) ;
2013-03-04 14:18:18 +00:00
2013-10-03 01:54:02 +00:00
/* If we are ftype_length-limited,
* make sure we decode as many LSBs as possible .
*/
if ( encoding = = ENC_BIG_ENDIAN ) {
decodable_offset + = ( len - decodable_len ) ;
}
2013-03-04 14:18:18 +00:00
2013-10-03 01:54:02 +00:00
if ( parent_tree ) {
2013-03-04 14:18:18 +00:00
decodable_value = get_uint_value ( parent_tree , tvb , decodable_offset ,
decodable_len , encoding ) ;
/* The root item covers all the bytes even if we can't decode them all */
item = proto_tree_add_uint ( parent_tree , hf_hdr , tvb , offset , len ,
decodable_value ) ;
2013-10-03 01:54:02 +00:00
}
2013-03-04 14:18:18 +00:00
2013-10-03 01:54:02 +00:00
if ( decodable_len < len ) {
/* Dissector likely requires updating for new protocol revision */
expert_add_info_format ( NULL , item , exp ,
" Only least-significant %d of %d bytes decoded " ,
decodable_len , len ) ;
}
2013-03-04 14:18:18 +00:00
2013-10-03 01:54:02 +00:00
if ( item ) {
2016-02-01 23:19:10 +00:00
value = get_uint64_value ( parent_tree , tvb , decodable_offset , decodable_len , encoding ) ;
2013-03-04 14:18:18 +00:00
proto_item_add_bitmask_tree ( item , tvb , decodable_offset , decodable_len ,
2016-02-01 23:19:10 +00:00
ett , fields , BMT_NO_INT | BMT_NO_TFS , FALSE , FALSE , NULL , value ) ;
2013-03-04 14:18:18 +00:00
}
return item ;
}
2008-08-04 20:41:43 +00:00
/* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
proto_item *
2010-04-26 20:48:13 +00:00
proto_tree_add_bitmask_text ( proto_tree * parent_tree , tvbuff_t * tvb ,
const guint offset , const guint len ,
const char * name , const char * fallback ,
const gint ett , const int * * fields ,
2011-10-24 19:52:43 +00:00
const guint encoding , const int flags )
2008-08-04 20:41:43 +00:00
{
proto_item * item = NULL ;
2016-02-01 23:19:10 +00:00
guint64 value ;
2008-08-04 20:41:43 +00:00
if ( parent_tree ) {
2015-09-21 02:20:40 +00:00
item = proto_tree_add_text_internal ( parent_tree , tvb , offset , len , " %s " , name ? name : " " ) ;
2016-02-01 23:19:10 +00:00
value = get_uint64_value ( parent_tree , tvb , offset , len , encoding ) ;
if ( proto_item_add_bitmask_tree ( item , tvb , offset , len , ett , fields ,
flags , TRUE , FALSE , NULL , value ) & & fallback ) {
2008-08-04 20:41:43 +00:00
/* Still at first item - append 'fallback' text if any */
proto_item_append_text ( item , " %s " , fallback ) ;
}
}
2006-11-27 14:50:23 +00:00
return item ;
}
2007-04-26 06:39:29 +00:00
proto_item *
2013-07-11 14:58:11 +00:00
proto_tree_add_bits_item ( proto_tree * tree , const int hfindex , tvbuff_t * tvb ,
2012-04-04 21:54:22 +00:00
const guint bit_offset , const gint no_of_bits ,
2011-09-27 12:04:29 +00:00
const guint encoding )
2007-04-26 06:39:29 +00:00
{
2012-03-14 17:11:39 +00:00
header_field_info * hfinfo ;
2013-12-23 17:20:07 +00:00
gint octet_length ;
gint octet_offset ;
2009-08-19 19:08:34 +00:00
2013-07-11 14:58:11 +00:00
PROTO_REGISTRAR_GET_NTH ( hfindex , hfinfo ) ;
2013-07-11 14:46:30 +00:00
2013-10-17 12:24:25 +00:00
octet_length = ( no_of_bits + 7 ) > > 3 ;
2013-07-11 14:46:30 +00:00
octet_offset = bit_offset > > 3 ;
2013-10-22 16:02:13 +00:00
test_length ( hfinfo , tvb , octet_offset , octet_length ) ;
2013-07-11 14:46:30 +00:00
/* Yes, we try to fake this item again in proto_tree_add_bits_ret_val()
* but only after doing a bunch more work ( which we can , in the common
* case , shortcut here ) .
*/
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hfinfo ) ;
2007-04-26 06:39:29 +00:00
2013-07-11 14:58:11 +00:00
return proto_tree_add_bits_ret_val ( tree , hfindex , tvb , bit_offset , no_of_bits , NULL , encoding ) ;
2007-04-26 06:39:29 +00:00
}
2010-01-23 16:17:17 +00:00
2007-12-07 18:50:41 +00:00
/*
2009-04-22 19:50:34 +00:00
* This function will dissect a sequence of bits that does not need to be byte aligned ; the bits
2010-01-23 16:17:17 +00:00
* set will be shown in the tree as . .10 10. . and the integer value returned if return_value is set .
2007-04-28 12:13:25 +00:00
* Offset should be given in bits from the start of the tvb .
2007-04-24 19:24:14 +00:00
*/
2010-05-02 15:37:23 +00:00
static proto_item *
2013-07-11 14:58:11 +00:00
_proto_tree_add_bits_ret_val ( proto_tree * tree , const int hfindex , tvbuff_t * tvb ,
2012-04-04 21:54:22 +00:00
const guint bit_offset , const gint no_of_bits ,
2011-09-27 12:04:29 +00:00
guint64 * return_value , const guint encoding )
2007-04-24 19:24:14 +00:00
{
2012-03-14 17:11:39 +00:00
gint offset ;
guint length ;
guint8 tot_no_bits ;
char * bf_str ;
char lbl_str [ ITEM_LABEL_LENGTH ] ;
guint64 value = 0 ;
proto_item * pi ;
2007-04-24 19:24:14 +00:00
header_field_info * hf_field ;
2012-03-14 17:11:39 +00:00
2009-12-28 21:20:27 +00:00
const true_false_string * tfstring ;
2007-04-24 19:24:14 +00:00
2009-08-21 17:11:02 +00:00
/* We can't fake it just yet. We have to fill in the 'return_value' parameter */
2013-07-11 14:58:11 +00:00
PROTO_REGISTRAR_GET_NTH ( hfindex , hf_field ) ;
2007-04-24 19:24:14 +00:00
2012-03-14 17:11:39 +00:00
if ( hf_field - > bitmask ! = 0 ) {
2015-01-18 17:15:26 +00:00
REPORT_DISSECTOR_BUG ( wmem_strdup_printf ( wmem_packet_scope ( ) ,
" Incompatible use of proto_tree_add_bits_ret_val "
" with field '%s' (%s) with bitmask != 0 " ,
hf_field - > abbrev , hf_field - > name ) ) ;
2008-04-16 09:49:39 +00:00
}
2008-11-03 07:32:55 +00:00
2012-03-14 17:11:39 +00:00
DISSECTOR_ASSERT ( no_of_bits > 0 ) ;
2008-11-03 07:32:55 +00:00
2007-04-28 12:13:25 +00:00
/* Byte align offset */
2007-04-24 19:24:14 +00:00
offset = bit_offset > > 3 ;
2007-12-07 18:50:41 +00:00
/*
2007-04-28 12:13:25 +00:00
* Calculate the number of octets used to hold the bits
*/
2012-03-15 14:15:48 +00:00
tot_no_bits = ( ( bit_offset & 0x7 ) + no_of_bits ) ;
2013-07-11 14:46:30 +00:00
length = ( tot_no_bits + 7 ) > > 3 ;
2007-04-24 19:24:14 +00:00
2012-03-14 17:11:39 +00:00
if ( no_of_bits < 65 ) {
2011-09-27 12:04:29 +00:00
value = tvb_get_bits64 ( tvb , bit_offset , no_of_bits , encoding ) ;
2012-03-15 14:15:48 +00:00
} else {
2007-05-18 16:46:35 +00:00
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
return NULL ;
}
2007-04-28 12:13:25 +00:00
2011-09-20 11:29:53 +00:00
/* Sign extend for signed types */
2012-03-14 17:11:39 +00:00
switch ( hf_field - > type ) {
case FT_INT8 :
case FT_INT16 :
case FT_INT24 :
case FT_INT32 :
2014-12-17 20:19:20 +00:00
case FT_INT40 :
case FT_INT48 :
case FT_INT56 :
2012-03-14 17:11:39 +00:00
case FT_INT64 :
2013-12-18 22:25:18 +00:00
value = ws_sign_ext64 ( value , no_of_bits ) ;
2012-03-14 17:11:39 +00:00
break ;
2011-09-20 11:29:53 +00:00
2012-03-14 17:11:39 +00:00
default :
break ;
2011-09-20 11:29:53 +00:00
}
2012-03-14 17:11:39 +00:00
if ( return_value ) {
* return_value = value ;
2008-11-03 07:32:55 +00:00
}
2007-04-28 12:13:25 +00:00
2009-08-21 17:11:02 +00:00
/* Coast clear. Try and fake it */
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hf_field ) ;
2009-08-21 17:11:02 +00:00
2011-09-16 06:12:12 +00:00
bf_str = decode_bits_in_field ( bit_offset , no_of_bits , value ) ;
2007-04-24 19:24:14 +00:00
2012-03-14 17:11:39 +00:00
switch ( hf_field - > type ) {
2007-04-28 12:13:25 +00:00
case FT_BOOLEAN :
2007-04-24 19:24:14 +00:00
/* Boolean field */
2009-12-28 21:20:27 +00:00
tfstring = ( const true_false_string * ) & tfs_true_false ;
if ( hf_field - > strings )
2012-03-14 17:11:39 +00:00
tfstring = ( const true_false_string * ) hf_field - > strings ;
2013-07-11 14:58:11 +00:00
return proto_tree_add_boolean_format ( tree , hfindex , tvb , offset , length , ( guint32 ) value ,
2011-09-16 06:12:12 +00:00
" %s = %s: %s " ,
bf_str , hf_field - > name ,
2014-09-17 16:39:22 +00:00
( guint64 ) value ? tfstring - > true_string : tfstring - > false_string ) ;
2007-04-24 19:24:14 +00:00
break ;
2008-11-03 07:32:55 +00:00
2007-04-28 12:13:25 +00:00
case FT_UINT8 :
case FT_UINT16 :
case FT_UINT24 :
case FT_UINT32 :
2013-07-11 14:58:11 +00:00
pi = proto_tree_add_uint ( tree , hfindex , tvb , offset , length , ( guint32 ) value ) ;
2013-06-28 21:46:41 +00:00
fill_label_number ( PITEM_FINFO ( pi ) , lbl_str , FALSE ) ;
2007-04-28 12:13:25 +00:00
break ;
2008-11-03 07:32:55 +00:00
2011-09-20 11:29:53 +00:00
case FT_INT8 :
case FT_INT16 :
case FT_INT24 :
case FT_INT32 :
2013-07-11 14:58:11 +00:00
pi = proto_tree_add_int ( tree , hfindex , tvb , offset , length , ( gint32 ) value ) ;
2013-06-28 21:46:41 +00:00
fill_label_number ( PITEM_FINFO ( pi ) , lbl_str , TRUE ) ;
2011-09-20 11:29:53 +00:00
break ;
2014-12-17 20:19:20 +00:00
case FT_UINT40 :
case FT_UINT48 :
case FT_UINT56 :
2007-04-28 12:13:25 +00:00
case FT_UINT64 :
2013-07-11 14:58:11 +00:00
pi = proto_tree_add_uint64 ( tree , hfindex , tvb , offset , length , value ) ;
2013-07-01 15:24:42 +00:00
fill_label_number64 ( PITEM_FINFO ( pi ) , lbl_str , FALSE ) ;
2007-04-24 19:24:14 +00:00
break ;
2008-11-03 07:32:55 +00:00
2014-12-17 20:19:20 +00:00
case FT_INT40 :
case FT_INT48 :
case FT_INT56 :
2011-09-20 11:29:53 +00:00
case FT_INT64 :
2013-07-11 14:58:11 +00:00
pi = proto_tree_add_int64 ( tree , hfindex , tvb , offset , length , ( gint64 ) value ) ;
2013-07-01 15:24:42 +00:00
fill_label_number64 ( PITEM_FINFO ( pi ) , lbl_str , TRUE ) ;
2011-09-20 11:29:53 +00:00
break ;
2007-04-24 19:24:14 +00:00
default :
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
return NULL ;
2007-04-28 12:13:25 +00:00
break ;
2007-04-24 19:24:14 +00:00
}
2011-09-16 06:12:12 +00:00
proto_item_set_text ( pi , " %s = %s " , bf_str , lbl_str ) ;
return pi ;
2007-04-28 12:13:25 +00:00
}
2008-10-10 17:00:38 +00:00
2012-02-29 17:13:43 +00:00
proto_item *
2013-07-11 14:58:11 +00:00
proto_tree_add_split_bits_item_ret_val ( proto_tree * tree , const int hfindex , tvbuff_t * tvb ,
2012-04-04 21:54:22 +00:00
const guint bit_offset , const crumb_spec_t * crumb_spec ,
2012-03-14 17:11:39 +00:00
guint64 * return_value )
{
proto_item * pi ;
gint no_of_bits ;
gint octet_offset ;
2012-04-04 21:54:22 +00:00
guint mask_initial_bit_offset ;
guint mask_greatest_bit_offset ;
2012-03-14 17:11:39 +00:00
guint octet_length ;
guint8 i ;
2015-01-08 18:59:33 +00:00
char bf_str [ 256 ] ;
2012-03-14 17:11:39 +00:00
char lbl_str [ ITEM_LABEL_LENGTH ] ;
guint64 value ;
guint64 composite_bitmask ;
guint64 composite_bitmap ;
header_field_info * hf_field ;
2012-02-29 17:13:43 +00:00
const true_false_string * tfstring ;
/* We can't fake it just yet. We have to fill in the 'return_value' parameter */
2013-07-11 14:58:11 +00:00
PROTO_REGISTRAR_GET_NTH ( hfindex , hf_field ) ;
2012-02-29 17:13:43 +00:00
2012-03-14 17:11:39 +00:00
if ( hf_field - > bitmask ! = 0 ) {
2015-01-18 17:15:26 +00:00
REPORT_DISSECTOR_BUG ( wmem_strdup_printf ( wmem_packet_scope ( ) ,
" Incompatible use of proto_tree_add_split_bits_item_ret_val "
" with field '%s' (%s) with bitmask != 0 " ,
hf_field - > abbrev , hf_field - > name ) ) ;
2012-03-14 17:11:39 +00:00
}
mask_initial_bit_offset = bit_offset % 8 ;
no_of_bits = 0 ;
value = 0 ;
i = 0 ;
mask_greatest_bit_offset = 0 ;
composite_bitmask = 0 ;
composite_bitmap = 0 ;
while ( crumb_spec [ i ] . crumb_bit_length ! = 0 ) {
guint64 crumb_mask , crumb_value ;
guint8 crumb_end_bit_offset ;
DISSECTOR_ASSERT ( i < 64 ) ;
crumb_value = tvb_get_bits64 ( tvb ,
bit_offset + crumb_spec [ i ] . crumb_bit_offset ,
crumb_spec [ i ] . crumb_bit_length ,
ENC_BIG_ENDIAN ) ;
value + = crumb_value ;
no_of_bits + = crumb_spec [ i ] . crumb_bit_length ;
/* The bitmask is 64 bit, left-aligned, starting at the first bit of the
octet containing the initial offset .
If the mask is beyond 32 bits , then give up on bit map display .
This could be improved in future , probably showing a table
of 32 or 64 bits per row */
if ( mask_greatest_bit_offset < 32 ) {
crumb_end_bit_offset = mask_initial_bit_offset
+ crumb_spec [ i ] . crumb_bit_offset
+ crumb_spec [ i ] . crumb_bit_length ;
2012-05-28 18:37:10 +00:00
crumb_mask = ( G_GUINT64_CONSTANT ( 1 ) < < crumb_spec [ i ] . crumb_bit_length ) - 1 ;
2012-03-14 17:11:39 +00:00
if ( crumb_end_bit_offset > mask_greatest_bit_offset ) {
mask_greatest_bit_offset = crumb_end_bit_offset ;
}
composite_bitmask | = ( crumb_mask < < ( 64 - crumb_end_bit_offset ) ) ;
composite_bitmap | = ( crumb_value < < ( 64 - crumb_end_bit_offset ) ) ;
}
/* Shift left for the next segment */
value < < = crumb_spec [ + + i ] . crumb_bit_length ;
}
/* Sign extend for signed types */
switch ( hf_field - > type ) {
case FT_INT8 :
case FT_INT16 :
case FT_INT24 :
case FT_INT32 :
2014-12-17 20:19:20 +00:00
case FT_INT40 :
case FT_INT48 :
case FT_INT56 :
2012-03-14 17:11:39 +00:00
case FT_INT64 :
2013-12-18 22:25:18 +00:00
value = ws_sign_ext64 ( value , no_of_bits ) ;
2012-03-14 17:11:39 +00:00
break ;
default :
break ;
}
if ( return_value ) {
* return_value = value ;
}
/* Coast clear. Try and fake it */
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hf_field ) ;
2012-03-14 17:11:39 +00:00
/* initialise the format string */
bf_str [ 0 ] = ' \0 ' ;
octet_offset = bit_offset > > 3 ;
/* Round up mask length to nearest octet */
octet_length = ( ( mask_greatest_bit_offset + 7 ) > > 3 ) ;
mask_greatest_bit_offset = octet_length < < 3 ;
/* As noted above, we currently only produce a bitmap if the crumbs span less than 4 octets of the tvb.
It would be a useful enhancement to eliminate this restriction . */
2014-10-16 12:04:57 +00:00
if ( mask_greatest_bit_offset > 0 & & mask_greatest_bit_offset < = 32 ) {
2012-03-14 17:11:39 +00:00
other_decode_bitfield_value ( bf_str ,
( guint32 ) ( composite_bitmap > > ( 64 - mask_greatest_bit_offset ) ) ,
( guint32 ) ( composite_bitmask > > ( 64 - mask_greatest_bit_offset ) ) ,
mask_greatest_bit_offset ) ;
}
switch ( hf_field - > type ) {
2012-02-29 17:13:43 +00:00
case FT_BOOLEAN : /* it is a bit odd to have a boolean encoded as split-bits, but possible, I suppose? */
/* Boolean field */
tfstring = ( const true_false_string * ) & tfs_true_false ;
if ( hf_field - > strings )
tfstring = ( const true_false_string * ) hf_field - > strings ;
2013-07-11 14:58:11 +00:00
return proto_tree_add_boolean_format ( tree , hfindex ,
2012-03-14 17:11:39 +00:00
tvb , octet_offset , octet_length , ( guint32 ) value ,
" %s = %s: %s " ,
bf_str , hf_field - > name ,
2014-09-17 16:39:22 +00:00
( guint64 ) value ? tfstring - > true_string : tfstring - > false_string ) ;
2012-02-29 17:13:43 +00:00
break ;
case FT_UINT8 :
case FT_UINT16 :
case FT_UINT24 :
case FT_UINT32 :
2013-07-11 14:58:11 +00:00
pi = proto_tree_add_uint ( tree , hfindex , tvb , octet_offset , octet_length , ( guint32 ) value ) ;
2013-06-28 21:46:41 +00:00
fill_label_number ( PITEM_FINFO ( pi ) , lbl_str , FALSE ) ;
2012-02-29 17:13:43 +00:00
break ;
case FT_INT8 :
case FT_INT16 :
case FT_INT24 :
case FT_INT32 :
2013-07-11 14:58:11 +00:00
pi = proto_tree_add_int ( tree , hfindex , tvb , octet_offset , octet_length , ( gint32 ) value ) ;
2013-06-28 21:46:41 +00:00
fill_label_number ( PITEM_FINFO ( pi ) , lbl_str , TRUE ) ;
2012-02-29 17:13:43 +00:00
break ;
2014-12-17 20:19:20 +00:00
case FT_UINT40 :
case FT_UINT48 :
case FT_UINT56 :
2012-02-29 17:13:43 +00:00
case FT_UINT64 :
2013-07-11 14:58:11 +00:00
pi = proto_tree_add_uint64 ( tree , hfindex , tvb , octet_offset , octet_length , value ) ;
2013-07-01 15:24:42 +00:00
fill_label_number64 ( PITEM_FINFO ( pi ) , lbl_str , FALSE ) ;
2012-02-29 17:13:43 +00:00
break ;
2014-12-17 20:19:20 +00:00
case FT_INT40 :
case FT_INT48 :
case FT_INT56 :
2012-02-29 17:13:43 +00:00
case FT_INT64 :
2013-07-11 14:58:11 +00:00
pi = proto_tree_add_int64 ( tree , hfindex , tvb , octet_offset , octet_length , ( gint64 ) value ) ;
2013-07-01 15:24:42 +00:00
fill_label_number64 ( PITEM_FINFO ( pi ) , lbl_str , TRUE ) ;
2012-02-29 17:13:43 +00:00
break ;
default :
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
return NULL ;
break ;
}
proto_item_set_text ( pi , " %s = %s " , bf_str , lbl_str ) ;
return pi ;
}
2012-03-14 17:11:39 +00:00
void
2013-07-11 14:58:11 +00:00
proto_tree_add_split_bits_crumb ( proto_tree * tree , const int hfindex , tvbuff_t * tvb , const guint bit_offset ,
2012-03-14 17:11:39 +00:00
const crumb_spec_t * crumb_spec , guint16 crumb_index )
2012-02-29 17:13:43 +00:00
{
2013-07-11 14:58:11 +00:00
header_field_info * hfinfo ;
2012-02-29 17:13:43 +00:00
2013-07-11 14:58:11 +00:00
PROTO_REGISTRAR_GET_NTH ( hfindex , hfinfo ) ;
2015-09-21 02:20:40 +00:00
proto_tree_add_text_internal ( tree , tvb ,
2012-03-14 17:11:39 +00:00
bit_offset > > 3 ,
( ( bit_offset + crumb_spec [ crumb_index ] . crumb_bit_length - 1 ) > > 3 ) - ( bit_offset > > 3 ) + 1 ,
" %s crumb %d of %s (decoded above) " ,
decode_bits_in_field ( bit_offset , crumb_spec [ crumb_index ] . crumb_bit_length ,
tvb_get_bits ( tvb ,
bit_offset ,
crumb_spec [ crumb_index ] . crumb_bit_length ,
ENC_BIG_ENDIAN ) ) ,
crumb_index ,
2013-07-11 14:58:11 +00:00
hfinfo - > name ) ;
2012-02-29 17:13:43 +00:00
}
2010-01-23 16:17:17 +00:00
proto_item *
2013-07-11 14:58:11 +00:00
proto_tree_add_bits_ret_val ( proto_tree * tree , const int hfindex , tvbuff_t * tvb ,
2012-04-04 21:54:22 +00:00
const guint bit_offset , const gint no_of_bits ,
2011-09-27 12:04:29 +00:00
guint64 * return_value , const guint encoding )
2010-05-02 15:37:23 +00:00
{
proto_item * item ;
2013-07-11 14:58:11 +00:00
if ( ( item = _proto_tree_add_bits_ret_val ( tree , hfindex , tvb ,
2012-03-14 17:11:39 +00:00
bit_offset , no_of_bits ,
return_value , encoding ) ) ) {
2010-05-02 15:37:23 +00:00
FI_SET_FLAG ( PNODE_FINFO ( item ) , FI_BITS_OFFSET ( bit_offset ) ) ;
FI_SET_FLAG ( PNODE_FINFO ( item ) , FI_BITS_SIZE ( no_of_bits ) ) ;
}
return item ;
}
static proto_item *
2013-07-11 14:58:11 +00:00
_proto_tree_add_bits_format_value ( proto_tree * tree , const int hfindex ,
2012-04-04 21:54:22 +00:00
tvbuff_t * tvb , const guint bit_offset ,
2010-04-26 20:48:13 +00:00
const gint no_of_bits , void * value_ptr ,
gchar * value_str )
2010-01-23 16:17:17 +00:00
{
2012-03-14 17:11:39 +00:00
gint offset ;
guint length ;
guint8 tot_no_bits ;
char * str ;
guint64 value = 0 ;
2010-01-23 16:17:17 +00:00
header_field_info * hf_field ;
/* We do not have to return a value, try to fake it as soon as possible */
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hf_field ) ;
2010-01-23 16:17:17 +00:00
2012-03-14 17:11:39 +00:00
if ( hf_field - > bitmask ! = 0 ) {
2015-01-18 17:15:26 +00:00
REPORT_DISSECTOR_BUG ( wmem_strdup_printf ( wmem_packet_scope ( ) ,
" Incompatible use of proto_tree_add_bits_format_value "
" with field '%s' (%s) with bitmask != 0 " ,
hf_field - > abbrev , hf_field - > name ) ) ;
2010-01-23 16:17:17 +00:00
}
DISSECTOR_ASSERT ( no_of_bits > 0 ) ;
/* Byte align offset */
offset = bit_offset > > 3 ;
/*
* Calculate the number of octets used to hold the bits
*/
2012-03-15 14:15:48 +00:00
tot_no_bits = ( ( bit_offset & 0x7 ) + no_of_bits ) ;
2012-03-14 17:11:39 +00:00
length = tot_no_bits > > 3 ;
2010-01-24 12:08:14 +00:00
/* If we are using part of the next octet, increase length by 1 */
if ( tot_no_bits & 0x07 )
2010-01-23 16:17:17 +00:00
length + + ;
2012-03-14 17:11:39 +00:00
if ( no_of_bits < 65 ) {
2012-02-29 17:13:43 +00:00
value = tvb_get_bits64 ( tvb , bit_offset , no_of_bits , ENC_BIG_ENDIAN ) ;
2012-03-14 17:11:39 +00:00
} else {
2010-01-23 16:17:17 +00:00
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
return NULL ;
}
2010-01-25 18:26:47 +00:00
str = decode_bits_in_field ( bit_offset , no_of_bits , value ) ;
2010-01-23 16:17:17 +00:00
2014-04-01 04:20:07 +00:00
g_strlcat ( str , " = " , 256 + 64 ) ;
g_strlcat ( str , hf_field - > name , 256 + 64 ) ;
2010-01-23 16:17:17 +00:00
/*
* This function does not receive an actual value but a dimensionless pointer to that value .
* For this reason , the type of the header field is examined in order to determine
* what kind of value we should read from this address .
* The caller of this function must make sure that for the specific header field type the address of
* a compatible value is provided .
*/
2012-03-14 17:11:39 +00:00
switch ( hf_field - > type ) {
2010-01-23 16:17:17 +00:00
case FT_BOOLEAN :
2013-07-11 14:58:11 +00:00
return proto_tree_add_boolean_format ( tree , hfindex , tvb , offset , length , * ( guint32 * ) value_ptr ,
2012-03-14 17:11:39 +00:00
" %s: %s " , str , value_str ) ;
2010-01-23 16:17:17 +00:00
break ;
case FT_UINT8 :
case FT_UINT16 :
case FT_UINT24 :
case FT_UINT32 :
2013-07-11 14:58:11 +00:00
return proto_tree_add_uint_format ( tree , hfindex , tvb , offset , length , * ( guint32 * ) value_ptr ,
2012-03-14 17:11:39 +00:00
" %s: %s " , str , value_str ) ;
2010-01-23 16:17:17 +00:00
break ;
2014-12-17 20:19:20 +00:00
case FT_UINT40 :
case FT_UINT48 :
case FT_UINT56 :
2010-01-23 16:17:17 +00:00
case FT_UINT64 :
2013-07-11 14:58:11 +00:00
return proto_tree_add_uint64_format ( tree , hfindex , tvb , offset , length , * ( guint64 * ) value_ptr ,
2012-03-14 17:11:39 +00:00
" %s: %s " , str , value_str ) ;
2010-01-23 16:17:17 +00:00
break ;
case FT_INT8 :
case FT_INT16 :
case FT_INT24 :
case FT_INT32 :
2013-07-11 14:58:11 +00:00
return proto_tree_add_int_format ( tree , hfindex , tvb , offset , length , * ( gint32 * ) value_ptr ,
2012-03-14 17:11:39 +00:00
" %s: %s " , str , value_str ) ;
2010-01-23 16:17:17 +00:00
break ;
2014-12-17 20:19:20 +00:00
case FT_INT40 :
case FT_INT48 :
case FT_INT56 :
2011-10-25 10:55:52 +00:00
case FT_INT64 :
2013-07-11 14:58:11 +00:00
return proto_tree_add_int64_format ( tree , hfindex , tvb , offset , length , * ( gint64 * ) value_ptr ,
2012-03-14 17:11:39 +00:00
" %s: %s " , str , value_str ) ;
2011-10-25 10:55:52 +00:00
break ;
2010-01-23 16:17:17 +00:00
case FT_FLOAT :
2013-07-11 14:58:11 +00:00
return proto_tree_add_float_format ( tree , hfindex , tvb , offset , length , * ( float * ) value_ptr ,
2012-03-14 17:11:39 +00:00
" %s: %s " , str , value_str ) ;
2010-01-23 16:17:17 +00:00
break ;
default :
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
return NULL ;
break ;
}
}
2013-03-24 10:53:31 +00:00
static proto_item *
2013-07-11 14:58:11 +00:00
proto_tree_add_bits_format_value ( proto_tree * tree , const int hfindex ,
2012-04-04 21:54:22 +00:00
tvbuff_t * tvb , const guint bit_offset ,
2010-05-02 15:37:23 +00:00
const gint no_of_bits , void * value_ptr ,
gchar * value_str )
{
proto_item * item ;
2013-07-11 14:58:11 +00:00
if ( ( item = _proto_tree_add_bits_format_value ( tree , hfindex ,
2012-03-14 17:11:39 +00:00
tvb , bit_offset , no_of_bits ,
value_ptr , value_str ) ) ) {
2010-05-02 15:37:23 +00:00
FI_SET_FLAG ( PNODE_FINFO ( item ) , FI_BITS_OFFSET ( bit_offset ) ) ;
FI_SET_FLAG ( PNODE_FINFO ( item ) , FI_BITS_SIZE ( no_of_bits ) ) ;
}
return item ;
}
2010-01-23 16:17:17 +00:00
# define CREATE_VALUE_STRING(dst,format,ap) \
2012-03-14 17:11:39 +00:00
va_start ( ap , format ) ; \
2015-01-11 00:04:06 +00:00
dst = wmem_strdup_vprintf ( wmem_packet_scope ( ) , format , ap ) ; \
2010-01-23 16:17:17 +00:00
va_end ( ap ) ;
proto_item *
2013-07-11 14:58:11 +00:00
proto_tree_add_uint_bits_format_value ( proto_tree * tree , const int hfindex ,
2012-04-04 21:54:22 +00:00
tvbuff_t * tvb , const guint bit_offset ,
2010-04-26 20:48:13 +00:00
const gint no_of_bits , guint32 value ,
const char * format , . . . )
2010-01-23 16:17:17 +00:00
{
va_list ap ;
2012-03-14 17:11:39 +00:00
gchar * dst ;
2010-01-23 16:17:17 +00:00
header_field_info * hf_field ;
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hf_field ) ;
2010-01-23 16:17:17 +00:00
2012-03-14 17:11:39 +00:00
switch ( hf_field - > type ) {
case FT_UINT8 :
case FT_UINT16 :
case FT_UINT24 :
case FT_UINT32 :
break ;
2010-01-23 16:17:17 +00:00
2012-03-14 17:11:39 +00:00
default :
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
return NULL ;
break ;
2010-01-23 16:17:17 +00:00
}
2012-03-14 17:11:39 +00:00
CREATE_VALUE_STRING ( dst , format , ap ) ;
2010-01-23 16:17:17 +00:00
2013-07-11 14:58:11 +00:00
return proto_tree_add_bits_format_value ( tree , hfindex , tvb , bit_offset , no_of_bits , & value , dst ) ;
2010-01-23 16:17:17 +00:00
}
2014-12-17 20:19:20 +00:00
proto_item *
proto_tree_add_uint64_bits_format_value ( proto_tree * tree , const int hfindex ,
tvbuff_t * tvb , const guint bit_offset ,
const gint no_of_bits , guint64 value ,
const char * format , . . . )
{
va_list ap ;
gchar * dst ;
header_field_info * hf_field ;
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-12-17 20:19:20 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hf_field ) ;
switch ( hf_field - > type ) {
case FT_UINT40 :
case FT_UINT48 :
case FT_UINT56 :
case FT_UINT64 :
break ;
default :
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
return NULL ;
break ;
}
CREATE_VALUE_STRING ( dst , format , ap ) ;
return proto_tree_add_bits_format_value ( tree , hfindex , tvb , bit_offset , no_of_bits , & value , dst ) ;
}
2010-01-23 16:17:17 +00:00
proto_item *
2013-07-11 14:58:11 +00:00
proto_tree_add_float_bits_format_value ( proto_tree * tree , const int hfindex ,
2012-04-04 21:54:22 +00:00
tvbuff_t * tvb , const guint bit_offset ,
2010-04-26 20:48:13 +00:00
const gint no_of_bits , float value ,
const char * format , . . . )
2010-01-23 16:17:17 +00:00
{
va_list ap ;
2012-03-14 17:11:39 +00:00
gchar * dst ;
2010-01-23 16:17:17 +00:00
header_field_info * hf_field ;
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hf_field ) ;
2010-01-23 16:17:17 +00:00
2014-12-21 23:17:13 +00:00
DISSECTOR_ASSERT_FIELD_TYPE ( hf_field , FT_FLOAT ) ;
2010-09-23 01:14:44 +00:00
2012-03-14 17:11:39 +00:00
CREATE_VALUE_STRING ( dst , format , ap ) ;
2010-01-23 16:17:17 +00:00
2013-07-11 14:58:11 +00:00
return proto_tree_add_bits_format_value ( tree , hfindex , tvb , bit_offset , no_of_bits , & value , dst ) ;
2010-01-23 16:17:17 +00:00
}
proto_item *
2013-07-11 14:58:11 +00:00
proto_tree_add_int_bits_format_value ( proto_tree * tree , const int hfindex ,
2012-04-04 21:54:22 +00:00
tvbuff_t * tvb , const guint bit_offset ,
2010-04-26 20:48:13 +00:00
const gint no_of_bits , gint32 value ,
const char * format , . . . )
2010-01-23 16:17:17 +00:00
{
va_list ap ;
2012-03-14 17:11:39 +00:00
gchar * dst ;
2010-01-23 16:17:17 +00:00
header_field_info * hf_field ;
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hf_field ) ;
2010-01-23 16:17:17 +00:00
2012-03-14 17:11:39 +00:00
switch ( hf_field - > type ) {
case FT_INT8 :
case FT_INT16 :
case FT_INT24 :
case FT_INT32 :
break ;
2010-01-23 16:17:17 +00:00
2012-03-14 17:11:39 +00:00
default :
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
return NULL ;
break ;
2010-01-23 16:17:17 +00:00
}
2012-03-14 17:11:39 +00:00
CREATE_VALUE_STRING ( dst , format , ap ) ;
2010-01-23 16:17:17 +00:00
2013-07-11 14:58:11 +00:00
return proto_tree_add_bits_format_value ( tree , hfindex , tvb , bit_offset , no_of_bits , & value , dst ) ;
2010-01-23 16:17:17 +00:00
}
2014-12-17 20:19:20 +00:00
proto_item *
proto_tree_add_int64_bits_format_value ( proto_tree * tree , const int hfindex ,
tvbuff_t * tvb , const guint bit_offset ,
const gint no_of_bits , gint64 value ,
const char * format , . . . )
{
va_list ap ;
gchar * dst ;
header_field_info * hf_field ;
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-12-17 20:19:20 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hf_field ) ;
switch ( hf_field - > type ) {
case FT_INT40 :
case FT_INT48 :
case FT_INT56 :
case FT_INT64 :
break ;
default :
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
return NULL ;
break ;
}
CREATE_VALUE_STRING ( dst , format , ap ) ;
return proto_tree_add_bits_format_value ( tree , hfindex , tvb , bit_offset , no_of_bits , & value , dst ) ;
}
2010-01-23 16:17:17 +00:00
proto_item *
2013-07-11 14:58:11 +00:00
proto_tree_add_boolean_bits_format_value ( proto_tree * tree , const int hfindex ,
2012-04-04 21:54:22 +00:00
tvbuff_t * tvb , const guint bit_offset ,
2010-04-26 20:48:13 +00:00
const gint no_of_bits , guint32 value ,
const char * format , . . . )
2010-01-23 16:17:17 +00:00
{
va_list ap ;
2012-03-14 17:11:39 +00:00
gchar * dst ;
2010-01-23 16:17:17 +00:00
header_field_info * hf_field ;
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hf_field ) ;
2010-01-23 16:17:17 +00:00
2014-12-21 23:17:13 +00:00
DISSECTOR_ASSERT_FIELD_TYPE ( hf_field , FT_BOOLEAN ) ;
2010-09-23 01:14:44 +00:00
2012-03-14 17:11:39 +00:00
CREATE_VALUE_STRING ( dst , format , ap ) ;
2010-01-23 16:17:17 +00:00
2013-07-11 14:58:11 +00:00
return proto_tree_add_bits_format_value ( tree , hfindex , tvb , bit_offset , no_of_bits , & value , dst ) ;
2010-01-23 16:17:17 +00:00
}
2014-12-17 20:19:20 +00:00
proto_item *
proto_tree_add_boolean_bits_format_value64 ( proto_tree * tree , const int hfindex ,
tvbuff_t * tvb , const guint bit_offset ,
const gint no_of_bits , guint64 value ,
const char * format , . . . )
{
va_list ap ;
gchar * dst ;
header_field_info * hf_field ;
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-12-17 20:19:20 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hf_field ) ;
DISSECTOR_ASSERT ( hf_field - > type = = FT_BOOLEAN ) ;
CREATE_VALUE_STRING ( dst , format , ap ) ;
return proto_tree_add_bits_format_value ( tree , hfindex , tvb , bit_offset , no_of_bits , & value , dst ) ;
}
2014-01-01 14:33:19 +00:00
proto_item *
proto_tree_add_ts_23_038_7bits_item ( proto_tree * tree , const int hfindex , tvbuff_t * tvb ,
const guint bit_offset , const gint no_of_chars )
{
proto_item * pi ;
header_field_info * hfinfo ;
gint byte_length ;
gint byte_offset ;
gchar * string ;
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hfinfo ) ;
2014-01-01 14:33:19 +00:00
2014-12-21 23:17:13 +00:00
DISSECTOR_ASSERT_FIELD_TYPE ( hfinfo , FT_STRING ) ;
2014-01-01 14:33:19 +00:00
byte_length = ( ( ( no_of_chars + 1 ) * 7 ) + ( bit_offset & 0x07 ) ) > > 3 ;
byte_offset = bit_offset > > 3 ;
string = tvb_get_ts_23_038_7bits_string ( wmem_packet_scope ( ) , tvb , bit_offset , no_of_chars ) ;
2014-04-13 16:53:29 +00:00
if ( hfinfo - > display = = STR_UNICODE ) {
DISSECTOR_ASSERT ( g_utf8_validate ( string , - 1 , NULL ) ) ;
}
pi = proto_tree_add_pi ( tree , hfinfo , tvb , byte_offset , & byte_length ) ;
DISSECTOR_ASSERT ( byte_length > = 0 ) ;
proto_tree_set_string ( PNODE_FINFO ( pi ) , string ) ;
return pi ;
}
proto_item *
proto_tree_add_ascii_7bits_item ( proto_tree * tree , const int hfindex , tvbuff_t * tvb ,
const guint bit_offset , const gint no_of_chars )
{
proto_item * pi ;
header_field_info * hfinfo ;
gint byte_length ;
gint byte_offset ;
gchar * string ;
2016-01-09 02:25:26 +00:00
CHECK_FOR_NULL_TREE ( tree ) ;
2014-09-12 21:18:49 +00:00
TRY_TO_FAKE_THIS_ITEM ( tree , hfindex , hfinfo ) ;
2014-04-13 16:53:29 +00:00
2014-12-21 23:17:13 +00:00
DISSECTOR_ASSERT_FIELD_TYPE ( hfinfo , FT_STRING ) ;
2014-04-13 16:53:29 +00:00
byte_length = ( ( ( no_of_chars + 1 ) * 7 ) + ( bit_offset & 0x07 ) ) > > 3 ;
byte_offset = bit_offset > > 3 ;
string = tvb_get_ascii_7bits_string ( wmem_packet_scope ( ) , tvb , bit_offset , no_of_chars ) ;
2014-01-01 14:33:19 +00:00
if ( hfinfo - > display = = STR_UNICODE ) {
DISSECTOR_ASSERT ( g_utf8_validate ( string , - 1 , NULL ) ) ;
}
pi = proto_tree_add_pi ( tree , hfinfo , tvb , byte_offset , & byte_length ) ;
DISSECTOR_ASSERT ( byte_length > = 0 ) ;
proto_tree_set_string ( PNODE_FINFO ( pi ) , string ) ;
return pi ;
}
2008-10-10 17:00:38 +00:00
guchar
proto_check_field_name ( const gchar * field_name )
{
2012-03-14 17:11:39 +00:00
return wrs_check_charset ( fld_abbrev_chars , field_name ) ;
2008-10-10 17:00:38 +00:00
}
2013-01-17 03:37:41 +00:00
2013-07-07 16:33:49 +00:00
gboolean
tree_expanded ( int tree_type )
{
g_assert ( tree_type > = 0 & & tree_type < num_tree_types ) ;
2015-04-30 18:13:50 +00:00
return tree_is_expanded [ tree_type > > 5 ] & ( 1U < < ( tree_type & 31 ) ) ;
2013-07-07 16:33:49 +00:00
}
void
tree_expanded_set ( int tree_type , gboolean value )
{
g_assert ( tree_type > = 0 & & tree_type < num_tree_types ) ;
2013-07-07 17:13:17 +00:00
if ( value )
2015-04-30 18:13:50 +00:00
tree_is_expanded [ tree_type > > 5 ] | = ( 1U < < ( tree_type & 31 ) ) ;
2013-07-07 17:13:17 +00:00
else
2015-04-30 18:13:50 +00:00
tree_is_expanded [ tree_type > > 5 ] & = ~ ( 1U < < ( tree_type & 31 ) ) ;
2013-07-07 16:33:49 +00:00
}
2013-01-17 03:37:41 +00:00
/*
* Editor modelines - http : //www.wireshark.org/tools/modelines.html
*
* Local variables :
* c - basic - offset : 8
* tab - width : 8
* indent - tabs - mode : t
* End :
*
* vi : set shiftwidth = 8 tabstop = 8 noexpandtab :
* : indentSize = 8 : tabSize = 8 : noTabs = false :
*/