Add BASE_PT_ field display types

Avoid displaying duplicate port numbers with transport name resolution disabled and
make some dissector code simpler.

Introduces port_with_resolution_to_str_buf() function and amends UDP/TCP/DCCP/SCTP to
use the new field display type.

Change-Id: Ifb97810b9c669ccbb1a310a2c0ffd6e2b63af210
Reviewed-on: https://code.wireshark.org/review/10625
Petri-Dish: Michael Mann <mmann78@netscape.net>
Reviewed-by: João Valverde <j@v6e.pt>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Michael Mann <mmann78@netscape.net>
This commit is contained in:
João Valverde 2015-10-05 11:53:07 +01:00 committed by Michael Mann
parent d52322efb3
commit a459ac72a2
9 changed files with 149 additions and 123 deletions

View File

@ -115,6 +115,10 @@ FIELDDISPLAY --For FT_UINT{8,16,24,32,40,48,56,64} and
or BASE_CUSTOM, possibly ORed with BASE_RANGE_STRING,
BASE_EXT_STRING or BASE_VAL64_STRING
--For FT_UINT16:
BASE_PT_UDP, BASE_PT_TCP, BASE_PT_DCCP or BASE_PT_SCTP
--For FT_ABSOLUTE_TIME:
ABSOLUTE_TIME_LOCAL, ABSOLUTE_TIME_UTC, or
@ -823,6 +827,11 @@ and the second argument is the value to be formatted.
Both custom_fmt_func_t and custom_fmt_func_64_t are defined in epan/proto.h.
For FT_UINT16 'display' can be used to select a transport layer protocol using one
of BASE_PT_UDP, BASE_PT_TCP, BASE_PT_DCCP or BASE_PT_SCTP. If transport name
resolution is enabled the port field label is displayed in decimal and as a well-known
service name (if one is available).
For FT_BOOLEAN fields that are also bitfields (i.e., 'bitmask' is non-zero),
'display' is used specify a "field-width" (i.e., tell the proto_tree how
wide the parent bitfield is). (If the FT_BOOLEAN 'bitmask' is zero, then

View File

@ -621,8 +621,8 @@ wmem_utoa(wmem_allocator_t *allocator, guint port)
}
static gchar
*serv_name_lookup(const guint port, const port_type proto)
static const gchar *
serv_name_lookup(const guint port, const port_type proto)
{
serv_port_t *serv_port_table;
gchar *name;
@ -659,10 +659,7 @@ static gchar
} /* proto */
}
/* getservbyport() was used here but it was to expensive, if the functionality is desired
* it would be better to pre parse etc/services or C:\Windows\System32\drivers\etc at
* startup
*/
/* Use numerical port string */
name = (gchar*)g_malloc(16);
guint32_to_str_buf(port, name, 16);
@ -3001,6 +2998,20 @@ sctp_port_to_display(wmem_allocator_t *allocator, guint port)
} /* sctp_port_to_display */
int
port_with_resolution_to_str_buf(gchar *buf, gulong buf_size, port_type port_typ, guint16 port_num)
{
const gchar *port_res_str;
if (!gbl_resolv_flags.transport_name ||
(port_typ == PT_NONE) ||
((port_res_str = serv_name_lookup(port_num, port_typ)) == NULL)) {
/* No name resolution support, just return port string */
return g_snprintf(buf, buf_size, "%u", port_num);
}
return g_snprintf(buf, buf_size, "%s (%u)", port_res_str, port_num);
}
gchar *
get_ether_name(const guint8 *addr)
{

View File

@ -53,7 +53,7 @@ extern "C" {
typedef struct _e_addr_resolve {
gboolean mac_name; /**< Whether to resolve Ethernet MAC to manufacturer names */
gboolean network_name; /**< Whether to resolve IPv4, IPv6, and IPX addresses into host names */
gboolean transport_name; /**< Whether to resolve TCP/UDP ports into service names */
gboolean transport_name; /**< Whether to resolve TCP/UDP/DCCP/SCTP ports into service names */
gboolean concurrent_dns; /**< Whether to use concurrent DNS name resolution */
gboolean dns_pkt_addr_resolution; /**< Whether to resolve addresses using captured DNS packets */
gboolean use_external_net_name_resolver; /**< Whether to system's configured DNS server to resolve names */
@ -140,6 +140,13 @@ extern gchar *dccp_port_to_display(wmem_allocator_t *allocator, guint port);
*/
WS_DLL_PUBLIC gchar *sctp_port_to_display(wmem_allocator_t *allocator, guint port);
/*
* port_with_resolution_to_str_buf() prints the "<resolved> (<numerical>)" port
* string to 'buf'. Return value is the same as g_snprintf().
*/
WS_DLL_PUBLIC int port_with_resolution_to_str_buf(gchar *buf, gulong buf_size,
port_type port_typ, guint16 port_num);
/*
* Asynchronous host name lookup initialization, processing, and cleanup
*/

View File

@ -56,6 +56,8 @@
#include <epan/expert.h>
#include <epan/conversation.h>
#include <epan/tap.h>
#include <wsutil/utf8_entities.h>
#include "packet-dccp.h"
/*
@ -607,6 +609,7 @@ dissect_dccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_
guint advertised_dccp_header_len = 0;
guint options_len = 0;
e_dccphdr *dccph;
gchar *src_port_str, *dst_port_str;
dccph = wmem_new0(wmem_packet_scope(), e_dccphdr);
@ -618,43 +621,33 @@ dissect_dccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_
col_set_str(pinfo->cinfo, COL_PROTOCOL, "DCCP");
col_clear(pinfo->cinfo, COL_INFO);
dccp_item = proto_tree_add_item(tree, proto_dccp, tvb, offset, -1, ENC_NA);
dccp_tree = proto_item_add_subtree(dccp_item, ett_dccp);
/* Extract generic header */
dccph->sport = tvb_get_ntohs(tvb, offset);
proto_tree_add_uint_format_value(dccp_tree, hf_dccp_srcport, tvb,
offset, 2, dccph->sport,
"%s (%u)",
dccp_port_to_display(wmem_packet_scope(), dccph->sport),
dccph->sport);
dccph->dport = tvb_get_ntohs(tvb, offset);
src_port_str = dccp_port_to_display(wmem_packet_scope(), dccph->sport);
dst_port_str = dccp_port_to_display(wmem_packet_scope(), dccph->dport);
col_add_lstr(pinfo->cinfo, COL_INFO,
src_port_str,
" "UTF8_RIGHTWARDS_ARROW" ",
dst_port_str,
COL_ADD_LSTR_TERMINATOR);
dccp_item = proto_tree_add_item(tree, proto_dccp, tvb, offset, -1, ENC_NA);
if (dccp_summary_in_tree) {
proto_item_append_text(dccp_item, ", Src Port: %s (%u)",
dccp_port_to_display(wmem_packet_scope(), dccph->sport), dccph->sport);
proto_item_append_text(dccp_item, ", Src Port: %s (%u), Dst Port: %s (%u)",
src_port_str, dccph->sport,
dst_port_str, dccph->dport);
}
col_add_fstr(pinfo->cinfo, COL_INFO,
"%s ", dccp_port_to_display(wmem_packet_scope(), dccph->sport));
hidden_item =
proto_tree_add_uint(dccp_tree, hf_dccp_port, tvb, offset, 2,
dccph->sport);
dccp_tree = proto_item_add_subtree(dccp_item, ett_dccp);
proto_tree_add_item(dccp_tree, hf_dccp_srcport, tvb, offset, 2, ENC_BIG_ENDIAN);
hidden_item = proto_tree_add_item(dccp_tree, hf_dccp_port, tvb, offset, 2, ENC_BIG_ENDIAN);
PROTO_ITEM_SET_HIDDEN(hidden_item);
offset += 2;
dccph->dport = tvb_get_ntohs(tvb, offset);
proto_tree_add_uint_format_value(dccp_tree, hf_dccp_dstport, tvb,
offset, 2, dccph->dport,
"%s (%u)",
dccp_port_to_display(wmem_packet_scope(), dccph->dport),
dccph->dport);
if (dccp_summary_in_tree) {
proto_item_append_text(dccp_item, ", Dst Port: %s (%u)",
dccp_port_to_display(wmem_packet_scope(), dccph->dport), dccph->dport);
}
col_append_fstr(pinfo->cinfo, COL_INFO, " > %s",
dccp_port_to_display(wmem_packet_scope(), dccph->dport));
hidden_item =
proto_tree_add_uint(dccp_tree, hf_dccp_port, tvb, offset, 2,
dccph->dport);
proto_tree_add_item(dccp_tree, hf_dccp_dstport, tvb, offset, 2, ENC_BIG_ENDIAN);
hidden_item = proto_tree_add_item(dccp_tree, hf_dccp_port, tvb, offset, 2, ENC_BIG_ENDIAN);
PROTO_ITEM_SET_HIDDEN(hidden_item);
offset += 2;
@ -1054,7 +1047,7 @@ proto_register_dccp(void)
&hf_dccp_srcport,
{
"Source Port", "dccp.srcport",
FT_UINT16, BASE_DEC, NULL, 0x0,
FT_UINT16, BASE_PT_DCCP, NULL, 0x0,
NULL, HFILL
}
},
@ -1062,7 +1055,7 @@ proto_register_dccp(void)
&hf_dccp_dstport,
{
"Destination Port", "dccp.dstport",
FT_UINT16, BASE_DEC, NULL, 0x0,
FT_UINT16, BASE_PT_DCCP, NULL, 0x0,
NULL, HFILL
}
},
@ -1070,7 +1063,7 @@ proto_register_dccp(void)
&hf_dccp_port,
{
"Source or Destination Port", "dccp.port",
FT_UINT16, BASE_DEC, NULL, 0x0,
FT_UINT16, BASE_PT_DCCP, NULL, 0x0,
NULL, HFILL
}
},

View File

@ -4736,9 +4736,9 @@ proto_register_sctp(void)
/* Setup list of header fields */
static hf_register_info hf[] = {
{ &hf_source_port, { "Source port", "sctp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
{ &hf_destination_port, { "Destination port", "sctp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
{ &hf_port, { "Port", "sctp.port", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
{ &hf_source_port, { "Source port", "sctp.srcport", FT_UINT16, BASE_PT_SCTP, NULL, 0x0, NULL, HFILL } },
{ &hf_destination_port, { "Destination port", "sctp.dstport", FT_UINT16, BASE_PT_SCTP, NULL, 0x0, NULL, HFILL } },
{ &hf_port, { "Port", "sctp.port", FT_UINT16, BASE_PT_SCTP, NULL, 0x0, NULL, HFILL } },
{ &hf_verification_tag, { "Verification tag", "sctp.verification_tag", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
{ &hf_checksum, { "Checksum", "sctp.checksum", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
{ &hf_checksum_bad, { "Bad checksum", "sctp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } },
@ -4786,7 +4786,7 @@ proto_register_sctp(void)
{ &hf_sack_chunk_gap_block_end_tsn, { "End TSN", "sctp.sack_gap_block_end_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
{ &hf_sack_chunk_number_tsns_gap_acked, { "Number of TSNs in gap acknowledgement blocks", "sctp.sack_number_of_tsns_gap_acked", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
{ &hf_sack_chunk_duplicate_tsn, { "Duplicate TSN", "sctp.sack_duplicate_tsn", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
{ &hf_nr_sack_chunk_ns, { "Nounce sum", "sctp.nr_sack_nounce_sum", FT_UINT8, BASE_DEC, NULL, SCTP_NR_SACK_CHUNK_NS_BIT, NULL, HFILL } },
{ &hf_nr_sack_chunk_ns, { "Nounce sum", "sctp.nr_sack_nounce_sum", FT_UINT8, BASE_DEC, NULL, SCTP_NR_SACK_CHUNK_NS_BIT, NULL, HFILL } },
{ &hf_nr_sack_chunk_cumulative_tsn_ack, { "Cumulative TSN ACK", "sctp.nr_sack_cumulative_tsn_ack", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
{ &hf_nr_sack_chunk_adv_rec_window_credit, { "Advertised receiver window credit (a_rwnd)", "sctp.nr_sack_a_rwnd", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
{ &hf_nr_sack_chunk_number_of_gap_blocks, { "Number of gap acknowledgement blocks", "sctp.nr_sack_number_of_gap_blocks", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },

View File

@ -4388,13 +4388,11 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
tcp_tree = proto_item_add_subtree(ti, ett_tcp);
p_add_proto_data(pinfo->pool, pinfo, proto_tcp, pinfo->curr_layer_num, tcp_tree);
proto_tree_add_uint_format_value(tcp_tree, hf_tcp_srcport, tvb, offset, 2, tcph->th_sport,
"%s (%u)", src_port_str, tcph->th_sport);
proto_tree_add_uint_format_value(tcp_tree, hf_tcp_dstport, tvb, offset + 2, 2, tcph->th_dport,
"%s (%u)", dst_port_str, tcph->th_dport);
hidden_item = proto_tree_add_uint(tcp_tree, hf_tcp_port, tvb, offset, 2, tcph->th_sport);
proto_tree_add_item(tcp_tree, hf_tcp_srcport, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(tcp_tree, hf_tcp_dstport, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
hidden_item = proto_tree_add_item(tcp_tree, hf_tcp_port, tvb, offset, 2, ENC_BIG_ENDIAN);
PROTO_ITEM_SET_HIDDEN(hidden_item);
hidden_item = proto_tree_add_uint(tcp_tree, hf_tcp_port, tvb, offset + 2, 2, tcph->th_dport);
hidden_item = proto_tree_add_item(tcp_tree, hf_tcp_port, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
PROTO_ITEM_SET_HIDDEN(hidden_item);
/* If we're dissecting the headers of a TCP packet in an ICMP packet
@ -5122,20 +5120,18 @@ tcp_cleanup(void)
void
proto_register_tcp(void)
{
static value_string tcp_ports[65536+1];
static hf_register_info hf[] = {
{ &hf_tcp_srcport,
{ "Source Port", "tcp.srcport", FT_UINT16, BASE_DEC, VALS(tcp_ports), 0x0,
{ "Source Port", "tcp.srcport", FT_UINT16, BASE_PT_TCP, NULL, 0x0,
NULL, HFILL }},
{ &hf_tcp_dstport,
{ "Destination Port", "tcp.dstport", FT_UINT16, BASE_DEC, VALS(tcp_ports), 0x0,
{ "Destination Port", "tcp.dstport", FT_UINT16, BASE_PT_TCP, NULL, 0x0,
NULL, HFILL }},
{ &hf_tcp_port,
{ "Source or Destination Port", "tcp.port", FT_UINT16, BASE_DEC, VALS(tcp_ports), 0x0,
{ "Source or Destination Port", "tcp.port", FT_UINT16, BASE_PT_TCP, NULL, 0x0,
NULL, HFILL }},
{ &hf_tcp_stream,
@ -5978,28 +5974,6 @@ proto_register_tcp(void)
module_t *tcp_module;
expert_module_t* expert_tcp;
{
int i, j;
gboolean transport_name_old = gbl_resolv_flags.transport_name;
gbl_resolv_flags.transport_name = TRUE;
for (i = 0, j = 0; i <= 65535; i++) {
const char *serv = tcp_port_to_display(wmem_epan_scope(), i);
if (serv) {
value_string *p = &tcp_ports[j++];
p->value = i;
p->strptr = serv;
}
}
/* NULL terminate */
tcp_ports[j].value = 0;
tcp_ports[j].strptr = NULL;
gbl_resolv_flags.transport_name = transport_name_old;
}
proto_tcp = proto_register_protocol("Transmission Control Protocol", "TCP", "tcp");
register_dissector("tcp", dissect_tcp, proto_tcp);
proto_register_field_array(proto_tcp, hf, array_length(hf));

View File

@ -54,8 +54,6 @@ static dissector_handle_t udplite_handle;
static int udp_tap = -1;
static int udp_follow_tap = -1;
static value_string udp_ports[65536+1];
static header_field_info *hfi_udp = NULL;
static header_field_info *hfi_udplite = NULL;
@ -63,15 +61,15 @@ static header_field_info *hfi_udplite = NULL;
#define UDPLITE_HFI_INIT HFI_INIT(proto_udplite)
static header_field_info hfi_udp_srcport UDP_HFI_INIT =
{ "Source Port", "udp.srcport", FT_UINT16, BASE_DEC, VALS(udp_ports), 0x0,
{ "Source Port", "udp.srcport", FT_UINT16, BASE_PT_UDP, NULL, 0x0,
NULL, HFILL };
static header_field_info hfi_udp_dstport UDP_HFI_INIT =
{ "Destination Port", "udp.dstport", FT_UINT16, BASE_DEC, VALS(udp_ports), 0x0,
{ "Destination Port", "udp.dstport", FT_UINT16, BASE_PT_UDP, NULL, 0x0,
NULL, HFILL };
static header_field_info hfi_udp_port UDP_HFI_INIT =
{ "Source or Destination Port", "udp.port", FT_UINT16, BASE_DEC, VALS(udp_ports), 0x0,
{ "Source or Destination Port", "udp.port", FT_UINT16, BASE_PT_UDP, NULL, 0x0,
NULL, HFILL };
static header_field_info hfi_udp_stream UDP_HFI_INIT =
@ -733,8 +731,7 @@ dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 ip_proto)
udp_tree = proto_item_add_subtree(ti, ett_udp);
p_add_proto_data(pinfo->pool, pinfo, hfi_udp->id, pinfo->curr_layer_num, udp_tree);
port_item = proto_tree_add_uint_format_value(udp_tree, hfi_udp_srcport.id, tvb, offset, 2, udph->uh_sport,
"%s (%u)", src_port_str, udph->uh_sport);
port_item = proto_tree_add_item(udp_tree, &hfi_udp_srcport, tvb, offset, 2, ENC_BIG_ENDIAN);
/* The beginning port number, 32768 + 666 (33434), is from LBL's traceroute.c source code and this code
* further assumes that 3 attempts are made per hop */
if ((udph->uh_sport > (32768 + 666)) && (udph->uh_sport <= (32768 + 666 + 30)))
@ -743,17 +740,16 @@ dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 ip_proto)
((udph->uh_sport - 32768 - 666 - 1) % 3) + 1
);
port_item = proto_tree_add_uint_format_value(udp_tree, hfi_udp_dstport.id, tvb, offset + 2, 2, udph->uh_dport,
"%s (%u)", dst_port_str, udph->uh_dport);
port_item = proto_tree_add_item(udp_tree, &hfi_udp_dstport, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
if ((udph->uh_dport > (32768 + 666)) && (udph->uh_dport <= (32768 + 666 + 30)))
expert_add_info_format(pinfo, port_item, &ei_udp_possible_traceroute, "Possible traceroute: hop #%u, attempt #%u",
((udph->uh_dport - 32768 - 666 - 1) / 3) + 1,
((udph->uh_dport - 32768 - 666 - 1) % 3) + 1
);
hidden_item = proto_tree_add_uint(udp_tree, &hfi_udp_port, tvb, offset, 2, udph->uh_sport);
hidden_item = proto_tree_add_item(udp_tree, &hfi_udp_port, tvb, offset, 2, ENC_BIG_ENDIAN);
PROTO_ITEM_SET_HIDDEN(hidden_item);
hidden_item = proto_tree_add_uint(udp_tree, &hfi_udp_port, tvb, offset+2, 2, udph->uh_dport);
hidden_item = proto_tree_add_item(udp_tree, &hfi_udp_port, tvb, offset+2, 2, ENC_BIG_ENDIAN);
PROTO_ITEM_SET_HIDDEN(hidden_item);
}
@ -1091,27 +1087,7 @@ proto_register_udp(void)
static decode_as_t udp_da = {"udp", "Transport", "udp.port", 3, 2, udp_da_values, "UDP", "port(s) as",
decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL};
int proto_udp, proto_udplite, i, j;
gboolean transport_name_old = gbl_resolv_flags.transport_name;
gbl_resolv_flags.transport_name = TRUE;
for (i = 0, j = 0; i <= 65535; i++) {
const char *serv = udp_port_to_display(wmem_epan_scope(), i);
if (serv) {
value_string *p = &udp_ports[j++];
p->value = i;
p->strptr = serv;
}
}
/* NULL terminate */
udp_ports[j].value = 0;
udp_ports[j].strptr = NULL;
gbl_resolv_flags.transport_name = transport_name_old;
int proto_udp, proto_udplite;
proto_udp = proto_register_protocol("User Datagram Protocol",
"UDP", "udp");

View File

@ -5923,8 +5923,30 @@ static const value_string hf_display[] = {
{ ABSOLUTE_TIME_LOCAL, "ABSOLUTE_TIME_LOCAL" },
{ ABSOLUTE_TIME_UTC, "ABSOLUTE_TIME_UTC" },
{ ABSOLUTE_TIME_DOY_UTC, "ABSOLUTE_TIME_DOY_UTC" },
{ BASE_PT_UDP, "BASE_PT_UDP" },
{ BASE_PT_TCP, "BASE_PT_TCP" },
{ BASE_PT_DCCP, "BASE_PT_DCCP" },
{ BASE_PT_SCTP, "BASE_PT_SCTP" },
{ 0, NULL } };
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;
}
/* temporary function containing assert part for easier profiling */
static void
tmp_fld_check_assert(header_field_info *hfinfo)
@ -6062,6 +6084,26 @@ tmp_fld_check_assert(header_field_info *hfinfo)
case FT_UINT48:
case FT_UINT56:
case FT_UINT64:
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;
}
/* Require integral types (other than frame number,
* which is always displayed in decimal) to have a
* number base.
@ -6992,7 +7034,7 @@ fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed)
fmtfunc(tmp, value);
label_fill(label_str, 0, hfinfo, tmp);
}
else if (hfinfo->strings && hfinfo->type != FT_FRAMENUM) { /* Add fill_label_framenum? */
else if (hfinfo->strings && hfinfo->type != FT_FRAMENUM) { /* Add fill_label_framenum? */
const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
out = hfinfo_number_vals_format(hfinfo, buf, value);
@ -7001,6 +7043,13 @@ fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed)
else
label_fill_descr(label_str, 0, hfinfo, val_str, out);
}
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);
}
else {
out = hfinfo_number_value_format(hfinfo, buf, value);

View File

@ -497,9 +497,8 @@ WS_DLL_PUBLIC WS_MSVC_NORETURN void proto_report_dissector_bug(const char *messa
/* For integral types, the display format is a BASE_* field_display_e value
* possibly ORed with BASE_*_STRING */
/** FIELD_DISPLAY_E_MASK selects the field_display_e value. Its current
* value means that we may have at most 16 field_display_e values. */
#define FIELD_DISPLAY_E_MASK 0x0F
/** FIELD_DISPLAY_E_MASK selects the field_display_e value. */
#define FIELD_DISPLAY_E_MASK 0xFF
typedef enum {
/* Integral types */
@ -514,28 +513,36 @@ typedef enum {
/* String types */
STR_ASCII = BASE_NONE, /**< shows non-printable ASCII characters as C-style escapes */
/* XXX, support for format_text_wsp() ? */
STR_UNICODE = 7, /**< shows non-printable UNICODE characters as \\uXXXX (XXX for now non-printable characters display depends on UI) */
STR_UNICODE = 7, /**< shows non-printable UNICODE characters as \\uXXXX (XXX for now non-printable characters display depends on UI) */
/* Byte types */
SEP_DOT = 8, /**< hexadecimal bytes with a period (.) between each byte */
SEP_DASH = 9, /**< hexadecimal bytes with a dash (-) between each byte */
SEP_COLON = 10, /**< hexadecimal bytes with a colon (:) between each byte */
SEP_SPACE = 11, /**< hexadecimal bytes with a space between each byte */
SEP_DOT = 8, /**< hexadecimal bytes with a period (.) between each byte */
SEP_DASH = 9, /**< hexadecimal bytes with a dash (-) between each byte */
SEP_COLON = 10, /**< hexadecimal bytes with a colon (:) between each byte */
SEP_SPACE = 11, /**< hexadecimal bytes with a space between each byte */
/* Address types */
BASE_NETMASK = 12 /**< Used for IPv4 address that shouldn't be resolved (like for netmasks) */
BASE_NETMASK = 12, /**< Used for IPv4 address that shouldn't be resolved (like for netmasks) */
/* Port types */
BASE_PT_UDP = 13, /**< UDP port */
BASE_PT_TCP = 14, /**< TCP port */
BASE_PT_DCCP = 15, /**< DCCP port */
BASE_PT_SCTP = 16, /**< SCTP port */
} field_display_e;
/* Following constants have to be ORed with a field_display_e when dissector
* want to use specials value-string MACROs for a header_field_info */
#define BASE_RANGE_STRING 0x10
#define BASE_EXT_STRING 0x20
#define BASE_VAL64_STRING 0x40
#define BASE_RANGE_STRING 0x100
#define BASE_EXT_STRING 0x200
#define BASE_VAL64_STRING 0x400
/** BASE_ values that cause the field value to be displayed twice */
#define IS_BASE_DUAL(b) ((b)==BASE_DEC_HEX||(b)==BASE_HEX_DEC)
/** BASE_PT_ values display decimal and transport port service name */
#define IS_BASE_PORT(b) (((b)==BASE_PT_UDP||(b)==BASE_PT_TCP||(b)==BASE_PT_DCCP||(b)==BASE_PT_SCTP))
/* For FT_ABSOLUTE_TIME, the display format is an absolute_time_display_e
* as per time_fmt.h. */
@ -554,7 +561,7 @@ struct _header_field_info {
const char *name; /**< [FIELDNAME] full name of this field */
const char *abbrev; /**< [FIELDABBREV] abbreviated name of this field */
enum ftenum type; /**< [FIELDTYPE] field type, one of FT_ (from ftypes.h) */
int display; /**< [FIELDDISPLAY] one of BASE_, or field bit-width if FT_BOOLEAN and non-zero bitmask */
int display; /**< [FIELDDISPLAY] one of BASE_, or field bit-width if FT_BOOLEAN and non-zero bitmask */
const void *strings; /**< [FIELDCONVERT] value_string, val64_string, range_string or true_false_string,
typically converted by VALS(), RVALS() or TFS().
If this is an FT_PROTOCOL then it points to the