diff --git a/debian/libwireshark0.symbols b/debian/libwireshark0.symbols index a32d22a510..f6aae54821 100644 --- a/debian/libwireshark0.symbols +++ b/debian/libwireshark0.symbols @@ -979,6 +979,8 @@ libwireshark.so.0 libwireshark0 #MINVER# proto_tree_add_ipxnet_format_value@Base 1.9.1 proto_tree_add_item@Base 1.9.1 proto_tree_add_item_new@Base 1.12.0~rc1 + proto_tree_add_item_ret_int@Base 1.9.4 + proto_tree_add_item_ret_uint@Base 1.9.4 proto_tree_add_none_format@Base 1.9.1 proto_tree_add_protocol_format@Base 1.9.1 proto_tree_add_string@Base 1.9.1 diff --git a/doc/README.dissector b/doc/README.dissector index abe33c0e7d..1440370ae3 100644 --- a/doc/README.dissector +++ b/doc/README.dissector @@ -1125,6 +1125,14 @@ protocol or field labels to the proto_tree: proto_item* proto_tree_add_item(tree, id, tvb, start, length, encoding); + proto_item* + proto_tree_add_item_ret_int(tree, id, tvb, start, length, encoding, + *retval); + + proto_item* + proto_tree_add_item_ret_uint(tree, id, tvb, start, length, encoding, + *retval); + proto_item* proto_tree_add_subtree(tree, tvb, start, length, idx, tree_item, text); @@ -1532,6 +1540,12 @@ Subarea Nodes. The user does not have to shift the value of the FID to the high nibble of the byte ("sna.th.fid == 0xf0") as was necessary in the past. +proto_tree_add_item_ret_XXX() +------------------------------ +proto_tree_add_item_ret_XXX is used when you want the displayed value returned +for futher processing only integer and unsigned integer types up to 32 bits are +supported usage of proper FT_ is checked. + proto_tree_add_XXX_item() --------------------- proto_tree_add_XXX_item is used when you wish to do no special formatting, diff --git a/epan/dissectors/packet-tcp.c b/epan/dissectors/packet-tcp.c index a478010e83..c47c4ca05f 100644 --- a/epan/dissectors/packet-tcp.c +++ b/epan/dissectors/packet-tcp.c @@ -2622,7 +2622,8 @@ static void dissect_tcpopt_wscale(const ip_tcp_opt *optp _U_, tvbuff_t *tvb, int offset, guint optlen _U_, packet_info *pinfo, proto_tree *opt_tree, void *data _U_) { - guint8 val, shift; + guint8 val; + guint32 shift; proto_item *wscale_pi, *shift_pi, *gen_pi; proto_tree *wscale_tree; struct tcp_analysis *tcpd=NULL; @@ -2637,9 +2638,7 @@ dissect_tcpopt_wscale(const ip_tcp_opt *optp _U_, tvbuff_t *tvb, proto_tree_add_item(wscale_tree, hf_tcp_option_len, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; - shift_pi = proto_tree_add_item(wscale_tree, hf_tcp_option_wscale_shift, tvb, - offset, 1, ENC_BIG_ENDIAN); - shift = tvb_get_guint8(tvb, offset); + shift_pi = proto_tree_add_item_ret_uint(wscale_tree, hf_tcp_option_wscale_shift, tvb, offset, 1, ENC_BIG_ENDIAN, &shift); if (shift > 14) { /* RFC 1323: "If a Window Scale option is received with a shift.cnt * value exceeding 14, the TCP should log the error but use 14 instead @@ -2785,14 +2784,12 @@ dissect_tcpopt_timestamp(const ip_tcp_opt *optp _U_, tvbuff_t *tvb, proto_tree_add_item(ts_tree, hf_tcp_option_len, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; - proto_tree_add_item(ts_tree, hf_tcp_option_timestamp_tsval, tvb, offset, - 4, ENC_BIG_ENDIAN); - ts_val = tvb_get_ntohl(tvb, offset); + proto_tree_add_item_ret_uint(ts_tree, hf_tcp_option_timestamp_tsval, tvb, offset, + 4, ENC_BIG_ENDIAN, &ts_val); offset += 4; - proto_tree_add_item(ts_tree, hf_tcp_option_timestamp_tsecr, tvb, offset, - 4, ENC_BIG_ENDIAN); - ts_ecr = tvb_get_ntohl(tvb, offset); + proto_tree_add_item_ret_uint(ts_tree, hf_tcp_option_timestamp_tsecr, tvb, offset, + 4, ENC_BIG_ENDIAN, &ts_ecr); /* offset += 4; */ proto_item_append_text(ti, "TSval %u, TSecr %u", ts_val, ts_ecr); @@ -4307,7 +4304,7 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint8 th_off_x2; /* combines th_off and th_x2 */ guint16 th_sum; - guint16 th_urp; + guint32 th_urp; proto_tree *tcp_tree = NULL, *field_tree = NULL; proto_item *ti = NULL, *tf, *hidden_item; proto_item *options_item; @@ -4847,13 +4844,13 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) } } - th_urp = tvb_get_ntohs(tvb, offset + 18); - item = proto_tree_add_item(tcp_tree, hf_tcp_urgent_pointer, tvb, offset + 18, 2, ENC_BIG_ENDIAN); + item = proto_tree_add_item_ret_uint(tcp_tree, hf_tcp_urgent_pointer, tvb, offset + 18, 2, ENC_BIG_ENDIAN, &th_urp); + if (tcph->th_flags & TH_URG) { /* Export the urgent pointer, for the benefit of protocols such as rlogin. */ tcpinfo.urgent = TRUE; - tcpinfo.urgent_pointer = th_urp; + tcpinfo.urgent_pointer = (guint16)th_urp; tcp_info_append_uint(pinfo, "Urg", th_urp); } else { tcpinfo.urgent = FALSE; diff --git a/epan/proto.c b/epan/proto.c index cbc761c0e5..e48566363a 100644 --- a/epan/proto.c +++ b/epan/proto.c @@ -2071,6 +2071,85 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree, return pi; } + +/* ok, so this is going to be ugly, but repeating this code in multiple functions +is also bad mojo, so I'm picking the lesser of two evils I think */ +#define PROTO_TREE_ADD_XXX_ITEM(ctype,gtype,hfinfo) \ + \ + DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!"); \ + /* 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_" #gtype "_item", \ + 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_ ## ctype ## _value(tree, tvb, start, length, encoding); \ + \ + if (retval) \ + *retval = value; \ + \ + TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo); \ + \ + new_fi = new_field_info(tree, hfinfo, tvb, start, length); \ + \ + if (new_fi == NULL) \ + return NULL; \ + \ + proto_tree_set_uint(new_fi, value); \ + \ + FI_SET_FLAG(new_fi, \ + (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN); \ + \ + return proto_tree_add_node(tree, new_fi) + + +proto_item * +proto_tree_add_item_ret_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, +const gint start, gint length, const guint encoding, +gint32 *retval) +{ + header_field_info *hfinfo = proto_registrar_get_nth(hfindex); + field_info *new_fi; + guint32 value; + + switch (hfinfo->type){ + case FT_INT8: + case FT_INT16: + case FT_INT24: + case FT_INT32: + break; + default: + DISSECTOR_ASSERT_NOT_REACHED(); + } + PROTO_TREE_ADD_XXX_ITEM(int, gint32, hfinfo); +} + +proto_item * +proto_tree_add_item_ret_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, +const gint start, gint length, const guint encoding, +guint32 *retval) +{ + header_field_info *hfinfo = proto_registrar_get_nth(hfindex); + field_info *new_fi; + guint32 value; + + switch (hfinfo->type){ + case FT_UINT8: + case FT_UINT16: + case FT_UINT24: + case FT_UINT32: + break; + default: + DISSECTOR_ASSERT_NOT_REACHED(); + } + PROTO_TREE_ADD_XXX_ITEM(int, gint32, hfinfo); +} + /* Gets data from tvbuff, adds it to proto_tree, increments offset, and returns proto_item* */ proto_item * diff --git a/epan/proto.h b/epan/proto.h index f0222e01f8..45fb0506ba 100644 --- a/epan/proto.h +++ b/epan/proto.h @@ -980,6 +980,43 @@ WS_DLL_PUBLIC proto_item * proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb, const gint start, gint length, const guint encoding); +/** 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, and the retrieved +value is also set to *retval so the caller gets it back for other uses. + +This function retrieves the value even if the passed-in tree param is NULL, +so that it can be used by dissectors at all times to both get the value +and set the tree item to it. + +Like other proto_tree_add functions, if there is a tree and the value cannot +be decoded from the tvbuff, then an expert info error is reported. + +This function accepts ENC_LITTLE_ENDIAN and ENC_BIG_ENDIAN for native number +encoding in the tvbuff + +The length argument must +be set to the appropriate size of the native type as in other proto_add routines. + +Integers of 8, 16, 24 and 32 bits can be retreived with these functions. + +@param tree the tree to append this item to +@param hfindex field +@param tvb the tv buffer of the current data +@param start start of data in tvb (cannot be negative) +@param length length of data in tvb (for strings can be -1 for remaining) +@param encoding data encoding (e.g, ENC_LITTLE_ENDIAN, ENC_BIG_ENDIAN, ENC_ASCII|ENC_STRING, etc.) +@param[out] retval points to a gint/guint 8/16/32/64 or gfloat/gdouble which will be set +@param[out] err gets set to 0 if no failure, else the errno code (EDOM or ERANGE) +@return the newly created item, and value is set to the decoded value +*/ +WS_DLL_PUBLIC proto_item * +proto_tree_add_item_ret_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, +const gint start, gint length, const guint encoding, gint32 *retval); + +WS_DLL_PUBLIC proto_item * +proto_tree_add_item_ret_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, +const gint start, gint length, const guint encoding, guint32 *retval); + /** (DEPRECATED) Add a text-only node to a proto_tree. @param tree the tree to append this item to @param tvb the tv buffer of the current data diff --git a/tools/checkAPIs.pl b/tools/checkAPIs.pl index 598e95a03b..5352709c7b 100755 --- a/tools/checkAPIs.pl +++ b/tools/checkAPIs.pl @@ -1587,7 +1587,7 @@ sub check_proto_tree_add_XXX_encoding($$) $args =~ s/\(.*\)//sg; if ($args =~ /,\s*ENC_/xos) { - if (!($func =~ /proto_tree_add_(time|item|bitmask|bits_item|bits_ret_val)/xos) + if (!($func =~ /proto_tree_add_(time|item|bitmask|bits_item|bits_ret_val|item_ret_int|item_ret_uint)/xos) ) { print STDERR "Error: ".$filename." uses $func with ENC_*.\n"; $errorCount++;