diff --git a/doc/README.dissector b/doc/README.dissector index addd967d5a..97db00b14f 100644 --- a/doc/README.dissector +++ b/doc/README.dissector @@ -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 diff --git a/epan/addr_resolv.c b/epan/addr_resolv.c index 648d6274dc..8aab2bdc9c 100644 --- a/epan/addr_resolv.c +++ b/epan/addr_resolv.c @@ -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) { diff --git a/epan/addr_resolv.h b/epan/addr_resolv.h index b3d1f70297..13e48df667 100644 --- a/epan/addr_resolv.h +++ b/epan/addr_resolv.h @@ -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 " ()" 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 */ diff --git a/epan/dissectors/packet-dccp.c b/epan/dissectors/packet-dccp.c index 0caef2e8b6..9e6dd39788 100644 --- a/epan/dissectors/packet-dccp.c +++ b/epan/dissectors/packet-dccp.c @@ -56,6 +56,8 @@ #include #include #include +#include + #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 } }, diff --git a/epan/dissectors/packet-sctp.c b/epan/dissectors/packet-sctp.c index 21720a7183..2cbdddb7ef 100644 --- a/epan/dissectors/packet-sctp.c +++ b/epan/dissectors/packet-sctp.c @@ -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 } }, diff --git a/epan/dissectors/packet-tcp.c b/epan/dissectors/packet-tcp.c index 21011f470c..36c82b701a 100644 --- a/epan/dissectors/packet-tcp.c +++ b/epan/dissectors/packet-tcp.c @@ -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)); diff --git a/epan/dissectors/packet-udp.c b/epan/dissectors/packet-udp.c index d0acf286ad..800f1e8f4b 100644 --- a/epan/dissectors/packet-udp.c +++ b/epan/dissectors/packet-udp.c @@ -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"); diff --git a/epan/proto.c b/epan/proto.c index 3bbb04c0fe..5e6b032227 100644 --- a/epan/proto.c +++ b/epan/proto.c @@ -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); diff --git a/epan/proto.h b/epan/proto.h index 3f0cef278d..0b98ba39e5 100644 --- a/epan/proto.h +++ b/epan/proto.h @@ -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