From e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 10 Apr 2024 22:34:10 +0200 Subject: Adding upstream version 4.2.2. Signed-off-by: Daniel Baumann --- epan/dissectors/packet-nsip.c | 1170 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1170 insertions(+) create mode 100644 epan/dissectors/packet-nsip.c (limited to 'epan/dissectors/packet-nsip.c') diff --git a/epan/dissectors/packet-nsip.c b/epan/dissectors/packet-nsip.c new file mode 100644 index 00000000..16f1d45d --- /dev/null +++ b/epan/dissectors/packet-nsip.c @@ -0,0 +1,1170 @@ +/* packet-nsip.c + * Routines for Network Service Over IP dissection + * Copyright 2000, Susanne Edlund + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* 3GPP TS 48.016 V 5.3.0 (2004-07) Release 6 + CR013 */ + +#include "config.h" + +#include + +#include +#include +#include + +void proto_register_nsip(void); +void proto_reg_handoff_nsip(void); + +#define NSIP_DEBUG 0 +#define NSIP_SEP ", " /* Separator string */ + +#define DEFAULT_NSIP_PORT_RANGE "2157,19999" /* Not IANA registered */ + +/* Initialize the protocol and registered fields */ +static int proto_nsip = -1; + +static int hf_nsip_cause = -1; +static int hf_nsip_ns_vci = -1; +static int hf_nsip_pdu_type = -1; +static int hf_nsip_bvci = -1; +static int hf_nsip_nsei = -1; +/* static int hf_nsip_ip4_elements = -1; */ +/* static int hf_nsip_ip6_elements = -1; */ +static int hf_nsip_max_num_ns_vc = -1; +static int hf_nsip_num_ip4_endpoints = -1; +static int hf_nsip_num_ip6_endpoints = -1; +static int hf_nsip_reset_flag = -1; +static int hf_nsip_reset_flag_bit = -1; +static int hf_nsip_reset_flag_spare = -1; +static int hf_nsip_ip_address_type = -1; +static int hf_nsip_ip_address_ipv4 = -1; +static int hf_nsip_ip_address_ipv6 = -1; +static int hf_nsip_end_flag = -1; +static int hf_nsip_end_flag_bit = -1; +static int hf_nsip_end_flag_spare = -1; +static int hf_nsip_control_bits = -1; +static int hf_nsip_control_bits_r = -1; +static int hf_nsip_control_bits_c = -1; +static int hf_nsip_control_bits_spare = -1; +static int hf_nsip_transaction_id = -1; +/* static int hf_nsip_ip_element_ip_address_ipv4 = -1; */ +/* static int hf_nsip_ip_element_ip_address_ipv6 = -1; */ +static int hf_nsip_ip_element_udp_port = -1; +static int hf_nsip_ip_element_signalling_weight = -1; +static int hf_nsip_ip_element_data_weight = -1; +static int hf_nsip_ns_pdu = -1; +static int hf_nsip_ns_sdu = -1; + +/* Initialize the subtree pointers */ +static gint ett_nsip = -1; +static gint ett_nsip_control_bits = -1; +static gint ett_nsip_reset_flag = -1; +static gint ett_nsip_end_flag = -1; +static gint ett_nsip_ip_element = -1; +static gint ett_nsip_ip_element_list = -1; + +/* PDU type coding, v5.3.0, table 10.3.7.1, p 51 */ +#define NSIP_PDU_NS_UNITDATA 0x00 +#define NSIP_PDU_NS_RESET 0x02 +#define NSIP_PDU_NS_RESET_ACK 0x03 +#define NSIP_PDU_NS_BLOCK 0x04 +#define NSIP_PDU_NS_BLOCK_ACK 0x05 +#define NSIP_PDU_NS_UNBLOCK 0x06 +#define NSIP_PDU_NS_UNBLOCK_ACK 0x07 +#define NSIP_PDU_NS_STATUS 0x08 +#define NSIP_PDU_NS_ALIVE 0x0a +#define NSIP_PDU_NS_ALIVE_ACK 0x0b +#define NSIP_PDU_SNS_ACK 0x0c +#define NSIP_PDU_SNS_ADD 0x0d +#define NSIP_PDU_SNS_CHANGEWEIGHT 0x0e +#define NSIP_PDU_SNS_CONFIG 0x0f +#define NSIP_PDU_SNS_CONFIG_ACK 0x10 +#define NSIP_PDU_SNS_DELETE 0x11 +#define NSIP_PDU_SNS_SIZE 0x12 +#define NSIP_PDU_SNS_SIZE_ACK 0x13 + +static const value_string tab_nsip_pdu_types[] = { + { NSIP_PDU_NS_UNITDATA, "NS_UNITDATA" }, + { NSIP_PDU_NS_RESET, "NS_RESET" }, + { NSIP_PDU_NS_RESET_ACK, "NS_RESET_ACK" }, + { NSIP_PDU_NS_BLOCK, "NS_BLOCK" }, + { NSIP_PDU_NS_BLOCK_ACK, "NS_BLOCK_ACK" }, + { NSIP_PDU_NS_UNBLOCK, "NS_UNBLOCK" }, + { NSIP_PDU_NS_UNBLOCK_ACK, "NS_UNBLOCK_ACK" }, + { NSIP_PDU_NS_STATUS, "NS_STATUS" }, + { NSIP_PDU_NS_ALIVE, "NS_ALIVE" }, + { NSIP_PDU_NS_ALIVE_ACK, "NS_ALIVE_ACK" }, + { NSIP_PDU_SNS_ACK, "SNS_ACK" }, + { NSIP_PDU_SNS_ADD, "SNS_ADD" }, + { NSIP_PDU_SNS_CHANGEWEIGHT, "SNS_CHANGEWEIGHT" }, + { NSIP_PDU_SNS_CONFIG, "SNS_CONFIG" }, + { NSIP_PDU_SNS_CONFIG_ACK, "SNS_CONFIG_ACK" }, + { NSIP_PDU_SNS_DELETE, "SNS_DELETE" }, + { NSIP_PDU_SNS_SIZE, "SNS_SIZE" }, + { NSIP_PDU_SNS_SIZE_ACK, "SNS_SIZE_ACK" }, + { 0, NULL }, +}; + +/* Information element coding, v 5.3.0, table 10.3.1, p 46 */ +#define NSIP_IE_CAUSE 0x00 +#define NSIP_IE_NS_VCI 0x01 +#define NSIP_IE_NS_PDU 0x02 +#define NSIP_IE_BVCI 0x03 +#define NSIP_IE_NSEI 0x04 +#define NSIP_IE_IP4_ELEMENTS 0x05 +#define NSIP_IE_IP6_ELEMENTS 0x06 +#define NSIP_IE_MAX_NUM_NS_VC 0x07 +#define NSIP_IE_NUM_IP4_ENDPOINTS 0x08 +#define NSIP_IE_NUM_IP6_ENDPOINTS 0x09 +#define NSIP_IE_RESET_FLAG 0x0a +#define NSIP_IE_IP_ADDRESS 0x0b + +#if NSIP_DEBUG +static const value_string tab_nsip_ieis[] = { + { NSIP_IE_CAUSE, "Cause" }, + { NSIP_IE_NS_VCI, "NS-VCI" }, + { NSIP_IE_NS_PDU, "NS PDU" }, + { NSIP_IE_BVCI, "BVCI" }, + { NSIP_IE_NSEI, "NSEI" }, + { NSIP_IE_IP4_ELEMENTS, "List of IP4 Elements" }, + { NSIP_IE_IP6_ELEMENTS, "List of IP6 Elements" }, + { NSIP_IE_MAX_NUM_NS_VC, "Maximum Number of NC-VCs" }, + { NSIP_IE_NUM_IP4_ENDPOINTS, "Number of IP4 Endpoints" }, + { NSIP_IE_NUM_IP6_ENDPOINTS, "Number of IP6 Endpoints"}, + { NSIP_IE_RESET_FLAG, "Reset Flag" }, + { NSIP_IE_IP_ADDRESS, "IP Address" }, + { 0, NULL }, +}; +#endif + +/* Cause values, v 5.3.0, table 10.3.2.1, p 47 */ +#define NSIP_CAUSE_TRANSIT_NETWORK_FAILURE 0x00 +#define NSIP_CAUSE_OM_INTERVENTION 0x01 +#define NSIP_CAUSE_EQUIPMENT_FAILURE 0x02 +#define NSIP_CAUSE_NS_VC_BLOCKED 0x03 +#define NSIP_CAUSE_NS_VC_UNKNOWN 0x04 +#define NSIP_CAUSE_BVCI_UNKNOWN 0x05 +#define NSIP_CAUSE_SEMANTICALLY_INCORRECT_PDU 0x08 +#define NSIP_CAUSE_NSIP_PDU_NOT_COMPATIBLE 0x0a +#define NSIP_CAUSE_PROTOCOL_ERROR 0x0b +#define NSIP_CAUSE_INVALID_ESSENTIAL_IE 0x0c +#define NSIP_CAUSE_MISSING_ESSENTIAL_IE 0x0d +#define NSIP_CAUSE_INVALID_NUM_IP4_ENDPOINTS 0x0e +#define NSIP_CAUSE_INVALID_NUM_IP6_ENDPOINTS 0x0f +#define NSIP_CAUSE_INVALID_NUM_NS_VC 0x10 +#define NSIP_CAUSE_INVALID_WEIGHTS 0x11 +#define NSIP_CAUSE_UNKNOWN_IP_ENDPOINT 0x12 +#define NSIP_CAUSE_UNKNOWN_IP_ADDRESS 0x13 +#define NSIP_CAUSE_IP_TEST_FAILED 0x14 + +static const value_string tab_nsip_cause_values[] = { + { NSIP_CAUSE_TRANSIT_NETWORK_FAILURE, "Transit network failure" }, + { NSIP_CAUSE_OM_INTERVENTION, "O&M intervention" }, + { NSIP_CAUSE_EQUIPMENT_FAILURE, "Equipment failure" }, + { NSIP_CAUSE_NS_VC_BLOCKED, "NS-VC blocked" }, + { NSIP_CAUSE_NS_VC_UNKNOWN, "NS-VC unknown" }, + { NSIP_CAUSE_BVCI_UNKNOWN, "BVCI unknown on that NSE" }, + { NSIP_CAUSE_SEMANTICALLY_INCORRECT_PDU, "Semantically incorrect PDU" }, + { NSIP_CAUSE_NSIP_PDU_NOT_COMPATIBLE, "PDU not compatible with the protocol state" }, + { NSIP_CAUSE_PROTOCOL_ERROR, "Protocol error - unspecified" }, + { NSIP_CAUSE_INVALID_ESSENTIAL_IE, "Invalid essential IE" }, + { NSIP_CAUSE_MISSING_ESSENTIAL_IE, "Missing essential IE" }, + { NSIP_CAUSE_INVALID_NUM_IP4_ENDPOINTS, "Invalid number of IP4 endpoints" }, + { NSIP_CAUSE_INVALID_NUM_IP6_ENDPOINTS, "Invalid number of IP6 endpoints" }, + { NSIP_CAUSE_INVALID_NUM_NS_VC, "Invalid number of NS-VCs" }, + { NSIP_CAUSE_INVALID_WEIGHTS, "Invalid weights" }, + { NSIP_CAUSE_UNKNOWN_IP_ENDPOINT, "Unknown IP endpoint" }, + { NSIP_CAUSE_UNKNOWN_IP_ADDRESS, "Unknown IP address" }, + { NSIP_CAUSE_IP_TEST_FAILED, "IP test failed" }, + { 0, NULL }, +}; + +/* Presence requirements of Information Elements + v 5.3.0, chapter 8.1.1, p. 35 */ +#define NSIP_IE_PRESENCE_M 1 /* Mandatory */ +#define NSIP_IE_PRESENCE_O 2 /* Conditional */ +#define NSIP_IE_PRESENCE_C 3 /* Optional */ + +/* Format options */ +#define NSIP_IE_FORMAT_V 1 +#define NSIP_IE_FORMAT_TV 2 +#define NSIP_IE_FORMAT_TLV 3 + +/* IP address types, v 5.3.0, chapter 10.3.2b, p. 48 */ +#define NSIP_IP_ADDRESS_TYPE_IPV4 1 +#define NSIP_IP_ADDRESS_TYPE_IPV6 2 +#define NSIP_IP_VERSION_4 4 +#define NSIP_IP_VERSION_6 6 + +static const value_string ip_address_type_vals[] = { + { 0, "Reserved" }, + { NSIP_IP_ADDRESS_TYPE_IPV4, "IPv4 Address" }, + { NSIP_IP_ADDRESS_TYPE_IPV6, "IPv6 Address" }, + { 0, NULL }, +}; + + +#define NSIP_MASK_CONTROL_BITS_R 0x01 +#define NSIP_MASK_CONTROL_BITS_C 0x02 +#define NSIP_MASK_CONTROL_BITS_SPARE 0xFC +#define NSIP_MASK_END_FLAG 0x01 +#define NSIP_MASK_END_FLAG_SPARE 0xFE +#define NSIP_MASK_RESET_FLAG 0x01 +#define NSIP_MASK_RESET_FLAG_SPARE 0xFE + +static dissector_handle_t bssgp_handle; +static dissector_handle_t nsip_handle; + +static gboolean nsip_is_recursive = FALSE; + +typedef struct { + guint8 iei; + guint8 presence_req; + int format; + guint16 value_length; /* in bytes */ + guint16 total_length; /* as specified, or 0 if unspecified */ +} nsip_ie_t; + +typedef struct { + tvbuff_t *tvb; + int offset; + packet_info *pinfo; + proto_tree *nsip_tree; + proto_tree *parent_tree; + proto_item *ti; +} build_info_t; + +typedef struct { + int version; + int address_length; + int total_length; +} nsip_ip_element_info_t; + +static nsip_ip_element_info_t ipv4_element = { NSIP_IP_VERSION_4, 4, 8 }; +static nsip_ip_element_info_t ipv6_element = { NSIP_IP_VERSION_6, 16, 20 }; + +static void +get_value_length(nsip_ie_t *ie, build_info_t *bi) { + /* length indicator in bit 8, 0 => two bytes, 1 => one byte */ + const guint8 MASK_LENGTH_INDICATOR = 0x80; + const guint8 MASK_ONE_BYTE_LENGTH = 0x7f; + guint8 length_len; + guint16 length; + + length = tvb_get_guint8(bi->tvb, bi->offset); + length_len = 1; + + if (length & MASK_LENGTH_INDICATOR) { + length &= MASK_ONE_BYTE_LENGTH; + } + else { + length_len++; + length <<= 8; + length |= tvb_get_guint8(bi->tvb, bi->offset+1); + } + ie->value_length = length; + ie->total_length += length_len + length; + bi->offset += length_len; +} + +static int +check_correct_iei(nsip_ie_t *ie, build_info_t *bi) { + guint8 fetched_iei = tvb_get_guint8(bi->tvb, bi->offset); + +#if NSIP_DEBUG + if (fetched_iei != ie->iei) { + proto_tree_add_debug(bi->nsip_tree, bi->tvb, bi->offset, 1, + "Tried IEI %s (%#02x), found IEI %s (%#02x)", + val_to_str_const(ie->iei, tab_nsip_ieis, "Unknown"), + ie->iei, + val_to_str_const(fetched_iei, tab_nsip_ieis, "Unknown"), + fetched_iei); + } +#endif + return (fetched_iei == ie->iei); +} + +static void +decode_iei_cause(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) { + guint8 cause; + + cause = tvb_get_guint8(bi->tvb, bi->offset); + proto_tree_add_uint(bi->nsip_tree, hf_nsip_cause, + bi->tvb, ie_start_offset, ie->total_length, + cause); + col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, NSIP_SEP, + "Cause: %s", + val_to_str(cause, tab_nsip_cause_values, "Unknown (0x%02x)")); + + proto_item_append_text(bi->ti, ", Cause: %s", + val_to_str(cause, tab_nsip_cause_values, "Unknown (0x%02x)")); + + bi->offset += ie->value_length; +} + +static void +decode_iei_ns_vci(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) { + guint16 ns_vci; + + ns_vci = tvb_get_ntohs(bi->tvb, bi->offset); + + proto_tree_add_uint(bi->nsip_tree, hf_nsip_ns_vci, + bi->tvb, ie_start_offset, ie->total_length, + ns_vci); + col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, NSIP_SEP, + "NS VCI: %#04x", ns_vci); + proto_item_append_text(bi->ti, ", NS VCI: %#04x", ns_vci); + + bi->offset += ie->value_length; +} + +static void +decode_iei_ns_pdu(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) { + tvbuff_t * next_tvb; + + proto_tree_add_bytes_format(bi->nsip_tree, hf_nsip_ns_pdu, bi->tvb, ie_start_offset, + ie->total_length, NULL, + "NS PDU (%u bytes)", ie->value_length); + next_tvb = tvb_new_subset_length_caplen(bi->tvb, bi->offset, ie->value_length, -1); + if (nsip_handle) { + gboolean was_recursive; + was_recursive = nsip_is_recursive; + nsip_is_recursive = TRUE; + call_dissector(nsip_handle, next_tvb, bi->pinfo, bi->nsip_tree); + nsip_is_recursive = was_recursive; + } + bi->offset += ie->value_length; +} + +static void +decode_iei_nsei(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) { + guint16 nsei = tvb_get_ntohs(bi->tvb, bi->offset); + + proto_tree_add_uint(bi->nsip_tree, hf_nsip_nsei, bi->tvb, + ie_start_offset, ie->total_length, nsei); + bi->offset += ie->value_length; + + col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, NSIP_SEP, + "NSEI %u", nsei); + + proto_item_append_text(bi->ti, ", NSEI %u", nsei); +} + +static void +decode_iei_bvci(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) { + guint16 bvci = tvb_get_ntohs(bi->tvb, bi->offset); + + proto_tree_add_uint(bi->nsip_tree, hf_nsip_bvci, bi->tvb, + ie_start_offset, ie->total_length, bvci); + bi->offset += ie->value_length; + + col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, NSIP_SEP, + "BVCI %u", bvci); + proto_item_append_text(bi->ti, ", BVCI %u", bvci); +} + +static proto_item * +decode_ip_element(nsip_ip_element_info_t *element, build_info_t *bi, proto_tree * element_tree) { + guint16 udp_port; + proto_item *tf; + proto_tree *field_tree; + + field_tree = proto_tree_add_subtree(element_tree, bi->tvb, bi->offset, + element->total_length, ett_nsip_ip_element, &tf, "IP Element"); + if (bi->nsip_tree) { + + /* IP address */ + switch (element->version) { + case NSIP_IP_VERSION_4: + proto_tree_add_item(field_tree, hf_nsip_ip_address_ipv4, + bi->tvb, bi->offset, element->address_length, + ENC_BIG_ENDIAN); + proto_item_append_text(tf, ": IP address: %s", + tvb_ip_to_str(wmem_packet_scope(), bi->tvb, bi->offset)); + + break; + case NSIP_IP_VERSION_6: + proto_tree_add_item(field_tree, hf_nsip_ip_address_ipv6, bi->tvb, + bi->offset, element->address_length, + ENC_NA); + proto_item_append_text(tf, ": IP address: %s", + tvb_ip6_to_str(wmem_packet_scope(), bi->tvb, bi->offset)); + break; + default: + ; + } + } + bi->offset += element->address_length; + + if (bi->nsip_tree) { + /* UDP port value */ + udp_port = tvb_get_ntohs(bi->tvb, bi->offset); + proto_tree_add_item(field_tree, hf_nsip_ip_element_udp_port, + bi->tvb, bi->offset, 2, ENC_BIG_ENDIAN); + proto_item_append_text(tf, ", UDP Port: %u", udp_port); + } + bi->offset += 2; + + if (bi->nsip_tree) { + /* Signalling weight */ + proto_tree_add_item(field_tree, hf_nsip_ip_element_signalling_weight, + bi->tvb, bi->offset, 1, ENC_BIG_ENDIAN); + } + bi->offset++; + + if (bi->nsip_tree) { + /* Data weight */ + proto_tree_add_item(field_tree, hf_nsip_ip_element_data_weight, + bi->tvb, bi->offset, 1, ENC_BIG_ENDIAN); + } + bi->offset++; + return tf; +} + +static proto_item * +decode_ip_elements(nsip_ip_element_info_t *element, nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) { + int i; + int num_elements = ie->value_length / element->total_length; + proto_item *tf; + proto_tree *field_tree; + + field_tree = proto_tree_add_subtree_format(bi->nsip_tree, bi->tvb, ie_start_offset, + ie->total_length, ett_nsip_ip_element_list, &tf, + "List of IP%u Elements (%u Elements)", + element->version, num_elements); + + for (i = 0; i < num_elements; i++) { + decode_ip_element(element, bi, field_tree); + } + return tf; +} + +static void +decode_iei_max_num_ns_vc(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) { + guint16 num_ns_vc; + + if (bi->nsip_tree) { + num_ns_vc = tvb_get_ntohs(bi->tvb, bi->offset); + + proto_tree_add_uint(bi->nsip_tree, hf_nsip_max_num_ns_vc, + bi->tvb, ie_start_offset, ie->total_length, + num_ns_vc); + } + bi->offset += 2; +} + +static void +decode_iei_num_ip4_endpoints(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) { + guint16 num_endpoints; + + if (bi->nsip_tree) { + num_endpoints = tvb_get_ntohs(bi->tvb, bi->offset); + + proto_tree_add_uint(bi->nsip_tree, hf_nsip_num_ip4_endpoints, + bi->tvb, ie_start_offset, ie->total_length, + num_endpoints); + } + bi->offset += 2; +} + +static void +decode_iei_num_ip6_endpoints(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) { + guint16 num_endpoints; + + if (bi->nsip_tree) { + num_endpoints = tvb_get_ntohs(bi->tvb, bi->offset); + + proto_tree_add_uint(bi->nsip_tree, hf_nsip_num_ip6_endpoints, + bi->tvb, ie_start_offset, ie->total_length, + num_endpoints); + } + bi->offset += 2; +} + +static void +decode_iei_reset_flag(nsip_ie_t *ie _U_, build_info_t *bi, int ie_start_offset _U_) { + guint8 flag; + static int * const reset_flags[] = { + &hf_nsip_reset_flag_bit, + &hf_nsip_reset_flag_spare, + NULL + }; + + flag = tvb_get_guint8(bi->tvb, bi->offset); + proto_tree_add_bitmask(bi->nsip_tree, bi->tvb, bi->offset, hf_nsip_reset_flag, + ett_nsip_reset_flag, reset_flags, ENC_NA); + + if (flag & NSIP_MASK_RESET_FLAG) { + col_append_sep_str(bi->pinfo->cinfo, COL_INFO, NSIP_SEP, "Reset"); + } + bi->offset += 1; +} + +static void +decode_iei_ip_address(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) { + guint8 addr_type; + guint32 ip4_addr; + ws_in6_addr ip6_addr; + + addr_type = tvb_get_guint8(bi->tvb, bi->offset); + proto_tree_add_item(bi->nsip_tree, hf_nsip_ip_address_type, + bi->tvb, bi->offset, 1, ENC_BIG_ENDIAN); + switch (addr_type) { + case NSIP_IP_ADDRESS_TYPE_IPV4: + ie->total_length = 2 + ipv4_element.address_length; + ip4_addr = tvb_get_ipv4(bi->tvb, bi->offset+1); + proto_tree_add_ipv4(bi->nsip_tree, hf_nsip_ip_address_ipv4, + bi->tvb, ie_start_offset, ie->total_length, + ip4_addr); + break; + case NSIP_IP_ADDRESS_TYPE_IPV6: + ie->total_length = 2 + ipv6_element.address_length; + tvb_get_ipv6(bi->tvb, bi->offset+1, &ip6_addr); + proto_tree_add_ipv6(bi->nsip_tree, hf_nsip_ip_address_ipv4, + bi->tvb, ie_start_offset, ie->total_length, + &ip6_addr); + break; + default: + return; /* error */ + } + bi->offset += ie->value_length; +} + +static void +decode_iei_transaction_id(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) { + guint8 id; + id = tvb_get_guint8(bi->tvb, bi->offset); + proto_tree_add_uint(bi->nsip_tree, hf_nsip_transaction_id, + bi->tvb, ie_start_offset, ie->total_length, id); + col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, NSIP_SEP, + "Transaction Id: %d", id); + bi->offset += 1; +} + +static void +decode_iei_end_flag(nsip_ie_t *ie _U_, build_info_t *bi, int ie_start_offset) { + static int * const end_flags[] = { + &hf_nsip_end_flag_bit, + &hf_nsip_end_flag_spare, + NULL + }; + + proto_tree_add_bitmask(bi->nsip_tree, bi->tvb, ie_start_offset, hf_nsip_end_flag, + ett_nsip_end_flag, end_flags, ENC_NA); + bi->offset += 1; +} + +static void +decode_iei_control_bits(nsip_ie_t *ie _U_, build_info_t *bi, int ie_start_offset) { + guint8 control_bits; + static int * const flags[] = { + &hf_nsip_control_bits_r, + &hf_nsip_control_bits_c, + &hf_nsip_control_bits_spare, + NULL + }; + + control_bits = tvb_get_guint8(bi->tvb, bi->offset); + proto_tree_add_bitmask(bi->nsip_tree, bi->tvb, ie_start_offset, hf_nsip_control_bits, + ett_nsip_control_bits, flags, ENC_NA); + bi->offset++; + + if (control_bits & NSIP_MASK_CONTROL_BITS_R) { + col_append_sep_str(bi->pinfo->cinfo, COL_INFO, NSIP_SEP, "Req CF"); + proto_item_append_text(bi->ti, ", Request Change Flow"); + } + + if (control_bits & NSIP_MASK_CONTROL_BITS_C) { + col_append_sep_str(bi->pinfo->cinfo, COL_INFO, NSIP_SEP, "Conf CF"); + proto_item_append_text(bi->ti, ", Confirm Change Flow"); + } +} + + +static void +decode_ie(nsip_ie_t *ie, build_info_t *bi) { + + int org_offset = bi->offset; + + if (tvb_captured_length_remaining(bi->tvb, bi->offset) < 1) { + return; + } + switch (ie->format) { + case NSIP_IE_FORMAT_TLV: + if (!check_correct_iei(ie, bi)) { + return; + } + bi->offset++; /* Account for type */ + ie->total_length = 1; + get_value_length(ie, bi); + break; + case NSIP_IE_FORMAT_TV: + if (!check_correct_iei(ie, bi)) { + return; + } + bi->offset++; /* Account for type */ + ie->value_length = ie->total_length - 1; + break; + case NSIP_IE_FORMAT_V: + ie->value_length = ie->total_length; + default: + ; + } + switch (ie->iei) { + case NSIP_IE_CAUSE: + decode_iei_cause(ie, bi, org_offset); + break; + case NSIP_IE_NS_VCI: + decode_iei_ns_vci(ie, bi, org_offset); + break; + case NSIP_IE_NS_PDU: + decode_iei_ns_pdu(ie, bi, org_offset); + break; + case NSIP_IE_NSEI: + decode_iei_nsei(ie, bi, org_offset); + break; + case NSIP_IE_BVCI: + decode_iei_bvci(ie, bi, org_offset); + break; + case NSIP_IE_IP4_ELEMENTS: + decode_ip_elements(&ipv4_element, ie, bi, org_offset); + break; + case NSIP_IE_IP6_ELEMENTS: + decode_ip_elements(&ipv6_element, ie, bi, org_offset); + break; + case NSIP_IE_MAX_NUM_NS_VC: + decode_iei_max_num_ns_vc(ie, bi, org_offset); + break; + case NSIP_IE_NUM_IP4_ENDPOINTS: + decode_iei_num_ip4_endpoints(ie, bi, org_offset); + break; + case NSIP_IE_NUM_IP6_ENDPOINTS: + decode_iei_num_ip6_endpoints(ie, bi, org_offset); + break; + case NSIP_IE_RESET_FLAG: + decode_iei_reset_flag(ie, bi, org_offset); + break; + case NSIP_IE_IP_ADDRESS: + decode_iei_ip_address(ie, bi, org_offset); + break; + default: + ; + } +} + +static void +decode_pdu_general(nsip_ie_t *ies, int num_ies, build_info_t *bi) { + int i; + for (i = 0; i < num_ies; i++) { + decode_ie(&ies[i], bi); + } +} + +static void +decode_pdu_ns_unitdata(build_info_t *bi) { + tvbuff_t *next_tvb; + + nsip_ie_t ies[] = { + { 0, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_V, 0, 1 }, /* Control bits */ + { NSIP_IE_BVCI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_V, 0, 2 }, + { 0, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_V, 0, 0 }, + /* NS SDU, length unknown */ + }; + gint sdu_length; + + decode_iei_control_bits(ies, bi, bi->offset); + decode_pdu_general(&ies[1], 1, bi); + + next_tvb = tvb_new_subset_remaining(bi->tvb, bi->offset); + if (bssgp_handle) { + call_dissector(bssgp_handle, next_tvb, bi->pinfo, bi->parent_tree); + } + else { + sdu_length = tvb_captured_length_remaining(bi->tvb, bi->offset); + proto_tree_add_bytes_format(bi->nsip_tree, hf_nsip_ns_sdu, bi->tvb, bi->offset, sdu_length, + NULL, "NS SDU (%u bytes)", sdu_length); + } +} + +static void +decode_pdu_ns_reset(build_info_t *bi) { + nsip_ie_t ies[] = { + { NSIP_IE_CAUSE, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 3 }, + { NSIP_IE_NS_VCI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4 }, + { NSIP_IE_NSEI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4 }, + }; + decode_pdu_general(ies, 3, bi); +} + +static void +decode_pdu_ns_reset_ack(build_info_t *bi) { + nsip_ie_t ies[] = { + { NSIP_IE_NS_VCI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4 }, + { NSIP_IE_NSEI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4 }, + }; + decode_pdu_general(ies, 2, bi); +} + +static void +decode_pdu_ns_block(build_info_t *bi) { + nsip_ie_t ies[] = { + { NSIP_IE_CAUSE, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 3 }, + { NSIP_IE_NS_VCI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4 }, + }; + decode_pdu_general(ies, 2, bi); +} + +static void +decode_pdu_ns_block_ack(build_info_t *bi) { + nsip_ie_t ies[] = { { NSIP_IE_NS_VCI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, + 0, 1 }, }; + decode_pdu_general(ies, 1, bi); +} + +static void +decode_pdu_ns_status(build_info_t *bi) { + nsip_ie_t ies[] = { + { NSIP_IE_CAUSE, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 3 }, + { NSIP_IE_NS_VCI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4 }, + { NSIP_IE_NS_PDU, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 0 }, + /* Unknown length */ + { NSIP_IE_BVCI, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 4 }, + { NSIP_IE_IP4_ELEMENTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 0 }, + /* Unknown length */ + { NSIP_IE_IP6_ELEMENTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 0 }, + /* Unknown length */ + }; + decode_pdu_general(ies, 6, bi); +} + +static void +decode_pdu_sns_ack(build_info_t *bi) { + nsip_ie_t ies[] = { + { NSIP_IE_NSEI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4 }, + { 0, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_V, 0, 1 }, /* Transaction id */ + { NSIP_IE_CAUSE, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 3 }, + { NSIP_IE_IP_ADDRESS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TV, 0, 0 }, + /* Unknown length */ + { NSIP_IE_IP4_ELEMENTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 0 }, + { NSIP_IE_IP6_ELEMENTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 0 }, + }; + decode_pdu_general(ies, 1, bi); + decode_iei_transaction_id(&ies[1], bi, bi->offset); + decode_pdu_general(&ies[2], 4, bi); +} + +static void +decode_pdu_sns_add(build_info_t *bi) { + nsip_ie_t ies[] = { + { NSIP_IE_NSEI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4 }, + { 0, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_V, 0, 1 }, /* Transaction id */ + { NSIP_IE_IP4_ELEMENTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 0 }, + /* Unknown length */ + { NSIP_IE_IP6_ELEMENTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 0 }, + /* Unknown length */ + }; + decode_pdu_general(ies, 1, bi); + decode_iei_transaction_id(&ies[1], bi, bi->offset); + decode_pdu_general(&ies[2], 2, bi); +} + +static void +decode_pdu_sns_changeweight(build_info_t *bi) { + nsip_ie_t ies[] = { + { NSIP_IE_NSEI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4 }, + { 0, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_V, 0, 1 }, /* Transaction id */ + { NSIP_IE_IP4_ELEMENTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 0 }, + /* Unknown length */ + { NSIP_IE_IP6_ELEMENTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 0 }, + /* Unknown length */ + }; + decode_pdu_general(ies, 1, bi); + decode_iei_transaction_id(&ies[1], bi, bi->offset); + decode_pdu_general(&ies[2], 2, bi); +} + +static void +decode_pdu_sns_config(build_info_t *bi) { + + nsip_ie_t ies[] = { + { 0, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_V, 0, 1 }, /* End flag */ + { NSIP_IE_NSEI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4 }, + { NSIP_IE_IP4_ELEMENTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 0 }, + /* Unknown length */ + { NSIP_IE_IP6_ELEMENTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 0 }, + /* Unknown length */ + }; + decode_iei_end_flag(ies, bi, bi->offset); + decode_pdu_general(&ies[1], 3, bi); +} + +static void +decode_pdu_sns_config_ack(build_info_t *bi) { + nsip_ie_t ies[] = { + { NSIP_IE_NSEI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4 }, + { NSIP_IE_CAUSE, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 3 }, + }; + decode_pdu_general(ies, 2, bi); +} + +static void +decode_pdu_sns_delete(build_info_t *bi) { + nsip_ie_t ies[] = { + { NSIP_IE_NSEI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4}, /* CR013 */ + { 0, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_V, 0, 1 }, /* Transaction id */ + { NSIP_IE_IP_ADDRESS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TV, 0, 0 }, + /* Unknown length */ + { NSIP_IE_IP4_ELEMENTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 0 }, + { NSIP_IE_IP6_ELEMENTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 0 }, + }; + decode_pdu_general(ies, 1, bi); + decode_iei_transaction_id(&ies[1], bi, bi->offset); + decode_pdu_general(&ies[2], 3, bi); +} + +static void +decode_pdu_sns_size(build_info_t *bi) { + nsip_ie_t ies[] = { + { NSIP_IE_NSEI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4 }, + { NSIP_IE_RESET_FLAG, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TV, 0, 2 }, + { NSIP_IE_MAX_NUM_NS_VC, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TV, 0, 3 }, + { NSIP_IE_NUM_IP4_ENDPOINTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TV, + 0, 3 }, + { NSIP_IE_NUM_IP6_ENDPOINTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TV, + 0, 3 }, + }; + decode_pdu_general(ies, 5, bi); +} + +static void +decode_pdu_sns_size_ack(build_info_t *bi) { + nsip_ie_t ies[] = { + { NSIP_IE_NSEI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4 }, + { NSIP_IE_CAUSE, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 3 }, + }; + decode_pdu_general(ies, 2, bi); +} + +static void +decode_pdu(guint8 pdu_type, build_info_t *bi, packet_info *pinfo) { + switch (pdu_type) { + case NSIP_PDU_NS_UNITDATA: + decode_pdu_ns_unitdata(bi); + break; + case NSIP_PDU_NS_RESET: + decode_pdu_ns_reset(bi); + break; + case NSIP_PDU_NS_RESET_ACK: + decode_pdu_ns_reset_ack(bi); + break; + case NSIP_PDU_NS_BLOCK: + decode_pdu_ns_block(bi); + break; + case NSIP_PDU_NS_BLOCK_ACK: + decode_pdu_ns_block_ack(bi); + break; + case NSIP_PDU_NS_STATUS: + pinfo->flags.in_error_pkt = TRUE; + decode_pdu_ns_status(bi); + break; + case NSIP_PDU_SNS_ACK: + decode_pdu_sns_ack(bi); + break; + case NSIP_PDU_SNS_ADD: + decode_pdu_sns_add(bi); + break; + case NSIP_PDU_SNS_CHANGEWEIGHT: + decode_pdu_sns_changeweight(bi); + break; + case NSIP_PDU_SNS_CONFIG: + decode_pdu_sns_config(bi); + break; + case NSIP_PDU_SNS_CONFIG_ACK: + decode_pdu_sns_config_ack(bi); + break; + case NSIP_PDU_SNS_DELETE: + decode_pdu_sns_delete(bi); + break; + case NSIP_PDU_SNS_SIZE: + decode_pdu_sns_size(bi); + break; + case NSIP_PDU_SNS_SIZE_ACK: + decode_pdu_sns_size_ack(bi); + break; + case NSIP_PDU_NS_ALIVE: + case NSIP_PDU_NS_ALIVE_ACK: + case NSIP_PDU_NS_UNBLOCK: + case NSIP_PDU_NS_UNBLOCK_ACK: + /* Only contains PDU type, which has already been decoded */ + default: ; + } +} + +static int +dissect_nsip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { + guint8 pdu_type; + build_info_t bi = { NULL, 0, NULL, NULL, NULL, NULL }; + proto_tree *nsip_tree; + + bi.tvb = tvb; + bi.pinfo = pinfo; + bi.parent_tree = tree; + + if (!nsip_is_recursive) { + col_set_str(pinfo->cinfo, COL_PROTOCOL, "GPRS-NS"); + col_clear(pinfo->cinfo, COL_INFO); + } + + pdu_type = tvb_get_guint8(tvb, 0); + bi.offset++; + + if (tree) { + bi.ti = proto_tree_add_item(tree, proto_nsip, tvb, 0, -1, + ENC_NA); + nsip_tree = proto_item_add_subtree(bi.ti, ett_nsip); + proto_tree_add_item(nsip_tree, hf_nsip_pdu_type, tvb, 0, 1, ENC_BIG_ENDIAN); + proto_item_append_text(bi.ti, ", PDU type: %s", + val_to_str_const(pdu_type, tab_nsip_pdu_types, "Unknown")); + bi.nsip_tree = nsip_tree; + } + + if (!nsip_is_recursive) { + col_set_str(pinfo->cinfo, COL_INFO, + val_to_str_const(pdu_type, tab_nsip_pdu_types, "Unknown PDU type")); + } else { + col_append_sep_str(pinfo->cinfo, COL_INFO, NSIP_SEP, + val_to_str_const(pdu_type, tab_nsip_pdu_types, "Unknown PDU type")); + } + decode_pdu(pdu_type, &bi, pinfo); + return tvb_captured_length(tvb); +} + +void +proto_register_nsip(void) +{ + static hf_register_info hf[] = { + { &hf_nsip_cause, + { "Cause", "nsip.cause", + FT_UINT8, BASE_HEX, VALS(tab_nsip_cause_values), 0x0, + NULL, HFILL } + }, + { &hf_nsip_ns_vci, + { "NS-VCI", "nsip.ns_vci", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Network Service Virtual Link Identifier", HFILL } + }, + { &hf_nsip_pdu_type, + { "PDU type", "nsip.pdu_type", + FT_UINT8, BASE_HEX, VALS(tab_nsip_pdu_types), 0x0, + "PDU type information element", HFILL } + }, + { &hf_nsip_bvci, + { "BVCI", "nsip.bvci", + FT_UINT16, BASE_DEC, NULL, 0x0, + "BSSGP Virtual Connection Identifier", HFILL } + }, + { &hf_nsip_nsei, + { "NSEI", "nsip.nsei", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Network Service Entity Identifier", HFILL } + }, +#if 0 + { &hf_nsip_ip4_elements, + { "IP4 elements", "nsip.ip4_elements", + FT_NONE, BASE_NONE, NULL, 0x0, + "List of IP4 elements", HFILL } + }, +#endif +#if 0 + { &hf_nsip_ip6_elements, + { "IP6 elements", "nsip.ip6_elements", + FT_NONE, BASE_NONE, NULL, 0x0, + "List of IP6 elements", HFILL } + }, +#endif + { &hf_nsip_max_num_ns_vc, + { "Maximum number of NS-VCs", "nsip.max_num_ns_vc", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_nsip_num_ip4_endpoints, + { "Number of IP4 endpoints", "nsip.num_ip4_endpoints", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_nsip_num_ip6_endpoints, + { "Number of IP6 endpoints", "nsip.num_ip6_endpoints", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_nsip_reset_flag, + { "Reset flag", "nsip.reset_flag", + FT_UINT8, BASE_HEX, NULL, 0, + NULL, HFILL } + }, + { &hf_nsip_reset_flag_bit, + { "Reset flag", "nsip.reset_flag.flag", + FT_BOOLEAN, 8, TFS(&tfs_set_notset), NSIP_MASK_RESET_FLAG, + NULL, HFILL } + }, + { &hf_nsip_reset_flag_spare, + { "Reset flag spare bits", "nsip.reset_flag.spare", + FT_UINT8, BASE_HEX, NULL, NSIP_MASK_RESET_FLAG_SPARE, + NULL, HFILL } + }, + { &hf_nsip_ip_address_type, + { "IP Address Type", "nsip.ip_address_type", + FT_UINT8, BASE_DEC, VALS(ip_address_type_vals), 0x0, + NULL, HFILL } + }, + { &hf_nsip_ip_address_ipv4, + { "IP Address", "nsip.ipv4_address", + FT_IPv4, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_nsip_ip_address_ipv6, + { "IP Address", "nsip.ipv6_address", + FT_IPv6, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_nsip_end_flag, + { "End flag", "nsip.end_flag", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_nsip_end_flag_bit, + { "End flag", "nsip.end_flag.flag", + FT_BOOLEAN, 8, TFS(&tfs_set_notset), NSIP_MASK_END_FLAG, + NULL, HFILL } + }, + { &hf_nsip_end_flag_spare, + { "End flag spare bits", "nsip.end_flag.spare", + FT_UINT8, BASE_HEX, NULL, NSIP_MASK_END_FLAG_SPARE, + NULL, HFILL } + }, + { &hf_nsip_control_bits, + { "NS SDU Control bits", "nsip.control_bits", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_nsip_control_bits_r, + { "Request change flow", "nsip.control_bits.r", + FT_BOOLEAN, 8, TFS(&tfs_set_notset), NSIP_MASK_CONTROL_BITS_R, + NULL, HFILL } + }, + { &hf_nsip_control_bits_c, + { "Confirm change flow", "nsip.control_bits.c", + FT_BOOLEAN, 8, TFS(&tfs_set_notset), NSIP_MASK_CONTROL_BITS_C, + NULL, HFILL } + }, + { &hf_nsip_control_bits_spare, + { "Spare bits", "nsip.control_bits.spare", + FT_UINT8, BASE_HEX, NULL, NSIP_MASK_CONTROL_BITS_SPARE, + NULL, HFILL } + }, + { &hf_nsip_transaction_id, + { "Transaction ID", "nsip.transaction_id", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, +#if 0 + { &hf_nsip_ip_element_ip_address_ipv4, + { "IP Address", "nsip.ip_element.ipv4_address", + FT_IPv4, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, +#endif +#if 0 + { &hf_nsip_ip_element_ip_address_ipv6, + { "IP Address", "nsip.ip_element.ipv6_address", + FT_IPv6, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, +#endif + { &hf_nsip_ip_element_udp_port, + { "UDP Port", "nsip.ip_element.udp_port", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_nsip_ip_element_signalling_weight, + { "Signalling Weight", "nsip.ip_element.signalling_weight", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_nsip_ip_element_data_weight, + { "Data Weight", "nsip.ip_element.data_weight", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_nsip_ns_pdu, + { "NS PDU", "nsip.ns_pdu", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_nsip_ns_sdu, + { "NS SDU", "nsip.ns_sdu", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + }; + + /* Setup protocol subtree array */ + static gint *ett[] = { + &ett_nsip, + &ett_nsip_control_bits, + &ett_nsip_reset_flag, + &ett_nsip_end_flag, + &ett_nsip_ip_element, + &ett_nsip_ip_element_list, + }; + + module_t *nsip_module; + + /* Register the protocol name and description */ + proto_nsip = proto_register_protocol("GPRS Network Service", "GPRS-NS", "gprs-ns"); + + /* Required function calls to register the header fields and + subtrees used */ + proto_register_field_array(proto_nsip, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + register_dissector("gprs_ns", dissect_nsip, proto_nsip); + + /* Register configuration options */ + nsip_module = prefs_register_protocol(proto_nsip, NULL); + /* For reading older preference files with "nsip." preferences */ + prefs_register_module_alias("nsip", nsip_module); + prefs_register_obsolete_preference(nsip_module, "udp.port1"); + prefs_register_obsolete_preference(nsip_module, "udp.port2"); +} + +void +proto_reg_handoff_nsip(void) { + + nsip_handle = find_dissector_add_dependency("gprs_ns", proto_nsip); + bssgp_handle = find_dissector_add_dependency("bssgp", proto_nsip); + + dissector_add_uint_range_with_preference("udp.port", DEFAULT_NSIP_PORT_RANGE, nsip_handle); + dissector_add_uint("atm.aal5.type", TRAF_GPRS_NS, nsip_handle); + +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 2 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=2 tabstop=8 expandtab: + * :indentSize=2:tabSize=8:noTabs=true: + */ -- cgit v1.2.3