summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-nsip.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
commite4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch)
tree68cb5ef9081156392f1dd62a00c6ccc1451b93df /epan/dissectors/packet-nsip.c
parentInitial commit. (diff)
downloadwireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz
wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'epan/dissectors/packet-nsip.c')
-rw-r--r--epan/dissectors/packet-nsip.c1170
1 files changed, 1170 insertions, 0 deletions
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 <susanne.edlund@ericsson.com>
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * 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 <epan/packet.h>
+
+#include <epan/prefs.h>
+#include <epan/to_str.h>
+#include <wiretap/wtap.h>
+
+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:
+ */