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