diff options
author | John Tapparo <j.tapparo@f5.com> | 2018-11-16 09:44:50 -0500 |
---|---|---|
committer | Jörg Mayer <jmayer@loplof.de> | 2018-11-18 18:17:46 +0000 |
commit | 87862cb74b1518131cfb7dc90d32a7f8cbd3b5ae (patch) | |
tree | 5c06f4628cbd282b58b3b53b406c66da8916c3c7 | |
parent | 2294ac3dfe3e3bb1fd74bfa5cd5523fd45b22c1c (diff) |
f5ethtrailer: Update for new format trailers
Bug: 15284
Change-Id: I062b7d85b31ced6f4e8478cdbf048fc15b0edf5e
Reviewed-on: https://code.wireshark.org/review/30671
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot
Reviewed-by: Jörg Mayer <jmayer@loplof.de>
-rw-r--r-- | epan/dissectors/packet-f5ethtrailer.c | 817 | ||||
-rw-r--r-- | epan/dissectors/packet-f5ethtrailer.h | 4 |
2 files changed, 739 insertions, 82 deletions
diff --git a/epan/dissectors/packet-f5ethtrailer.c b/epan/dissectors/packet-f5ethtrailer.c index efc5589b38..f07bfd67b5 100644 --- a/epan/dissectors/packet-f5ethtrailer.c +++ b/epan/dissectors/packet-f5ethtrailer.c @@ -1,6 +1,6 @@ /* packet-f5ethtrailer.c * - * F5 Ethernet Trailer Copyright 2008-2017 F5 Networks + * F5 Ethernet Trailer Copyright 2008-2018 F5 Networks * * SPDX-License-Identifier: GPL-2.0-or-later */ @@ -233,13 +233,13 @@ Notes: #include "packet-f5ethtrailer.h" #undef F5FILEINFOTAP_SRC -#define PROTO_TAG_F5ETHTRAILER "F5ETHTRAILER" - /* Wireshark ID of the F5ETHTRAILER protocol */ static int proto_f5ethtrailer = -1; static int tap_f5ethtrailer = -1; static int proto_f5fileinfo = -1; static int tap_f5fileinfo = -1; +/** Helper dissector for DPT format noise */ +static int proto_f5ethtrailer_dpt_noise = -1; void proto_reg_handoff_f5ethtrailer(void); void proto_register_f5ethtrailer(void); @@ -248,9 +248,12 @@ void proto_reg_handoff_f5fileinfo(void); void proto_register_f5fileinfo(void); /* Common Fields */ +static gint hf_provider = -1; static gint hf_type = -1; static gint hf_length = -1; static gint hf_version = -1; +static gint hf_data = -1; +static gint hf_dpt_unknown = -1; /* Low */ static gint hf_low_id = -1; static gint hf_ingress = -1; @@ -305,11 +308,17 @@ static gint hf_tcp_tcpport = -1; static gint hf_udp_udpport = -1; #endif +static gint hf_dpt_magic = -1; +static gint hf_dpt_ver = -1; +static gint hf_dpt_len = -1; + static expert_field ei_f5eth_flowlost = EI_INIT; static expert_field ei_f5eth_flowreuse = EI_INIT; +static expert_field ei_f5eth_badlen = EI_INIT; /* These are the ids of the subtrees that we may be creating */ static gint ett_f5ethtrailer = -1; +static gint ett_f5ethtrailer_unknown = -1; static gint ett_f5ethtrailer_low = -1; static gint ett_f5ethtrailer_med = -1; static gint ett_f5ethtrailer_high = -1; @@ -344,6 +353,9 @@ static gint tap_tcp_enabled; * and in the info column information.) */ static const true_false_string f5tfs_ing = { "IN", "OUT" }; +/** Table containing subdissectors for different providers */ +static dissector_table_t provider_subdissector_table; + /*-----------------------------------------------------------------------------------------------*/ /** \brief Convert a Wireshark port type to a IP protocol number. @@ -1049,6 +1061,7 @@ static const guint8 fileinfomagic1[] = { #define F5_OFF_VERSION 2 #define F5_OFF_VALUE 3 +/** This is used only for legacy trailers. The highest version number is 3 for medium trailers. */ #define F5TRAILER_VER_MAX 3 #define F5TRAILER_TYPE(tvb, offset) (tvb_get_guint8(tvb, offset)) @@ -1073,6 +1086,8 @@ static const guint8 fileinfomagic1[] = { * Max length with RST cause in medium(v3) is 35 + 8 + 1 + 96 (might be 35+96)? * Min length is 8 on v9.4 medium detail. * Min length is 7 on v11.2 low trailer with no VIP name. + * + * These are only used for legacy trailers. */ #define F5_MIN_SANE 7 #define F5_MAX_SANE 140 @@ -1080,6 +1095,7 @@ static const guint8 fileinfomagic1[] = { #define F5_HIV0_LEN 42 +/* Legacy trailers */ #define F5_MEDV94_LEN 8 #define F5_MEDV10_LEN 21 #define F5_MEDV11_LEN 29 @@ -1105,6 +1121,36 @@ static const guint8 fileinfomagic1[] = { #define F5_LOWV1_LENMIN 7 #define F5TRL_LOWV1_VIPLEN(tvb, offset) tvb_get_guint8(tvb, (offset)+(F5_LOWV1_LENMIN-1)) +/* DPT trailers */ +#define F5_MEDV4_LENMIN 32 /**< Minimum length without TLV header */ +#define F5TRL_MEDV4_RSTCLEN(tvb, offset) tvb_get_guint8(tvb, (offset)+(F5_MEDV4_LENMIN-1)) +#define F5TRL_MEDV4_RSTCVER(tvb, offset) \ + ((tvb_get_guint8(tvb, (offset)+F5_MEDV4_LENMIN) & 0xfe) >> 1) +#define F5TRL_MEDV4_RSTCPEER(tvb, offset) (tvb_get_guint8(tvb, (offset)+F5_MEDV4_LENMIN) & 0x01) + +#define F5_DPT_V1_HDR_MAGIC_OFF 0 +#define F5_DPT_V1_HDR_MAGIC_LEN 4 +#define F5_DPT_V1_HDR_MAGIC 0xf5deb0f5 +#define F5_DPT_V1_HDR_LENGTH_OFF (F5_DPT_V1_HDR_MAGIC_OFF + F5_DPT_V1_HDR_MAGIC_LEN) +#define F5_DPT_V1_HDR_LENGTH_LEN 2 +#define F5_DPT_V1_HDR_VERSION_OFF (F5_DPT_V1_HDR_LENGTH_OFF + F5_DPT_V1_HDR_LENGTH_LEN) +#define F5_DPT_V1_HDR_VERSION_LEN 2 +#define F5_DPT_V1_HDR_VERSION_MIN 1 /**< Minimum DPT version handled by this dissector. */ +#define F5_DPT_V1_HDR_VERSION_MAX 1 /**< Maximum DPT version handled by this dissector. */ +#define F5_DPT_V1_HDR_LEN (F5_DPT_V1_HDR_VERSION_OFF + F5_DPT_V1_HDR_VERSION_LEN) + +#define F5_DPT_PROVIDER_NOISE 1 + +#define F5_DPT_V1_TLV_PROVIDER_OFF 0 +#define F5_DPT_V1_TLV_PROVIDER_LEN 2 +#define F5_DPT_V1_TLV_TYPE_OFF (F5_DPT_V1_TLV_PROVIDER_OFF + F5_DPT_V1_TLV_PROVIDER_LEN) +#define F5_DPT_V1_TLV_TYPE_LEN 2 +#define F5_DPT_V1_TLV_LENGTH_OFF (F5_DPT_V1_TLV_TYPE_OFF + F5_DPT_V1_TLV_TYPE_LEN) +#define F5_DPT_V1_TLV_LENGTH_LEN 2 +#define F5_DPT_V1_TLV_VERSION_OFF (F5_DPT_V1_TLV_LENGTH_OFF + F5_DPT_V1_TLV_LENGTH_LEN) +#define F5_DPT_V1_TLV_VERSION_LEN 2 +#define F5_DPT_V1_TLV_HDR_LEN (F5_DPT_V1_TLV_VERSION_OFF+F5_DPT_V1_TLV_VERSION_LEN) + /*===============================================================================================*/ /* This section is for performing analysis of the trailer information. */ @@ -1511,48 +1557,6 @@ static proto_item *displayIPv6as4( /*---------------------------------------------------------------------------*/ -/* Render the flow flags field */ -static guint render_flow_flags( - tvbuff_t *tvb, - packet_info *pinfo _U_, - proto_tree *tree, - guint offset, - guint8 trailer_type _U_, - guint8 trailer_length _U_, - guint8 trailer_ver, - f5eth_tap_data_t *tdata _U_) -{ - guint o; - - o = offset; - if(trailer_ver >= 3) { - proto_tree_add_item(tree, hf_cf_flags2, tvb, o, 4, ENC_BIG_ENDIAN); - o += 4; - } - proto_tree_add_item(tree, hf_cf_flags, tvb, o, 4, ENC_BIG_ENDIAN); - o += 4; - return(o - offset); -} /* render_flow_flags() */ - - -/*---------------------------------------------------------------------------*/ -/* Render the flow type field */ -static guint render_flow_type( - tvbuff_t *tvb, - packet_info *pinfo _U_, - proto_tree *tree, - guint offset, - guint8 trailer_type _U_, - guint8 trailer_length _U_, - guint8 trailer_ver _U_, - f5eth_tap_data_t *tdata _U_) -{ - proto_tree_add_item(tree, hf_flow_type, tvb, offset, 1, ENC_BIG_ENDIAN); - return(1); -} /* render_flow_type() */ - - -/*---------------------------------------------------------------------------*/ /* High level trailers */ static guint dissect_high_trailer( @@ -1699,7 +1703,6 @@ dissect_med_trailer( guint o; guint rstcauselen = 0; guint rstcausever = 0xff; - guint8 trailer_type; switch(trailer_ver) { case 0: @@ -1777,8 +1780,6 @@ dissect_med_trailer( o = offset; - /* We don't need to see type and versions of the TLV trailers. */ - trailer_type = tvb_get_guint8(tvb,o); proto_tree_add_item(tree, hf_type, tvb, o, 1, ENC_BIG_ENDIAN); o += 1; proto_tree_add_item(tree, hf_length, tvb, o, 1, ENC_BIG_ENDIAN); @@ -1814,8 +1815,14 @@ dissect_med_trailer( o += 8; } tdata->flows_set = 1; - o += render_flow_flags(tvb,pinfo,tree,o,trailer_type,trailer_length,trailer_ver,tdata); - o += render_flow_type(tvb,pinfo,tree,o,trailer_type,trailer_length,trailer_ver,tdata); + if(trailer_ver >= 3) { + proto_tree_add_item(tree, hf_cf_flags2, tvb, o, 4, ENC_BIG_ENDIAN); + o += 4; + } + proto_tree_add_item(tree, hf_cf_flags, tvb, o, 4, ENC_BIG_ENDIAN); + o += 4; + proto_tree_add_item(tree, hf_flow_type, tvb, o, 1, ENC_BIG_ENDIAN); + o += 1; } /* We do not need to do anything if we don't have a tree */ @@ -1907,7 +1914,6 @@ dissect_low_trailer( guint slot_display = 0; gint slot_display_field = -1; guint tmm; - guint8 trailer_type; switch(trailer_ver) { case 0: @@ -1977,8 +1983,6 @@ dissect_low_trailer( o = offset; - /* We don't need to see type and versions of the TLV trailers. */ - trailer_type = tvb_get_guint8(tvb,o); proto_tree_add_item(tree, hf_type, tvb, o, 1, ENC_BIG_ENDIAN); o += 1; proto_tree_add_item(tree, hf_length, tvb, o, 1, ENC_BIG_ENDIAN); @@ -2013,8 +2017,10 @@ dissect_low_trailer( PROTO_ITEM_SET_HIDDEN(pi); o += 4; tdata->flows_set = 1; - o += render_flow_flags(tvb,pinfo,tree,o,trailer_type,trailer_length,trailer_ver,tdata); - o += render_flow_type(tvb,pinfo,tree,o,trailer_type,trailer_length,trailer_ver,tdata); + proto_tree_add_item(tree, hf_cf_flags, tvb, o, 4, ENC_BIG_ENDIAN); + o += 4; + proto_tree_add_item(tree, hf_flow_type, tvb, o, 1, ENC_BIG_ENDIAN); + o += 1; } /* We do not need to do anything more if we don't have a tree */ @@ -2031,6 +2037,591 @@ dissect_low_trailer( return(trailer_length); } /* dissect_low_trailer() */ + +static void +render_f5dptv1_tlvhdr( + tvbuff_t *tvb, + packet_info *pinfo _U_, + proto_tree *tree, + void *data _U_, + gint offset +) { + proto_tree_add_item(tree, hf_provider, tvb, offset+F5_DPT_V1_TLV_PROVIDER_OFF, + F5_DPT_V1_TLV_PROVIDER_LEN, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_type, tvb, offset+F5_DPT_V1_TLV_TYPE_OFF, + F5_DPT_V1_TLV_TYPE_LEN, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_length, tvb, offset+F5_DPT_V1_TLV_LENGTH_OFF, + F5_DPT_V1_TLV_LENGTH_LEN, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_version, tvb, offset+F5_DPT_V1_TLV_VERSION_OFF, + F5_DPT_V1_TLV_VERSION_LEN, ENC_BIG_ENDIAN); +} /* render_f5dptv1_tlvhdr() */ + + +/*---------------------------------------------------------------------------*/ +/** \brief Render the data for DPT high noise trailer TLV + * + * @param tvb The tvbuff containing the TLV block (header and data) + * @param pinfo The pinfo structure for the frame + * @param tree The tree to render the TVB under + * @param data Pointer to tdata for the trailer + * @return The size of the TVB + */ +static int +dissect_dpt_trailer_noise_high( + tvbuff_t *tvb, + packet_info *pinfo, + proto_tree *tree, + void *data +) { + proto_item *pi; + gint o; + gint len; + gint ver; + guint8 ipproto; + f5eth_tap_data_t *tdata = (f5eth_tap_data_t *)data; + + DISSECTOR_ASSERT(tdata != NULL); + len = tvb_get_ntohs(tvb, F5_DPT_V1_TLV_LENGTH_OFF); + ver = tvb_get_ntohs(tvb, F5_DPT_V1_TLV_VERSION_OFF); + + /* Unknown version, cannot do anything */ + if(ver != 1) { + return(0); + } + + if(tree == NULL) { + /* We do not need to do anything if we do not have a tree */ + return(len); + } + + pi = proto_tree_add_item(tree, hf_high_id, tvb, 0, len, ENC_NA); + tree = proto_item_add_subtree(pi, ett_f5ethtrailer_high); + + render_f5dptv1_tlvhdr(tvb, pinfo, tree, data, 0); + + o = F5_DPT_V1_TLV_HDR_LEN; + + /* If there was no peer id in the medium trailer, then there is no peer flow information to + * render; skip it all. + */ + if(tdata->peer_flow == 0) { + proto_tree_add_item(tree, hf_peer_nopeer, tvb, o, len-o, ENC_NA); + return(len); + } + + /* Add in the high order structures. */ + ipproto = tvb_get_guint8(tvb,o); + proto_tree_add_item(tree, hf_peer_ipproto, tvb, o, 1, ENC_BIG_ENDIAN); + o += 1; + proto_tree_add_item(tree, hf_peer_vlan, tvb, o, 2, ENC_BIG_ENDIAN); + o += 2; + + /* peer remote address */ +#ifdef F5_POP_OTHERFIELDS + if(pop_other_fields) { + displayIPv6as4(tree, hf_ip_ipaddr, -1, tvb, o, TRUE); + pi = proto_tree_add_item(tree, hf_ip6_ip6addr, tvb, o, 16, ENC_NA); + PROTO_ITEM_SET_HIDDEN(pi); + } +#endif + displayIPv6as4(tree, hf_peer_remote_addr, hf_peer_remote_rtdom, tvb, o, FALSE); + displayIPv6as4(tree, hf_peer_ipaddr, hf_peer_rtdom, tvb, o, TRUE); + proto_tree_add_item(tree, hf_peer_remote_ip6addr, tvb, o, 16, ENC_NA); + pi = proto_tree_add_item(tree, hf_peer_ip6addr, tvb, o, 16, ENC_NA); + PROTO_ITEM_SET_HIDDEN(pi); + o += 16; + + /* peer local address */ +#ifdef F5_POP_OTHERFIELDS + if(pop_other_fields) { + displayIPv6as4(tree, hf_ip_ipaddr, -1, tvb, o, TRUE); + pi = proto_tree_add_item(tree, hf_ip6_ip6addr, tvb, o, 16, ENC_NA); + PROTO_ITEM_SET_HIDDEN(pi); + } +#endif + displayIPv6as4(tree, hf_peer_local_addr, hf_peer_local_rtdom, tvb, o, FALSE); + displayIPv6as4(tree, hf_peer_ipaddr, hf_peer_rtdom, tvb, o, TRUE); + proto_tree_add_item(tree, hf_peer_local_ip6addr, tvb, o, 16, ENC_NA); + pi = proto_tree_add_item(tree, hf_peer_ip6addr, tvb, o, 16, ENC_NA); + PROTO_ITEM_SET_HIDDEN(pi); + o += 16; + + /* peer remote port */ +#ifdef F5_POP_OTHERFIELDS + if(pop_other_fields) { + switch (ipproto) + { + case IP_PROTO_TCP: + pi = proto_tree_add_item(tree, hf_tcp_tcpport, tvb, o, 2, ENC_BIG_ENDIAN); + PROTO_ITEM_SET_HIDDEN(pi); + break; + case IP_PROTO_UDP: + pi = proto_tree_add_item(tree, hf_udp_udpport, tvb, o, 2, ENC_BIG_ENDIAN); + PROTO_ITEM_SET_HIDDEN(pi); + break; + } + } +#endif + proto_tree_add_item(tree, hf_peer_remote_port, tvb, o, 2, ENC_BIG_ENDIAN); + pi = proto_tree_add_item(tree, hf_peer_port, tvb, o, 2, ENC_BIG_ENDIAN); + PROTO_ITEM_SET_HIDDEN(pi); + o += 2; + + /* peer remote port */ +#ifdef F5_POP_OTHERFIELDS + if(pop_other_fields) { + switch (ipproto) + { + case IP_PROTO_TCP: + pi = proto_tree_add_item(tree, hf_tcp_tcpport, tvb, o, 2, ENC_BIG_ENDIAN); + PROTO_ITEM_SET_HIDDEN(pi); + break; + case IP_PROTO_UDP: + pi = proto_tree_add_item(tree, hf_udp_udpport, tvb, o, 2, ENC_BIG_ENDIAN); + PROTO_ITEM_SET_HIDDEN(pi); + break; + } + } +#endif + proto_tree_add_item(tree, hf_peer_local_port, tvb, o, 2, ENC_BIG_ENDIAN); + pi = proto_tree_add_item(tree, hf_peer_port, tvb, o, 2, ENC_BIG_ENDIAN); + PROTO_ITEM_SET_HIDDEN(pi); + o += 2; + + return(len); +} /* dissect_dpt_trailer_noise_high() */ + + +/*---------------------------------------------------------------------------*/ +/** \brief Render the data for DPT medium noise trailer TVB + * + * @param tvb The tvbuff containing the TLV block (header and data) + * @param pinfo The pinfo structure for the frame + * @param tree The tree to render the TVB under + * @param data Pointer to tdata for the trailer + * @return The size of the TVB + */ +static int +dissect_dpt_trailer_noise_med( + tvbuff_t *tvb, + packet_info *pinfo, + proto_tree *tree, + void *data +) { + proto_item *pi; + gint o; + int rstcauselen = 0; + int badrstcauselen = 0; + guint rstcausever = 0xff; + gint len; + gint ver; + f5eth_tap_data_t *tdata = (f5eth_tap_data_t *)data; + + DISSECTOR_ASSERT(tdata != NULL); + len = tvb_get_ntohs(tvb, F5_DPT_V1_TLV_LENGTH_OFF); + ver = tvb_get_ntohs(tvb, F5_DPT_V1_TLV_VERSION_OFF); + + /* Unknown version, cannot do anything */ + if(ver != 4) { + return(0); + } + + pi = proto_tree_add_item(tree, hf_med_id, tvb, 0, len, ENC_NA); + tree = proto_item_add_subtree(pi, ett_f5ethtrailer_med); + + render_f5dptv1_tlvhdr(tvb, pinfo, tree, data, 0); + + o = F5_DPT_V1_TLV_HDR_LEN; + rstcauselen = F5TRL_MEDV4_RSTCLEN(tvb,o); + /* Check for an invalid reset cause length and do not try to reference any of the data if it is + * bad + */ + if(tvb_reported_length_remaining(tvb, o + F5_MEDV4_LENMIN) < rstcauselen) { + badrstcauselen = 1; + /* Set this to zero to prevent processing of things that utilze it */ + rstcauselen = 0; + } + if(rstcauselen) rstcausever = F5TRL_MEDV4_RSTCVER(tvb,o); + /* If we want the RST cause in the summary, we need to do it here, + * before the tree check below */ + if(rstcauselen && rstcause_in_info) { + if(rstcausever == 0x00) { + col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "[F5RST%s: %s]", + F5TRL_MEDV4_RSTCPEER(tvb, o) ? "(peer)" : "", + tvb_get_string_enc(wmem_packet_scope(), tvb, o+F5_MEDV4_LENMIN+9, + rstcauselen-9, ENC_ASCII)); + } + } + + /* We do not need to do anything more if we don't have a tree and we are not performing + * analysis */ + if(pref_perform_analysis == FALSE && tree == NULL) return(len); + + tdata->flow = tvb_get_ntoh64(tvb,o); + proto_tree_add_item(tree, hf_flow_id, tvb, o, 8, ENC_BIG_ENDIAN); + pi = proto_tree_add_item(tree, hf_any_flow, tvb, o, 8, ENC_BIG_ENDIAN); + PROTO_ITEM_SET_HIDDEN(pi); + o += 8; + tdata->peer_flow = tvb_get_ntoh64(tvb,o); + proto_tree_add_item(tree, hf_peer_id, tvb, o, 8, ENC_BIG_ENDIAN); + pi = proto_tree_add_item(tree, hf_any_flow, tvb, o, 8, ENC_BIG_ENDIAN); + PROTO_ITEM_SET_HIDDEN(pi); + o += 8; + tdata->flows_set = 1; + proto_tree_add_item(tree, hf_cf_flags2, tvb, o, 4, ENC_BIG_ENDIAN); + o += 4; + proto_tree_add_item(tree, hf_cf_flags, tvb, o, 4, ENC_BIG_ENDIAN); + o += 4; + proto_tree_add_item(tree, hf_flow_type, tvb, o, 1, ENC_BIG_ENDIAN); + o += 1; + + /* We do not need to do anything if we don't have a tree */ + /* Needed to get here so that analysis and tap will work. */ + if(tree == NULL) { + return(len); + } + + proto_tree_add_item(tree, hf_ha_unit, tvb, o, 1, ENC_BIG_ENDIAN); + o += 1; + proto_tree_add_item(tree, hf_ingress_slot, tvb, o, 2, ENC_BIG_ENDIAN); + o += 2; + proto_tree_add_item(tree, hf_ingress_port, tvb, o, 2, ENC_BIG_ENDIAN); + o += 2; + proto_tree_add_item(tree, hf_priority, tvb, o, 1, ENC_BIG_ENDIAN); + o += 1; + if(badrstcauselen) { + proto_tree *rc_tree; + proto_item *rc_item; + + rc_item = proto_tree_add_item(tree, hf_rstcause, tvb, o, len-o, ENC_NA); + rc_tree = proto_item_add_subtree(rc_item, ett_f5ethtrailer_rstcause); + rc_item = proto_tree_add_item(rc_tree, hf_rstcause_len, tvb, o, 1, ENC_BIG_ENDIAN); + expert_add_info(pinfo, rc_item, &ei_f5eth_badlen); + } else if(rstcauselen) { + proto_tree *rc_tree; + proto_item *rc_item; + guint64 rstcauseval; + guint64 rstcauseline; + guint startcause; + guint8 rstcausepeer; + + rc_item = proto_tree_add_item(tree, hf_rstcause, tvb, o, rstcauselen+1, ENC_NA); + rc_tree = proto_item_add_subtree(rc_item, ett_f5ethtrailer_rstcause); + proto_tree_add_item(rc_tree, hf_rstcause_len, tvb, o, 1, ENC_BIG_ENDIAN); + o += 1; + + startcause = o; + switch(rstcausever) { + case 0x00: + rstcausepeer = tvb_get_guint8(tvb,o) & 0x1; + + proto_tree_add_item(rc_tree, hf_rstcause_ver, tvb, o, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(rc_tree, hf_rstcause_peer, tvb, o, 1, ENC_BIG_ENDIAN); + o += 1; + + rstcauseval = tvb_get_ntoh64(tvb,o); + rstcauseline = (rstcauseval & 0x000000000000ffffLL); + rstcauseval = (rstcauseval & 0xffffffffffff0000LL) >> 16; + proto_tree_add_uint64_format_value(rc_tree, hf_rstcause_val, tvb, o, 6, + rstcauseval, "0x%012" G_GINT64_MODIFIER "x", rstcauseval); + proto_tree_add_item(rc_tree, hf_rstcause_line, tvb, o+6, 2, ENC_BIG_ENDIAN); + o += 8; + + proto_item_append_text(rc_item, ": [%" G_GINT64_MODIFIER "x:%" G_GINT64_MODIFIER + "u]%s %s", rstcauseval, rstcauseline, rstcausepeer ? " {peer}" : "", + tvb_get_string_enc(wmem_packet_scope(), tvb, o, rstcauselen-(o-startcause), + ENC_ASCII)); + proto_tree_add_item(rc_tree, hf_rstcause_txt, tvb, o, rstcauselen-(o-startcause), + ENC_ASCII|ENC_NA); + o = startcause + rstcauselen; + break; + default: + o += rstcauselen; + break; + } + } + + return(len); +} /* dissect_dpt_trailer_noise_med() */ + + +/*---------------------------------------------------------------------------*/ +/** \brief Render the data for DPT low noise trailer TVB + * + * @param tvb The tvbuff containing the TLV block (header and data) + * @param pinfo The pinfo structure for the frame + * @param tree The tree to render the TVB under + * @param data Pointer to tdata for the trailer + * @return The size of the TVB + */ +static int +dissect_dpt_trailer_noise_low( + tvbuff_t *tvb, + packet_info *pinfo, + proto_tree *tree, + void *data +) { + proto_item *pi; + guint ingress; + gint o; + int vipnamelen; + int badvipnamelen = 0; + guint slot_display = 0; + guint tmm; + gint len; + gint ver; + f5eth_tap_data_t *tdata = (f5eth_tap_data_t *)data; + + DISSECTOR_ASSERT(tdata != NULL); + len = tvb_get_ntohs(tvb, F5_DPT_V1_TLV_LENGTH_OFF); + ver = tvb_get_ntohs(tvb, F5_DPT_V1_TLV_VERSION_OFF); + + /* Unknown version, cannot do anything */ + if(ver != 2) { + return(0); + } + + pi = proto_tree_add_item(tree, hf_low_id, tvb, 0, len, ENC_NA); + tree = proto_item_add_subtree(pi, ett_f5ethtrailer_low); + + render_f5dptv1_tlvhdr(tvb, pinfo, tree, data, 0); + + o = F5_DPT_V1_TLV_HDR_LEN; + + /* Direction */ + ingress = tvb_get_guint8(tvb, o); + tdata->ingress = ingress == 0 ? 0 : 1; + /* Slot */ + slot_display = tvb_get_guint8(tvb, o + 1) + 1; + /* TMM */ + tmm = tvb_get_guint8(tvb, o + 2); + if(tmm < F5ETH_TAP_TMM_MAX && slot_display < F5ETH_TAP_SLOT_MAX) { + tdata->tmm = tmm; + tdata->slot = slot_display; + } + /* VIP Name */ + vipnamelen = tvb_get_guint8(tvb, o + 3); + /* Check for an invalid vip name length and do not try to reference any of the data if it is + * bad + */ + if(tvb_reported_length_remaining(tvb, o + 4) < vipnamelen) { + badvipnamelen = 1; + /* Set this to zero to prevent processing of things that utilze it */ + vipnamelen = 0; + } + if(vipnamelen > 0 && have_tap_listener(tap_f5ethtrailer)) { + tdata->virtual_name = tvb_get_string_enc(wmem_packet_scope(), tvb, + o + 4, vipnamelen, ENC_ASCII); + } + + /* Is the column visible? */ + if(pref_info_type != none) { + f5eth_set_info_col(pinfo, ingress, slot_display, tmm); + } + + /* We do not need to do anything more if we don't have a tree. */ + if(tree == NULL) { + return(len); + } + + /* Use special formatting here so that users do not have to filter on "IN" + * and "OUT", but rather can continue to use typical boolean values. "IN" + * and "OUT" are provided as convenience. */ + proto_tree_add_boolean_format_value(tree, hf_ingress, tvb, + o, 1, ingress, "%s (%s)", + ingress ? tfs_true_false.true_string : tfs_true_false.false_string, + ingress ? f5tfs_ing.true_string : f5tfs_ing.false_string); + o++; + + proto_tree_add_uint(tree, hf_slot1, tvb, o, 1, slot_display); + o += 1; + + proto_tree_add_item(tree, hf_tmm, tvb, o, 1, ENC_BIG_ENDIAN); + o += 1; + pi = proto_tree_add_item(tree, hf_vipnamelen, tvb, o, 1, ENC_BIG_ENDIAN); + if(badvipnamelen) { + expert_add_info(pinfo, pi, &ei_f5eth_badlen); + /* Cannot go any further */ + return(len); + } + o += 1; + proto_tree_add_item(tree, hf_vip, tvb, o, vipnamelen, ENC_ASCII|ENC_NA); + o += vipnamelen; + + return(len); +} /* dissect_dpt_trailer_noise_low() */ + + +/*---------------------------------------------------------------------------*/ +/* \brief Render the data for DPT noise provider TVB + * + * @param tvb The tvbuff containing the packet data for this TLV + * @param pinfo The pinfo structure for the frame + * @param tree The tree to render the TVB under + * @param data Pointer to tdata for the trailer + * @return The size of the TVB + */ +static int +dissect_dpt_trailer_noise( + tvbuff_t *tvb, + packet_info *pinfo, + proto_tree *tree, + void *data +) { + f5eth_tap_data_t *tdata = (f5eth_tap_data_t *)data; + int processed; + + switch(tvb_get_ntohs(tvb, F5_DPT_V1_TLV_TYPE_OFF)) { + case F5TYPE_LOW: + processed = dissect_dpt_trailer_noise_low(tvb, pinfo, tree, data); + if(processed > 0) { + tdata->noise_low = 1; + } + break; + case F5TYPE_MED: + processed = dissect_dpt_trailer_noise_med(tvb, pinfo, tree, data); + if(processed > 0) + tdata->noise_med = 1; + break; + case F5TYPE_HIGH: + processed = dissect_dpt_trailer_noise_high(tvb, pinfo, tree, data); + if(processed > 0) + tdata->noise_high = 1; + break; + default: + /* Skip unknown TLV types */ + processed = 0; + break; + } + return(processed); +} /* dissect_dpt_trailer_noise() */ + + +/*---------------------------------------------------------------------------*/ +/* \brief Render the data for DPT TVB for an unknown provider + * + * @param tvb The tvbuff containing the packet data for this DPT + * @param pinfo The pinfo structure for the frame + * @param tree The tree to render the TVB under + * @param data Pointer to tdata for the trailer + * @return The size of the TVB + */ +static int +dissect_dpt_trailer_unknown( + tvbuff_t *tvb, + packet_info *pinfo, + proto_tree *tree, + void *data +) { + proto_item *pi; + gint len; + + len = tvb_get_ntohs(tvb, F5_DPT_V1_TLV_LENGTH_OFF); + + if(tree) { + pi = proto_tree_add_item(tree, hf_dpt_unknown, tvb, 0, len, ENC_NA); + tree = proto_item_add_subtree(pi, ett_f5ethtrailer_unknown); + + render_f5dptv1_tlvhdr(tvb, pinfo, tree, data, 0); + + proto_tree_add_item(tree, hf_data, tvb, F5_DPT_V1_TLV_HDR_LEN, + len - F5_DPT_V1_TLV_HDR_LEN, ENC_NA); + } + + return(len); +} /* dissect_dpt_trailer_unknown() */ + + +/*---------------------------------------------------------------------------*/ +/* \brief Render the data for DPT block + * + * @param tvb The tvbuff containing the packet data for this DPT block + * @param pinfo The pinfo structure for the frame + * @param tree The tree to render the DPT block in + * @param data Pointer to tdata for the trailer + * @return The size of the DPT block + */ +static int +dissect_dpt_trailer( + tvbuff_t *tvb, + packet_info *pinfo, + proto_tree *tree, + void *data +) { + proto_item *pi; + gint dpt_len; + gint dpt_ver; + gint o; /* offset*/ + + dpt_len = tvb_get_ntohs(tvb, F5_DPT_V1_HDR_LENGTH_OFF); + dpt_ver = tvb_get_ntohs(tvb, F5_DPT_V1_HDR_VERSION_OFF); + + /* Render the DPT header */ + proto_tree_add_item(tree, hf_dpt_magic, tvb, F5_DPT_V1_HDR_MAGIC_OFF, + F5_DPT_V1_HDR_MAGIC_LEN, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_dpt_len, tvb, F5_DPT_V1_HDR_LENGTH_OFF, + F5_DPT_V1_HDR_LENGTH_LEN, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_dpt_ver, tvb, F5_DPT_V1_HDR_VERSION_OFF, + F5_DPT_V1_HDR_VERSION_LEN, ENC_BIG_ENDIAN); + + /* If this is an unknown version, return after rendering header and data */ + if(dpt_ver < F5_DPT_V1_HDR_VERSION_MIN || dpt_ver > F5_DPT_V1_HDR_VERSION_MAX ) { + proto_tree_add_item(tree, hf_data, tvb, F5_DPT_V1_HDR_LEN, + dpt_len - F5_DPT_V1_HDR_LEN, ENC_NA); + return(dpt_len); + } + + o = F5_DPT_V1_HDR_LEN; + + while(tvb_reported_length_remaining(tvb, o) >= F5_DPT_V1_TLV_HDR_LEN) { + tvbuff_t *tvb_dpt_tlv; + gint tvb_dpt_tlv_len; + gint provider_id; + + tvb_dpt_tlv_len = tvb_get_ntohs(tvb, o+F5_DPT_V1_TLV_LENGTH_OFF); + /* Report an error if the length specified in the header is either + * Not long enough to contain the header + * Indicates that the TLV is longer than the data that would have been captured. + */ + if(tvb_dpt_tlv_len < F5_DPT_V1_TLV_HDR_LEN + || tvb_dpt_tlv_len > tvb_reported_length_remaining(tvb, o)) + { + proto_tree *subtree; + pi = proto_tree_add_item(tree, hf_dpt_unknown, tvb, o, + F5_DPT_V1_TLV_HDR_LEN, ENC_NA); + subtree = proto_item_add_subtree(pi, ett_f5ethtrailer_unknown); + proto_tree_add_item(subtree, hf_provider, tvb, o + F5_DPT_V1_TLV_PROVIDER_OFF, + F5_DPT_V1_TLV_PROVIDER_LEN, ENC_BIG_ENDIAN); + proto_tree_add_item(subtree, hf_type, tvb, o + F5_DPT_V1_TLV_TYPE_OFF, + F5_DPT_V1_TLV_TYPE_LEN, ENC_BIG_ENDIAN); + pi = proto_tree_add_item(subtree, hf_length, tvb, o + F5_DPT_V1_TLV_LENGTH_OFF, + F5_DPT_V1_TLV_LENGTH_LEN, ENC_BIG_ENDIAN); + expert_add_info(pinfo, pi, &ei_f5eth_badlen); + if(tvb_dpt_tlv_len >= F5_DPT_V1_TLV_HDR_LEN) { + proto_tree_add_item(subtree, hf_version, tvb, o + F5_DPT_V1_TLV_VERSION_OFF, + F5_DPT_V1_TLV_VERSION_LEN, ENC_BIG_ENDIAN); + } + /* If the length here is bad, then we probably will not index to the next TLV, so + * abort and do not try to render anymore TLVs. + */ + break; + } + provider_id = tvb_get_ntohs(tvb, o+F5_DPT_V1_TLV_PROVIDER_OFF); + tvb_dpt_tlv = tvb_new_subset_length(tvb, o, tvb_dpt_tlv_len); + if(dissector_try_uint_new(provider_subdissector_table, provider_id, tvb_dpt_tlv, pinfo, + tree, FALSE, data) == 0) + { + /* Render the TLV header as unknown */ + dissect_dpt_trailer_unknown(tvb_dpt_tlv, pinfo, tree, data); + } + o += tvb_dpt_tlv_len; + } + + return(dpt_len); +} /* dissect_dpt_trailer() */ + + + /*---------------------------------------------------------------------------*/ /* Main dissector entry point for the trailer data * @@ -2065,30 +2656,52 @@ dissect_f5ethtrailer( tdata->slot = F5ETH_TAP_SLOT_MAX; tdata->tmm = F5ETH_TAP_TMM_MAX; - /* If there is no reference to the fields here, then there is no need to - * populate a tree. We only need to populate the column information. Set - * tree to NULL to prevent the subdissectors from doing much work. */ - if(!proto_field_is_referenced(tree, proto_f5ethtrailer)) - tree = NULL; - - /* While we still have data in the trailer - * (need type, length, version)... */ - while(tvb_reported_length_remaining(tvb, offset) > F5_OFF_VERSION) { + /* While we still have data in the trailer. For legacy trailers, this needs + * type, length, version (3 bytes) and for new format trailers, the magic header (4 bytes). + * All legacy trailers are at least 4 bytes long, so just check for length of magic. + */ + while(tvb_reported_length_remaining(tvb, offset) > F5_DPT_V1_HDR_MAGIC_LEN) { processed = 0; - len = F5TRAILER_LEN(tvb, offset); - ver = F5TRAILER_VER(tvb,offset); - if(len <= tvb_reported_length_remaining(tvb, offset) - && len >= F5_MIN_SANE && len <= F5_MAX_SANE - && ver <= F5TRAILER_VER_MAX) + + /* Check for new format trailer. (Magic number and at least enough bytes for a header) */ + if(tvb_get_ntohl(tvb,offset) == F5_DPT_V1_HDR_MAGIC + && tvb_reported_length_remaining(tvb, offset) >= F5_DPT_V1_HDR_LEN) { - type = F5TRAILER_TYPE(tvb, offset); - processed = 0; + tvbuff_t *tvb_dpt; + gint dpt_len; - /* This should probably be in the case statements below, but putting it here - * prevents the code duplication. We only want to create the trailer subtree - * if we believe that we have actually found a trailer. + dpt_len = tvb_get_ntohs(tvb,offset+F5_DPT_V1_HDR_LENGTH_OFF); + /* Only process this if the length specified in the header is both + * At least as long as the header + * Less than or equal to the data that would have been captured */ - if(trailer_item == NULL && type >= F5TYPE_LOW && type <= F5TYPE_HIGH && tree) + if(dpt_len >= F5_DPT_V1_HDR_LEN + && dpt_len <= tvb_reported_length_remaining(tvb, offset)) + { + tvb_dpt = tvb_new_subset_length(tvb, offset, dpt_len); + if(trailer_item == NULL && tree) { + start = offset; + trailer_item = proto_tree_add_item(tree, proto_f5ethtrailer, tvb, + start, 0, ENC_NA); + tree = proto_item_add_subtree(trailer_item, ett_f5ethtrailer); + } + dissect_dpt_trailer(tvb_dpt, pinfo, tree, tdata); + processed = dpt_len; + tdata->trailer_len += dpt_len; + } + } + + type = F5TRAILER_TYPE(tvb, offset); + len = F5TRAILER_LEN(tvb, offset); + ver = F5TRAILER_VER(tvb, offset); + + /* If there was no new format trailer (processed == 0), need to check for legacy */ + if(processed == 0 && len <= tvb_reported_length_remaining(tvb, offset) + && type >= F5TYPE_LOW && type <= F5TYPE_HIGH + && len >= F5_MIN_SANE && len <= F5_MAX_SANE + && ver <= F5TRAILER_VER_MAX) + { + if(trailer_item == NULL && tree) { start = offset; trailer_item = proto_tree_add_item(tree, proto_f5ethtrailer, tvb, start, 0, ENC_NA); @@ -2283,16 +2896,28 @@ void proto_register_f5ethtrailer (void) * {&(field id), {name, abrv, type, display, strs, bitmask, blurb, HFILL}}. */ static hf_register_info hf[] = { + { &hf_provider, + { "Provider", "f5ethtrailer.provider", FT_UINT16, BASE_DEC, NULL, + 0x0, NULL, HFILL } + }, { &hf_type, - { "Type", "f5ethtrailer.type", FT_UINT8, BASE_DEC, NULL, + { "Type", "f5ethtrailer.type", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_length, - { "Trailer length", "f5ethtrailer.length", FT_UINT8, BASE_DEC, NULL, + { "Trailer length", "f5ethtrailer.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_version, - { "Version", "f5ethtrailer.version", FT_UINT8, BASE_DEC, NULL, + { "Version", "f5ethtrailer.version", FT_UINT16, BASE_DEC, NULL, + 0x0, NULL, HFILL } + }, + { &hf_dpt_unknown, + { "Unknown trailer", "f5ethtrailer.unknown_trailer", FT_NONE, BASE_NONE, NULL, + 0x0, NULL, HFILL } + }, + { &hf_data, + { "Data", "f5ethtrailer.data", FT_BYTES, SEP_SPACE, NULL, 0x0, NULL, HFILL } }, @@ -2470,11 +3095,26 @@ void proto_register_f5ethtrailer (void) { &hf_analysis, { "Analysis", "f5ethtrailer.analysis", FT_NONE, BASE_NONE, NULL, 0x0, "Analysis of details", HFILL } + }, + + { &hf_dpt_magic, + { "Magic", "f5ethtrailer.trailer_magic", FT_UINT32, BASE_HEX, NULL, + 0x0, NULL, HFILL } + }, + { &hf_dpt_ver, + { "Version", "f5ethtrailer.trailer_version", FT_UINT16, BASE_DEC, NULL, + 0x0, NULL, HFILL } + }, + { &hf_dpt_len, + { "Length", "f5ethtrailer.trailer_length", FT_UINT16, BASE_DEC, NULL, + 0x0, NULL, HFILL } } + }; static gint *ett[] = { &ett_f5ethtrailer, + &ett_f5ethtrailer_unknown, &ett_f5ethtrailer_low, &ett_f5ethtrailer_med, &ett_f5ethtrailer_high, @@ -2483,8 +3123,13 @@ void proto_register_f5ethtrailer (void) expert_module_t *expert_f5ethtrailer; static ei_register_info ei[] = { - { &ei_f5eth_flowlost, { "f5ethtrailer.flowlost", PI_SEQUENCE, PI_WARN, "Flow lost, incorrect VLAN, loose initiation, tunnel, or SYN cookie use", EXPFILL } }, - { &ei_f5eth_flowreuse, { "f5ethtrailer.flowreuse", PI_SEQUENCE, PI_WARN, "Flow reuse or SYN retransmit", EXPFILL } } + { &ei_f5eth_flowlost, { "f5ethtrailer.flowlost", PI_SEQUENCE, PI_WARN, + "Flow lost, incorrect VLAN, loose initiation, tunnel, or SYN cookie use", + EXPFILL } }, + { &ei_f5eth_flowreuse, { "f5ethtrailer.flowreuse", PI_SEQUENCE, PI_WARN, + "Flow reuse or SYN retransmit", EXPFILL } }, + { &ei_f5eth_badlen, { "f5ethtrailer.badlen", PI_MALFORMED, PI_ERROR, + "Bad length", EXPFILL } } }; proto_f5ethtrailer = proto_register_protocol ("F5 Ethernet Trailer Protocol", "F5 Ethernet trailer", "f5ethtrailer"); @@ -2561,6 +3206,13 @@ void proto_register_f5ethtrailer (void) register_init_routine(proto_init_f5ethtrailer); register_cleanup_routine(f5ethtrailer_cleanup); + /* Register dissector table for additional providers */ + provider_subdissector_table = register_dissector_table("f5ethtrailer.provider", + "F5 Ethernet trailer provider", proto_f5ethtrailer, FT_UINT16, BASE_DEC); + proto_f5ethtrailer_dpt_noise = proto_register_protocol_in_name_only( + "F5 Ethernet trailer provider - Noise", "Noise", "f5ethtrailer.provider.noise", + proto_f5ethtrailer, FT_BYTES); + /* Analyze Menu Items */ register_conversation_filter("f5ethtrailer", "F5 TCP", f5_tcp_conv_valid, f5_tcp_conv_filter); register_conversation_filter("f5ethtrailer", "F5 UDP", f5_udp_conv_valid, f5_udp_conv_filter); @@ -2582,9 +3234,14 @@ void proto_register_f5ethtrailer (void) void proto_reg_handoff_f5ethtrailer(void) { + dissector_handle_t h; + heur_dissector_add("eth.trailer", dissect_f5ethtrailer, "F5 Ethernet Trailer", "f5ethtrailer", proto_f5ethtrailer, HEURISTIC_DISABLE); + /* Register helper dissectors */ + h = create_dissector_handle(dissect_dpt_trailer_noise, proto_f5ethtrailer_dpt_noise); + dissector_add_uint("f5ethtrailer.provider", F5_DPT_PROVIDER_NOISE, h); #ifdef F5_POP_OTHERFIELDS /* These fields are duplicates of other, well-known fields so that * filtering on these fields will also pick up data out of the diff --git a/epan/dissectors/packet-f5ethtrailer.h b/epan/dissectors/packet-f5ethtrailer.h index ce41ff741a..02dec0d4e0 100644 --- a/epan/dissectors/packet-f5ethtrailer.h +++ b/epan/dissectors/packet-f5ethtrailer.h @@ -1,6 +1,6 @@ /* packet-f5ethtrailer.h * - * F5 Ethernet Trailer Copyright 2008-2017 F5 Networks + * F5 Ethernet Trailer Copyright 2008-2018 F5 Networks * * SPDX-License-Identifier: GPL-2.0-or-later */ @@ -206,7 +206,7 @@ static gboolean f5fileinfo_tap_pkt( #define F5FILEINFO_TAP_LISTEN(a) \ - register_tap_listener("f5fileinfo", (a), NULL, TL_REQUIRES_NOTHING, f5fileinfo_tap_reset, f5fileinfo_tap_pkt, NULL) + register_tap_listener("f5fileinfo", (a), NULL, TL_REQUIRES_NOTHING, f5fileinfo_tap_reset, f5fileinfo_tap_pkt, NULL, NULL) #endif /* ifndef F5INFOTAP_SRC */ |