GREbond: Add support for Huawei's GRE bonding (RFC8157) control protocol

This dissector is for the control messages of the GRE bonding protocol by
Huawei. These messages are encapsulated in GRE and can appear on both/all
bonding links.

During development, I made heavy use of traffic for Deutsche Telekom Hybrid
service. There fore, it also supports the first version which did not have an
IEEE assigned ethertype.
This commit is contained in:
Thomas Vogt 2022-06-20 16:38:17 +02:00 committed by A Wireshark GitLab Utility
parent 181a7c7d7d
commit 95b01dc4bf
4 changed files with 517 additions and 0 deletions

View File

@ -1149,6 +1149,7 @@ set(DISSECTOR_SRC
${CMAKE_CURRENT_SOURCE_DIR}/packet-gprs-llc.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-gprscdr.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-gre.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-grebonding.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-grpc.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-gsm_a_bssmap.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-gsm_a_common.c

View File

@ -119,6 +119,7 @@ const value_string gre_typevals[] = {
{ ETHERTYPE_CDMA2000_A10_UBS,"CDMA2000 A10 Unstructured byte stream" },
{ ETHERTYPE_3GPP2, "CDMA2000 A10 3GPP2 Packet" },
{ ETHERTYPE_CMD, "CiscoMetaData" },
{ GRE_GREBONDING, "Huawei GRE bonding" },
{ GRE_ARUBA_8200, "ARUBA WLAN" },
{ GRE_ARUBA_8210, "ARUBA WLAN" },
{ GRE_ARUBA_8220, "ARUBA WLAN" },

View File

@ -30,6 +30,7 @@
#define GRE_ERSPAN_22EB 0x22EB
#define GRE_MIKROTIK_EOIP 0x6400
#define GRE_AIROHIVE 0xFEAE
#define GRE_GREBONDING 0xB7EA
/* ************************************************************************* */
/* Aruba GRE Encapsulation ID */
/* ************************************************************************* */

View File

@ -0,0 +1,514 @@
/* packet-grebonding.c
* Routines for Huawei's GRE bonding control (RFC8157) dissection
* Thomas Vogt
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#include <epan/packet.h>
#include <epan/capture_dissectors.h>
#include <epan/expert.h>
#include <epan/to_str.h>
void proto_reg_handoff_greb(void);
void proto_register_greb(void);
static int proto_greb = -1;
static int hf_greb_message_type = -1;
static int hf_greb_tunnel_type = -1;
static int hf_greb_attr = -1;
static int hf_greb_attr_type = -1;
static int hf_greb_attr_length = -1;
static int hf_greb_attr_val_uint64 = -1;
static int hf_greb_attr_val_none = -1;
static int hf_greb_attr_val_ipv6 = -1;
static int hf_greb_attr_val_ipv4 = -1;
static int hf_greb_attr_val_time = -1;
static int hf_greb_attr_val_string = -1;
static int hf_greb_attr_filter_commit = -1;
static int hf_greb_attr_filter_ack = -1;
static int hf_greb_attr_filter_packetsum = -1;
static int hf_greb_attr_filter_packetid = -1;
static int hf_greb_attr_filter_item_type = -1;
static int hf_greb_attr_filter_item_length = -1;
static int hf_greb_attr_filter_item_enabled = -1;
static int hf_greb_attr_filter_item_desc_length = -1;
static int hf_greb_attr_filter_item_desc_val = -1;
static int hf_greb_attr_filter_item_val = -1;
static int hf_greb_attr_error = -1;
/* Initialize the subtree pointers */
static gint ett_grebonding = -1;
static gint ett_grebonding_attrb = -1;
static gint ett_grebonding_filter_list = -1;
static gint ett_grebonding_filter_item = -1;
static gint ett_grebonding_ipv6_prefix = -1;
static gint *ett[] = {
&ett_grebonding,
&ett_grebonding_attrb,
&ett_grebonding_filter_list,
&ett_grebonding_filter_item,
&ett_grebonding_ipv6_prefix
};
const value_string greb_message_types[] = {
#define GREB_TUNNEL_SETUP_REQ 1
{GREB_TUNNEL_SETUP_REQ, "Tunnel setup request"},
#define GREB_TUNNEL_SETUP_ACK 2
{GREB_TUNNEL_SETUP_ACK, "Tunnel setup accept"},
#define GREB_TUNNEL_SETUP_DENY 3
{GREB_TUNNEL_SETUP_DENY, "Tunnel setup deny"},
#define GREB_HELLO 4
{GREB_HELLO, "Hello"},
#define GREB_TUNNEL_TEAR_DOWN 5
{GREB_TUNNEL_TEAR_DOWN, "Tunnel tear down"},
#define GREB_NOTIFY 6
{GREB_NOTIFY, "Notify"},
{0, NULL}
};
const value_string greb_tunnel_types[] = {
#define GREB_TUNNEL_FIRST 0x0001
{GREB_TUNNEL_FIRST, "first tunnel (most likely the DSL GRE tunnel)"},
#define GREB_TUNNEL_SECOND 0x0010
{GREB_TUNNEL_SECOND, "second tunnel (most likely the LTE GRE tunnel)" },
{0, NULL}
};
const value_string greb_error_codes[] = {
#define GREB_ERROR_HAAP_UNREACHABLE_LTE 1
{GREB_ERROR_HAAP_UNREACHABLE_LTE, "HAAP not reachable over LTE"},
#define GREB_ERROR_HAAP_UNREACHABLE_DSL 2
{GREB_ERROR_HAAP_UNREACHABLE_DSL, "HAAP not reachable via DSL"},
#define GREB_ERROR_LTE_TUNNEL_FAILED 3
{GREB_ERROR_LTE_TUNNEL_FAILED, "LTE tunnel failed"},
#define GREB_ERROR_DSL_TUNNEL_FAILED 4
{GREB_ERROR_DSL_TUNNEL_FAILED, "DSL tunnel failed"},
#define GREB_ERROR_DSL_UID_NOT_ALLOWED 5
{GREB_ERROR_DSL_UID_NOT_ALLOWED, "DSL UID not allowed"},
#define GREB_ERROR_UID_NOT_ALLOWED 6
{GREB_ERROR_UID_NOT_ALLOWED, "UID not allowed"},
#define GREB_ERROR_UID_NOT_MATCHING 7
{GREB_ERROR_UID_NOT_MATCHING, "LTE and DSL User IDs do not match"},
#define GREB_ERROR_SECOND_SESSION_WITH_UID 8
{GREB_ERROR_SECOND_SESSION_WITH_UID, "Session with the same User ID already exists"},
#define GREB_ERROR_CIN_NOT_PERMITTED 9
{GREB_ERROR_CIN_NOT_PERMITTED, "Denied: CIN not permitted"},
#define GREB_ERROR_MAINTENANCE 10
{GREB_ERROR_MAINTENANCE, "Terminated for maintenance"},
#define GREB_ERROR_BACKEND_COMMUNICATION_FAILURE_LTE 11
{GREB_ERROR_BACKEND_COMMUNICATION_FAILURE_LTE, "HAAP Backend failure on LTE tunnel establishment"},
#define GREB_ERROR_BACKEND_COMMUNICATION_FAILURE_DSL 12
{GREB_ERROR_BACKEND_COMMUNICATION_FAILURE_DSL, "HAAP Backend failure on DSL tunnel establishment"},
{0,NULL}
};
const value_string greb_attribute_types[] = {
#define GREB_ATTRB_H_IP4_ADDR 1
{GREB_ATTRB_H_IP4_ADDR, "H IPv4 address"},
#define GREB_ATTRB_H_IP6_ADDR 2
{GREB_ATTRB_H_IP6_ADDR, "H IPv6 address"},
#define GREB_ATTRB_CIN 3
{GREB_ATTRB_CIN, "CIN (Client ID)"},
#define GREB_ATTRB_SESSIONID 4
{GREB_ATTRB_SESSIONID, "Session ID"},
#define GREB_ATTRB_TIME 5
{GREB_ATTRB_TIME, "Time"},
#define GREB_ATTRB_BYPASS_RATE 6
{GREB_ATTRB_BYPASS_RATE, "Bypass rate"},
#define GREB_ATTRB_DOWNSTREAM_RATE 7
{GREB_ATTRB_DOWNSTREAM_RATE, "Downstream rate"},
#define GREB_ATTRB_FILTER_LIST 8
{GREB_ATTRB_FILTER_LIST, "Filter list"},
#define GREB_ATTRB_RTT_THRESHOLD 9
{GREB_ATTRB_RTT_THRESHOLD, "RTT threshold"},
#define GREB_ATTRB_BYPASS_INTERVAL 10
{GREB_ATTRB_BYPASS_INTERVAL, "Bypass interval"},
#define GREB_ATTRB_ONLY_FIRST_TUNNEL 11
{GREB_ATTRB_ONLY_FIRST_TUNNEL, "only first tunnel (DSL)"},
#define GREB_ATTRB_OVERFLOW_TO_SECOND 12
{GREB_ATTRB_OVERFLOW_TO_SECOND, "overflow to second tunnel (LTE)"},
#define GREB_ATTRB_IPV6_PREFIX 13
{GREB_ATTRB_IPV6_PREFIX, "IPv6 prefix assigned by HAAP"},
#define GREB_ATTRB_ACTIVE_HELLO_INTERVAL 14
{GREB_ATTRB_ACTIVE_HELLO_INTERVAL, "Active hello interval"},
#define GREB_ATTRB_HELLO_RETRYS 15
{GREB_ATTRB_HELLO_RETRYS, "Hello retrys"},
#define GREB_ATTRB_IDLE_TIMEOUT 16
{GREB_ATTRB_IDLE_TIMEOUT, "Idle timeout"},
#define GREB_ATTRB_ERROR 17
{GREB_ATTRB_ERROR, "Error"},
#define GREB_ATTRB_DSL_FAIL 18
{GREB_ATTRB_DSL_FAIL, "DSL fail"},
#define GREB_ATTRB_LTE_FAIL 19
{GREB_ATTRB_LTE_FAIL, "LTE fail"},
#define GREB_ATTRB_BONDING_KEY 20
{GREB_ATTRB_BONDING_KEY, "Bonding key"},
#define GREB_ATTRB_IPV6_PREFIX2 21
{GREB_ATTRB_IPV6_PREFIX2, "IPv6 prefix assigned to host"},
#define GREB_ATTRB_CONFIGURED_UPSTREAM 22
{GREB_ATTRB_CONFIGURED_UPSTREAM, "Configured upstream"},
#define GREB_ATTRB_CONFIGURED_DOWNSTREAM 23
{GREB_ATTRB_CONFIGURED_DOWNSTREAM, "Configured downstream"},
#define GREB_ATTRB_RTT_VIOLATION 24
{GREB_ATTRB_RTT_VIOLATION, "RTT violation"},
#define GREB_ATTRB_RTT_COMPLIANCE 25
{GREB_ATTRB_RTT_COMPLIANCE, "RTT compliance"},
#define GREB_ATTRB_DIAG_START_BONDING 26
{GREB_ATTRB_DIAG_START_BONDING, "Diagnostic start bonding"},
#define GREB_ATTRB_DIAG_START_DSL 27
{GREB_ATTRB_DIAG_START_DSL, "Diagnostic start DSL"},
#define GREB_ATTRB_DIAG_END 29
{GREB_ATTRB_DIAG_END, "Diagnostic End"},
#define GREB_ATTRB_FILTER_LIST_ACK 30
{GREB_ATTRB_FILTER_LIST_ACK, "Filter list ACK"},
#define GREB_ATTRB_IDLE_HELLO_INTERVAL 31
{GREB_ATTRB_IDLE_HELLO_INTERVAL, "Idle hello interval"},
#define GREB_ATTRB_NO_TRAFFIC_INTERVAL 32
{GREB_ATTRB_NO_TRAFFIC_INTERVAL, "No traffic interval"},
#define GREB_ATTRB_ACTIVE_HELLO_STATE 33
{GREB_ATTRB_ACTIVE_HELLO_STATE, "Active hello state"},
#define GREB_ATTRB_IDLE_HELLO_STATE 34
{GREB_ATTRB_IDLE_HELLO_STATE, "Idle hello state"},
#define GREB_ATTRB_TUNNEL_VERIFICATION 35
{GREB_ATTRB_TUNNEL_VERIFICATION, "Tunnel verification"},
{255, "FIN"},
{0, NULL}
};
const value_string greb_filter_types[] = {
#define GREB_ATTRB_FILTER_FQDN 1
{GREB_ATTRB_FILTER_FQDN, "FQDN"},
#define GREB_ATTRB_FILTER_DSCP 2
{GREB_ATTRB_FILTER_DSCP, "DSCP"},
#define GREB_ATTRB_FILTER_DPORT 3
{GREB_ATTRB_FILTER_DPORT, "Destination Port"},
#define GREB_ATTRB_FILTER_DIP 4
{GREB_ATTRB_FILTER_DIP, "Destination IP"},
#define GREB_ATTRB_FILTER_DIPPORT 5
{GREB_ATTRB_FILTER_DIPPORT, "Destination IP&Port"},
#define GREB_ATTRB_FILTER_SPORT 6
{GREB_ATTRB_FILTER_SPORT, "Source Port"},
#define GREB_ATTRB_FILTER_SIP 7
{GREB_ATTRB_FILTER_SIP, "Source IP"},
#define GREB_ATTRB_FILTER_SIPPORT 8
{GREB_ATTRB_FILTER_SIPPORT, "Source IP&Port"},
#define GREB_ATTRB_FILTER_SMAC 9
{GREB_ATTRB_FILTER_SMAC, "Source Mac"},
#define GREB_ATTRB_FILTER_PROTO 10
{GREB_ATTRB_FILTER_PROTO, "Protocol"},
#define GREB_ATTRB_FILTER_SIPR 11
{GREB_ATTRB_FILTER_SIPR, "Source IP Range"},
#define GREB_ATTRB_FILTER_DIPR 12
{GREB_ATTRB_FILTER_DIPR, "Destination IP Range"},
#define GREB_ATTRB_FILTER_SIPRPORT 13
{GREB_ATTRB_FILTER_SIPRPORT, "Source IP Range&Port"},
#define GREB_ATTRB_FILTER_DIPRPORT 14
{GREB_ATTRB_FILTER_DIPRPORT, "Destination IP Range&Port"},
{0, NULL}
};
const value_string greb_filter_ack_codes[] = {
#define GREB_ATTRB_FILTER_ACK 0
{GREB_ATTRB_FILTER_ACK, "Filter list acknowledged"},
#define GREB_ATTRB_FILTER_NACK_NO_OLD 1
{GREB_ATTRB_FILTER_NACK_NO_OLD, "Filter list not acknowledged. No previous filter list to use."},
#define GREB_ATTRB_FILTER_NACK_OLD_USED 2
{GREB_ATTRB_FILTER_NACK_OLD_USED, "Filter list not acknowledged. Previous filter list will be used."},
{0, NULL}
};
static void
dissect_greb_h_gateway_ip_address(tvbuff_t *tvb, proto_tree *attrb_tree, guint offset, guint attrb_length)
{
if (attrb_length == 16)
proto_tree_add_item(attrb_tree, hf_greb_attr_val_ipv6, tvb, offset, attrb_length, ENC_NA);
else if (attrb_length == 4)
proto_tree_add_item(attrb_tree, hf_greb_attr_val_ipv4, tvb, offset, attrb_length, ENC_BIG_ENDIAN);
else
proto_tree_add_item(attrb_tree, hf_greb_attr_val_uint64, tvb, offset, attrb_length, ENC_BIG_ENDIAN);
}
static void
dissect_greb_filter_list_ack(tvbuff_t *tvb, proto_tree *attrb_tree, guint offset, guint attrb_length)
{
proto_item *it_filter;
proto_tree *filter_tree;
guint filter_commit_count = tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN);
it_filter = proto_tree_add_none_format(attrb_tree, hf_greb_attr_val_none, tvb, offset, attrb_length,
"Filter list ACK - Commit %d", filter_commit_count);
filter_tree = proto_item_add_subtree(it_filter, ett_grebonding_filter_list);
proto_tree_add_item(filter_tree, hf_greb_attr_filter_commit, tvb, offset, attrb_length - 1, ENC_BIG_ENDIAN);
proto_tree_add_item(filter_tree, hf_greb_attr_filter_ack, tvb, offset + attrb_length, 1, ENC_BIG_ENDIAN);
}
static void
dissect_greb_filter_list(tvbuff_t *tvb, proto_tree *attrb_tree, guint offset, guint attrb_length)
{
proto_item *it_filter;
proto_tree *filter_tree;
guint filter_commit_count = tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN);
guint filter_packet_sum = tvb_get_guint16(tvb, offset + 4, ENC_BIG_ENDIAN);
guint filter_packet_id = tvb_get_guint16(tvb, offset + 6, ENC_BIG_ENDIAN);
it_filter = proto_tree_add_none_format(attrb_tree, hf_greb_attr_val_none, tvb, offset, attrb_length,
"Filter list - Commit %d, Packet %d/%d", filter_commit_count, filter_packet_id, filter_packet_sum);
filter_tree = proto_item_add_subtree(it_filter, ett_grebonding_filter_list);
proto_tree_add_item(filter_tree, hf_greb_attr_filter_commit, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(filter_tree, hf_greb_attr_filter_packetid, tvb, offset + 6, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(filter_tree, hf_greb_attr_filter_packetsum, tvb, offset + 4, 2, ENC_BIG_ENDIAN);
offset += 8;
while (offset < attrb_length) {
proto_item *it_filter_item;
proto_tree *filter_item_tree;
guint filter_item_length = tvb_get_guint16(tvb, offset + 2, ENC_BIG_ENDIAN);
guint filter_item_desc_length = tvb_get_guint16(tvb, offset + 6, ENC_BIG_ENDIAN);
// bound lengths to not exceed packet
if (filter_item_length > (guint) tvb_reported_length_remaining(tvb, offset + 2))
filter_item_length = tvb_reported_length_remaining(tvb, offset + 2);
if (filter_item_desc_length > filter_item_length)
filter_item_length = filter_item_desc_length;
it_filter_item = proto_tree_add_none_format(filter_tree, hf_greb_attr_val_none, tvb, offset,
filter_item_length + 4, "Filter item - %s", tvb_get_string_enc(wmem_packet_scope(), tvb, offset + 8,
filter_item_desc_length, ENC_UTF_8));
filter_item_tree = proto_item_add_subtree(it_filter_item, ett_grebonding_filter_item);
proto_tree_add_item(filter_item_tree, hf_greb_attr_filter_item_type, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(filter_item_tree, hf_greb_attr_filter_item_length, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(filter_item_tree, hf_greb_attr_filter_item_enabled, tvb, offset + 4, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(filter_item_tree, hf_greb_attr_filter_item_desc_length, tvb, offset + 6, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(filter_item_tree, hf_greb_attr_filter_item_desc_val, tvb, offset + 8,
filter_item_desc_length, ENC_UTF_8 | ENC_NA);
proto_tree_add_item(filter_item_tree, hf_greb_attr_filter_item_val, tvb, offset + 8 + filter_item_desc_length,
filter_item_length - 4 - filter_item_desc_length, ENC_UTF_8 | ENC_NA);
offset += filter_item_length + 4;
}
}
static void
dissect_greb_ipv6_prefix(packet_info *pinfo, tvbuff_t *tvb, proto_tree *attrb_tree, guint offset, guint attrb_length)
{
proto_item *item_ipv6_prefix;
proto_tree *ipv6_prefix_tree;
guint addr_length = attrb_length - 1;
ipv6_prefix_tree = proto_tree_add_subtree_format(attrb_tree, tvb, offset, attrb_length,
ett_grebonding_ipv6_prefix, &item_ipv6_prefix, "IPv6 prefix - %s/%d",
tvb_ip6_to_str(pinfo->pool, tvb, offset), tvb_get_guint8(tvb, offset + addr_length));
proto_tree_add_item(ipv6_prefix_tree, hf_greb_attr_val_ipv6, tvb, offset, addr_length, ENC_NA);
proto_tree_add_item(ipv6_prefix_tree, hf_greb_attr_val_uint64, tvb, offset + addr_length, 1, ENC_BIG_ENDIAN);
}
static int
dissect_greb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
{
proto_item *ti, *it_attrb;
proto_tree *greb_tree, *attrb_tree = NULL;
guint offset = 0;
guint message_type = tvb_get_guint8(tvb, offset) >> 4;
col_set_str(pinfo->cinfo, COL_PROTOCOL, "GREbond");
ti = proto_tree_add_protocol_format(tree, proto_greb, tvb, offset, -1, "Huawei GRE bonding control message (%s)",
val_to_str(message_type, greb_message_types, "0x%01X (unknown)"));
col_add_str(pinfo->cinfo, COL_INFO, val_to_str(message_type, greb_message_types, "0x%02X (unknown)"));
greb_tree = proto_item_add_subtree(ti, ett_grebonding);
proto_tree_add_item(greb_tree, hf_greb_message_type, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(greb_tree, hf_greb_tunnel_type, tvb, offset, 1, ENC_BIG_ENDIAN);
offset++;
// going through the attributes, off by one to assure length field exists
while (offset + 1 < tvb_captured_length(tvb)) {
guint attrb_type = tvb_get_guint8(tvb, offset);
guint attrb_length = tvb_get_guint16(tvb, offset + 1, ENC_BIG_ENDIAN);
it_attrb = proto_tree_add_none_format(greb_tree, hf_greb_attr, tvb, offset, attrb_length + 3, "Attribute - %s",
val_to_str(attrb_type, greb_attribute_types, "unknown (%d)"));
attrb_tree = proto_item_add_subtree(it_attrb, ett_grebonding_attrb);
proto_tree_add_item(attrb_tree, hf_greb_attr_type, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(attrb_tree, hf_greb_attr_length, tvb, offset + 1, 2, ENC_BIG_ENDIAN);
offset += 3;
// bound attrb_length to not exced packet
if (attrb_length > (guint) tvb_reported_length_remaining(tvb, offset))
attrb_length = tvb_reported_length_remaining(tvb, offset);
if (attrb_length > 0) {
switch (attrb_type) {
case GREB_ATTRB_H_IP4_ADDR:
case GREB_ATTRB_H_IP6_ADDR:
dissect_greb_h_gateway_ip_address(tvb, attrb_tree, offset, attrb_length);
break;
case GREB_ATTRB_IPV6_PREFIX2:
case GREB_ATTRB_IPV6_PREFIX:
dissect_greb_ipv6_prefix(pinfo, tvb, attrb_tree, offset, attrb_length);
break;
case GREB_ATTRB_TIME:
proto_tree_add_item(attrb_tree, hf_greb_attr_val_time, tvb, offset, attrb_length,
ENC_TIME_TIMEVAL);
break;
case GREB_ATTRB_FILTER_LIST:
dissect_greb_filter_list(tvb, attrb_tree, offset, attrb_length);
break;
case GREB_ATTRB_FILTER_LIST_ACK:
dissect_greb_filter_list_ack(tvb, attrb_tree, offset, attrb_length);
break;
case GREB_ATTRB_CIN:
proto_tree_add_item(attrb_tree, hf_greb_attr_val_string, tvb, offset, attrb_length,
ENC_UTF_8 | ENC_NA);
break;
case GREB_ATTRB_ERROR:
proto_tree_add_item(attrb_tree, hf_greb_attr_error, tvb, offset, attrb_length, ENC_BIG_ENDIAN);
break;
default:
proto_tree_add_item(attrb_tree, hf_greb_attr_val_uint64, tvb, offset, attrb_length,
ENC_BIG_ENDIAN);
break;
}
offset += attrb_length;
}
}
return tvb_captured_length(tvb);
}
void
proto_register_greb(void)
{
static hf_register_info hf[] = {
{ &hf_greb_message_type,
{ "Message type", "grebonding.type", FT_UINT8, BASE_DEC, VALS(greb_message_types), 0xF0, "", HFILL }
},
{ &hf_greb_tunnel_type,
{ "Tunnel type", "grebonding.tunneltype", FT_UINT8, BASE_DEC, VALS(greb_tunnel_types), 0x0F, "", HFILL }
},
{ &hf_greb_attr,
{ "Attribute", "grebonding.attr", FT_NONE, BASE_NONE, NULL, 0, "", HFILL }
},
{ &hf_greb_attr_length,
{ "Attribute length", "grebonding.attr.length", FT_UINT16, BASE_DEC, NULL, 0, "", HFILL }
},
{ &hf_greb_attr_type,
{ "Attribute type", "grebonding.attr.type", FT_UINT8, BASE_DEC, VALS(greb_attribute_types), 0, "", HFILL }
},
{ &hf_greb_attr_val_uint64,
{ "Attribute value", "grebonding.attr.val.uint64",
FT_UINT64, BASE_DEC, NULL, 0, "", HFILL }
},
{ &hf_greb_attr_val_time,
{ "Attribute value", "grebonding.attr.val.time",
FT_RELATIVE_TIME, BASE_NONE, NULL, 0, "", HFILL }
},
{ &hf_greb_attr_val_string,
{ "Attribute value", "grebonding.attr.val.string",
FT_STRING, BASE_NONE, NULL, 0, "", HFILL }
},
{ &hf_greb_attr_val_none,
{ "Attribute value", "grebonding.attr.val",
FT_NONE, BASE_NONE, NULL, 0, "", HFILL }
},
{ &hf_greb_attr_val_ipv6,
{ "Attribute value", "grebonding.attr.val.ipv6",
FT_IPv6, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_greb_attr_val_ipv4,
{ "Attribute value", "grebonding.attr.val.ipv4",
FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_greb_attr_filter_commit,
{ "Commit", "grebonding.attr.val.filter.commit", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_greb_attr_filter_ack,
{ "Ack", "grebonding.attr.val.filter.ack",
FT_UINT8, BASE_DEC, VALS(greb_filter_ack_codes), 0, NULL, HFILL }
},
{ &hf_greb_attr_filter_packetsum,
{ "Packet sum", "grebonding.attr.val.filter.packetsum", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_greb_attr_filter_packetid,
{ "Packet ID", "grebonding.attr.val.filter.packetid", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_greb_attr_filter_item_enabled,
{ "Enabled", "grebonding.attr.val.filter.item.enabled", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_greb_attr_filter_item_length,
{ "Length (excl. type and length)", "grebonding.attr.val.filter.item.length",
FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_greb_attr_filter_item_type,
{ "Type", "grebonding.attr.val.filter.item.type",
FT_UINT16, BASE_DEC, VALS(greb_filter_types), 0, NULL, HFILL }
},
{ &hf_greb_attr_filter_item_desc_val,
{ "Descripton", "grebonding.attr.val.filter.item.desc", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_greb_attr_filter_item_desc_length,
{ "Descripton length", "grebonding.attr.val.filter.item.desc.length",
FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_greb_attr_filter_item_val,
{ "Value", "grebonding.attr.val.filter.item.val", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_greb_attr_error,
{ "Error message", "grebonding.attr.val.error",
FT_UINT32, BASE_DEC, VALS(greb_error_codes), 0, NULL, HFILL }
}
};
proto_greb = proto_register_protocol("Huawei GRE bonding", "GREbond", "grebonding");
proto_register_field_array(proto_greb, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
}
void
proto_reg_handoff_greb(void)
{
dissector_handle_t greb_handle;
greb_handle = create_dissector_handle(dissect_greb, proto_greb);
dissector_add_uint("gre.proto", 0x0101, greb_handle); // used in production at Deutsche Telekom
dissector_add_uint("gre.proto", 0xB7EA, greb_handle); // according to RFC
// TODO
// when capturing on the gre-interfaces itself, "Linux cooked" interfaces
//dissector_add_uint("sll.ltype", 0x0101, greb_handle);
//dissector_add_uint("sll.ltype", 0xB7EA, greb_handle);
//dissector_add_uint("sll.gretype", 0x0101, greb_handle);
//dissector_add_uint("sll.gretype", 0xB7EA, greb_handle);
}