HTTPS (almost) everywhere.
[metze/wireshark/wip.git] / epan / dissectors / packet-nsip.c
1 /* packet-nsip.c
2  * Routines for Network Service Over IP dissection
3  * Copyright 2000, Susanne Edlund <susanne.edlund@ericsson.com>
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * SPDX-License-Identifier: GPL-2.0-or-later
10  */
11
12 /* 3GPP TS 48.016 V 5.3.0 (2004-07) Release 6 + CR013 */
13
14 #include "config.h"
15
16 #include <epan/packet.h>
17
18 #include <epan/prefs.h>
19 #include <epan/to_str.h>
20 #include <wiretap/wtap.h>
21
22 void proto_register_nsip(void);
23 void proto_reg_handoff_nsip(void);
24
25 #define NSIP_DEBUG 0
26 #define NSIP_SEP ", " /* Separator string */
27
28 #define DEFAULT_NSIP_PORT_RANGE "2157,19999" /* Not IANA registered */
29
30 /* Initialize the protocol and registered fields */
31 static int proto_nsip = -1;
32
33 static int hf_nsip_cause = -1;
34 static int hf_nsip_ns_vci = -1;
35 static int hf_nsip_pdu_type = -1;
36 static int hf_nsip_bvci = -1;
37 static int hf_nsip_nsei = -1;
38 /* static int hf_nsip_ip4_elements = -1; */
39 /* static int hf_nsip_ip6_elements = -1; */
40 static int hf_nsip_max_num_ns_vc = -1;
41 static int hf_nsip_num_ip4_endpoints = -1;
42 static int hf_nsip_num_ip6_endpoints = -1;
43 static int hf_nsip_reset_flag = -1;
44 static int hf_nsip_reset_flag_bit = -1;
45 static int hf_nsip_reset_flag_spare = -1;
46 static int hf_nsip_ip_address_type = -1;
47 static int hf_nsip_ip_address_ipv4 = -1;
48 static int hf_nsip_ip_address_ipv6 = -1;
49 static int hf_nsip_end_flag = -1;
50 static int hf_nsip_end_flag_bit = -1;
51 static int hf_nsip_end_flag_spare = -1;
52 static int hf_nsip_control_bits = -1;
53 static int hf_nsip_control_bits_r = -1;
54 static int hf_nsip_control_bits_c = -1;
55 static int hf_nsip_control_bits_spare = -1;
56 static int hf_nsip_transaction_id = -1;
57 /* static int hf_nsip_ip_element_ip_address_ipv4 = -1; */
58 /* static int hf_nsip_ip_element_ip_address_ipv6 = -1; */
59 static int hf_nsip_ip_element_udp_port = -1;
60 static int hf_nsip_ip_element_signalling_weight = -1;
61 static int hf_nsip_ip_element_data_weight = -1;
62 static int hf_nsip_ns_pdu = -1;
63 static int hf_nsip_ns_sdu = -1;
64
65 /* Initialize the subtree pointers */
66 static gint ett_nsip = -1;
67 static gint ett_nsip_control_bits = -1;
68 static gint ett_nsip_reset_flag = -1;
69 static gint ett_nsip_end_flag = -1;
70 static gint ett_nsip_ip_element = -1;
71 static gint ett_nsip_ip_element_list = -1;
72
73 /* PDU type coding, v5.3.0, table 10.3.7.1, p 51 */
74 #define NSIP_PDU_NS_UNITDATA        0x00
75 #define NSIP_PDU_NS_RESET           0x02
76 #define NSIP_PDU_NS_RESET_ACK       0x03
77 #define NSIP_PDU_NS_BLOCK           0x04
78 #define NSIP_PDU_NS_BLOCK_ACK       0x05
79 #define NSIP_PDU_NS_UNBLOCK         0x06
80 #define NSIP_PDU_NS_UNBLOCK_ACK     0x07
81 #define NSIP_PDU_NS_STATUS          0x08
82 #define NSIP_PDU_NS_ALIVE           0x0a
83 #define NSIP_PDU_NS_ALIVE_ACK       0x0b
84 #define NSIP_PDU_SNS_ACK            0x0c
85 #define NSIP_PDU_SNS_ADD            0x0d
86 #define NSIP_PDU_SNS_CHANGEWEIGHT   0x0e
87 #define NSIP_PDU_SNS_CONFIG         0x0f
88 #define NSIP_PDU_SNS_CONFIG_ACK     0x10
89 #define NSIP_PDU_SNS_DELETE         0x11
90 #define NSIP_PDU_SNS_SIZE           0x12
91 #define NSIP_PDU_SNS_SIZE_ACK       0x13
92
93 static const value_string tab_nsip_pdu_types[] = {
94   { NSIP_PDU_NS_UNITDATA,        "NS_UNITDATA" },
95   { NSIP_PDU_NS_RESET,           "NS_RESET" },
96   { NSIP_PDU_NS_RESET_ACK,       "NS_RESET_ACK" },
97   { NSIP_PDU_NS_BLOCK,           "NS_BLOCK" },
98   { NSIP_PDU_NS_BLOCK_ACK,       "NS_BLOCK_ACK" },
99   { NSIP_PDU_NS_UNBLOCK,         "NS_UNBLOCK" },
100   { NSIP_PDU_NS_UNBLOCK_ACK,     "NS_UNBLOCK_ACK" },
101   { NSIP_PDU_NS_STATUS,          "NS_STATUS" },
102   { NSIP_PDU_NS_ALIVE,           "NS_ALIVE" },
103   { NSIP_PDU_NS_ALIVE_ACK,       "NS_ALIVE_ACK" },
104   { NSIP_PDU_SNS_ACK,            "SNS_ACK" },
105   { NSIP_PDU_SNS_ADD,            "SNS_ADD" },
106   { NSIP_PDU_SNS_CHANGEWEIGHT,   "SNS_CHANGEWEIGHT" },
107   { NSIP_PDU_SNS_CONFIG,         "SNS_CONFIG" },
108   { NSIP_PDU_SNS_CONFIG_ACK,     "SNS_CONFIG_ACK" },
109   { NSIP_PDU_SNS_DELETE,         "SNS_DELETE" },
110   { NSIP_PDU_SNS_SIZE,           "SNS_SIZE" },
111   { NSIP_PDU_SNS_SIZE_ACK,       "SNS_SIZE_ACK" },
112   { 0,                            NULL },
113 };
114
115 /* Information element coding, v 5.3.0, table 10.3.1, p 46 */
116 #define NSIP_IE_CAUSE              0x00
117 #define NSIP_IE_NS_VCI             0x01
118 #define NSIP_IE_NS_PDU             0x02
119 #define NSIP_IE_BVCI               0x03
120 #define NSIP_IE_NSEI               0x04
121 #define NSIP_IE_IP4_ELEMENTS       0x05
122 #define NSIP_IE_IP6_ELEMENTS       0x06
123 #define NSIP_IE_MAX_NUM_NS_VC      0x07
124 #define NSIP_IE_NUM_IP4_ENDPOINTS  0x08
125 #define NSIP_IE_NUM_IP6_ENDPOINTS  0x09
126 #define NSIP_IE_RESET_FLAG         0x0a
127 #define NSIP_IE_IP_ADDRESS         0x0b
128
129 #if NSIP_DEBUG
130 static const value_string tab_nsip_ieis[] = {
131   { NSIP_IE_CAUSE,               "Cause" },
132   { NSIP_IE_NS_VCI,              "NS-VCI" },
133   { NSIP_IE_NS_PDU,              "NS PDU" },
134   { NSIP_IE_BVCI,                "BVCI" },
135   { NSIP_IE_NSEI,                "NSEI" },
136   { NSIP_IE_IP4_ELEMENTS,        "List of IP4 Elements" },
137   { NSIP_IE_IP6_ELEMENTS,        "List of IP6 Elements" },
138   { NSIP_IE_MAX_NUM_NS_VC,       "Maximum Number of NC-VCs" },
139   { NSIP_IE_NUM_IP4_ENDPOINTS,   "Number of IP4 Endpoints" },
140   { NSIP_IE_NUM_IP6_ENDPOINTS,   "Number of IP6 Endpoints"},
141   { NSIP_IE_RESET_FLAG,          "Reset Flag" },
142   { NSIP_IE_IP_ADDRESS,          "IP Address" },
143   { 0,                            NULL },
144 };
145 #endif
146
147 /* Cause values, v 5.3.0, table 10.3.2.1, p 47 */
148 #define NSIP_CAUSE_TRANSIT_NETWORK_FAILURE      0x00
149 #define NSIP_CAUSE_OM_INTERVENTION              0x01
150 #define NSIP_CAUSE_EQUIPMENT_FAILURE            0x02
151 #define NSIP_CAUSE_NS_VC_BLOCKED                0x03
152 #define NSIP_CAUSE_NS_VC_UNKNOWN                0x04
153 #define NSIP_CAUSE_BVCI_UNKNOWN                 0x05
154 #define NSIP_CAUSE_SEMANTICALLY_INCORRECT_PDU   0x08
155 #define NSIP_CAUSE_NSIP_PDU_NOT_COMPATIBLE      0x0a
156 #define NSIP_CAUSE_PROTOCOL_ERROR               0x0b
157 #define NSIP_CAUSE_INVALID_ESSENTIAL_IE         0x0c
158 #define NSIP_CAUSE_MISSING_ESSENTIAL_IE         0x0d
159 #define NSIP_CAUSE_INVALID_NUM_IP4_ENDPOINTS    0x0e
160 #define NSIP_CAUSE_INVALID_NUM_IP6_ENDPOINTS    0x0f
161 #define NSIP_CAUSE_INVALID_NUM_NS_VC            0x10
162 #define NSIP_CAUSE_INVALID_WEIGHTS              0x11
163 #define NSIP_CAUSE_UNKNOWN_IP_ENDPOINT          0x12
164 #define NSIP_CAUSE_UNKNOWN_IP_ADDRESS           0x13
165 #define NSIP_CAUSE_IP_TEST_FAILED               0x14
166
167 static const value_string tab_nsip_cause_values[] = {
168   { NSIP_CAUSE_TRANSIT_NETWORK_FAILURE,   "Transit network failure" },
169   { NSIP_CAUSE_OM_INTERVENTION,           "O&M intervention" },
170   { NSIP_CAUSE_EQUIPMENT_FAILURE,         "Equipment failure" },
171   { NSIP_CAUSE_NS_VC_BLOCKED,             "NS-VC blocked" },
172   { NSIP_CAUSE_NS_VC_UNKNOWN,             "NS-VC unknown" },
173   { NSIP_CAUSE_BVCI_UNKNOWN,              "BVCI unknown on that NSE" },
174   { NSIP_CAUSE_SEMANTICALLY_INCORRECT_PDU, "Semantically incorrect PDU" },
175   { NSIP_CAUSE_NSIP_PDU_NOT_COMPATIBLE,   "PDU not compatible with the protocol state" },
176   { NSIP_CAUSE_PROTOCOL_ERROR,            "Protocol error - unspecified" },
177   { NSIP_CAUSE_INVALID_ESSENTIAL_IE,      "Invalid essential IE" },
178   { NSIP_CAUSE_MISSING_ESSENTIAL_IE,      "Missing essential IE" },
179   { NSIP_CAUSE_INVALID_NUM_IP4_ENDPOINTS, "Invalid number of IP4 endpoints" },
180   { NSIP_CAUSE_INVALID_NUM_IP6_ENDPOINTS, "Invalid number of IP6 endpoints" },
181   { NSIP_CAUSE_INVALID_NUM_NS_VC,         "Invalid number of NS-VCs" },
182   { NSIP_CAUSE_INVALID_WEIGHTS,           "Invalid weights" },
183   { NSIP_CAUSE_UNKNOWN_IP_ENDPOINT,       "Unknown IP endpoint" },
184   { NSIP_CAUSE_UNKNOWN_IP_ADDRESS,        "Unknown IP address" },
185   { NSIP_CAUSE_IP_TEST_FAILED,            "IP test failed" },
186   { 0,                                     NULL },
187 };
188
189 /* Presence requirements of Information Elements
190    v 5.3.0, chapter 8.1.1, p. 35 */
191 #define NSIP_IE_PRESENCE_M 1   /* Mandatory */
192 #define NSIP_IE_PRESENCE_O 2   /* Conditional */
193 #define NSIP_IE_PRESENCE_C 3   /* Optional */
194
195 /* Format options */
196 #define NSIP_IE_FORMAT_V 1
197 #define NSIP_IE_FORMAT_TV 2
198 #define NSIP_IE_FORMAT_TLV 3
199
200 /* IP address types, v 5.3.0, chapter 10.3.2b, p. 48 */
201 #define NSIP_IP_ADDRESS_TYPE_IPV4 1
202 #define NSIP_IP_ADDRESS_TYPE_IPV6 2
203 #define NSIP_IP_VERSION_4 4
204 #define NSIP_IP_VERSION_6 6
205
206 static const value_string ip_address_type_vals[] = {
207   { 0,                         "Reserved" },
208   { NSIP_IP_ADDRESS_TYPE_IPV4, "IPv4 Address" },
209   { NSIP_IP_ADDRESS_TYPE_IPV6, "IPv6 Address" },
210   { 0,                            NULL },
211 };
212
213
214 #define NSIP_MASK_CONTROL_BITS_R 0x01
215 #define NSIP_MASK_CONTROL_BITS_C 0x02
216 #define NSIP_MASK_CONTROL_BITS_SPARE 0xFC
217 #define NSIP_MASK_END_FLAG 0x01
218 #define NSIP_MASK_END_FLAG_SPARE 0xFE
219 #define NSIP_MASK_RESET_FLAG 0x01
220 #define NSIP_MASK_RESET_FLAG_SPARE 0xFE
221
222 static dissector_handle_t bssgp_handle;
223 static dissector_handle_t nsip_handle;
224
225 static gboolean nsip_is_recursive = FALSE;
226
227 typedef struct {
228   guint8        iei;
229   guint8        presence_req;
230   int           format;
231   guint16       value_length; /* in bytes */
232   guint16       total_length; /* as specified, or 0 if unspecified */
233 } nsip_ie_t;
234
235 typedef struct {
236   tvbuff_t     *tvb;
237   int           offset;
238   packet_info  *pinfo;
239   proto_tree   *nsip_tree;
240   proto_tree   *parent_tree;
241   proto_item   *ti;
242 } build_info_t;
243
244 typedef struct {
245   int version;
246   int address_length;
247   int total_length;
248 } nsip_ip_element_info_t;
249
250 static nsip_ip_element_info_t ipv4_element = { NSIP_IP_VERSION_4, 4, 8 };
251 static nsip_ip_element_info_t ipv6_element = { NSIP_IP_VERSION_6, 16, 20 };
252
253 static void
254 get_value_length(nsip_ie_t *ie, build_info_t *bi) {
255   /* length indicator in bit 8, 0 => two bytes, 1 => one byte */
256   const guint8 MASK_LENGTH_INDICATOR = 0x80;
257   const guint8 MASK_ONE_BYTE_LENGTH = 0x7f;
258   guint8 length_len;
259   guint16 length;
260
261   length = tvb_get_guint8(bi->tvb, bi->offset);
262   length_len = 1;
263
264   if (length & MASK_LENGTH_INDICATOR) {
265     length &= MASK_ONE_BYTE_LENGTH;
266   }
267   else {
268     length_len++;
269     length <<= 8;
270     length |= tvb_get_guint8(bi->tvb, bi->offset+1);
271   }
272   ie->value_length = length;
273   ie->total_length += length_len + length;
274   bi->offset += length_len;
275 }
276
277 static int
278 check_correct_iei(nsip_ie_t *ie, build_info_t *bi) {
279   guint8 fetched_iei = tvb_get_guint8(bi->tvb, bi->offset);
280
281 #if NSIP_DEBUG
282   if (fetched_iei != ie->iei) {
283     proto_tree_add_debug(bi->nsip_tree, bi->tvb, bi->offset, 1,
284                         "Tried IEI %s (%#02x), found IEI %s (%#02x)",
285                         val_to_str_const(ie->iei, tab_nsip_ieis, "Unknown"),
286                         ie->iei,
287                         val_to_str_const(fetched_iei, tab_nsip_ieis, "Unknown"),
288                         fetched_iei);
289   }
290 #endif
291   return (fetched_iei == ie->iei);
292 }
293
294 static void
295 decode_iei_cause(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) {
296   guint8 cause;
297
298   cause = tvb_get_guint8(bi->tvb, bi->offset);
299   proto_tree_add_uint(bi->nsip_tree, hf_nsip_cause,
300       bi->tvb, ie_start_offset, ie->total_length,
301       cause);
302   col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, NSIP_SEP,
303       "Cause: %s",
304       val_to_str(cause, tab_nsip_cause_values, "Unknown (0x%02x)"));
305
306   proto_item_append_text(bi->ti, ", Cause: %s",
307             val_to_str(cause, tab_nsip_cause_values, "Unknown (0x%02x)"));
308
309   bi->offset += ie->value_length;
310 }
311
312 static void
313 decode_iei_ns_vci(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) {
314   guint16 ns_vci;
315
316   ns_vci = tvb_get_ntohs(bi->tvb, bi->offset);
317
318   proto_tree_add_uint(bi->nsip_tree, hf_nsip_ns_vci,
319       bi->tvb, ie_start_offset, ie->total_length,
320       ns_vci);
321   col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, NSIP_SEP,
322       "NS VCI: %#04x", ns_vci);
323   proto_item_append_text(bi->ti, ", NS VCI: %#04x", ns_vci);
324
325   bi->offset += ie->value_length;
326 }
327
328 static void
329 decode_iei_ns_pdu(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) {
330   tvbuff_t * next_tvb;
331
332   proto_tree_add_bytes_format(bi->nsip_tree, hf_nsip_ns_pdu, bi->tvb, ie_start_offset,
333                       ie->total_length, NULL,
334                       "NS PDU (%u bytes)", ie->value_length);
335   next_tvb = tvb_new_subset_length_caplen(bi->tvb, bi->offset, ie->value_length, -1);
336   if (nsip_handle) {
337     gboolean was_recursive;
338     was_recursive = nsip_is_recursive;
339     nsip_is_recursive = TRUE;
340     call_dissector(nsip_handle, next_tvb, bi->pinfo, bi->nsip_tree);
341     nsip_is_recursive = was_recursive;
342   }
343   bi->offset += ie->value_length;
344 }
345
346 static void
347 decode_iei_nsei(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) {
348   guint16 nsei = tvb_get_ntohs(bi->tvb, bi->offset);
349
350   proto_tree_add_uint(bi->nsip_tree, hf_nsip_nsei, bi->tvb,
351                       ie_start_offset, ie->total_length, nsei);
352   bi->offset += ie->value_length;
353
354   col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, NSIP_SEP,
355                         "NSEI %u", nsei);
356
357   proto_item_append_text(bi->ti, ", NSEI %u", nsei);
358 }
359
360 static void
361 decode_iei_bvci(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) {
362   guint16 bvci = tvb_get_ntohs(bi->tvb, bi->offset);
363
364   proto_tree_add_uint(bi->nsip_tree, hf_nsip_bvci, bi->tvb,
365                       ie_start_offset, ie->total_length, bvci);
366   bi->offset += ie->value_length;
367
368   col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, NSIP_SEP,
369                         "BVCI %u", bvci);
370   proto_item_append_text(bi->ti, ", BVCI %u", bvci);
371 }
372
373 static proto_item *
374 decode_ip_element(nsip_ip_element_info_t *element, build_info_t *bi, proto_tree * element_tree) {
375   guint16 udp_port;
376   proto_item *tf;
377   proto_tree *field_tree;
378
379   field_tree = proto_tree_add_subtree(element_tree, bi->tvb, bi->offset,
380                              element->total_length, ett_nsip_ip_element, &tf, "IP Element");
381   if (bi->nsip_tree) {
382
383     /* IP address */
384     switch (element->version) {
385     case NSIP_IP_VERSION_4:
386       proto_tree_add_item(field_tree, hf_nsip_ip_address_ipv4,
387                           bi->tvb, bi->offset, element->address_length,
388                           ENC_BIG_ENDIAN);
389       proto_item_append_text(tf, ": IP address: %s",
390                              tvb_ip_to_str(bi->tvb, bi->offset));
391
392       break;
393     case NSIP_IP_VERSION_6:
394       proto_tree_add_item(field_tree, hf_nsip_ip_address_ipv6, bi->tvb,
395                           bi->offset, element->address_length,
396                           ENC_NA);
397       proto_item_append_text(tf, ": IP address: %s",
398                              tvb_ip6_to_str(bi->tvb, bi->offset));
399       break;
400     default:
401       ;
402     }
403   }
404   bi->offset += element->address_length;
405
406   if (bi->nsip_tree) {
407     /* UDP port value */
408     udp_port = tvb_get_ntohs(bi->tvb, bi->offset);
409     proto_tree_add_item(field_tree, hf_nsip_ip_element_udp_port,
410                                bi->tvb, bi->offset, 2, ENC_BIG_ENDIAN);
411     proto_item_append_text(tf, ", UDP Port: %u", udp_port);
412   }
413   bi->offset += 2;
414
415   if (bi->nsip_tree) {
416     /* Signalling weight */
417     proto_tree_add_item(field_tree, hf_nsip_ip_element_signalling_weight,
418                         bi->tvb, bi->offset, 1, ENC_BIG_ENDIAN);
419   }
420   bi->offset++;
421
422   if (bi->nsip_tree) {
423     /* Data weight */
424     proto_tree_add_item(field_tree, hf_nsip_ip_element_data_weight,
425                         bi->tvb, bi->offset, 1, ENC_BIG_ENDIAN);
426   }
427   bi->offset++;
428   return tf;
429 }
430
431 static proto_item *
432 decode_ip_elements(nsip_ip_element_info_t *element, nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) {
433   int i;
434   int num_elements = ie->value_length / element->total_length;
435   proto_item *tf;
436   proto_tree *field_tree;
437
438   field_tree = proto_tree_add_subtree_format(bi->nsip_tree, bi->tvb, ie_start_offset,
439                            ie->total_length, ett_nsip_ip_element_list, &tf,
440                            "List of IP%u Elements (%u Elements)",
441                            element->version, num_elements);
442
443   for (i = 0; i < num_elements; i++) {
444     decode_ip_element(element, bi, field_tree);
445   }
446   return tf;
447 }
448
449 static void
450 decode_iei_max_num_ns_vc(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) {
451  guint16 num_ns_vc;
452
453  if (bi->nsip_tree) {
454    num_ns_vc = tvb_get_ntohs(bi->tvb, bi->offset);
455
456    proto_tree_add_uint(bi->nsip_tree, hf_nsip_max_num_ns_vc,
457                               bi->tvb, ie_start_offset, ie->total_length,
458                               num_ns_vc);
459  }
460  bi->offset += 2;
461 }
462
463 static void
464 decode_iei_num_ip4_endpoints(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) {
465   guint16 num_endpoints;
466
467   if (bi->nsip_tree) {
468     num_endpoints = tvb_get_ntohs(bi->tvb, bi->offset);
469
470     proto_tree_add_uint(bi->nsip_tree, hf_nsip_num_ip4_endpoints,
471                                bi->tvb, ie_start_offset, ie->total_length,
472                                num_endpoints);
473   }
474   bi->offset += 2;
475 }
476
477 static void
478 decode_iei_num_ip6_endpoints(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) {
479   guint16 num_endpoints;
480
481   if (bi->nsip_tree) {
482     num_endpoints = tvb_get_ntohs(bi->tvb, bi->offset);
483
484     proto_tree_add_uint(bi->nsip_tree, hf_nsip_num_ip6_endpoints,
485                                bi->tvb, ie_start_offset, ie->total_length,
486                                num_endpoints);
487   }
488   bi->offset += 2;
489 }
490
491 static void
492 decode_iei_reset_flag(nsip_ie_t *ie _U_, build_info_t *bi, int ie_start_offset _U_) {
493   guint8 flag;
494   static const int * reset_flags[] = {
495     &hf_nsip_reset_flag_bit,
496     &hf_nsip_reset_flag_spare,
497     NULL
498   };
499
500   flag = tvb_get_guint8(bi->tvb, bi->offset);
501   proto_tree_add_bitmask(bi->nsip_tree,  bi->tvb, bi->offset, hf_nsip_reset_flag,
502                            ett_nsip_reset_flag, reset_flags, ENC_NA);
503
504   if (flag & NSIP_MASK_RESET_FLAG) {
505     col_append_sep_str(bi->pinfo->cinfo, COL_INFO, NSIP_SEP, "Reset");
506   }
507   bi->offset += 1;
508 }
509
510 static void
511 decode_iei_ip_address(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) {
512   guint8 addr_type;
513   guint32 ip4_addr;
514   ws_in6_addr ip6_addr;
515
516   addr_type = tvb_get_guint8(bi->tvb, bi->offset);
517   proto_tree_add_item(bi->nsip_tree, hf_nsip_ip_address_type,
518                           bi->tvb, bi->offset, 1, ENC_BIG_ENDIAN);
519   switch (addr_type) {
520   case NSIP_IP_ADDRESS_TYPE_IPV4:
521     ie->total_length = 2 + ipv4_element.address_length;
522     ip4_addr = tvb_get_ipv4(bi->tvb, bi->offset+1);
523     proto_tree_add_ipv4(bi->nsip_tree, hf_nsip_ip_address_ipv4,
524         bi->tvb, ie_start_offset, ie->total_length,
525         ip4_addr);
526     break;
527   case NSIP_IP_ADDRESS_TYPE_IPV6:
528     ie->total_length = 2 + ipv6_element.address_length;
529     tvb_get_ipv6(bi->tvb, bi->offset+1, &ip6_addr);
530     proto_tree_add_ipv6(bi->nsip_tree, hf_nsip_ip_address_ipv4,
531         bi->tvb, ie_start_offset, ie->total_length,
532         &ip6_addr);
533     break;
534   default:
535     return; /* error */
536   }
537   bi->offset += ie->value_length;
538 }
539
540 static void
541 decode_iei_transaction_id(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) {
542   guint8 id;
543   id = tvb_get_guint8(bi->tvb, bi->offset);
544   proto_tree_add_uint(bi->nsip_tree, hf_nsip_transaction_id,
545                       bi->tvb, ie_start_offset, ie->total_length, id);
546   col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, NSIP_SEP,
547             "Transaction Id: %d", id);
548   bi->offset += 1;
549 }
550
551 static void
552 decode_iei_end_flag(nsip_ie_t *ie _U_, build_info_t *bi, int ie_start_offset) {
553   static const int * end_flags[] = {
554     &hf_nsip_end_flag_bit,
555     &hf_nsip_end_flag_spare,
556     NULL
557   };
558
559   proto_tree_add_bitmask(bi->nsip_tree,  bi->tvb, ie_start_offset, hf_nsip_end_flag,
560                            ett_nsip_end_flag, end_flags, ENC_NA);
561   bi->offset += 1;
562 }
563
564 static void
565 decode_iei_control_bits(nsip_ie_t *ie _U_, build_info_t *bi, int ie_start_offset) {
566   guint8 control_bits;
567   static const int * flags[] = {
568     &hf_nsip_control_bits_r,
569     &hf_nsip_control_bits_c,
570     &hf_nsip_control_bits_spare,
571     NULL
572   };
573
574   control_bits = tvb_get_guint8(bi->tvb, bi->offset);
575   proto_tree_add_bitmask(bi->nsip_tree, bi->tvb, ie_start_offset, hf_nsip_control_bits,
576                          ett_nsip_control_bits, flags, ENC_NA);
577   bi->offset++;
578
579   if (control_bits & NSIP_MASK_CONTROL_BITS_R) {
580     col_append_sep_str(bi->pinfo->cinfo, COL_INFO, NSIP_SEP, "Req CF");
581     proto_item_append_text(bi->ti, ", Request Change Flow");
582   }
583
584   if (control_bits & NSIP_MASK_CONTROL_BITS_C) {
585     col_append_sep_str(bi->pinfo->cinfo, COL_INFO, NSIP_SEP, "Conf CF");
586     proto_item_append_text(bi->ti, ", Confirm Change Flow");
587   }
588 }
589
590
591 static void
592 decode_ie(nsip_ie_t *ie, build_info_t *bi) {
593
594   int org_offset = bi->offset;
595
596   if (tvb_captured_length_remaining(bi->tvb, bi->offset) < 1) {
597     return;
598   }
599   switch (ie->format) {
600   case NSIP_IE_FORMAT_TLV:
601     if (!check_correct_iei(ie, bi)) {
602       return;
603     }
604     bi->offset++; /* Account for type */
605     ie->total_length = 1;
606     get_value_length(ie, bi);
607     break;
608   case NSIP_IE_FORMAT_TV:
609     if (!check_correct_iei(ie, bi)) {
610       return;
611     }
612     bi->offset++; /* Account for type */
613     ie->value_length = ie->total_length - 1;
614     break;
615   case NSIP_IE_FORMAT_V:
616     ie->value_length = ie->total_length;
617   default:
618     ;
619   }
620   switch (ie->iei) {
621   case NSIP_IE_CAUSE:
622     decode_iei_cause(ie, bi, org_offset);
623     break;
624   case NSIP_IE_NS_VCI:
625     decode_iei_ns_vci(ie, bi, org_offset);
626     break;
627   case NSIP_IE_NS_PDU:
628     decode_iei_ns_pdu(ie, bi, org_offset);
629     break;
630   case NSIP_IE_NSEI:
631     decode_iei_nsei(ie, bi, org_offset);
632     break;
633   case NSIP_IE_BVCI:
634     decode_iei_bvci(ie, bi, org_offset);
635     break;
636   case NSIP_IE_IP4_ELEMENTS:
637     decode_ip_elements(&ipv4_element, ie, bi, org_offset);
638     break;
639   case NSIP_IE_IP6_ELEMENTS:
640     decode_ip_elements(&ipv6_element, ie, bi, org_offset);
641     break;
642   case NSIP_IE_MAX_NUM_NS_VC:
643     decode_iei_max_num_ns_vc(ie, bi, org_offset);
644     break;
645   case NSIP_IE_NUM_IP4_ENDPOINTS:
646     decode_iei_num_ip4_endpoints(ie, bi, org_offset);
647     break;
648   case NSIP_IE_NUM_IP6_ENDPOINTS:
649     decode_iei_num_ip6_endpoints(ie, bi, org_offset);
650     break;
651   case NSIP_IE_RESET_FLAG:
652     decode_iei_reset_flag(ie, bi, org_offset);
653     break;
654   case NSIP_IE_IP_ADDRESS:
655     decode_iei_ip_address(ie, bi, org_offset);
656     break;
657   default:
658     ;
659   }
660 }
661
662 static void
663 decode_pdu_general(nsip_ie_t *ies, int num_ies, build_info_t *bi) {
664   int i;
665   for (i = 0; i < num_ies; i++) {
666     decode_ie(&ies[i], bi);
667   }
668 }
669
670 static void
671 decode_pdu_ns_unitdata(build_info_t *bi) {
672   tvbuff_t *next_tvb;
673
674   nsip_ie_t ies[] = {
675     { 0, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_V, 0, 1 }, /* Control bits */
676     { NSIP_IE_BVCI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_V, 0, 2 },
677     { 0, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_V, 0, 0 },
678     /* NS SDU, length unknown */
679   };
680   gint sdu_length;
681
682   decode_iei_control_bits(ies, bi, bi->offset);
683   decode_pdu_general(&ies[1], 1, bi);
684
685   next_tvb = tvb_new_subset_remaining(bi->tvb, bi->offset);
686   if (bssgp_handle) {
687     call_dissector(bssgp_handle, next_tvb, bi->pinfo, bi->parent_tree);
688   }
689   else {
690     sdu_length = tvb_captured_length_remaining(bi->tvb, bi->offset);
691     proto_tree_add_bytes_format(bi->nsip_tree, hf_nsip_ns_sdu, bi->tvb, bi->offset, sdu_length,
692                         NULL, "NS SDU (%u bytes)", sdu_length);
693   }
694 }
695
696 static void
697 decode_pdu_ns_reset(build_info_t *bi) {
698   nsip_ie_t ies[] = {
699     { NSIP_IE_CAUSE, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 3 },
700     { NSIP_IE_NS_VCI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4 },
701     { NSIP_IE_NSEI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4 },
702   };
703   decode_pdu_general(ies, 3, bi);
704 }
705
706 static void
707 decode_pdu_ns_reset_ack(build_info_t *bi) {
708   nsip_ie_t ies[] = {
709     { NSIP_IE_NS_VCI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4 },
710     { NSIP_IE_NSEI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4 },
711   };
712   decode_pdu_general(ies, 2, bi);
713 }
714
715 static void
716 decode_pdu_ns_block(build_info_t *bi) {
717   nsip_ie_t ies[] = {
718     { NSIP_IE_CAUSE, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 3 },
719     { NSIP_IE_NS_VCI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4 },
720   };
721   decode_pdu_general(ies, 2, bi);
722 }
723
724 static void
725 decode_pdu_ns_block_ack(build_info_t *bi) {
726   nsip_ie_t ies[] = { { NSIP_IE_NS_VCI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV,
727                         0, 1 }, };
728   decode_pdu_general(ies, 1, bi);
729 }
730
731 static void
732 decode_pdu_ns_status(build_info_t *bi) {
733   nsip_ie_t ies[] = {
734     { NSIP_IE_CAUSE, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 3 },
735     { NSIP_IE_NS_VCI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4 },
736     { NSIP_IE_NS_PDU, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 0 },
737     /* Unknown length */
738     { NSIP_IE_BVCI, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 4 },
739     { NSIP_IE_IP4_ELEMENTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 0 },
740     /* Unknown length */
741     { NSIP_IE_IP6_ELEMENTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 0 },
742     /* Unknown length */
743   };
744   decode_pdu_general(ies, 6, bi);
745 }
746
747 static void
748 decode_pdu_sns_ack(build_info_t *bi) {
749   nsip_ie_t ies[] = {
750     { NSIP_IE_NSEI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4 },
751     { 0, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_V, 0, 1 }, /* Transaction id */
752     { NSIP_IE_CAUSE, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 3 },
753     { NSIP_IE_IP_ADDRESS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TV, 0, 0 },
754     /* Unknown length */
755     { NSIP_IE_IP4_ELEMENTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 0 },
756     { NSIP_IE_IP6_ELEMENTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 0 },
757   };
758   decode_pdu_general(ies, 1, bi);
759   decode_iei_transaction_id(&ies[1], bi, bi->offset);
760   decode_pdu_general(&ies[2], 4, bi);
761 }
762
763 static void
764 decode_pdu_sns_add(build_info_t *bi) {
765   nsip_ie_t ies[] = {
766     { NSIP_IE_NSEI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4 },
767     { 0, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_V, 0, 1 }, /* Transaction id */
768     { NSIP_IE_IP4_ELEMENTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 0 },
769     /* Unknown length */
770     { NSIP_IE_IP6_ELEMENTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 0 },
771     /* Unknown length */
772   };
773   decode_pdu_general(ies, 1, bi);
774   decode_iei_transaction_id(&ies[1], bi, bi->offset);
775   decode_pdu_general(&ies[2], 2, bi);
776 }
777
778 static void
779 decode_pdu_sns_changeweight(build_info_t *bi) {
780   nsip_ie_t ies[] = {
781     { NSIP_IE_NSEI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4 },
782     { 0, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_V, 0, 1 }, /* Transaction id */
783     { NSIP_IE_IP4_ELEMENTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 0 },
784     /* Unknown length */
785     { NSIP_IE_IP6_ELEMENTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 0 },
786     /* Unknown length */
787   };
788   decode_pdu_general(ies, 1, bi);
789   decode_iei_transaction_id(&ies[1], bi, bi->offset);
790   decode_pdu_general(&ies[2], 2, bi);
791 }
792
793 static void
794 decode_pdu_sns_config(build_info_t *bi) {
795
796     nsip_ie_t ies[] = {
797       { 0, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_V, 0, 1 }, /* End flag */
798       { NSIP_IE_NSEI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4 },
799       { NSIP_IE_IP4_ELEMENTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 0 },
800       /* Unknown length */
801       { NSIP_IE_IP6_ELEMENTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 0 },
802       /* Unknown length */
803     };
804     decode_iei_end_flag(ies, bi, bi->offset);
805     decode_pdu_general(&ies[1], 3, bi);
806 }
807
808 static void
809 decode_pdu_sns_config_ack(build_info_t *bi) {
810   nsip_ie_t ies[] = {
811     { NSIP_IE_NSEI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4 },
812     { NSIP_IE_CAUSE, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 3 },
813   };
814   decode_pdu_general(ies, 2, bi);
815 }
816
817 static void
818 decode_pdu_sns_delete(build_info_t *bi) {
819   nsip_ie_t ies[] = {
820     { NSIP_IE_NSEI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4}, /* CR013 */
821     { 0, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_V, 0, 1 }, /* Transaction id */
822     { NSIP_IE_IP_ADDRESS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TV, 0, 0 },
823     /* Unknown length */
824     { NSIP_IE_IP4_ELEMENTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 0 },
825     { NSIP_IE_IP6_ELEMENTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 0 },
826   };
827   decode_pdu_general(ies, 1, bi);
828   decode_iei_transaction_id(&ies[1], bi, bi->offset);
829   decode_pdu_general(&ies[2], 3, bi);
830 }
831
832 static void
833 decode_pdu_sns_size(build_info_t *bi) {
834   nsip_ie_t ies[] = {
835     { NSIP_IE_NSEI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4 },
836     { NSIP_IE_RESET_FLAG, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TV, 0, 2 },
837     { NSIP_IE_MAX_NUM_NS_VC, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TV, 0, 3 },
838     { NSIP_IE_NUM_IP4_ENDPOINTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TV,
839       0, 3 },
840     { NSIP_IE_NUM_IP6_ENDPOINTS, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TV,
841       0, 3 },
842   };
843   decode_pdu_general(ies, 5, bi);
844 }
845
846 static void
847 decode_pdu_sns_size_ack(build_info_t *bi) {
848   nsip_ie_t ies[] = {
849     { NSIP_IE_NSEI, NSIP_IE_PRESENCE_M, NSIP_IE_FORMAT_TLV, 0, 4 },
850     { NSIP_IE_CAUSE, NSIP_IE_PRESENCE_C, NSIP_IE_FORMAT_TLV, 0, 3 },
851   };
852   decode_pdu_general(ies, 2, bi);
853 }
854
855 static void
856 decode_pdu(guint8 pdu_type, build_info_t *bi) {
857   switch (pdu_type) {
858   case NSIP_PDU_NS_UNITDATA:
859     decode_pdu_ns_unitdata(bi);
860     break;
861   case NSIP_PDU_NS_RESET:
862     decode_pdu_ns_reset(bi);
863     break;
864   case NSIP_PDU_NS_RESET_ACK:
865     decode_pdu_ns_reset_ack(bi);
866     break;
867   case NSIP_PDU_NS_BLOCK:
868     decode_pdu_ns_block(bi);
869     break;
870   case NSIP_PDU_NS_BLOCK_ACK:
871     decode_pdu_ns_block_ack(bi);
872     break;
873   case NSIP_PDU_NS_STATUS:
874     decode_pdu_ns_status(bi);
875     break;
876   case NSIP_PDU_SNS_ACK:
877     decode_pdu_sns_ack(bi);
878     break;
879   case NSIP_PDU_SNS_ADD:
880     decode_pdu_sns_add(bi);
881     break;
882   case NSIP_PDU_SNS_CHANGEWEIGHT:
883     decode_pdu_sns_changeweight(bi);
884     break;
885   case NSIP_PDU_SNS_CONFIG:
886     decode_pdu_sns_config(bi);
887     break;
888   case NSIP_PDU_SNS_CONFIG_ACK:
889     decode_pdu_sns_config_ack(bi);
890     break;
891   case NSIP_PDU_SNS_DELETE:
892     decode_pdu_sns_delete(bi);
893     break;
894   case NSIP_PDU_SNS_SIZE:
895     decode_pdu_sns_size(bi);
896     break;
897   case NSIP_PDU_SNS_SIZE_ACK:
898     decode_pdu_sns_size_ack(bi);
899     break;
900   case NSIP_PDU_NS_ALIVE:
901   case NSIP_PDU_NS_ALIVE_ACK:
902   case NSIP_PDU_NS_UNBLOCK:
903   case NSIP_PDU_NS_UNBLOCK_ACK:
904     /* Only contains PDU type, which has already been decoded */
905   default: ;
906   }
907 }
908
909 static int
910 dissect_nsip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) {
911   guint8 pdu_type;
912   build_info_t bi = { NULL, 0, NULL, NULL, NULL, NULL };
913   proto_tree *nsip_tree;
914
915   bi.tvb = tvb;
916   bi.pinfo = pinfo;
917   bi.parent_tree = tree;
918
919   if (!nsip_is_recursive) {
920     col_set_str(pinfo->cinfo, COL_PROTOCOL, "GPRS-NS");
921     col_clear(pinfo->cinfo, COL_INFO);
922   }
923
924   pdu_type = tvb_get_guint8(tvb, 0);
925   bi.offset++;
926
927   if (tree) {
928     bi.ti = proto_tree_add_item(tree, proto_nsip, tvb, 0, -1,
929                              ENC_NA);
930     nsip_tree = proto_item_add_subtree(bi.ti, ett_nsip);
931     proto_tree_add_item(nsip_tree, hf_nsip_pdu_type, tvb, 0, 1, ENC_BIG_ENDIAN);
932     proto_item_append_text(bi.ti, ", PDU type: %s",
933                                val_to_str_const(pdu_type, tab_nsip_pdu_types, "Unknown"));
934     bi.nsip_tree = nsip_tree;
935   }
936
937   if (!nsip_is_recursive) {
938     col_set_str(pinfo->cinfo, COL_INFO,
939                 val_to_str_const(pdu_type, tab_nsip_pdu_types, "Unknown PDU type"));
940   } else {
941     col_append_sep_str(pinfo->cinfo, COL_INFO, NSIP_SEP,
942                 val_to_str_const(pdu_type, tab_nsip_pdu_types, "Unknown PDU type"));
943   }
944   decode_pdu(pdu_type, &bi);
945   return tvb_captured_length(tvb);
946 }
947
948 void
949 proto_register_nsip(void)
950 {
951   static hf_register_info hf[] = {
952     { &hf_nsip_cause,
953       { "Cause", "nsip.cause",
954         FT_UINT8, BASE_HEX, VALS(tab_nsip_cause_values), 0x0,
955         NULL, HFILL }
956     },
957     { &hf_nsip_ns_vci,
958       { "NS-VCI", "nsip.ns_vci",
959         FT_UINT16, BASE_HEX, NULL, 0x0,
960         "Network Service Virtual Link Identifier", HFILL }
961     },
962     { &hf_nsip_pdu_type,
963       { "PDU type", "nsip.pdu_type",
964         FT_UINT8, BASE_HEX, VALS(tab_nsip_pdu_types), 0x0,
965         "PDU type information element", HFILL }
966     },
967     { &hf_nsip_bvci,
968       { "BVCI", "nsip.bvci",
969         FT_UINT16, BASE_DEC, NULL, 0x0,
970         "BSSGP Virtual Connection Identifier", HFILL }
971     },
972     { &hf_nsip_nsei,
973       { "NSEI", "nsip.nsei",
974         FT_UINT16, BASE_DEC, NULL, 0x0,
975         "Network Service Entity Identifier", HFILL }
976     },
977 #if 0
978     { &hf_nsip_ip4_elements,
979       { "IP4 elements", "nsip.ip4_elements",
980         FT_NONE, BASE_NONE, NULL, 0x0,
981         "List of IP4 elements", HFILL }
982     },
983 #endif
984 #if 0
985     { &hf_nsip_ip6_elements,
986       { "IP6 elements", "nsip.ip6_elements",
987         FT_NONE, BASE_NONE, NULL, 0x0,
988         "List of IP6 elements", HFILL }
989     },
990 #endif
991     { &hf_nsip_max_num_ns_vc,
992       { "Maximum number of NS-VCs", "nsip.max_num_ns_vc",
993         FT_UINT16, BASE_DEC, NULL, 0x0,
994         NULL, HFILL }
995     },
996     { &hf_nsip_num_ip4_endpoints,
997       { "Number of IP4 endpoints", "nsip.num_ip4_endpoints",
998         FT_UINT16, BASE_DEC, NULL, 0x0,
999         NULL, HFILL }
1000     },
1001     { &hf_nsip_num_ip6_endpoints,
1002       { "Number of IP6 endpoints", "nsip.num_ip6_endpoints",
1003         FT_UINT16, BASE_DEC, NULL, 0x0,
1004         NULL, HFILL }
1005     },
1006     { &hf_nsip_reset_flag,
1007       { "Reset flag", "nsip.reset_flag",
1008         FT_UINT8, BASE_HEX, NULL, 0,
1009         NULL, HFILL }
1010     },
1011     { &hf_nsip_reset_flag_bit,
1012       { "Reset flag", "nsip.reset_flag.flag",
1013         FT_BOOLEAN, 8, TFS(&tfs_set_notset), NSIP_MASK_RESET_FLAG,
1014         NULL, HFILL }
1015     },
1016     { &hf_nsip_reset_flag_spare,
1017       { "Reset flag spare bits", "nsip.reset_flag.spare",
1018         FT_UINT8, BASE_HEX, NULL, NSIP_MASK_RESET_FLAG_SPARE,
1019         NULL, HFILL }
1020     },
1021     { &hf_nsip_ip_address_type,
1022       { "IP Address Type", "nsip.ip_address_type",
1023         FT_UINT8, BASE_DEC, VALS(ip_address_type_vals), 0x0,
1024         NULL, HFILL }
1025     },
1026     { &hf_nsip_ip_address_ipv4,
1027       { "IP Address", "nsip.ipv4_address",
1028         FT_IPv4, BASE_NONE, NULL, 0x0,
1029         NULL, HFILL }
1030     },
1031     { &hf_nsip_ip_address_ipv6,
1032       { "IP Address", "nsip.ipv6_address",
1033         FT_IPv6, BASE_NONE, NULL, 0x0,
1034         NULL, HFILL }
1035     },
1036     { &hf_nsip_end_flag,
1037       { "End flag", "nsip.end_flag",
1038         FT_UINT8, BASE_HEX, NULL, 0x0,
1039         NULL, HFILL }
1040     },
1041     { &hf_nsip_end_flag_bit,
1042       { "End flag", "nsip.end_flag.flag",
1043         FT_BOOLEAN, 8, TFS(&tfs_set_notset), NSIP_MASK_END_FLAG,
1044         NULL, HFILL }
1045     },
1046     { &hf_nsip_end_flag_spare,
1047       { "End flag spare bits", "nsip.end_flag.spare",
1048         FT_UINT8, BASE_HEX, NULL, NSIP_MASK_END_FLAG_SPARE,
1049         NULL, HFILL }
1050     },
1051     { &hf_nsip_control_bits,
1052       { "NS SDU Control bits", "nsip.control_bits",
1053         FT_UINT8, BASE_HEX, NULL, 0x0,
1054         NULL, HFILL }
1055     },
1056     { &hf_nsip_control_bits_r,
1057       { "Request change flow", "nsip.control_bits.r",
1058         FT_BOOLEAN, 8, TFS(&tfs_set_notset), NSIP_MASK_CONTROL_BITS_R,
1059         NULL, HFILL }
1060     },
1061     { &hf_nsip_control_bits_c,
1062       { "Confirm change flow", "nsip.control_bits.c",
1063         FT_BOOLEAN, 8, TFS(&tfs_set_notset), NSIP_MASK_CONTROL_BITS_C,
1064         NULL, HFILL }
1065     },
1066     { &hf_nsip_control_bits_spare,
1067       { "Spare bits", "nsip.control_bits.spare",
1068         FT_UINT8, BASE_HEX, NULL, NSIP_MASK_CONTROL_BITS_SPARE,
1069         NULL, HFILL }
1070     },
1071     { &hf_nsip_transaction_id,
1072       { "Transaction ID", "nsip.transaction_id",
1073       FT_UINT8, BASE_DEC, NULL, 0x0,
1074       NULL, HFILL }
1075     },
1076 #if 0
1077     { &hf_nsip_ip_element_ip_address_ipv4,
1078       { "IP Address", "nsip.ip_element.ipv4_address",
1079         FT_IPv4, BASE_NONE, NULL, 0x0,
1080         NULL, HFILL }
1081     },
1082 #endif
1083 #if 0
1084     { &hf_nsip_ip_element_ip_address_ipv6,
1085       { "IP Address", "nsip.ip_element.ipv6_address",
1086         FT_IPv6, BASE_NONE, NULL, 0x0,
1087         NULL, HFILL }
1088     },
1089 #endif
1090     { &hf_nsip_ip_element_udp_port,
1091       { "UDP Port", "nsip.ip_element.udp_port",
1092         FT_UINT16, BASE_DEC, NULL, 0x0,
1093         NULL, HFILL }
1094     },
1095     { &hf_nsip_ip_element_signalling_weight,
1096       { "Signalling Weight", "nsip.ip_element.signalling_weight",
1097         FT_UINT8, BASE_DEC, NULL, 0x0,
1098         NULL, HFILL }
1099     },
1100     { &hf_nsip_ip_element_data_weight,
1101       { "Data Weight", "nsip.ip_element.data_weight",
1102         FT_UINT8, BASE_DEC, NULL, 0x0,
1103         NULL, HFILL }
1104     },
1105     { &hf_nsip_ns_pdu,
1106       { "NS PDU", "nsip.ns_pdu",
1107         FT_BYTES, BASE_NONE, NULL, 0x0,
1108         NULL, HFILL }
1109     },
1110     { &hf_nsip_ns_sdu,
1111       { "NS SDU", "nsip.ns_sdu",
1112         FT_BYTES, BASE_NONE, NULL, 0x0,
1113         NULL, HFILL }
1114     },
1115   };
1116
1117   /* Setup protocol subtree array */
1118   static gint *ett[] = {
1119     &ett_nsip,
1120     &ett_nsip_control_bits,
1121     &ett_nsip_reset_flag,
1122     &ett_nsip_end_flag,
1123     &ett_nsip_ip_element,
1124     &ett_nsip_ip_element_list,
1125   };
1126
1127   module_t *nsip_module;
1128
1129   /* Register the protocol name and description */
1130   proto_nsip = proto_register_protocol("GPRS Network Service", "GPRS-NS", "gprs-ns");
1131
1132   /* Required function calls to register the header fields and
1133      subtrees used */
1134   proto_register_field_array(proto_nsip, hf, array_length(hf));
1135   proto_register_subtree_array(ett, array_length(ett));
1136
1137   register_dissector("gprs_ns", dissect_nsip, proto_nsip);
1138
1139   /* Register configuration options */
1140   nsip_module = prefs_register_protocol(proto_nsip, NULL);
1141   /* For reading older preference files with "nsip." preferences */
1142   prefs_register_module_alias("nsip", nsip_module);
1143   prefs_register_obsolete_preference(nsip_module, "udp.port1");
1144   prefs_register_obsolete_preference(nsip_module, "udp.port2");
1145 }
1146
1147 void
1148 proto_reg_handoff_nsip(void) {
1149
1150   nsip_handle = find_dissector_add_dependency("gprs_ns", proto_nsip);
1151   bssgp_handle = find_dissector_add_dependency("bssgp", proto_nsip);
1152
1153   dissector_add_uint_range_with_preference("udp.port", DEFAULT_NSIP_PORT_RANGE, nsip_handle);
1154   dissector_add_uint("atm.aal5.type", TRAF_GPRS_NS, nsip_handle);
1155
1156 }
1157
1158 /*
1159  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1160  *
1161  * Local variables:
1162  * c-basic-offset: 2
1163  * tab-width: 8
1164  * indent-tabs-mode: nil
1165  * End:
1166  *
1167  * vi: set shiftwidth=2 tabstop=8 expandtab:
1168  * :indentSize=2:tabSize=8:noTabs=true:
1169  */