/* packet-grebonding.c * Routines for Huawei's GRE bonding control (RFC8157) dissection * Thomas Vogt * * Wireshark - Network traffic analyzer * By Gerald Combs * 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 #include #include #include void proto_reg_handoff_greb(void); void proto_register_greb(void); static dissector_handle_t greb_handle; static int proto_greb; static int hf_greb_message_type; static int hf_greb_tunnel_type; static int hf_greb_attr; static int hf_greb_attr_type; static int hf_greb_attr_length; static int hf_greb_attr_val_uint64; static int hf_greb_attr_val_none; static int hf_greb_attr_val_ipv6; static int hf_greb_attr_val_ipv4; static int hf_greb_attr_val_time; static int hf_greb_attr_val_string; static int hf_greb_attr_DSL_prot; static int hf_greb_attr_dt_bras_name; static int hf_greb_attr_filter_commit; static int hf_greb_attr_filter_ack; static int hf_greb_attr_filter_packetsum; static int hf_greb_attr_filter_packetid; static int hf_greb_attr_filter_item_type; static int hf_greb_attr_filter_item_length; static int hf_greb_attr_filter_item_enabled; static int hf_greb_attr_filter_item_desc_length; static int hf_greb_attr_filter_item_desc_val; static int hf_greb_attr_filter_item_val; static int hf_greb_attr_error; /* Initialize the subtree pointers */ static int ett_grebonding; static int ett_grebonding_attrb; static int ett_grebonding_filter_list; static int ett_grebonding_filter_item; static int ett_grebonding_ipv6_prefix; static int *ett[] = { &ett_grebonding, &ett_grebonding_attrb, &ett_grebonding_filter_list, &ett_grebonding_filter_item, &ett_grebonding_ipv6_prefix }; static 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"}, #define GREB_LINK_DETECTION 10 {GREB_LINK_DETECTION, "Link Detection (Telekom specific)"}, {0, NULL} }; static const value_string greb_tunnel_types[] = { #define GREB_TUNNEL_LTE 0b0000 {GREB_TUNNEL_LTE, "LTE-GRE tunnel (Telekom specific)"}, #define GREB_TUNNEL_FIRST 0b0001 {GREB_TUNNEL_FIRST, "first tunnel (most likely the DSL GRE tunnel)"}, #define GREB_TUNNEL_SECOND 0b0010 {GREB_TUNNEL_SECOND, "second tunnel (most likely the LTE GRE tunnel)" }, #define GREB_TUNNEL_DSL 0b1000 {GREB_TUNNEL_DSL, "DSL Tunnel (Telekom specific)" }, {0, NULL} }; static 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"}, #define GREB_ERROR_DT_HAAP_UNREACHABLE_DSL 401 {GREB_ERROR_DT_HAAP_UNREACHABLE_DSL, "DSL GRE tunnel to the HAAP failed (Telekom specific)"}, #define GREB_ERROR_DT_HAAP_UNREACHABLE_LTE 402 {GREB_ERROR_DT_HAAP_UNREACHABLE_LTE, "LTE GRE tunnel to the HAAP failed (Telekom specific)"}, #define GREB_ERROR_DT_UID_NOT_MATCHING 403 {GREB_ERROR_DT_UID_NOT_MATCHING, "Mismatch of LTE and DSL User IDs (Telekom specific)"}, #define GREB_ERROR_DT_SECOND_SESSION_WITH_UID 404 {GREB_ERROR_DT_SECOND_SESSION_WITH_UID, "Session with the same User ID already exists (Telekom specific)"}, #define GREB_ERROR_DT_CIN_NOT_PERMITTED 405 {GREB_ERROR_DT_CIN_NOT_PERMITTED, "Client uses a not permitted CIN (Telekom specific)"}, #define GREB_ERROR_DT_DSL_TUNNEL_FAILED 406 {GREB_ERROR_DT_DSL_TUNNEL_FAILED, "Communication error during the DSL Tunnel setup (Telekom specific)"}, #define GREB_ERROR_DT_LTE_TUNNEL_FAILED 407 {GREB_ERROR_DT_LTE_TUNNEL_FAILED, "Communication error during the LTE Tunnel setup (Telekom specific)"}, #define GREB_ERROR_DT_MAINTENANCE 501 {GREB_ERROR_DT_MAINTENANCE, "Terminated for maintenance (Telekom specific)"}, #define GREB_ERROR_DT_LTE_PARAM_UPDATE 502 {GREB_ERROR_DT_LTE_PARAM_UPDATE, "LTE terminated to update parameters (Telekom specific)"}, #define GREB_ERROR_DT_DSL_PARAM_UPDATE 503 {GREB_ERROR_DT_DSL_PARAM_UPDATE, "DSL terminated to update parameters (Telekom specific)"}, {0,NULL} }; static 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 retries"}, #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"}, #define GREB_ATTRB_DT_DSL_PROT 53 {GREB_ATTRB_DT_DSL_PROT, "DSL protocol / link type (Telekom specific)"}, #define GREB_ATTRB_DT_BRAS_NAME 54 {GREB_ATTRB_DT_BRAS_NAME, "Broadband Remote Access Server name (Telekom specific)"}, #define GREB_ATTRB_DT_DOWN_REORDER_TIME 56 {GREB_ATTRB_DT_DOWN_REORDER_TIME, "Max. downstream reordering buffer time (Telekom specific)"}, #define GREB_ATTRB_DT_COM_UP_BURST_TIME 57 {GREB_ATTRB_DT_COM_UP_BURST_TIME, "Committed upstream burst time (Telekom specific)"}, #define GREB_ATTRB_DT_UPSTREAM_RATE 59 {GREB_ATTRB_DT_UPSTREAM_RATE, "DSL synchronization Rate upstream (Telekom specific)"}, {255, "FIN"}, {0, NULL} }; static const value_string greb_DT_DSL_prots[] = { #define DT_UNDEF 0 {DT_UNDEF, "Undefined"}, #define DT_ADSL_B 1 {DT_ADSL_B, "ADSL/ADSL2/ADSL2+ Annex B"}, #define DT_ADSL_J 2 {DT_ADSL_J, "ADSL2+ Annex J"}, #define DT_VDSL 3 {DT_VDSL, "VDSL2"}, #define DT_VDSL_VEC 4 {DT_VDSL_VEC, "VDSL2 Vectoring"}, {0, NULL} }; static 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"}, #define GREB_ATTRB_DT_COMBO 15 {GREB_ATTRB_DT_COMBO, "Combination (Telekom specific)"}, {0, NULL} }; static 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, unsigned offset, unsigned 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, unsigned offset, unsigned attrb_length) { proto_item *it_filter; proto_tree *filter_tree; unsigned filter_commit_count = tvb_get_uint32(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(packet_info *pinfo, tvbuff_t *tvb, proto_tree *attrb_tree, unsigned offset, unsigned attrb_length) { proto_item *it_filter; proto_tree *filter_tree; unsigned filter_commit_count = tvb_get_uint32(tvb, offset, ENC_BIG_ENDIAN); unsigned filter_packet_sum = tvb_get_uint16(tvb, offset + 4, ENC_BIG_ENDIAN); unsigned filter_packet_id = tvb_get_uint16(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; unsigned filter_item_length = tvb_get_uint16(tvb, offset + 2, ENC_BIG_ENDIAN); unsigned filter_item_desc_length = tvb_get_uint16(tvb, offset + 6, ENC_BIG_ENDIAN); // bound lengths to not exceed packet if (filter_item_length > (unsigned) 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(pinfo->pool, 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, unsigned offset, unsigned attrb_length) { proto_item *item_ipv6_prefix; proto_tree *ipv6_prefix_tree; unsigned 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_uint8(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; unsigned offset = 0; unsigned message_type = tvb_get_uint8(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)) { unsigned attrb_type = tvb_get_uint8(tvb, offset); unsigned attrb_length = tvb_get_uint16(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 > (unsigned) 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(pinfo, 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_DT_BRAS_NAME: proto_tree_add_item(attrb_tree, hf_greb_attr_dt_bras_name, 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; case GREB_ATTRB_DT_DSL_PROT: proto_tree_add_item(attrb_tree, hf_greb_attr_DSL_prot, 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_DSL_prot, { "DSL Protocol", "grebonding.attr.val.dslproto", FT_UINT8, BASE_DEC, VALS(greb_DT_DSL_prots), 0, NULL, HFILL } }, { &hf_greb_attr_dt_bras_name, { "Broadband Remote Access Server (BRAS) name", "grebonding.attr.val.bras_name", FT_STRING, BASE_NONE, NULL, 0, "", 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, { "Description", "grebonding.attr.val.filter.item.desc", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_greb_attr_filter_item_desc_length, { "Description 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)); greb_handle = register_dissector("grebonding", dissect_greb, proto_greb); } void proto_reg_handoff_greb(void) { 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); }