diff options
author | etxrab <etxrab@f5534014-38df-0310-8fa8-9805f1628bb7> | 2004-11-30 21:19:25 +0000 |
---|---|---|
committer | etxrab <etxrab@f5534014-38df-0310-8fa8-9805f1628bb7> | 2004-11-30 21:19:25 +0000 |
commit | f7d38b45974bb14a8df613adb42121fc7f345ac9 (patch) | |
tree | 2efbf11e4cf0610ffe2b093ed266ceb7b206ff97 /epan/dissectors/packet-nsip.c | |
parent | e802b18cd604428aa906879efdf2d3575dd3d1c4 (diff) |
New dissector for NSIP from Susanne Edlund, default port2 changed to unallocated port 19999
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@12626 f5534014-38df-0310-8fa8-9805f1628bb7
Diffstat (limited to 'epan/dissectors/packet-nsip.c')
-rw-r--r-- | epan/dissectors/packet-nsip.c | 1285 |
1 files changed, 1285 insertions, 0 deletions
diff --git a/epan/dissectors/packet-nsip.c b/epan/dissectors/packet-nsip.c new file mode 100644 index 0000000000..c4f5fd39ab --- /dev/null +++ b/epan/dissectors/packet-nsip.c @@ -0,0 +1,1285 @@ +/* packet-nsip.c + * Routines for Network Service Over IP dissection + * Copyright 2000, Susanne Edlund <susanne.edlund@ericsson.com> + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@ethereal.com> + * Copyright 1998 Gerald Combs + * + * Copied from WHATEVER_FILE_YOU_USED (where "WHATEVER_FILE_YOU_USED" + * is a dissector file; if you just copied this from README.developer, + * don't bother with the "Copied from" - you don't even need to put + * in a "Copied from" if you copied an existing dissector, especially + * if the bulk of the code in the new dissector is your code) + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* 3GPP TS 48.016 V 5.3.0 (2004-07) Release 6 + CR013 */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <glib.h> + +#include <epan/packet.h> +#include <epan/ipv6-utils.h> +#include <prefs.h> + +#define NSIP_DEBUG 0 +#define DECODE_AS_NSIP 1 +#define NSIP_UDP_PORT1 2157 +#define NSIP_UDP_PORT2 19999 +#define NSIP_SEP ", " /* Separator string */ +#define NSIP_LITTLE_ENDIAN 0 + +#define ERICSSON_INTERNAL + +#ifdef ERICSSON_INTERNAL +#define ERICSSON_DESCR_LEN 50 +#define ERICSSON_RIP_TYPE 223 /* Ip address of format x.x.223.x */ +#define ERICSSON_LIP_TYPE 80 /* Ip address of format x.x.80.x */ +static int hf_nsip_ericsson_rip = -1; +static int hf_nsip_ericsson_lip = -1; +static int hf_nsip_ericsson_rp = -1; +#endif + +static int nsip_udp_port1 = NSIP_UDP_PORT1; +static int nsip_udp_port2 = NSIP_UDP_PORT2; +void proto_reg_handoff_nsip(void); + +/* 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_ip_address_ipv4 = -1; +static int hf_nsip_ip_address_ipv6 = -1; +static int hf_nsip_end_flag = -1; +static int hf_nsip_control_bits_r = -1; +static int hf_nsip_control_bits_c = -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; + + +/* Initialize the subtree pointers */ +static gint ett_nsip = -1; +static gint ett_nsip_control_bits = -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 + +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 }, +}; + +/* 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 adress 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 + +#define NSIP_MASK_CONTROL_BITS_R 0x01 +#define NSIP_MASK_CONTROL_BITS_C 0x02 +#define NSIP_MASK_END_FLAG 0x01 +#define NSIP_MASK_RESET_FLAG 0x01 + +static dissector_handle_t bssgp_handle; +static dissector_handle_t nsip_handle; + +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; +} 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 true_false_string set_unset = { + "Set", + "Not set" +}; + +#ifdef ERICSSON_INTERNAL +static void +add_ericsson_internal_info(address addr, build_info_t *bi, char *descr) { + const guint8 MIN_RIP_ID = 3; + const guint8 MAX_RIP_ID = 16; + const guint8 MIN_LIP_ID = 10; + const guint8 MAX_LIP_ID = 13; + + int rp; + guint8 addr_type, addr_id; + guint8 dummy_len = 1; + gchar **ip_str_parts; + + if (addr.type != AT_IPv4) { + descr = NULL; + return; + } + ip_str_parts = g_strsplit((ip_to_str(addr.data)), ".", 4); + addr_type = (guint8)atol(ip_str_parts[2]); + addr_id = (guint8)atol(ip_str_parts[3]); + + g_strfreev(ip_str_parts); + + switch (addr_type) { + case ERICSSON_RIP_TYPE: + if ((addr_id >= MIN_RIP_ID) && (addr_id <= MAX_RIP_ID)) { + if (bi->nsip_tree) { + proto_tree_add_uint_hidden(bi->nsip_tree, hf_nsip_ericsson_rip, + bi->tvb, bi->offset, dummy_len, addr_id); + } + g_snprintf(descr, ERICSSON_DESCR_LEN, "RIP .%d", addr_id); + } + else { + g_snprintf(descr, ERICSSON_DESCR_LEN, "Unknown RIP (.%d)", addr_id); + } + break; + case ERICSSON_LIP_TYPE: + if ((addr_id >= MIN_LIP_ID) && (addr_id <= MAX_LIP_ID)) { + switch (addr_id) { + case 13: rp = 101; break; + case 12: rp = 100; break; + case 11: rp = 99; break; + case 10: rp = 98; break; + default: rp = -1; break; + } + if (bi->nsip_tree) { + proto_tree_add_uint_hidden(bi->nsip_tree, hf_nsip_ericsson_lip, + bi->tvb, bi->offset, dummy_len, addr_id); + if (rp != -1) { + proto_tree_add_uint_hidden(bi->nsip_tree, hf_nsip_ericsson_rp, + bi->tvb, bi->offset, dummy_len, + (guint8)rp); + } + } + if (rp != -1) { + g_snprintf(descr, ERICSSON_DESCR_LEN, "LIP .%d (RP%d)", addr_id, rp); + } + else { + g_snprintf(descr, ERICSSON_DESCR_LEN, "LIP .%d (Unknown RP)", + addr_id); + } + } + else { + g_snprintf(descr, ERICSSON_DESCR_LEN, "Unknown LIP (.%d)", addr_id); + } + break; + default: + g_snprintf(descr, ERICSSON_DESCR_LEN, "Not a RIP or LIP (.%d.%d)", + addr_type, addr_id); + } +} +#endif + +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); + } + 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); + +#ifdef NSIP_DEBUG + if (fetched_iei != ie->iei) { + proto_tree_add_text(bi->nsip_tree, bi->tvb, bi->offset, 1, + "Tried IEI %s (%#02x), found IEI %s (%#02x)", + val_to_str(ie->iei, tab_nsip_ieis, "Unknown"), + ie->iei, + val_to_str(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; + + if (bi->nsip_tree) { + cause = tvb_get_guint8(bi->tvb, bi->offset); + proto_tree_add_uint_format(bi->nsip_tree, hf_nsip_cause, + bi->tvb, ie_start_offset, ie->total_length, + cause, + "Cause: %s (%#02x)", + val_to_str(cause, tab_nsip_cause_values, + "Unknown"), cause); + } + 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; + + if (bi->nsip_tree) { + ns_vci = tvb_get_ntohs(bi->tvb, bi->offset); + + proto_tree_add_uint_format(bi->nsip_tree, hf_nsip_ns_vci, + bi->tvb, ie_start_offset, ie->total_length, + ns_vci, + "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; + + if (bi->nsip_tree) { + proto_tree_add_text(bi->nsip_tree, bi->tvb, ie_start_offset, + ie->total_length, + "NS PDU (%u bytes)", ie->value_length); + } + next_tvb = tvb_new_subset(bi->tvb, bi->offset, ie->value_length, -1); + if (nsip_handle) { + call_dissector(nsip_handle, next_tvb, bi->pinfo, bi->nsip_tree); + } + else { + 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); + + if (bi->nsip_tree) { + proto_tree_add_uint(bi->nsip_tree, hf_nsip_nsei, bi->tvb, + ie_start_offset, ie->total_length, nsei); + } + bi->offset += ie->value_length; + + if (check_col(bi->pinfo->cinfo, COL_INFO)) { + col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, NSIP_SEP, + "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); + + if (bi->nsip_tree) { + proto_tree_add_uint(bi->nsip_tree, hf_nsip_bvci, bi->tvb, + ie_start_offset, ie->total_length, bvci); + } + bi->offset += ie->value_length; + + if (check_col(bi->pinfo->cinfo, COL_INFO)) { + col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, NSIP_SEP, + "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; + guint32 ip4_addr; + struct e_in6_addr ip6_addr; + proto_item *tf = NULL; + proto_tree *field_tree = NULL; + + if (bi->nsip_tree) { + tf = proto_tree_add_text(element_tree, bi->tvb, bi->offset, + element->total_length, "IP Element"); + field_tree = proto_item_add_subtree(tf, ett_nsip_ip_element); + + /* IP address */ + switch (element->version) { + case NSIP_IP_VERSION_4: + tvb_memcpy(bi->tvb, (guint8 *)&ip4_addr, bi->offset, + element->address_length); + proto_tree_add_item(field_tree, hf_nsip_ip_address_ipv4, + bi->tvb, bi->offset, element->address_length, + NSIP_LITTLE_ENDIAN); + proto_item_append_text(tf, ": IP address: %s", + ip_to_str((guint8 *)&ip4_addr)); + + break; + case NSIP_IP_VERSION_6: + tvb_memcpy(bi->tvb, (guint8 *)&ip6_addr, bi->offset, + sizeof(struct e_in6_addr)); + proto_tree_add_item(field_tree, hf_nsip_ip_address_ipv6, bi->tvb, + bi->offset, element->address_length, + NSIP_LITTLE_ENDIAN); + proto_item_append_text(tf, ": IP address: %s", + ip6_to_str((struct e_in6_addr *)&ip6_addr)); + 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_uint_format(field_tree, hf_nsip_ip_element_udp_port, + bi->tvb, bi->offset, 2, udp_port, + "UDP Port: %u", udp_port); + 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, NSIP_LITTLE_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, NSIP_LITTLE_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, *ti = NULL; + proto_tree *field_tree; + + tf = proto_tree_add_text(bi->nsip_tree, bi->tvb, ie_start_offset, + ie->total_length, + "List of IP%u Elements (%u Elements)", + element->version, num_elements); + field_tree = proto_item_add_subtree(tf, ett_nsip_ip_element_list); + + for (i = 0; i < num_elements; i++) { + ti = 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_format(bi->nsip_tree, hf_nsip_max_num_ns_vc, + bi->tvb, ie_start_offset, ie->total_length, + num_ns_vc, + "Maximum Number of NS-VCs: %u", 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_format(bi->nsip_tree, hf_nsip_num_ip4_endpoints, + bi->tvb, ie_start_offset, ie->total_length, + num_endpoints, + "Number of IP4 Endpoints: %u", 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_format(bi->nsip_tree, hf_nsip_num_ip6_endpoints, + bi->tvb, ie_start_offset, ie->total_length, + num_endpoints, + "Number of IP6 Endpoints: %u", num_endpoints); + } + bi->offset += 2; +} + +static void +decode_iei_reset_flag(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) { + guint8 flag; + flag = tvb_get_guint8(bi->tvb, bi->offset); + + if (bi->nsip_tree) { + proto_tree_add_boolean(bi->nsip_tree, hf_nsip_reset_flag, bi->tvb, + ie_start_offset, ie->total_length, + flag & NSIP_MASK_RESET_FLAG); + } + bi->offset += 1; +} + +static void +decode_iei_ip_address(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) { + guint8 address_type; + guint32 ip4_addr; + struct e_in6_addr ip6_addr; + + address_type = tvb_get_guint8(bi->tvb, bi->offset); + switch (address_type) { + case NSIP_IP_ADDRESS_TYPE_IPV4: + ie->total_length = 2 + ipv4_element.address_length; + tvb_memcpy(bi->tvb, (guint8 *)&ip4_addr, bi->offset, + ipv4_element.address_length); + if (bi->nsip_tree) { + 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_memcpy(bi->tvb, (guint8 *)&ip6_addr, bi->offset, + sizeof(struct e_in6_addr)); + if (bi->nsip_tree) { + proto_tree_add_ipv6(bi->nsip_tree, hf_nsip_ip_address_ipv4, + bi->tvb, ie_start_offset, ie->total_length, + (guint8 *)&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; + if (bi->nsip_tree) { + 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); + } + bi->offset += 1; +} + +static void +decode_iei_end_flag(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) { + guint8 flag; + if (bi->nsip_tree) { + flag = tvb_get_guint8(bi->tvb, bi->offset); + proto_tree_add_boolean(bi->nsip_tree, hf_nsip_end_flag, bi->tvb, + ie_start_offset, ie->total_length, + flag & NSIP_MASK_END_FLAG); + } + bi->offset += 1; +} + +static void +decode_iei_control_bits(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) { + guint8 control_bits; + proto_item *tf; + proto_tree *field_tree; + + control_bits = tvb_get_guint8(bi->tvb, bi->offset); + + if (bi->nsip_tree) { + tf = proto_tree_add_text(bi->nsip_tree, bi->tvb, ie_start_offset, + ie->total_length, + "NS SDU Control bits: %#02x", control_bits); + + field_tree = proto_item_add_subtree(tf, ett_nsip_control_bits); + proto_tree_add_boolean(field_tree, hf_nsip_control_bits_r, bi->tvb, + bi->offset, 1, + control_bits & NSIP_MASK_CONTROL_BITS_R); + proto_tree_add_boolean(field_tree, hf_nsip_control_bits_c, bi->tvb, + bi->offset, 1, + control_bits & NSIP_MASK_CONTROL_BITS_C); + } + bi->offset++; + + if (check_col(bi->pinfo->cinfo, COL_INFO)) { + if (control_bits & NSIP_MASK_CONTROL_BITS_R) { + col_append_sep_str(bi->pinfo->cinfo, COL_INFO, NSIP_SEP, "Req CF"); + } + + if (control_bits & NSIP_MASK_CONTROL_BITS_C) { + col_append_sep_str(bi->pinfo->cinfo, COL_INFO, NSIP_SEP, "Conf CF"); + } + } +} + + +static void +decode_ie(nsip_ie_t *ie, build_info_t *bi) { + + int org_offset = bi->offset; + + if (tvb_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(bi->tvb, bi->offset, -1, -1); + if (bssgp_handle) { + call_dissector(bssgp_handle, next_tvb, bi->pinfo, bi->parent_tree); + } + else { + sdu_length = tvb_length_remaining(bi->tvb, bi->offset); + proto_tree_add_text(bi->nsip_tree, bi->tvb, bi->offset, sdu_length, + "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_V, + 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) { + int use520 = 1; + + if (use520) { + /* According to v. 5.2.0 */ + 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); + } + else { /* According to v. 5.3.0 */ + 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 }, /* 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_pdu_general(ies, 1, bi); + decode_iei_end_flag(&ies[1], bi, bi->offset); + decode_pdu_general(&ies[2], 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_iei_transaction_id(ies, bi, bi->offset); + decode_pdu_general(&ies[1], 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) { + 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: + 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 void +dissect_nsip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { + guint8 pdu_type; + build_info_t bi = { tvb, 0, pinfo, NULL, tree }; + proto_item *ti; + proto_tree *nsip_tree; + char ericsson_src[ERICSSON_DESCR_LEN]; + char ericsson_dst[ERICSSON_DESCR_LEN]; + + pinfo->current_proto = "NSIP"; + + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, "NSIP"); + + if (check_col(pinfo->cinfo, COL_INFO)) + col_clear(pinfo->cinfo, COL_INFO); + + pdu_type = tvb_get_guint8(tvb, 0); + bi.offset++; + + if (tree) { + ti = proto_tree_add_item(tree, proto_nsip, tvb, 0, -1, + NSIP_LITTLE_ENDIAN); + nsip_tree = proto_item_add_subtree(ti, ett_nsip); + proto_tree_add_uint_format(nsip_tree, hf_nsip_pdu_type, tvb, 0, 1, + pdu_type, + "PDU type: %s (%#02x)", + val_to_str(pdu_type, tab_nsip_pdu_types, + "Unknown"), pdu_type); + bi.nsip_tree = nsip_tree; + } + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_str(pinfo->cinfo, COL_INFO, + val_to_str(pdu_type, tab_nsip_pdu_types, "Unknown PDU type")); + } + decode_pdu(pdu_type, &bi); + +#ifdef ERICSSON_INTERNAL + add_ericsson_internal_info(bi.pinfo->src, &bi, ericsson_src); + if (ericsson_src != NULL) { + pinfo->src.type = AT_NONE; + if (check_col(pinfo->cinfo, COL_DEF_SRC)) { + col_set_str(pinfo->cinfo, COL_DEF_SRC, ericsson_src); + } + } + add_ericsson_internal_info(bi.pinfo->dst, &bi, ericsson_dst); + if (ericsson_dst != NULL) { + pinfo->dst.type = AT_NONE; + if (check_col(pinfo->cinfo, COL_DEF_DST)) { + col_set_str(pinfo->cinfo, COL_DEF_DST, ericsson_dst); + } + } +#endif +} + +void +proto_register_nsip(void) +{ + static hf_register_info hf[] = { + { &hf_nsip_cause, + { "Cause", "nsip.cause", + FT_UINT8, BASE_OCT, VALS(tab_nsip_cause_values), 0x0, + "", HFILL } + }, + { &hf_nsip_ns_vci, + { "NS-VCI", "nsip.ns_vci", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Network Service Virtual Link Identifier", HFILL } + }, + { &hf_nsip_pdu_type, + { "PDU type", "nsip.pdu_type", + FT_UINT8, BASE_OCT, 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 } + }, + { &hf_nsip_ip4_elements, + { "IP4 elements", "nsip.ip4_elements", + FT_NONE, BASE_NONE, NULL, 0x0, + "List of IP4 elements", HFILL } + }, + { &hf_nsip_ip6_elements, + { "IP6 elements", "nsip.ip6_elements", + FT_NONE, BASE_NONE, NULL, 0x0, + "List of IP6 elements", HFILL } + }, + { &hf_nsip_max_num_ns_vc, + { "Maximum number of NS-VCs", "nsip.max_num_ns_vc", + FT_UINT16, BASE_DEC, NULL, 0x0, + "", HFILL } + }, + { &hf_nsip_num_ip4_endpoints, + { "Number of IP4 endpoints", "nsip.num_ip4_endpoints", + FT_UINT16, BASE_DEC, NULL, 0x0, + "", HFILL } + }, + { &hf_nsip_num_ip6_endpoints, + { "Number of IP6 endpoints", "nsip.num_ip6_endpoints", + FT_UINT16, BASE_DEC, NULL, 0x0, + "", HFILL } + }, + { &hf_nsip_reset_flag, + { "Reset flag", "nsip.reset_flag", + FT_BOOLEAN, 8, TFS(&set_unset), NSIP_MASK_RESET_FLAG, + "", HFILL } + }, + { &hf_nsip_ip_address_ipv4, + { "IP Address", "nsip.ip_address", + FT_IPv4, BASE_NONE, NULL, 0x0, + "", HFILL } + }, + { &hf_nsip_ip_address_ipv6, + { "IP Address", "nsip.ip_address", + FT_IPv6, BASE_NONE, NULL, 0x0, + "", HFILL } + }, + { &hf_nsip_end_flag, + { "End flag", "nsip.end_flag", + FT_BOOLEAN, 8, TFS(&set_unset), NSIP_MASK_END_FLAG, + "", HFILL } + }, + { &hf_nsip_control_bits_r, + { "Request change flow", "nsip.control_bits.r", + FT_BOOLEAN, 8, TFS(&set_unset), NSIP_MASK_CONTROL_BITS_R, + "", HFILL } + }, + { &hf_nsip_control_bits_c, + { "Confirm change flow", "nsip.control_bits.c", + FT_BOOLEAN, 8, TFS(&set_unset), NSIP_MASK_CONTROL_BITS_C, + "", HFILL } + }, + { &hf_nsip_transaction_id, + { "Transaction ID", "nsip.transaction_id", + FT_UINT8, BASE_DEC, NULL, 0x0, + "", HFILL } + }, + { &hf_nsip_ip_element_ip_address_ipv4, + { "IP Address", "nsip.ip_element.ip_address", + FT_IPv4, BASE_NONE, NULL, 0x0, + "", HFILL } + }, + { &hf_nsip_ip_element_ip_address_ipv6, + { "IP Address", "nsip.ip_element.ip_address", + FT_IPv6, BASE_NONE, NULL, 0x0, + "", HFILL } + }, + { &hf_nsip_ip_element_udp_port, + { "UDP Port", "nsip.ip_element.udp_port", + FT_UINT16, BASE_DEC, NULL, 0x0, + "", HFILL } + }, + { &hf_nsip_ip_element_signalling_weight, + { "Signalling Weight", "nsip.ip_element.signalling_weight", + FT_UINT8, BASE_DEC, NULL, 0x0, + "", HFILL } + }, + { &hf_nsip_ip_element_data_weight, + { "Data Weight", "nsip.ip_element.data_weight", + FT_UINT8, BASE_DEC, NULL, 0x0, + "", HFILL } + }, +#ifdef ERICSSON_INTERNAL + { &hf_nsip_ericsson_rip, + { "Ericsson RIP", "nsip.ericsson.rip", + FT_UINT8, BASE_DEC, NULL, 0x0, + "", HFILL } + }, + { &hf_nsip_ericsson_lip, + { "Ericsson LIP", "nsip.ericsson.lip", + FT_UINT8, BASE_DEC, NULL, 0x0, + "", HFILL } + }, + { &hf_nsip_ericsson_rp, + { "Ericsson RP", "nsip.ericsson.rp", + FT_UINT8, BASE_DEC, NULL, 0x0, + "", HFILL } + }, +#endif + }; + + /* Setup protocol subtree array */ + static gint *ett[] = { + &ett_nsip, + &ett_nsip_control_bits, + &ett_nsip_ip_element, + &ett_nsip_ip_element_list, + }; + + module_t *nsip_module; + + /* Register the protocol name and description */ + proto_nsip = proto_register_protocol("Network Service Over IP", + "NSIP", "nsip"); + + /* 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("nsip", dissect_nsip, proto_nsip); + + /* Register configuration options */ + nsip_module = prefs_register_protocol(proto_nsip, proto_reg_handoff_nsip); + prefs_register_uint_preference(nsip_module, "udp.port1", "NSIP UDP Port 1", + "Set the first UDP port", + 10, &nsip_udp_port1); + prefs_register_uint_preference(nsip_module, "udp.port2", "NSIP UDP Port 2", + "Set the second UDP port", + 10, &nsip_udp_port2); +} + +void +proto_reg_handoff_nsip(void) { + static int nsip_prefs_initialized = FALSE; + /* + nsip_handle = create_dissector_handle(dissect_nsip, proto_nsip); + if (nsip_handle) { + if (DECODE_AS_NSIP) { + dissector_add("udp.port", NSIP_UDP_PORT1, nsip_handle); + dissector_add("udp.port", NSIP_UDP_PORT2, nsip_handle); + } + else { + dissector_add_handle("udp.port", nsip_handle); + } + } + */ + if (!nsip_prefs_initialized) { + nsip_handle = create_dissector_handle(dissect_nsip, proto_nsip); + nsip_prefs_initialized = TRUE; + } + else { + dissector_delete("udp.port", nsip_udp_port1, nsip_handle); + dissector_delete("udp.port", nsip_udp_port2, nsip_handle); + } + + dissector_add("udp.port", nsip_udp_port1, nsip_handle); + dissector_add("udp.port", nsip_udp_port2, nsip_handle); + + bssgp_handle = find_dissector("bssgp"); +} |