smb2-dissector: learn the "REPLAY_OPERATION" flag
[obnox/wireshark/wip.git] / plugins / wimaxasncp / packet-wimaxasncp.c
1 /* packet-wimaxasncp.c
2  *
3  * Routines for WiMAX ASN Control Plane packet dissection dissection
4  *
5  * Copyright 2007, Mobile Metrics - http://mobilemetrics.net/
6  *
7  * Author: Stephen Croll <croll@mobilemetrics.net>
8  *
9  * $Id$
10  *
11  * Wireshark - Network traffic analyzer
12  * By Gerald Combs <gerald@wireshark.org>
13  * Copyright 1998 Gerald Combs
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
28  */
29
30
31 #ifdef HAVE_CONFIG_H
32 # include "config.h"
33 #endif
34
35 #include <stdio.h>
36 #include <string.h>
37 #include <ctype.h>
38
39 #include <glib.h>
40
41 #include <epan/packet.h>
42 #include <epan/prefs.h>
43 #include <epan/sminmpec.h>
44 #include <epan/addr_resolv.h>
45 #include <epan/ipproto.h>
46 #include <epan/expert.h>
47 #include <epan/filesystem.h>
48 #include <epan/report_err.h>
49 #include <epan/eap.h>
50
51 #include "wimaxasncp_dict.h"
52
53 /* Forward declarations we need below */
54 void proto_register_wimaxasncp(void);
55 void proto_reg_handoff_wimaxasncp(void);
56
57 /* Initialize the protocol and registered fields */
58 static int proto_wimaxasncp                     = -1;
59 static int hf_wimaxasncp_version                = -1;
60 static int hf_wimaxasncp_flags                  = -1;
61 static int hf_wimaxasncp_function_type          = -1;
62 static int hf_wimaxasncp_op_id                  = -1;
63 static int hf_wimaxasncp_message_type           = -1;
64 static int hf_wimaxasncp_qos_msg                = -1;
65 static int hf_wimaxasncp_ho_control_msg         = -1;
66 static int hf_wimaxasncp_data_path_control_msg  = -1;
67 static int hf_wimaxasncp_context_delivery_msg   = -1;
68 static int hf_wimaxasncp_r3_mobility_msg        = -1;
69 static int hf_wimaxasncp_paging_msg             = -1;
70 static int hf_wimaxasncp_rrm_msg                = -1;
71 static int hf_wimaxasncp_authentication_msg     = -1;
72 static int hf_wimaxasncp_ms_state_msg           = -1;
73 static int hf_wimaxasncp_reauthentication_msg   = -1;
74 static int hf_wimaxasncp_session_msg            = -1;
75 static int hf_wimaxasncp_length                 = -1;
76 static int hf_wimaxasncp_msid                   = -1;
77 static int hf_wimaxasncp_reserved1              = -1;
78 static int hf_wimaxasncp_transaction_id         = -1;
79 static int hf_wimaxasncp_reserved2              = -1;
80 static int hf_wimaxasncp_tlv                    = -1;
81 static int hf_wimaxasncp_tlv_type               = -1;
82 static int hf_wimaxasncp_tlv_length             = -1;
83 static int hf_wimaxasncp_tlv_value_bytes        = -1;
84 static int hf_wimaxasncp_tlv_value_bitflags8    = -1;
85 static int hf_wimaxasncp_tlv_value_bitflags16   = -1;
86 static int hf_wimaxasncp_tlv_value_bitflags32   = -1;
87 static int hf_wimaxasncp_tlv_value_protocol     = -1;
88 static int hf_wimaxasncp_tlv_value_vendor_id    = -1;
89
90 /* Preferences */
91 static gboolean show_transaction_id_d_bit      = FALSE;
92 static gboolean debug_enabled                  = FALSE;
93
94 /* Default WiMAX ASN control protocol port */
95 #define WIMAXASNCP_DEF_UDP_PORT     2231
96 static guint global_wimaxasncp_udp_port = WIMAXASNCP_DEF_UDP_PORT;
97
98
99 /* Initialize the subtree pointers */
100 static gint ett_wimaxasncp                                       = -1;
101 static gint ett_wimaxasncp_flags                                 = -1;
102 static gint ett_wimaxasncp_tlv                                   = -1;
103 static gint ett_wimaxasncp_tlv_value_bitflags8                   = -1;
104 static gint ett_wimaxasncp_tlv_value_bitflags16                  = -1;
105 static gint ett_wimaxasncp_tlv_value_bitflags32                  = -1;
106 static gint ett_wimaxasncp_tlv_protocol_list                     = -1;
107 static gint ett_wimaxasncp_tlv_port_range_list                   = -1;
108 static gint ett_wimaxasncp_tlv_ip_address_mask_list              = -1;
109 static gint ett_wimaxasncp_tlv_ip_address_mask                   = -1;
110 static gint ett_wimaxasncp_tlv_eap                               = -1;
111 static gint ett_wimaxasncp_tlv_vendor_specific_information_field = -1;
112
113 /* Header size, up to, but not including, the TLV fields. */
114 #define WIMAXASNCP_HEADER_SIZE       20
115
116 /* Offset to end of the length field in the headder. */
117 #define WIMAXASNCP_HEADER_LENGTH_END 6
118
119 #define WIMAXASNCP_BIT32(n) (1 << (31 - (n)))
120 #define WIMAXASNCP_BIT16(n) (1 << (15 - (n)))
121 #define WIMAXASNCP_BIT8(n)  (1 << ( 7 - (n)))
122
123 #define WIMAXASNCP_FLAGS_T  WIMAXASNCP_BIT8(6)
124 #define WIMAXASNCP_FLAGS_R  WIMAXASNCP_BIT8(7)
125
126 typedef struct {
127     GArray* hf;
128     GArray* ett;
129 } wimaxasncp_build_dict_t;
130
131 static wimaxasncp_dict_t *wimaxasncp_dict = NULL;
132
133 wimaxasncp_build_dict_t wimaxasncp_build_dict;
134
135 static wimaxasncp_dict_tlv_t wimaxasncp_tlv_not_found =
136 {
137     0, "Unknown", NULL, WIMAXASNCP_TLV_UNKNOWN, 0,
138     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
139     NULL, NULL, NULL
140 };
141
142 static dissector_handle_t eap_handle;
143
144 /* ------------------------------------------------------------------------- */
145
146 static const value_string wimaxasncp_flag_vals[] =
147 {
148     { WIMAXASNCP_BIT8(0), "Reserved" },
149     { WIMAXASNCP_BIT8(1), "Reserved" },
150     { WIMAXASNCP_BIT8(2), "Reserved" },
151     { WIMAXASNCP_BIT8(3), "Reserved" },
152     { WIMAXASNCP_BIT8(4), "Reserved" },
153     { WIMAXASNCP_BIT8(5), "Reserved" },
154     { WIMAXASNCP_FLAGS_T, "T - Source and Destination Identifier TLVs"},
155     { WIMAXASNCP_FLAGS_R, "R - Reset Next Expected Transaction ID"},
156     { 0,                  NULL}
157 };
158
159 /* ------------------------------------------------------------------------- */
160
161 static const value_string wimaxasncp_op_id_vals[] =
162 {
163     { 0,   "Invalid"},
164     { 1,   "Request/Initiation"},
165     { 2,   "Response"},
166     { 3,   "Ack"},
167     { 4,   "Indication"},
168     { 5,   "Reserved"},
169     { 6,   "Reserved"},
170     { 7,   "Reserved"},
171     { 0,   NULL}
172 };
173
174 /* ------------------------------------------------------------------------- */
175
176 #define WIMAXASNCP_FT_QOS                 1
177 #define WIMAXASNCP_FT_HO_CONTROL          2
178 #define WIMAXASNCP_FT_DATA_PATH_CONTROL   3
179 #define WIMAXASNCP_FT_CONTEXT_TRANSFER    4
180 #define WIMAXASNCP_FT_R3_MOBILITY         5
181 #define WIMAXASNCP_FT_PAGING              6
182 #define WIMAXASNCP_FT_RRM                 7
183 #define WIMAXASNCP_FT_AUTHENTICATION      8
184 #define WIMAXASNCP_FT_MS_STATE            9
185 #define WIMAXASNCP_FT_REAUTHENTICATION    10
186 /* since NWG R1 V1.2.0 */
187 #define WIMAXASNCP_FT_IM_OPERATIONS       10
188 /* since NWG R1 V1.2.1 */
189 #define WIMAXASNCP_FT_ACCOUNTING          11
190
191 /* ------------------------------------------------------------------------- */
192
193 /* struct to hold a value_string tuple, per version */
194 typedef struct _ver_value_string
195 {
196     guint32 since;
197     value_string vs;
198 } ver_value_string;
199
200 static const ver_value_string wimaxasncp_function_type_vals[] =
201 {
202     {0,                          { WIMAXASNCP_FT_QOS,                   "QoS"}},
203     {0,                          { WIMAXASNCP_FT_HO_CONTROL,            "HO Control"}},
204     {0,                          { WIMAXASNCP_FT_DATA_PATH_CONTROL,     "Data Path Control"}},
205     {0,                          { WIMAXASNCP_FT_CONTEXT_TRANSFER,      "Context Transfer"}},
206     {0,                          { WIMAXASNCP_FT_R3_MOBILITY,           "R3 Mobility"}},
207     {0,                          { WIMAXASNCP_FT_PAGING,                "Paging"}},
208     {0,                          { WIMAXASNCP_FT_RRM,                   "RRM"}},
209     {0,                          { WIMAXASNCP_FT_AUTHENTICATION,  "Authentication Relay"}},
210     {0,                          { WIMAXASNCP_FT_MS_STATE,              "MS State"}},
211     {0,                          { WIMAXASNCP_FT_REAUTHENTICATION,     "Re-Authentication"}},
212     {WIMAXASNCP_NWGVER_R10_V120, {WIMAXASNCP_FT_IM_OPERATIONS,          "IM Operations"}},
213     {WIMAXASNCP_NWGVER_R10_V121, { WIMAXASNCP_FT_ACCOUNTING,            "Accounting"}},
214     {0, { 0, NULL}}
215 };
216
217 /* ------------------------------------------------------------------------- */
218
219 static const ver_value_string wimaxasncp_qos_msg_vals[] =
220 {
221     {0,{ 1,  "RR_Req"}},
222     {0,{ 2,  "RR_Rsp"}},
223     {0,{ 3,  "RR_Ack"}},
224     {0,{ 0,   NULL}}
225 };
226
227 /* ------------------------------------------------------------------------- */
228
229 static const ver_value_string wimaxasncp_ho_control_msg_vals[] =
230 {
231     {0,                          { 1,  "HO_Ack"}},
232     {0,                          { 2,  "HO_Complete"}},
233     {0,                          { 3,  "HO_Cnf"}},
234     {0,                          { 4,  "HO_Req"}},
235     {0,                          { 5,  "HO_Rsp"}},
236     {WIMAXASNCP_NWGVER_R10_V120, { 1,  "HO_Req"}},
237     {WIMAXASNCP_NWGVER_R10_V120, { 2,  "HO_Rsp"}},
238     {WIMAXASNCP_NWGVER_R10_V120, { 3,  "HO_Ack"}},
239     {WIMAXASNCP_NWGVER_R10_V120, { 4,  "HO_Cnf"}},
240     {WIMAXASNCP_NWGVER_R10_V120, { 5,  "HO_Complete"}},
241     {WIMAXASNCP_NWGVER_R10_V120, { 6,  "HO_Directive"}},
242     {WIMAXASNCP_NWGVER_R10_V120, { 7,  "HO_Directive_Rsp"}},
243     {0, { 0,   NULL}}
244 };
245
246 /* ------------------------------------------------------------------------- */
247
248 static const ver_value_string wimaxasncp_data_path_control_msg_vals[] =
249 {
250     {0, { 1,   "Path_Dereg_Ack"}},
251     {0, { 2,   "Path_Dereg_Req"}},
252     {0, { 3,   "Path_Dereg_Rsp"}},
253     {0, { 4,   "Path_Modification_Ack"}},
254     {0, { 5,   "Path_Modification_Req"}},
255     {0, { 6,   "Path_Modification_Rsp"}},
256     {0, { 7,   "Path_Prereg_Ack"}},
257     {0, { 8,   "Path_Prereg_Req"}},
258     {0, { 9,   "Path_Prereg_Rsp"}},
259     {0, { 10,  "Path_Reg_Ack"}},
260     {0, { 11,  "Path_Reg_Req"}},
261     {0, { 12,  "Path_Reg_Rsp"}},
262     {0, { 13,  "MS_Attachment_Req"}},
263     {0, { 14,  "MS_Attachment_Rsp"}},
264     {0, { 15,  "MS_Attachment_Ack"}},
265     {0, { 16,  "Key_Change_Directive"}},
266     {0, { 0,   NULL}}
267 };
268
269 static const ver_value_string wimaxasncp_data_path_control_msg_vals_r1v120[] =
270 {
271     {WIMAXASNCP_NWGVER_R10_V120, { 1,   "Path_Dereg_Req"}},
272     {WIMAXASNCP_NWGVER_R10_V120, { 2,   "Path_Dereg_Rsp"}},
273     {WIMAXASNCP_NWGVER_R10_V120, { 3,   "Path_Dereg_Ack"}},
274     {WIMAXASNCP_NWGVER_R10_V120, { 4,   "Path_Modification_Req"}},
275     {WIMAXASNCP_NWGVER_R10_V120, { 5,   "Path_Modification_Rsp"}},
276     {WIMAXASNCP_NWGVER_R10_V120, { 6,   "Path_Modification_Ack"}},
277     {WIMAXASNCP_NWGVER_R10_V120, { 7,   "Path_Prereg_Req"}},
278     {WIMAXASNCP_NWGVER_R10_V120, { 8,   "Path_Prereg_Rsp"}},
279     {WIMAXASNCP_NWGVER_R10_V120, { 9,   "Path_Prereg_Ack"}},
280     {WIMAXASNCP_NWGVER_R10_V120, { 10,  "Path_Reg_Req"}},
281     {WIMAXASNCP_NWGVER_R10_V120, { 11,  "Path_Reg_Rsp"}},
282     {WIMAXASNCP_NWGVER_R10_V120, { 12,  "Path_Reg_Ack"}},
283     {WIMAXASNCP_NWGVER_R10_V120, { 13,  "Obsolete"}},
284     {WIMAXASNCP_NWGVER_R10_V120, { 14,  "Obsolete"}},
285     {WIMAXASNCP_NWGVER_R10_V120, { 15,  "Obsolete"}},
286     {WIMAXASNCP_NWGVER_R10_V120, { 16,  "Obsolete"}},
287     {0, { 0,   NULL}}
288 };
289
290 /* ------------------------------------------------------------------------- */
291
292 static const ver_value_string wimaxasncp_context_transfer_msg_vals[] =
293 {
294     {0,                          { 1,  "Context_Rpt"}},
295     {0,                          { 2,  "Context_Req"}},
296     {0,                          { 3,  "Context_Ack"}},
297     {WIMAXASNCP_NWGVER_R10_V120, { 1,  "Context_Req"}},
298     {WIMAXASNCP_NWGVER_R10_V120, { 2,  "Context_Rpt"}},
299     {WIMAXASNCP_NWGVER_R10_V120, { 4,  "CMAC_Key_Count_Update"}},
300     {WIMAXASNCP_NWGVER_R10_V120, { 5,  "CMAC_Key_Count_Update_ACK"}},
301     {WIMAXASNCP_NWGVER_R10_V120, { 6,  "CMAC_Key_Count_Req"}},
302     {WIMAXASNCP_NWGVER_R10_V120, { 7,  "CMAC_Key_Count_Rsp"}},
303     {WIMAXASNCP_NWGVER_R10_V120, { 8,  "Prepaid Request"}},
304     {WIMAXASNCP_NWGVER_R10_V120, { 9,  "Prepaid Notify"}},
305     {WIMAXASNCP_NWGVER_R10_V121, { 6,  "VOID"}},
306     {WIMAXASNCP_NWGVER_R10_V121, { 7,  "VOID"}},
307     {WIMAXASNCP_NWGVER_R10_V121, { 0,   NULL}}
308 };
309
310 /* ------------------------------------------------------------------------- */
311
312 static const ver_value_string wimaxasncp_r3_mobility_msg_vals[] =
313 {
314     {0,                          { 1,  "Anchor_DPF_HO_Req"}},
315     {0,                          { 2,  "Anchor_DPF_HO_Trigger"}},
316     {0,                          { 3,  "Anchor_DPF_HO_Rsp"}},
317     {0,                          { 4,  "Anchor_DPF_Relocate_Req"}},
318     {0,                          { 5,  "FA_Register_Req"}},
319     {0,                          { 6,  "FA_Register_Rsp"}},
320     {0,                          { 7,  "Anchor_DPF_Relocate_Rsp"}},
321     {0,                          { 8,  "FA_Revoke_Req"}},
322     {0,                          { 9,  "FA_Revoke_Rsp"}},
323     {WIMAXASNCP_NWGVER_R10_V120, { 5,  "Anchor_DPF_Relocate_Rsp"}},
324     {WIMAXASNCP_NWGVER_R10_V120, { 6,  "FA_Register_Req"}},
325     {WIMAXASNCP_NWGVER_R10_V120, { 7,  "FA_Register_Rsp"}},
326     {WIMAXASNCP_NWGVER_R10_V120, { 10, "Anchor_DPF_Release_Req"}},
327     {WIMAXASNCP_NWGVER_R10_V120, { 11, "Relocation_Ready_Req"}},
328     {WIMAXASNCP_NWGVER_R10_V120, { 12, "Relocation_Ready_Rsp"}},
329     {0, { 0,   NULL}}
330 };
331
332 /* ------------------------------------------------------------------------- */
333
334 static const ver_value_string wimaxasncp_paging_msg_vals[] =
335 {
336     {0,                          { 1,  "Initiate_Paging_Req"}},
337     {0,                          { 2,  "Initiate_Paging_Rsp"}},
338     {0,                          { 3,  "LU_Cnf"}},
339     {0,                          { 4,  "LU_Req"}},
340     {0,                          { 5,  "LU_Rsp"}},
341     {0,                          { 6,  "Paging_Announce"}},
342     {0,                          { 7,  "CMAC_Key_Count_Req"}},
343     {0,                          { 8,  "CMAC_Key_Count_Rsp"}},
344     {WIMAXASNCP_NWGVER_R10_V120, { 1,  "Paging_Announce"}},
345     {WIMAXASNCP_NWGVER_R10_V120, { 2,  "Delete_MS_Entry_Req"}},
346     {WIMAXASNCP_NWGVER_R10_V120, { 3,  "PC_Relocation_Ind"}},
347     {WIMAXASNCP_NWGVER_R10_V120, { 4,  "PC_Relocation_Ack"}},
348     {WIMAXASNCP_NWGVER_R10_V120, { 5,  "Obsolete"}},
349     {WIMAXASNCP_NWGVER_R10_V120, { 6,  "Obsolete"}},
350     {WIMAXASNCP_NWGVER_R10_V120, { 7,  "Obsolete"}},
351     {WIMAXASNCP_NWGVER_R10_V120, { 8,  "Obsolete"}},
352     {0, { 0,   NULL}}
353 };
354
355 /* ------------------------------------------------------------------------- */
356
357 static const ver_value_string wimaxasncp_rrm_msg_vals[] =
358 {
359     {0,                          { 1,  "R6 PHY_Parameters_Req"}},
360     {0,                          { 2,  "R6 PHY_Parameters_Rpt"}},
361     {0,                          { 3,  "R4/R6 Spare_Capacity_Req"}},
362     {0,                          { 4,  "R4/R6 Spare_Capacity_Rpt"}},
363     {0,                          { 5,  "R6 Neighbor_BS_Resource_Status_Update"}},
364     {0,                          { 6,  "R4/R6 Radio_Config_Update_Req"}},
365     {0,                          { 7,  "R4/R6 Radio_Config_Update_Rpt"}},
366     {WIMAXASNCP_NWGVER_R10_V120, { 8,  "R4/R6 Radio_Config_Update_Ack"}},
367     {0, { 0,   NULL}}
368 };
369
370 /* ------------------------------------------------------------------------- */
371
372 static const ver_value_string wimaxasncp_authentication_msg_vals[] =
373 {
374     {0,                          { 1,  "AR_Authenticated_Eap_Start"}},
375     {0,                          { 2,  "AR_Authenticated_EAP_Transfer"}},
376     {0,                          { 3,  "AR_Eap_Start"}},
377     {0,                          { 4,  "AR_EAP_Transfer"}},
378     {0,                          { 5,  "AR_EAP_Complete"}},
379     {WIMAXASNCP_NWGVER_R10_V120, { 1,  "AR_EAP_Start"}},
380     {WIMAXASNCP_NWGVER_R10_V120, { 2,  "AR_EAP_Transfer"}},
381     {WIMAXASNCP_NWGVER_R10_V120, { 3,  "Bulk_Interim_Update"}},
382     {WIMAXASNCP_NWGVER_R10_V120, { 4,  "Bulk_Interim_Update_Ack"}},
383     {WIMAXASNCP_NWGVER_R10_V120, { 5,  "Obsolete"}},
384     {0, { 0,   NULL}}
385 };
386
387 /* ------------------------------------------------------------------------- */
388
389 static const ver_value_string wimaxasncp_ms_state_msg_vals[] =
390 {
391     {0,                          { 1,  "IM_Entry_State_Change_Req"}},
392     {0,                          { 2,  "IM_Entry_State_Change_Rsp"}},
393     {0,                          { 3,  "IM_Exit_State_Change_Req"}},
394     {0,                          { 4,  "IM_Exit_State_Change_Rsp"}},
395     {0,                          { 5,  "NW_ReEntry_State_Change_Directive"}},
396     {0,                          { 6,  "MS_PreAttachment_Req"}},
397     {0,                          { 7,  "MS_PreAttachment_Rsp"}},
398     {0,                          { 8,  "MS_PreAttachment_Ack"}},
399     {WIMAXASNCP_NWGVER_R10_V120, { 1,  "MS_PreAttachment_Req"}},
400     {WIMAXASNCP_NWGVER_R10_V120, { 2,  "MS_PreAttachment_Rsp"}},
401     {WIMAXASNCP_NWGVER_R10_V120, { 3,  "MS_PreAttachment_Ack"}},
402     {WIMAXASNCP_NWGVER_R10_V120, { 4,  "MS_Attachment_Req"}},
403     {WIMAXASNCP_NWGVER_R10_V120, { 5,  "MS_Attachment_Rsp"}},
404     {WIMAXASNCP_NWGVER_R10_V120, { 6,  "MS_Attachment_Ack"}},
405     {WIMAXASNCP_NWGVER_R10_V120, { 7,  "Key_Change_Directive"}},
406     {WIMAXASNCP_NWGVER_R10_V120, { 8,  "Key_Change_Cnf"}},
407     {WIMAXASNCP_NWGVER_R10_V120, { 9,  "Key_Change_Ack"}},
408     {WIMAXASNCP_NWGVER_R10_V120, { 10, "Relocation_Conplete_Req"}},
409     {WIMAXASNCP_NWGVER_R10_V120, { 11, "Relocation_Conplete_Rsp"}},
410     {WIMAXASNCP_NWGVER_R10_V120, { 12, "Relocation_Conplete_Ack"}},
411     {WIMAXASNCP_NWGVER_R10_V120, { 13, "Relocation_Notify"}},
412     {WIMAXASNCP_NWGVER_R10_V120, { 14, "Relocation_Req"}},
413     {WIMAXASNCP_NWGVER_R10_V120, { 15, "Relocation_Rsp"}},
414     {WIMAXASNCP_NWGVER_R10_V120, { 16, "NetExit_MS_State_Change_Req"}},
415     {WIMAXASNCP_NWGVER_R10_V120, { 17, "NetExit_MS_State_Change_Rsp"}},
416     {0, { 0,   NULL}}
417 };
418
419 /* ------------------------------------------------------------------------- */
420
421 /* note - function type 10-im_operation, was once used for re-authrntication */
422 static const ver_value_string wimaxasncp_im_operations_msg_vals[] =
423 {
424     {0,                          { 1,  "AR_EAP_Start"}},
425     {0,                          { 2,  "Key_Change_Directive"}},
426     {0,                          { 3,  "Key_Change_Cnf"}},
427     {0,                          { 4,  "Relocation_Cnf"}},
428     {0,                          { 5,  "Relocation_Confirm_Ack"}},
429     {0,                          { 6,  "Relocation_Notify"}},
430     {0,                          { 7,  "Relocation_Notify_Ack"}},
431     {0,                          { 8,  "Relocation_Req"}},
432     {0,                          { 9,  "Relocation_Rsp"}},
433     {WIMAXASNCP_NWGVER_R10_V120, { 1,  "IM_Entry_State_Change_Req"}},
434     {WIMAXASNCP_NWGVER_R10_V120, { 2,  "IM_Entry_State_Change_Rsp"}},
435     {WIMAXASNCP_NWGVER_R10_V120, { 3,  "IM_Entry_State_Change_Ack"}},
436     {WIMAXASNCP_NWGVER_R10_V120, { 4,  "IM_Exit_State_Change_Req"}},
437     {WIMAXASNCP_NWGVER_R10_V120, { 5,  "IM_Exit_State_Change_Rsp"}},
438     {WIMAXASNCP_NWGVER_R10_V120, { 6,  "Initiate_Paging_Req"}},
439     {WIMAXASNCP_NWGVER_R10_V120, { 7,  "Initiate_Paging_Rsp"}},
440     {WIMAXASNCP_NWGVER_R10_V120, { 8,  "LU_Req"}},
441     {WIMAXASNCP_NWGVER_R10_V120, { 9,  "LU_Rsp"}},
442     {WIMAXASNCP_NWGVER_R10_V120, { 10, "LU_Cnf"}},
443     {0, { 0,   NULL}}
444 };
445
446 /* ------------------------------------------------------------------------- */
447
448 static const ver_value_string wimaxasncp_accounting_msg_vals_r1v121[] =
449 {
450     {WIMAXASNCP_NWGVER_R10_V121, { 1,  "Hot_lining_Req"}},
451     {WIMAXASNCP_NWGVER_R10_V121, { 2,  "Hot_lining_Rsp"}},
452     {0, { 0,   NULL}}
453 };
454
455 /* ------------------------------------------------------------------------- */
456
457 /* supported NWG versions */
458 static const enum_val_t wimaxasncp_nwg_versions[] = {
459     { "Release 1.0, Version 1.0.0" , "R1.0 v1.0.0" , WIMAXASNCP_NWGVER_R10_V100  },
460     { "Release 1.0, Version 1.2.0" , "R1.0 v1.2.0" , WIMAXASNCP_NWGVER_R10_V120  },
461     { "Release 1.0, Version 1.2.1" , "R1.0 v1.2.1" , WIMAXASNCP_NWGVER_R10_V121  },
462     { NULL, NULL, 0 }
463 };
464
465 /* ------------------------------------------------------------------------- */
466
467 /* NWG version */
468 #define WIMAXASNCP_DEF_NWGVER       WIMAXASNCP_NWGVER_R10_V121
469 static guint global_wimaxasncp_nwg_ver = WIMAXASNCP_DEF_NWGVER;
470
471 /* ========================================================================= */
472
473 typedef struct {
474     guint8 function_type;
475     const ver_value_string *vals;
476 } wimaxasncp_func_msg_t;
477
478 /* ------------------------------------------------------------------------ */
479
480 static const wimaxasncp_func_msg_t wimaxasncp_func_to_msg_vals_map[] =
481 {
482     { WIMAXASNCP_FT_QOS,               wimaxasncp_qos_msg_vals },
483     { WIMAXASNCP_FT_HO_CONTROL,        wimaxasncp_ho_control_msg_vals },
484     { WIMAXASNCP_FT_DATA_PATH_CONTROL, wimaxasncp_data_path_control_msg_vals },
485     { WIMAXASNCP_FT_CONTEXT_TRANSFER,  wimaxasncp_context_transfer_msg_vals },
486     { WIMAXASNCP_FT_R3_MOBILITY,       wimaxasncp_r3_mobility_msg_vals },
487     { WIMAXASNCP_FT_PAGING,            wimaxasncp_paging_msg_vals },
488     { WIMAXASNCP_FT_RRM,               wimaxasncp_rrm_msg_vals },
489     { WIMAXASNCP_FT_AUTHENTICATION,    wimaxasncp_authentication_msg_vals },
490     { WIMAXASNCP_FT_MS_STATE,          wimaxasncp_ms_state_msg_vals },
491     { WIMAXASNCP_FT_IM_OPERATIONS,     wimaxasncp_im_operations_msg_vals },
492     { WIMAXASNCP_FT_ACCOUNTING,        wimaxasncp_accounting_msg_vals_r1v121 }
493 };
494
495 /* ========================================================================= */
496
497 static const wimaxasncp_dict_tlv_t *wimaxasncp_get_tlv_info(
498     guint16 type)
499 {
500     wimaxasncp_dict_tlv_t *res = NULL;
501
502     if (wimaxasncp_dict)
503     {
504         wimaxasncp_dict_tlv_t *tlv;
505
506         for (tlv = wimaxasncp_dict->tlvs; tlv; tlv = tlv->next)
507         {
508             if (tlv->type == type)
509             {
510                 /* if the TLV is defined for current NWG version */
511                 if (tlv->since<= global_wimaxasncp_nwg_ver)
512                 {
513                     /* if the current TLV is newer then last found TLV, save it */
514                     if(!res || (tlv->since > res->since))
515                     {
516                         res = tlv;
517                     }
518                 }
519             }
520         }
521     }
522
523     if (debug_enabled && !res)
524     {
525         g_print("fix-me: unknown TLV type: %u\n", type);
526     }
527
528     return res? res:&wimaxasncp_tlv_not_found;
529 }
530
531 /* ========================================================================= */
532
533 static const gchar *wimaxasncp_get_enum_name(
534     const wimaxasncp_dict_tlv_t *tlv_info,
535     guint32 code)
536 {
537     if (tlv_info->enum_vs)
538     {
539         return val_to_str(code, tlv_info->enum_vs, "Unknown");
540     }
541     else
542     {
543         return "Unknown";
544     }
545 }
546
547 /* ========================================================================= */
548
549 static const value_string wimaxasncp_decode_type_vals[] =
550 {
551   { WIMAXASNCP_TLV_UNKNOWN,             "WIMAXASNCP_TLV_UNKNOWN"},
552   { WIMAXASNCP_TLV_TBD,                 "WIMAXASNCP_TLV_TBD"},
553   { WIMAXASNCP_TLV_COMPOUND,            "WIMAXASNCP_TLV_COMPOUND"},
554   { WIMAXASNCP_TLV_BYTES,               "WIMAXASNCP_TLV_BYTES"},
555   { WIMAXASNCP_TLV_ENUM8,               "WIMAXASNCP_TLV_ENUM8"},
556   { WIMAXASNCP_TLV_ENUM16,              "WIMAXASNCP_TLV_ENUM16"},
557   { WIMAXASNCP_TLV_ENUM32,              "WIMAXASNCP_TLV_ENUM32"},
558   { WIMAXASNCP_TLV_ETHER,               "WIMAXASNCP_TLV_ETHER"},
559   { WIMAXASNCP_TLV_ASCII_STRING,        "WIMAXASNCP_TLV_ASCII_STRING"},
560   { WIMAXASNCP_TLV_FLAG0,               "WIMAXASNCP_TLV_FLAG0"},
561   { WIMAXASNCP_TLV_BITFLAGS8,           "WIMAXASNCP_TLV_BITFLAGS8"},
562   { WIMAXASNCP_TLV_BITFLAGS16,          "WIMAXASNCP_TLV_BITFLAGS16"},
563   { WIMAXASNCP_TLV_BITFLAGS32,          "WIMAXASNCP_TLV_BITFLAGS32"},
564   { WIMAXASNCP_TLV_ID,                  "WIMAXASNCP_TLV_ID"},
565   { WIMAXASNCP_TLV_HEX8,                "WIMAXASNCP_TLV_HEX8"},
566   { WIMAXASNCP_TLV_HEX16,               "WIMAXASNCP_TLV_HEX16"},
567   { WIMAXASNCP_TLV_HEX32,               "WIMAXASNCP_TLV_HEX32"},
568   { WIMAXASNCP_TLV_DEC8,                "WIMAXASNCP_TLV_DEC8"},
569   { WIMAXASNCP_TLV_DEC16,               "WIMAXASNCP_TLV_DEC16"},
570   { WIMAXASNCP_TLV_DEC32,               "WIMAXASNCP_TLV_DEC32"},
571   { WIMAXASNCP_TLV_IP_ADDRESS,          "WIMAXASNCP_TLV_IP_ADDRESS"},
572   { WIMAXASNCP_TLV_IPV4_ADDRESS,        "WIMAXASNCP_TLV_IPV4_ADDRESS"},
573   { WIMAXASNCP_TLV_PROTOCOL_LIST,       "WIMAXASNCP_TLV_PROTOCOL_LIST"},
574   { WIMAXASNCP_TLV_PORT_RANGE_LIST,     "WIMAXASNCP_TLV_PORT_RANGE_LIST"},
575   { WIMAXASNCP_TLV_IP_ADDRESS_MASK_LIST,"WIMAXASNCP_TLV_IP_ADDRESS_MASK_LIST"},
576   { WIMAXASNCP_TLV_VENDOR_SPECIFIC,     "WIMAXASNCP_TLV_VENDOR_SPECIFIC"},
577   { 0, NULL}
578 };
579
580 /* ========================================================================= */
581
582 static void wimaxasncp_proto_tree_add_tlv_ipv4_value(
583     tvbuff_t *tvb,
584     proto_tree *tree,
585     proto_item *tlv_item,
586     guint offset,
587     const wimaxasncp_dict_tlv_t *tlv_info)
588 {
589     int hf_value;
590     guint32 ip;
591     const gchar *hostname;
592     const gchar *ip_str;
593
594     if (tlv_info->hf_ipv4 != -1)
595     {
596         hf_value = tlv_info->hf_ipv4;
597     }
598     else
599     {
600         hf_value = tlv_info->hf_value;
601     }
602
603     ip = tvb_get_ipv4(tvb, offset);
604     hostname = get_hostname(ip);
605     ip_str = ip_to_str((guint8 *)&ip);
606
607     proto_tree_add_ipv4_format(
608         tree, hf_value,
609         tvb, offset, 4, ip,
610         "Value: %s (%s)", hostname, ip_str);
611
612     proto_item_append_text(
613         tlv_item, " - %s (%s)",
614         hostname, ip_str);
615 }
616
617 /* ========================================================================= */
618
619 static void wimaxasncp_proto_tree_add_tlv_ipv6_value(
620     tvbuff_t *tvb,
621     proto_tree *tree,
622     proto_item *tlv_item,
623     guint offset,
624     const wimaxasncp_dict_tlv_t *tlv_info)
625 {
626     int hf_value;
627     struct e_in6_addr ip;
628     const gchar *hostname;
629     const gchar *ip_str;
630
631     if (tlv_info->hf_ipv4 != -1)
632     {
633         hf_value = tlv_info->hf_ipv6;
634     }
635     else
636     {
637         hf_value = tlv_info->hf_value;
638     }
639
640     tvb_get_ipv6(tvb, offset, &ip);
641     hostname = get_hostname6(&ip);
642     ip_str = ip6_to_str(&ip);
643
644     proto_tree_add_ipv6_format(
645         tree, hf_value,
646         tvb, offset, 16, (guint8 *)&ip,
647         "Value: %s (%s)", hostname, ip_str);
648
649     proto_item_append_text(
650         tlv_item, " - %s (%s)",
651         hostname, ip_str);
652 }
653
654 /* ========================================================================= */
655
656 static void wimaxasncp_proto_tree_add_ether_value(
657     tvbuff_t *tvb,
658     proto_tree *tree,
659     proto_item *tlv_item,
660     guint offset,
661     guint length,
662     const wimaxasncp_dict_tlv_t *tlv_info)
663 {
664     int hf_value;
665     const guint8 *p;
666     const gchar *ether_name;
667     const gchar *ether_str;
668
669     if (tlv_info->hf_bsid != -1)
670     {
671         hf_value = tlv_info->hf_bsid;
672     }
673     else
674     {
675         hf_value = tlv_info->hf_value;
676     }
677
678     p = tvb_get_ptr(tvb, offset, length);
679     ether_name = get_ether_name(p);
680     ether_str = ether_to_str(p);
681
682     proto_tree_add_ether_format(
683         tree, hf_value,
684         tvb, offset, length, p,
685         "Value: %s (%s)",
686         ether_name, ether_str);
687
688     proto_item_append_text(
689         tlv_item, " - %s (%s)",
690         ether_name, ether_str);
691 }
692
693 /* ========================================================================= */
694
695 static void wimaxasncp_dissect_tlv_value(
696     tvbuff_t *tvb,
697     packet_info *pinfo _U_,
698     proto_tree *tree,
699     proto_item *tlv_item,
700     const wimaxasncp_dict_tlv_t *tlv_info)
701 {
702     guint offset = 0;
703     guint length;
704     const guint max_show_bytes = 24; /* arbitrary */
705     const gchar *hex_note = "[hex]";
706
707     length = tvb_reported_length(tvb);
708
709     switch(tlv_info->decoder)
710     {
711     case WIMAXASNCP_TLV_ENUM8:
712     {
713         if (length != 1)
714         {
715             /* encoding error */
716             break;
717         }
718
719         if (tlv_info->enums == NULL)
720         {
721             if (debug_enabled)
722             {
723                 g_print("fix-me: enum values missing for TLV %s (%u)\n",
724                         tlv_info->name, tlv_info->type);
725             }
726         }
727
728         if (tree)
729         {
730             guint8 value;
731             const gchar *s;
732
733             value = tvb_get_guint8(tvb, offset);
734
735             s = wimaxasncp_get_enum_name(tlv_info, value);
736
737             proto_tree_add_uint_format(
738                 tree, tlv_info->hf_value,
739                 tvb, offset, length, value,
740                 "Value: %s (%u)", s, value);
741
742             proto_item_append_text(tlv_item, " - %s", s);
743         }
744
745         return;
746     }
747     case WIMAXASNCP_TLV_ENUM16:
748     {
749         if (length != 2)
750         {
751             /* encoding error */
752             break;
753         }
754
755         if (tlv_info->enums == NULL)
756         {
757             if (debug_enabled)
758             {
759                 g_print("fix-me: enum values missing for TLV %s (%u)\n",
760                         tlv_info->name, tlv_info->type);
761             }
762         }
763
764         if (tree)
765         {
766             guint16 value;
767             const gchar *s;
768
769             value = tvb_get_ntohs(tvb, offset);
770
771             s = wimaxasncp_get_enum_name(tlv_info, value);
772
773             proto_tree_add_uint_format(
774                 tree, tlv_info->hf_value,
775                 tvb, offset, length, value,
776                 "Value: %s (%u)", s, value);
777
778             proto_item_append_text(tlv_item, " - %s", s);
779         }
780
781         return;
782     }
783     case WIMAXASNCP_TLV_ENUM32:
784     {
785         if (length != 4)
786         {
787             /* encoding error */
788             break;
789         }
790
791         if (tlv_info->enums == NULL)
792         {
793             if (debug_enabled)
794             {
795                 g_print("fix-me: enum values missing for TLV %s (%u)\n",
796                         tlv_info->name, tlv_info->type);
797             }
798         }
799
800         if (tree)
801         {
802             guint32 value;
803             const gchar *s;
804
805             value = tvb_get_ntohl(tvb, offset);
806
807             s = wimaxasncp_get_enum_name(tlv_info, value);
808
809             proto_tree_add_uint_format(
810                 tree, tlv_info->hf_value,
811                 tvb, offset, length, value,
812                 "Value: %s (%u)", s, value);
813
814             proto_item_append_text(tlv_item, " - %s", s);
815         }
816
817         return;
818     }
819     case WIMAXASNCP_TLV_ETHER:
820     {
821         if (length != 6)
822         {
823             /* encoding error */
824             break;
825         }
826
827         if (tree)
828         {
829             wimaxasncp_proto_tree_add_ether_value(
830                 tvb, tree, tlv_item, offset, length, tlv_info);
831         }
832
833         return;
834     }
835     case WIMAXASNCP_TLV_ASCII_STRING:
836     {
837         if (tree)
838         {
839             const guint8 *p;
840             const gchar *s = tvb_get_ephemeral_string(tvb, offset, length);
841
842             p = tvb_get_ptr(tvb, offset, length);
843
844             proto_tree_add_string_format(
845                 tree, tlv_info->hf_value,
846                 tvb, offset, length, p,
847                 "Value: %s", s);
848
849             proto_item_append_text(
850                 tlv_item, " - %s", s);
851         }
852
853         return;
854     }
855     case WIMAXASNCP_TLV_FLAG0:
856     {
857         if (length != 0)
858         {
859             /* encoding error */
860             break;
861         }
862
863         return;
864     }
865     case WIMAXASNCP_TLV_BITFLAGS8:
866     {
867         if (length != 1)
868         {
869             /* encoding error */
870             break;
871         }
872
873         if (tlv_info->enums == NULL)
874         {
875             /* enum values missing */
876         }
877
878         if (tree)
879         {
880             proto_tree *flags_tree;
881             proto_item *item;
882             guint8 value;
883             guint i;
884
885             value = tvb_get_guint8(tvb, offset);
886
887             item = proto_tree_add_uint_format(
888                 tree, tlv_info->hf_value,
889                 tvb, offset, length, value,
890                 "Value: %s",
891                 decode_numeric_bitfield(value, 0xff, 8, "0x%02x"));
892
893             proto_item_append_text(tlv_item, " - 0x%02x", value);
894
895             if (value != 0)
896             {
897                 flags_tree = proto_item_add_subtree(
898                     item, ett_wimaxasncp_tlv_value_bitflags8);
899
900                 for (i = 0; i < 8; ++i)
901                 {
902                     guint8 mask;
903                     mask = 1 << (7 - i);
904
905                     if (value & mask)
906                     {
907                         const gchar *s;
908
909                         s = wimaxasncp_get_enum_name(tlv_info, value & mask);
910
911                         proto_tree_add_uint_format(
912                             flags_tree, hf_wimaxasncp_tlv_value_bitflags8,
913                             tvb, offset, length, value,
914                             "Bit #%u is set: %s", i, s);
915                     }
916                 }
917             }
918         }
919
920         return;
921     }
922     case WIMAXASNCP_TLV_BITFLAGS16:
923     {
924         if (length != 2)
925         {
926             /* encoding error */
927             break;
928         }
929
930         if (tlv_info->enums == NULL)
931         {
932             /* enum values missing */
933         }
934
935         if (tree)
936         {
937             proto_tree *flags_tree;
938             proto_item *item;
939             guint16 value;
940             guint i;
941
942             value = tvb_get_ntohs(tvb, offset);
943
944             item = proto_tree_add_uint_format(
945                 tree, tlv_info->hf_value,
946                 tvb, offset, length, value,
947                 "Value: %s",
948                 decode_numeric_bitfield(value, 0xffff, 16, "0x%04x"));
949
950             proto_item_append_text(tlv_item, " - 0x%04x", value);
951
952             if (value != 0)
953             {
954                 flags_tree = proto_item_add_subtree(
955                     item, ett_wimaxasncp_tlv_value_bitflags16);
956
957                 for (i = 0; i < 16; ++i)
958                 {
959                     guint16 mask;
960                     mask = 1 << (15 - i);
961
962                     if (value & mask)
963                     {
964                         const gchar *s;
965
966                         s = wimaxasncp_get_enum_name(tlv_info, value & mask);
967
968                         proto_tree_add_uint_format(
969                             flags_tree, hf_wimaxasncp_tlv_value_bitflags16,
970                             tvb, offset, length, value,
971                             "Bit #%u is set: %s", i, s);
972                     }
973                 }
974             }
975         }
976
977         return;
978     }
979     case WIMAXASNCP_TLV_BITFLAGS32:
980     {
981         if (length != 4)
982         {
983             /* encoding error */
984             break;
985         }
986
987         if (tlv_info->enums == NULL)
988         {
989             /* enum values missing */
990         }
991
992         if (tree)
993         {
994             proto_tree *flags_tree;
995             proto_item *item;
996             guint32 value;
997             guint i;
998
999             value = tvb_get_ntohl(tvb, offset);
1000
1001             item = proto_tree_add_uint_format(
1002                 tree, tlv_info->hf_value,
1003                 tvb, offset, length, value,
1004                 "Value: %s",
1005                 decode_numeric_bitfield(value, 0xffffffff, 32, "0x%08x"));
1006
1007             proto_item_append_text(tlv_item, " - 0x%08x", value);
1008
1009             if (value != 0)
1010             {
1011                 flags_tree = proto_item_add_subtree(
1012                     item, ett_wimaxasncp_tlv_value_bitflags32);
1013
1014                 for (i = 0; i < 32; ++i)
1015                 {
1016                     guint32 mask;
1017                     mask = 1 << (31 - i);
1018
1019                     if (value & mask)
1020                     {
1021                         const gchar *s;
1022                         s = wimaxasncp_get_enum_name(tlv_info, value & mask);
1023
1024                         proto_tree_add_uint_format(
1025                             flags_tree, hf_wimaxasncp_tlv_value_bitflags32,
1026                             tvb, offset, length, value,
1027                             "Bit #%u is set: %s", i, s);
1028                     }
1029                 }
1030             }
1031         }
1032
1033         return;
1034     }
1035     case WIMAXASNCP_TLV_ID:
1036     {
1037         if (length == 4)
1038         {
1039             if (tree)
1040             {
1041                 wimaxasncp_proto_tree_add_tlv_ipv4_value(
1042                     tvb, tree, tlv_item, offset, tlv_info);
1043             }
1044
1045             return;
1046         }
1047         else if (length == 6)
1048         {
1049             if (tree)
1050             {
1051                 wimaxasncp_proto_tree_add_ether_value(
1052                     tvb, tree, tlv_item, offset, length, tlv_info);
1053             }
1054
1055             return;
1056         }
1057         else if (length == 16)
1058         {
1059             if (tree)
1060             {
1061                 wimaxasncp_proto_tree_add_tlv_ipv6_value(
1062                     tvb, tree, tlv_item, offset, tlv_info);
1063             }
1064
1065             return;
1066         }
1067         else
1068         {
1069             /* encoding error */
1070             break;
1071         }
1072     }
1073     case WIMAXASNCP_TLV_BYTES:
1074     {
1075         if (tree)
1076         {
1077             const gchar *format1;
1078             const gchar *format2;
1079             const guint8 *p = tvb_get_ptr(tvb, offset, length);
1080             const gchar *s =
1081                 bytestring_to_str(p, MIN(length, max_show_bytes), 0);
1082
1083             if (length <= max_show_bytes)
1084             {
1085                 format1 = "Value: %s";
1086                 format2 = " - %s";
1087             }
1088             else
1089             {
1090                 format1 = "Value: %s...";
1091                 format2 = " - %s...";
1092             }
1093
1094             proto_tree_add_bytes_format(
1095                 tree, tlv_info->hf_value,
1096                 tvb, offset, length, p,
1097                 format1, s);
1098
1099             proto_item_append_text(
1100                 tlv_item, format2, s);
1101         }
1102
1103         return;
1104     }
1105     case WIMAXASNCP_TLV_HEX8:
1106     {
1107         if (length != 1)
1108         {
1109             /* encoding error */
1110             break;
1111         }
1112
1113         if (tree)
1114         {
1115             guint8 value;
1116
1117             value = tvb_get_guint8(tvb, offset);
1118
1119             proto_tree_add_uint_format(
1120                 tree, tlv_info->hf_value,
1121                 tvb, offset, length, value,
1122                 "Value: 0x%02x", value);
1123
1124             proto_item_append_text(tlv_item, " - 0x%02x", value);
1125         }
1126
1127         return;
1128     }
1129     case WIMAXASNCP_TLV_HEX16:
1130     {
1131         if (length != 2)
1132         {
1133             /* encoding error */
1134             break;
1135         }
1136
1137         if (tree)
1138         {
1139             guint16 value;
1140
1141             value = tvb_get_ntohs(tvb, offset);
1142
1143             proto_tree_add_uint_format(
1144                 tree, tlv_info->hf_value,
1145                 tvb, offset, length, value,
1146                 "Value: 0x%04x", value);
1147
1148             proto_item_append_text(tlv_item, " - 0x%04x", value);
1149         }
1150
1151         return;
1152     }
1153     case WIMAXASNCP_TLV_HEX32:
1154     {
1155         if (length != 4)
1156         {
1157             /* encoding error */
1158             break;
1159         }
1160
1161         if (tree)
1162         {
1163             guint32 value;
1164
1165             value = tvb_get_ntohl(tvb, offset);
1166
1167             proto_tree_add_uint_format(
1168                 tree, tlv_info->hf_value,
1169                 tvb, offset, length, value,
1170                 "Value: 0x%08x", value);
1171
1172             proto_item_append_text(tlv_item, " - 0x%08x", value);
1173         }
1174
1175         return;
1176     }
1177     case WIMAXASNCP_TLV_DEC8:
1178     {
1179         if (length != 1)
1180         {
1181             /* encoding error */
1182             break;
1183         }
1184
1185         if (tree)
1186         {
1187             guint8 value;
1188
1189             value = tvb_get_guint8(tvb, offset);
1190
1191             proto_tree_add_uint_format(
1192                 tree, tlv_info->hf_value,
1193                 tvb, offset, length, value,
1194                 "Value: %u", value);
1195
1196             proto_item_append_text(tlv_item, " - %u", value);
1197         }
1198
1199         return;
1200     }
1201     case WIMAXASNCP_TLV_DEC16:
1202     {
1203         if (length != 2)
1204         {
1205             /* encoding error */
1206             break;
1207         }
1208
1209         if (tree)
1210         {
1211             guint16 value;
1212
1213             value = tvb_get_ntohs(tvb, offset);
1214
1215             proto_tree_add_uint_format(
1216                 tree, tlv_info->hf_value,
1217                 tvb, offset, length, value,
1218                 "Value: %u", value);
1219
1220             proto_item_append_text(tlv_item, " - %u", value);
1221         }
1222
1223         return;
1224     }
1225     case WIMAXASNCP_TLV_DEC32:
1226     {
1227         if (length != 4)
1228         {
1229             /* encoding error */
1230             break;
1231         }
1232
1233         if (tree)
1234         {
1235             guint32 value;
1236
1237             value = tvb_get_ntohl(tvb, offset);
1238
1239             proto_tree_add_uint_format(
1240                 tree, tlv_info->hf_value,
1241                 tvb, offset, length, value,
1242                 "Value: %u", value);
1243
1244             proto_item_append_text(tlv_item, " - %u", value);
1245         }
1246
1247         return;
1248     }
1249     case WIMAXASNCP_TLV_TBD:
1250     {
1251         if (debug_enabled)
1252         {
1253             g_print(
1254                 "fix-me: TBD: TLV %s (%u)\n", tlv_info->name, tlv_info->type);
1255         }
1256
1257         if (tree)
1258         {
1259             const gchar *format;
1260             const guint8 *p = tvb_get_ptr(tvb, offset, length);
1261             const gchar *s =
1262                 bytestring_to_str(p, MIN(length, max_show_bytes), 0);
1263
1264             if (length <= max_show_bytes)
1265             {
1266                 format = "Value: %s %s";
1267             }
1268             else
1269             {
1270                 format = "Value: %s %s...";
1271             }
1272
1273             proto_tree_add_bytes_format(
1274                 tree, tlv_info->hf_value,
1275                 tvb, offset, length, p,
1276                 format, hex_note, s);
1277
1278             proto_item_append_text(tlv_item, " - TBD");
1279         }
1280
1281         return;
1282     }
1283     case WIMAXASNCP_TLV_IP_ADDRESS:
1284     {
1285         if (length == 4)
1286         {
1287             if (tree)
1288             {
1289                 wimaxasncp_proto_tree_add_tlv_ipv4_value(
1290                     tvb, tree, tlv_item, offset, tlv_info);
1291             }
1292
1293             return;
1294         }
1295         else if (length == 16)
1296         {
1297             if (tree)
1298             {
1299                 wimaxasncp_proto_tree_add_tlv_ipv6_value(
1300                     tvb, tree, tlv_item, offset, tlv_info);
1301             }
1302
1303             return;
1304         }
1305         else
1306         {
1307             /* encoding error */
1308             break;
1309         }
1310     }
1311     case WIMAXASNCP_TLV_IPV4_ADDRESS:
1312     {
1313         if (length != 4)
1314         {
1315             /* encoding error */
1316             break;
1317         }
1318
1319         if (tree)
1320         {
1321             wimaxasncp_proto_tree_add_tlv_ipv4_value(
1322                 tvb, tree, tlv_item, offset, tlv_info);
1323         }
1324
1325         return;
1326     }
1327     case WIMAXASNCP_TLV_PROTOCOL_LIST:
1328     {
1329         if (length % 2 != 0)
1330         {
1331             /* encoding error */
1332             break;
1333         }
1334
1335         if (tree && length > 0)
1336         {
1337             proto_tree *protocol_list_tree;
1338             proto_item *item;
1339             const guint max_protocols_in_tlv_item = 8; /* arbitrary */
1340
1341             item = proto_tree_add_text(
1342                 tree, tvb, offset, length,
1343                 "Value");
1344
1345             protocol_list_tree = proto_item_add_subtree(
1346                 item, ett_wimaxasncp_tlv_protocol_list);
1347
1348             /* hidden item for filtering */
1349             item = proto_tree_add_item(
1350                 protocol_list_tree, tlv_info->hf_value,
1351                 tvb, offset, length, FALSE);
1352
1353             PROTO_ITEM_SET_HIDDEN(item);
1354
1355             while (offset < tvb_length(tvb))
1356             {
1357                 guint16 protocol;
1358                 const gchar *protocol_name;
1359
1360                 protocol = tvb_get_ntohs(tvb, offset);
1361                 protocol_name = ipprotostr(protocol);
1362
1363                 proto_tree_add_uint_format(
1364                     protocol_list_tree, tlv_info->hf_protocol,
1365                     tvb, offset, 2, protocol,
1366                     "Protocol: %s (%u)", protocol_name, protocol);
1367
1368                 if (offset == 0)
1369                 {
1370                     proto_item_append_text(tlv_item, " - %s", protocol_name);
1371                 }
1372                 else if (offset < 2 * max_protocols_in_tlv_item)
1373                 {
1374                     proto_item_append_text(tlv_item, ", %s", protocol_name);
1375                 }
1376                 else if (offset == 2 * max_protocols_in_tlv_item)
1377                 {
1378                     proto_item_append_text(tlv_item, ", ...");
1379                 }
1380
1381                 offset += 2;
1382             }
1383         }
1384
1385         return;
1386     }
1387     case WIMAXASNCP_TLV_PORT_RANGE_LIST:
1388     {
1389         if (length % 4 != 0)
1390         {
1391             /* encoding error */
1392             break;
1393         }
1394
1395         if (tree && length > 0)
1396         {
1397             proto_tree *port_range_list_tree;
1398             proto_item *item;
1399             const guint max_port_ranges_in_tlv_item = 3; /* arbitrary */
1400
1401             item = proto_tree_add_text(
1402                 tree, tvb, offset, length,
1403                 "Value");
1404
1405             port_range_list_tree = proto_item_add_subtree(
1406                 item, ett_wimaxasncp_tlv_port_range_list);
1407
1408             /* hidden item for filtering */
1409             item = proto_tree_add_item(
1410                 port_range_list_tree, tlv_info->hf_value,
1411                 tvb, offset, length, FALSE);
1412
1413             PROTO_ITEM_SET_HIDDEN(item);
1414
1415             while (offset < tvb_length(tvb))
1416             {
1417                 guint16 portLow;
1418                 guint16 portHigh;
1419
1420                 portLow = tvb_get_ntohs(tvb, offset);
1421                 portHigh = tvb_get_ntohs(tvb, offset + 2);
1422
1423                 proto_tree_add_text(
1424                     port_range_list_tree, tvb, offset, 4,
1425                     "Port Range: %u-%u", portLow, portHigh);
1426
1427                 /* hidden items are for filtering */
1428
1429                 item = proto_tree_add_item(
1430                     port_range_list_tree, tlv_info->hf_port_low,
1431                     tvb, offset, 2, FALSE);
1432
1433                 PROTO_ITEM_SET_HIDDEN(item);
1434
1435                 item = proto_tree_add_item(
1436                     port_range_list_tree, tlv_info->hf_port_high,
1437                     tvb, offset + 2, 2, FALSE);
1438
1439                 PROTO_ITEM_SET_HIDDEN(item);
1440
1441                 if (offset == 0)
1442                 {
1443                     proto_item_append_text(
1444                         tlv_item, " - %u-%u", portLow, portHigh);
1445                 }
1446                 else if (offset < 4 * max_port_ranges_in_tlv_item)
1447                 {
1448                     proto_item_append_text(
1449                         tlv_item, ", %u-%u", portLow, portHigh);
1450                 }
1451                 else if (offset == 4 * max_port_ranges_in_tlv_item)
1452                 {
1453                     proto_item_append_text(tlv_item, ", ...");
1454                 }
1455
1456                 offset += 4;
1457             }
1458         }
1459
1460         return;
1461     }
1462     case WIMAXASNCP_TLV_IP_ADDRESS_MASK_LIST:
1463     {
1464         /* --------------------------------------------------------------------
1465          * The definion of these TLVs are ambiguous. The length in octets is
1466          * described as Nx8 (IPv4) or Nx32 (IPv6), but this function cannot
1467          * always differentiate between IPv4 and IPv6. For example, if length
1468          * = 32, then is it IPv4 where N=4 (4x8) or IPv6 where N=1 (1x32)?
1469          *
1470          * For now, we presume lengths that *can* indicate an IPv6 address and
1471          * mask list *do* denote an IPv6 address and mask list.
1472          * --------------------------------------------------------------------
1473          */
1474
1475         if (length % 8 != 0)
1476         {
1477             /* encoding error */
1478             break;
1479         }
1480
1481         if (tree && length > 0)
1482         {
1483             proto_tree *ip_address_mask_list_tree;
1484             proto_item *item;
1485
1486             item = proto_tree_add_text(
1487                 tree, tvb, offset, length,
1488                 "Value");
1489
1490             ip_address_mask_list_tree = proto_item_add_subtree(
1491                 item, ett_wimaxasncp_tlv_ip_address_mask_list);
1492
1493             /* hidden item for filtering */
1494             item = proto_tree_add_item(
1495                 ip_address_mask_list_tree, tlv_info->hf_value,
1496                 tvb, offset, length, FALSE);
1497
1498             PROTO_ITEM_SET_HIDDEN(item);
1499
1500             if (length % 32 == 0)
1501             {
1502                 /* ------------------------------------------------------------
1503                  * presume IPv6
1504                  * ------------------------------------------------------------
1505                  */
1506
1507                 while (offset < tvb_length(tvb))
1508                 {
1509                     proto_tree *ip_address_mask_tree;
1510                     struct e_in6_addr ip;
1511                     const gchar *s;
1512
1513                     item = proto_tree_add_text(
1514                         ip_address_mask_list_tree, tvb, offset, 32,
1515                         "IPv6 Address and Mask");
1516
1517                     ip_address_mask_tree = proto_item_add_subtree(
1518                         item, ett_wimaxasncp_tlv_ip_address_mask);
1519
1520                     /* --------------------------------------------------------
1521                      * address
1522                      * --------------------------------------------------------
1523                      */
1524
1525                     tvb_get_ipv6(tvb, offset, &ip);
1526
1527                     proto_tree_add_item(
1528                         ip_address_mask_tree,
1529                         tlv_info->hf_ipv6,
1530                         tvb, offset, 16, FALSE);
1531
1532                     /* too long to display ?
1533                     proto_item_append_text(
1534                         item, " - %s (%s)",
1535                         get_hostname6(&ip), ip6_to_str(&ip));
1536                     */
1537
1538                     offset += 16;
1539
1540                     /* --------------------------------------------------------
1541                      * mask
1542                      * --------------------------------------------------------
1543                      */
1544
1545                     tvb_get_ipv6(tvb, offset, &ip);
1546
1547                     s = ip6_to_str(&ip);
1548
1549                     proto_tree_add_ipv6_format_value(
1550                         ip_address_mask_tree,
1551                         tlv_info->hf_ipv6_mask,
1552                         tvb, offset, 16, (const guint8*)&ip,
1553                         "%s", s);
1554
1555                     /* too long to display ?
1556                     proto_item_append_text(
1557                         item, " / %s", s);
1558                     */
1559
1560                     offset += 16;
1561                 }
1562             }
1563             else
1564             {
1565                 /* ------------------------------------------------------------
1566                  * IPv4
1567                  * ------------------------------------------------------------
1568                  */
1569
1570                 while (offset < tvb_length(tvb))
1571                 {
1572                     proto_tree *ip_address_mask_tree;
1573                     guint32 ip;
1574                     const gchar *s;
1575
1576                     item = proto_tree_add_text(
1577                         ip_address_mask_list_tree, tvb, offset, 8,
1578                         "IPv4 Address and Mask");
1579
1580                     ip_address_mask_tree = proto_item_add_subtree(
1581                         item, ett_wimaxasncp_tlv_ip_address_mask);
1582
1583                     /* --------------------------------------------------------
1584                      * address
1585                      * --------------------------------------------------------
1586                      */
1587
1588                     ip = tvb_get_ipv4(tvb, offset);
1589
1590                     proto_tree_add_item(
1591                         ip_address_mask_tree,
1592                         tlv_info->hf_ipv4,
1593                         tvb, offset, 4, FALSE);
1594
1595                     proto_item_append_text(
1596                         item, " - %s (%s)",
1597                         get_hostname(ip), ip_to_str((guint8 *)&ip));
1598
1599                     offset += 4;
1600
1601                     /* --------------------------------------------------------
1602                      * mask
1603                      * --------------------------------------------------------
1604                      */
1605
1606                     ip = tvb_get_ipv4(tvb, offset);
1607
1608                     s = ip_to_str((guint8 *)&ip);
1609
1610                     proto_tree_add_ipv4_format_value(
1611                         ip_address_mask_tree,
1612                         tlv_info->hf_ipv4_mask,
1613                         tvb, offset, 4, ip,
1614                         "%s", s);
1615
1616                     proto_item_append_text(
1617                         item, " / %s", s);
1618
1619                     offset += 4;
1620                 }
1621             }
1622         }
1623
1624         return;
1625     }
1626     case WIMAXASNCP_TLV_EAP:
1627     {
1628         /*
1629          *   EAP payload, call eap dissector to dissect eap payload
1630          */
1631         guint8 eap_code;
1632         guint8 eap_type = 0;
1633
1634         /* Get code */
1635         eap_code = tvb_get_guint8(tvb, offset);
1636         if (eap_code == EAP_REQUEST || eap_code == EAP_RESPONSE)
1637         {
1638             /* Get type */
1639             eap_type = tvb_get_guint8(tvb, offset + 4);
1640         }
1641
1642         /* Add code and type to info column */
1643         col_append_str(pinfo->cinfo, COL_INFO, " [");
1644         col_append_str(pinfo->cinfo, COL_INFO,
1645                         val_to_str(eap_code, eap_code_vals, "Unknown code (0x%02X)"));
1646
1647         if (eap_code == EAP_REQUEST || eap_code == EAP_RESPONSE)
1648         {
1649             col_append_str(pinfo->cinfo, COL_INFO, ", ");
1650             col_append_str(pinfo->cinfo, COL_INFO,
1651                             val_to_str(eap_type, eap_type_vals, "Unknown type (0x%02X)"));
1652         }
1653
1654         col_append_str(pinfo->cinfo, COL_INFO, "]");
1655
1656
1657         {
1658             proto_tree *eap_tree;
1659             proto_item *item;
1660             gboolean save_writable;
1661             tvbuff_t *eap_tvb;
1662
1663             /* Create EAP subtree */
1664             item = proto_tree_add_item(tree, tlv_info->hf_value, tvb,
1665                                        offset, length, FALSE);
1666             proto_item_set_text(item, "Value");
1667             eap_tree = proto_item_add_subtree(item, ett_wimaxasncp_tlv_eap);
1668
1669             /* Also show high-level details in this root item */
1670             proto_item_append_text(item, " (%s",
1671                                    val_to_str(eap_code, eap_code_vals,
1672                                               "Unknown code (0x%02X)"));
1673             if (eap_code == EAP_REQUEST || eap_code == EAP_RESPONSE)
1674             {
1675                 proto_item_append_text(item, ", %s",
1676                                        val_to_str(eap_type, eap_type_vals,
1677                                        "Unknown type (0x%02X)"));
1678             }
1679             proto_item_append_text(item, ")");
1680
1681
1682             /* Extract remaining bytes into new tvb */
1683             eap_tvb = tvb_new_subset(tvb, offset, length,
1684                                      tvb_length_remaining(tvb, offset));
1685
1686             /* Disable writing to info column while calling eap dissector */
1687             save_writable = col_get_writable(pinfo->cinfo);
1688             col_set_writable(pinfo->cinfo, FALSE);
1689
1690             /* Call the EAP dissector. */
1691             call_dissector(eap_handle, eap_tvb, pinfo, eap_tree);
1692
1693             /* Restore previous writable state of info column */
1694             col_set_writable(pinfo->cinfo, save_writable);
1695         }
1696
1697         return;
1698     }
1699
1700     case WIMAXASNCP_TLV_VENDOR_SPECIFIC:
1701     {
1702         /* --------------------------------------------------------------------
1703          *  The format of the vendor specific information field (VSIF) is not
1704          *  clearly defined.  It appears to be compound as the spec states
1705          *  that the vendor ID field shall be the first TLV embedded inside
1706          *  the VSIF.  However, the vendor ID is shown as a 24-bit value. Does
1707          *  this mean the field is 24-bits?  If so, how is alignment/padding
1708          *  handled?
1709          *
1710          * For now, we decode the vendor ID as a non-padded 24-bit value and
1711          * dump the rest as hex.
1712          * --------------------------------------------------------------------
1713          */
1714
1715         if (length < 3)
1716         {
1717             /* encoding error */
1718             break;
1719         }
1720
1721         if (tree)
1722         {
1723             proto_tree *vsif_tree;
1724             proto_item *item;
1725             guint32 vendorId;
1726             const gchar *vendorName;
1727
1728             item = proto_tree_add_text(
1729                 tree, tvb, offset, length,
1730                 "Value");
1731
1732             vsif_tree = proto_item_add_subtree(
1733                 item, ett_wimaxasncp_tlv_vendor_specific_information_field);
1734
1735             /* hidden item for filtering */
1736             item = proto_tree_add_item(
1737                 vsif_tree, tlv_info->hf_value,
1738                 tvb, offset, length, FALSE);
1739
1740             PROTO_ITEM_SET_HIDDEN(item);
1741
1742             /* ----------------------------------------------------------------
1743              * vendor ID (24-bit)
1744              * ----------------------------------------------------------------
1745              */
1746
1747             vendorId = tvb_get_ntoh24(tvb, offset);
1748
1749             vendorName = val_to_str_ext_const(vendorId, &sminmpec_values_ext, "Unknown");
1750             proto_tree_add_uint_format(
1751                 vsif_tree, tlv_info->hf_vendor_id,
1752                 tvb, offset, 3, vendorId,
1753                 "Vendor ID: %s (%u)", vendorName, vendorId);
1754
1755             proto_item_append_text(tlv_item, " - %s", vendorName);
1756
1757             offset += 3;
1758
1759             /* ----------------------------------------------------------------
1760              * hex dump the rest
1761              * ----------------------------------------------------------------
1762              */
1763
1764             if (offset < tvb_length(tvb))
1765             {
1766                 proto_tree_add_item(
1767                     vsif_tree, tlv_info->hf_vendor_rest_of_info,
1768                     tvb, offset, length - offset, FALSE);
1769             }
1770         }
1771
1772         return;
1773     }
1774     case WIMAXASNCP_TLV_UNKNOWN:
1775     {
1776         if (tree)
1777         {
1778             const gchar *format1;
1779             const gchar *format2;
1780             const guint8 *p = tvb_get_ptr(tvb, offset, length);
1781             const gchar *s =
1782                 bytestring_to_str(p, MIN(length, max_show_bytes), 0);
1783
1784             if (length <= max_show_bytes)
1785             {
1786                 format1 = "Value: %s %s";
1787                 format2 = " - %s %s";
1788             }
1789             else
1790             {
1791                 format1 = "Value: %s %s...";
1792                 format2 = " - %s %s...";
1793             }
1794
1795             proto_tree_add_bytes_format(
1796                 tree, tlv_info->hf_value,
1797                 tvb, offset, length, p,
1798                 format1, hex_note, s);
1799
1800             proto_item_append_text(
1801                 tlv_item, format2, hex_note, s);
1802
1803         }
1804
1805         return;
1806     }
1807     default:
1808         if (debug_enabled)
1809         {
1810             g_print(
1811                 "fix-me: unknown decoder: %d\n", tlv_info->decoder);
1812         }
1813         break;
1814     }
1815
1816     /* default is hex dump */
1817
1818     if (tree)
1819     {
1820         const gchar *format;
1821         const guint8 *p = tvb_get_ptr(tvb, offset, length);
1822         const gchar *s = bytestring_to_str(p, MIN(length, max_show_bytes), 0);
1823
1824         if (length <= max_show_bytes)
1825         {
1826             format = "Value: %s %s";
1827         }
1828         else
1829         {
1830             format = "Value: %s %s...";
1831         }
1832
1833         proto_tree_add_bytes_format(
1834             tree, hf_wimaxasncp_tlv_value_bytes,
1835             tvb, offset, length, p,
1836             format, hex_note, s);
1837     }
1838 }
1839
1840 /* ========================================================================= */
1841
1842 static guint dissect_wimaxasncp_tlvs(
1843     tvbuff_t *tvb,
1844     packet_info *pinfo,
1845     proto_tree *tree)
1846 {
1847     guint offset;
1848
1849     offset = 0;
1850     while (offset < tvb_reported_length(tvb))
1851     {
1852         proto_tree *tlv_tree = NULL;
1853         proto_item *tlv_item = NULL;
1854         const wimaxasncp_dict_tlv_t *tlv_info;
1855
1856         guint16 type;
1857         guint16 length;
1858         guint pad;
1859
1860         /* --------------------------------------------------------------------
1861          * type and length
1862          * --------------------------------------------------------------------
1863          */
1864
1865         type = tvb_get_ntohs(tvb, offset);
1866         tlv_info = wimaxasncp_get_tlv_info(type);
1867
1868         length = tvb_get_ntohs(tvb, offset + 2);
1869         /* Commented out padding; As there is no mention of padding in
1870            the Latest specification
1871         pad = 4 - (length % 4);
1872         if (pad == 4)
1873         {
1874             pad = 0;
1875         }
1876         */
1877         pad = 0;
1878         if (tree)
1879         {
1880             proto_item *type_item;
1881
1882             gint tree_length = MIN(
1883                 (gint)(4 + length + pad), tvb_length_remaining(tvb, offset));
1884
1885             tlv_item = proto_tree_add_item(
1886                 tree, tlv_info->hf_root,
1887                 tvb, offset, tree_length, FALSE);
1888
1889             /* Set label for tlv item */
1890             proto_item_set_text(tlv_item, "TLV: %s", tlv_info->name);
1891
1892             /* Show code number if unknown */
1893             if (tlv_info->decoder == WIMAXASNCP_TLV_UNKNOWN)
1894             {
1895                 proto_item_append_text(tlv_item, " (%u)", type);
1896             }
1897
1898             /* Indicate if a compound tlv */
1899             if (tlv_info->decoder == WIMAXASNCP_TLV_COMPOUND)
1900             {
1901                 proto_item_append_text(tlv_item, " [Compound]");
1902             }
1903
1904             /* Create TLV subtree */
1905             tlv_tree = proto_item_add_subtree(
1906                 tlv_item, ett_wimaxasncp_tlv);
1907
1908             /* Type (expert item if unknown) */
1909             type_item = proto_tree_add_uint_format(
1910                 tlv_tree, hf_wimaxasncp_tlv_type,
1911                 tvb, offset, 2, type,
1912                 "Type: %s (%u)", tlv_info->name, type);
1913
1914             if (tlv_info->decoder == WIMAXASNCP_TLV_UNKNOWN)
1915             {
1916                 expert_add_info_format(pinfo, type_item,
1917                                        PI_UNDECODED, PI_WARN,
1918                                        "Unknown TLV type (%u)",
1919                                        type);
1920             }
1921
1922             /* Length */
1923             proto_tree_add_uint(
1924                 tlv_tree, hf_wimaxasncp_tlv_length,
1925                 tvb, offset + 2, 2, length);
1926
1927         }
1928
1929         offset += 4;
1930
1931         /* --------------------------------------------------------------------
1932          * value
1933          * --------------------------------------------------------------------
1934          */
1935
1936         if (tlv_info->decoder == WIMAXASNCP_TLV_COMPOUND)
1937         {
1938             if (length == 0)
1939             {
1940                 /* error? compound, but no TLVs inside */
1941             }
1942             else if (tvb_length_remaining(tvb, offset) > 0)
1943             {
1944                 tvbuff_t *tlv_tvb;
1945
1946                 /* N.B.  Not padding out tvb length */
1947                 tlv_tvb = tvb_new_subset(
1948                     tvb, offset,
1949                     MIN(length, tvb_length_remaining(tvb, offset)),
1950                     length);
1951
1952                 /* N.B.  This is a recursive call... */
1953                 dissect_wimaxasncp_tlvs(tlv_tvb, pinfo, tlv_tree);
1954             }
1955             else
1956             {
1957                 /* this should throw */
1958                 tvb_ensure_bytes_exist(tvb, offset, length + pad);
1959             }
1960         }
1961         else
1962         {
1963             tvbuff_t *tlv_tvb;
1964
1965             tvb_ensure_bytes_exist(tvb, offset, length + pad);
1966
1967             tlv_tvb = tvb_new_subset(
1968                 tvb, offset,
1969                 MIN(length, tvb_length_remaining(tvb, offset)),
1970                 length);
1971
1972             wimaxasncp_dissect_tlv_value(
1973                 tlv_tvb, pinfo, tlv_tree, tlv_item, tlv_info);
1974         }
1975
1976         offset += length + pad;
1977     }
1978
1979     return offset;
1980 }
1981
1982 /* ========================================================================= */
1983
1984 static guint dissect_wimaxasncp_backend(
1985     tvbuff_t *tvb,
1986     packet_info *pinfo,
1987     proto_tree *tree)
1988 {
1989     guint offset = 0;
1990     guint16 ui16;
1991     guint32 ui32;
1992     guint8 *pmsid = NULL;
1993     guint16 tid = 0;
1994     gboolean dbit_show;
1995
1996
1997     /* ------------------------------------------------------------------------
1998      * MSID
1999      * ------------------------------------------------------------------------
2000      */
2001
2002     if (tree)
2003     {
2004         proto_tree_add_item(
2005             tree, hf_wimaxasncp_msid,
2006             tvb, offset, 6, ENC_NA);
2007     }
2008     pmsid = tvb_ether_to_str(tvb, offset);
2009
2010     offset += 6;
2011
2012     /* ------------------------------------------------------------------------
2013      * reserved
2014      * ------------------------------------------------------------------------
2015      */
2016
2017     ui32 = tvb_get_ntohl(tvb, offset);
2018
2019     if (tree)
2020     {
2021         proto_tree_add_uint(
2022             tree, hf_wimaxasncp_reserved1,
2023             tvb, offset, 4, ui32);
2024     }
2025
2026     offset += 4;
2027
2028     /* ------------------------------------------------------------------------
2029      * transaction ID
2030      * ------------------------------------------------------------------------
2031      */
2032
2033     dbit_show = FALSE;
2034     ui16 = tvb_get_ntohs(tvb, offset);
2035
2036     if (show_transaction_id_d_bit)
2037     {
2038         const guint16 mask = 0x7fff;
2039
2040         if (ui16 & 0x8000)
2041         {
2042             proto_tree_add_uint_format(
2043                 tree, hf_wimaxasncp_transaction_id,
2044                 tvb, offset, 2, ui16,
2045                 "Transaction ID: D + 0x%04x (0x%04x)", mask & ui16, ui16);
2046
2047             tid = ui16 & mask;
2048             dbit_show = TRUE;
2049         }
2050         else
2051         {
2052             proto_tree_add_uint_format(
2053                 tree, hf_wimaxasncp_transaction_id,
2054                 tvb, offset, 2, ui16,
2055                 "Transaction ID: 0x%04x", ui16);
2056
2057             tid = ui16;
2058         }
2059     }
2060     else
2061     {
2062         proto_tree_add_uint(
2063             tree, hf_wimaxasncp_transaction_id,
2064             tvb, offset, 2, ui16);
2065
2066         tid = ui16;
2067     }
2068
2069     offset += 2;
2070
2071     /* ------------------------------------------------------------------------
2072      * reserved
2073      * ------------------------------------------------------------------------
2074      */
2075
2076     ui16 = tvb_get_ntohs(tvb, offset);
2077
2078     if (tree)
2079     {
2080         proto_tree_add_uint(
2081             tree, hf_wimaxasncp_reserved2,
2082             tvb, offset, 2, ui16);
2083     }
2084
2085     offset += 2;
2086
2087     /* ------------------------------------------------------------------------
2088      * TLVs
2089      * ------------------------------------------------------------------------
2090      */
2091
2092     if (offset < tvb_length(tvb))
2093     {
2094         tvbuff_t *tlv_tvb;
2095
2096         tlv_tvb = tvb_new_subset(
2097             tvb, offset,
2098             tvb_length(tvb) - offset,
2099             tvb_length(tvb) - offset);
2100
2101         offset += dissect_wimaxasncp_tlvs(tlv_tvb, pinfo, tree);
2102     }
2103
2104     col_append_fstr(pinfo->cinfo, COL_INFO, " - MSID:%s", pmsid);
2105     if (dbit_show)
2106     {
2107         col_append_fstr(pinfo->cinfo, COL_INFO, ", TID:D+0x%04x", tid);
2108     }
2109     else
2110     {
2111         col_append_fstr(pinfo->cinfo, COL_INFO, ", TID:0x%04x", tid);
2112     }
2113
2114     return offset;
2115 }
2116
2117 /* ========================================================================= */
2118
2119
2120 static const gchar*
2121 match_ver_value_string(
2122     const guint32 val,
2123     const ver_value_string* const strings,
2124     const guint32 max_ver)
2125 {
2126     const ver_value_string* vvs;
2127     const ver_value_string* res = NULL;
2128
2129     /* loop on the levels, from max to 0 */
2130     for(vvs=strings; vvs->vs.strptr; vvs++)
2131     {
2132         if((vvs->vs.value == val) && (vvs->since <= max_ver))
2133         {
2134             if(!res || vvs->since > res->since)
2135             {
2136                 res = vvs;
2137             }
2138         }
2139     }
2140
2141     return res? res->vs.strptr : NULL;
2142 }
2143
2144 static void register_wimaxasncp_fields(const char*);
2145
2146
2147 static int
2148 dissect_wimaxasncp(
2149     tvbuff_t *tvb,
2150     packet_info *pinfo,
2151     proto_tree *tree)
2152 {
2153     const gchar *unknown = "Unknown";
2154
2155     /* Set up structures needed to add the protocol subtree and manage it */
2156     proto_item *packet_item = NULL;
2157     proto_item *item = NULL;
2158     proto_tree *wimaxasncp_tree = NULL;
2159     tvbuff_t *subtree;
2160
2161     guint offset;
2162     guint8 ui8;
2163
2164     guint8 function_type;
2165     const gchar *function_type_name;
2166     proto_item *function_type_item;
2167     guint16 length;
2168
2169     const gchar *message_name;
2170     const wimaxasncp_func_msg_t *p = NULL;
2171     gsize i;
2172
2173     /* ------------------------------------------------------------------------
2174      * First, we do some heuristics to check if the packet cannot be our
2175      * protocol.
2176      * ------------------------------------------------------------------------
2177      */
2178
2179     /* Should we check a minimum size?  If so, uncomment out the following
2180      * code. */
2181     /*
2182     if (tvb_reported_length(tvb) < WIMAXASNCP_HEADER_SIZE)
2183     {
2184         return 0;
2185     }
2186     */
2187
2188     /* We currently only support version 1. */
2189     if (tvb_bytes_exist(tvb, 0, 1) && tvb_get_guint8(tvb, 0) != 1)
2190     {
2191         return 0;
2192     }
2193
2194     /* ------------------------------------------------------------------------
2195      * Initialize the protocol and info column.
2196      * ------------------------------------------------------------------------
2197      */
2198
2199     /* Make entries in Protocol column and Info column on summary display */
2200     col_set_str(pinfo->cinfo, COL_PROTOCOL, "WiMAX");
2201
2202     /* We'll fill in the "Info" column after fetch data, so we clear the
2203        column first in case calls to fetch data from the packet throw an
2204        exception. */
2205     col_clear(pinfo->cinfo, COL_INFO);
2206
2207     /* ========================================================================
2208      * Disesction starts here
2209      * ========================================================================
2210      */
2211
2212     /* ------------------------------------------------------------------------
2213      * total packet, we'll adjust after we read the length field
2214      * ------------------------------------------------------------------------
2215      */
2216
2217     offset = 0;
2218
2219     /* Register protocol fields, etc if haven't done yet. */
2220     if (wimaxasncp_dict == NULL)
2221     {
2222         register_wimaxasncp_fields(NULL);
2223     }
2224
2225     if (tree)
2226     {
2227         packet_item = proto_tree_add_item(
2228             tree, proto_wimaxasncp,
2229             tvb, 0, MIN(WIMAXASNCP_HEADER_LENGTH_END, tvb_length(tvb)), ENC_NA);
2230
2231         wimaxasncp_tree = proto_item_add_subtree(
2232             packet_item, ett_wimaxasncp);
2233     }
2234
2235     /* ------------------------------------------------------------------------
2236      * version
2237      * ------------------------------------------------------------------------
2238      */
2239
2240     if (tree)
2241     {
2242         proto_tree_add_item(
2243             wimaxasncp_tree, hf_wimaxasncp_version,
2244             tvb, offset, 1, ENC_BIG_ENDIAN);
2245     }
2246
2247     offset += 1;
2248
2249     /* ------------------------------------------------------------------------
2250      * flags
2251      * ------------------------------------------------------------------------
2252      */
2253
2254     ui8 = tvb_get_guint8(tvb, offset);
2255
2256     if (tree)
2257     {
2258         proto_tree *flags_tree;
2259
2260         if (ui8 == 0)
2261         {
2262             proto_tree_add_uint_format(
2263                 wimaxasncp_tree, hf_wimaxasncp_flags,
2264                 tvb, offset, 1, ui8,
2265                 "Flags: 0x%02x", ui8);
2266         }
2267         else
2268         {
2269             guint j;
2270             item = proto_tree_add_uint_format(
2271                 wimaxasncp_tree, hf_wimaxasncp_flags,
2272                 tvb, offset, 1, ui8,
2273                 "Flags: ");
2274
2275             if (ui8 & (WIMAXASNCP_FLAGS_T | WIMAXASNCP_FLAGS_R))
2276             {
2277                 if (ui8 & WIMAXASNCP_FLAGS_T)
2278                 {
2279                     proto_item_append_text(item, "T");
2280                 }
2281
2282                 if (ui8 & WIMAXASNCP_FLAGS_R)
2283                 {
2284                     proto_item_append_text(item, "R");
2285                 }
2286
2287                 proto_item_append_text(item, " - ");
2288             }
2289
2290             proto_item_append_text(
2291                 item, "%s", decode_numeric_bitfield(ui8, 0xff, 8, "0x%02x"));
2292
2293             flags_tree = proto_item_add_subtree(
2294                 item, ett_wimaxasncp_flags);
2295
2296             for (j = 0; j < 8; ++j)
2297             {
2298                 guint8 mask;
2299                 mask = 1 << (7 - j);
2300
2301                 /* Only add flags that are set */
2302                 if (ui8 & mask)
2303                 {
2304                     proto_tree_add_uint_format(
2305                         flags_tree, hf_wimaxasncp_flags,
2306                         tvb, offset, 1, ui8,
2307                         "Bit #%u is set: %s",
2308                         j,
2309                         val_to_str(
2310                             ui8 & mask, wimaxasncp_flag_vals, "Unknown"));
2311                 }
2312             }
2313         }
2314     }
2315
2316     offset += 1;
2317
2318     /* ------------------------------------------------------------------------
2319      * function type
2320      * ------------------------------------------------------------------------
2321      */
2322
2323     function_type = tvb_get_guint8(tvb, offset);
2324
2325     function_type_name = match_ver_value_string(function_type,
2326         wimaxasncp_function_type_vals,
2327         global_wimaxasncp_nwg_ver);
2328
2329     if( function_type_name )
2330     {
2331         /* add the item to the tree */
2332         proto_tree_add_uint_format(
2333             wimaxasncp_tree, hf_wimaxasncp_function_type,
2334             tvb, offset, 1, function_type,
2335             "%s (%u)", function_type_name, function_type);
2336     }
2337     else
2338     {
2339         /* if not matched, add the item and append expert item  */
2340         function_type_item = proto_tree_add_uint_format(
2341             wimaxasncp_tree, hf_wimaxasncp_function_type,
2342             tvb, offset, 1, function_type,
2343             "Unknown (%u)", function_type);
2344
2345         expert_add_info_format(pinfo, function_type_item,
2346                                PI_UNDECODED, PI_WARN,
2347                                "Unknown function type (%u)",
2348                                function_type);
2349     }
2350
2351     offset += 1;
2352
2353     /* ------------------------------------------------------------------------
2354      * OP ID and message type
2355      * ------------------------------------------------------------------------
2356      */
2357
2358     ui8 = tvb_get_guint8(tvb, offset);
2359
2360
2361     /* --------------------------------------------------------------------
2362      * OP ID
2363      * --------------------------------------------------------------------
2364      */
2365
2366     item = proto_tree_add_uint_format(
2367         wimaxasncp_tree, hf_wimaxasncp_op_id,
2368          tvb, offset, 1, ui8,
2369         "OP ID: %s", val_to_str(ui8 >> 5, wimaxasncp_op_id_vals, unknown));
2370
2371     proto_item_append_text(
2372         item, " (%s)", decode_numeric_bitfield(ui8, 0xe0, 8, "%u"));
2373
2374
2375     /* use the function type to find the message vals */
2376     for (i = 0; i < array_length(wimaxasncp_func_to_msg_vals_map); ++i)
2377     {
2378         p = &wimaxasncp_func_to_msg_vals_map[i];
2379
2380         if (function_type == p->function_type)
2381         {
2382             break;
2383         }
2384     }
2385
2386     /* --------------------------------------------------------------------
2387      * message type
2388      * --------------------------------------------------------------------
2389      */
2390
2391     message_name = p ? match_ver_value_string(0x1f & ui8, p->vals, global_wimaxasncp_nwg_ver) : unknown;
2392     if(message_name == NULL)
2393     {
2394         message_name = unknown;
2395     }
2396
2397     item = proto_tree_add_uint_format(
2398         wimaxasncp_tree, hf_wimaxasncp_op_id,
2399         tvb, offset, 1, ui8,
2400         "Message Type: %s", message_name);
2401
2402     proto_item_append_text(
2403         item, " (%s)", decode_numeric_bitfield(ui8, 0x1f, 8, "%u"));
2404
2405     /* Add expert item if not matched */
2406     if (strcmp(message_name, unknown) == 0)
2407     {
2408         expert_add_info_format(pinfo, item,
2409                                PI_UNDECODED, PI_WARN,
2410                                "Unknown message op (%u)",
2411                                0x1f & ui8);
2412     }
2413
2414     col_add_str(pinfo->cinfo, COL_INFO, message_name);
2415
2416     offset += 1;
2417
2418     /* ------------------------------------------------------------------------
2419      * length
2420      * ------------------------------------------------------------------------
2421      */
2422
2423     length = tvb_get_ntohs(tvb, offset);
2424
2425     if (tree)
2426     {
2427         proto_item_set_len(
2428             packet_item, MAX(WIMAXASNCP_HEADER_LENGTH_END, length));
2429
2430         item = proto_tree_add_uint(
2431             wimaxasncp_tree, hf_wimaxasncp_length,
2432             tvb, offset, 2, length);
2433     }
2434
2435     offset += 2;
2436
2437     if (length < WIMAXASNCP_HEADER_SIZE)
2438     {
2439         expert_add_info_format(
2440             pinfo, item, PI_MALFORMED, PI_ERROR, "Bad length");
2441
2442         if (tree)
2443         {
2444             proto_item_append_text(
2445                 item, " [error: specified length less than header size (20)]");
2446         }
2447
2448         if (length <= WIMAXASNCP_HEADER_LENGTH_END)
2449         {
2450             return offset;
2451         }
2452     }
2453
2454     /* ------------------------------------------------------------------------
2455      * remaining header fields and TLVs
2456      * ------------------------------------------------------------------------
2457      */
2458
2459     subtree = tvb_new_subset(
2460         tvb, offset,
2461         MIN(length, tvb_length(tvb) - offset),
2462         length - WIMAXASNCP_HEADER_LENGTH_END);
2463
2464     offset += dissect_wimaxasncp_backend(
2465         subtree, pinfo, wimaxasncp_tree);
2466
2467     /* ------------------------------------------------------------------------
2468      * done, return the amount of data this dissector was able to dissect
2469      * ------------------------------------------------------------------------
2470      */
2471
2472     return offset;
2473 }
2474
2475 /* ========================================================================= */
2476 /* Modify the given string to make a suitable display filter                 */
2477 static char *alnumerize(
2478     char *name)
2479 {
2480     char *r = name;  /* read pointer */
2481     char *w = name;  /* write pointer */
2482     char c;
2483
2484     for ( ; (c = *r); ++r)
2485     {
2486         if (isalnum((unsigned char)c) || c == '_' || c == '.')
2487         {
2488             /* These characters are fine - copy them */
2489             *(w++) = c;
2490         }
2491         else if (c == ' ' || c == '-' || c == '/')
2492         {
2493             /* Skip these others if haven't written any characters out yet */
2494             if (w == name)
2495             {
2496                 continue;
2497             }
2498
2499             /* Skip if we would produce multiple adjacent '_'s */
2500             if (*(w - 1) == '_')
2501             {
2502                 continue;
2503             }
2504
2505             /* OK, replace with underscore */
2506             *(w++) = '_';
2507         }
2508
2509         /* Other undesirable characters are just skipped */
2510     }
2511
2512     /* Terminate and return modified string */
2513     *w = '\0';
2514     return name;
2515 }
2516
2517 /* ========================================================================= */
2518
2519 static void add_reg_info(
2520     int *hf_ptr,
2521     const char *name,
2522     const char *abbrev,
2523     enum ftenum type,
2524     int  display,
2525     const char *blurb)
2526 {
2527     hf_register_info hf = {
2528         hf_ptr, { name, abbrev, type, display, NULL, 0x0, blurb, HFILL } };
2529
2530     g_array_append_val(wimaxasncp_build_dict.hf, hf);
2531 }
2532
2533 /* ========================================================================= */
2534
2535 static void add_tlv_reg_info(
2536     wimaxasncp_dict_tlv_t *tlv)
2537 {
2538     char *name;
2539     char *abbrev;
2540     char *blurb;
2541
2542     /* ------------------------------------------------------------------------
2543      * add root reg info
2544      * ------------------------------------------------------------------------
2545      */
2546
2547     name = g_strdup(tlv->name);
2548     abbrev = alnumerize(g_strdup_printf("wimaxasncp.tlv.%s", tlv->name));
2549
2550     switch (tlv->decoder)
2551     {
2552     case WIMAXASNCP_TLV_UNKNOWN:
2553         blurb = "type=Unknown";
2554         break;
2555     case WIMAXASNCP_TLV_TBD:
2556         blurb = g_strdup_printf("type=%u, TBD", tlv->type);
2557         break;
2558     case WIMAXASNCP_TLV_COMPOUND:
2559         blurb = g_strdup_printf("type=%u, Compound", tlv->type);
2560         break;
2561     case WIMAXASNCP_TLV_FLAG0:
2562         blurb = g_strdup_printf("type=%u, Value = Null", tlv->type);
2563         break;
2564     default:
2565         blurb = g_strdup_printf("type=%u", tlv->type);
2566         break;
2567     }
2568
2569     add_reg_info(
2570         &tlv->hf_root, name, abbrev, FT_BYTES, BASE_NONE, blurb);
2571
2572     /* ------------------------------------------------------------------------
2573      * add value(s) reg info
2574      * ------------------------------------------------------------------------
2575      */
2576
2577     name = g_strdup("Value");
2578     abbrev = alnumerize(g_strdup_printf("wimaxasncp.tlv.%s.value", tlv->name));
2579     blurb = g_strdup_printf("value for type=%u", tlv->type);
2580
2581     switch (tlv->decoder)
2582     {
2583     case WIMAXASNCP_TLV_UNKNOWN:
2584         g_free(blurb);
2585
2586         add_reg_info(
2587             &tlv->hf_value, name, abbrev, FT_BYTES, BASE_NONE,
2588             "value for unknown type");
2589         break;
2590
2591     case WIMAXASNCP_TLV_TBD:
2592         add_reg_info(
2593             &tlv->hf_value, name, abbrev, FT_BYTES, BASE_NONE, blurb);
2594         break;
2595
2596     case WIMAXASNCP_TLV_COMPOUND:
2597     case WIMAXASNCP_TLV_FLAG0:
2598         g_free(name);
2599         g_free(abbrev);
2600         g_free(blurb);
2601         break;
2602
2603     case WIMAXASNCP_TLV_BYTES:
2604         add_reg_info(
2605             &tlv->hf_value, name, abbrev, FT_BYTES, BASE_NONE, blurb);
2606         break;
2607
2608     case WIMAXASNCP_TLV_ENUM8:
2609         add_reg_info(
2610             &tlv->hf_value, name, abbrev, FT_UINT8, BASE_DEC, blurb);
2611         break;
2612
2613     case WIMAXASNCP_TLV_ENUM16:
2614         add_reg_info(
2615             &tlv->hf_value, name, abbrev, FT_UINT16, BASE_DEC, blurb);
2616         break;
2617
2618     case WIMAXASNCP_TLV_ENUM32:
2619         add_reg_info(
2620             &tlv->hf_value, name, abbrev, FT_UINT32, BASE_DEC, blurb);
2621         break;
2622
2623     case WIMAXASNCP_TLV_ETHER:
2624         add_reg_info(
2625             &tlv->hf_value, name, abbrev, FT_ETHER, BASE_NONE, blurb);
2626         break;
2627
2628     case WIMAXASNCP_TLV_ASCII_STRING:
2629         add_reg_info(
2630             &tlv->hf_value, name, abbrev, FT_STRING, BASE_NONE, blurb);
2631         break;
2632
2633     case WIMAXASNCP_TLV_BITFLAGS8:
2634         add_reg_info(
2635             &tlv->hf_value, name, abbrev, FT_UINT8, BASE_HEX, blurb);
2636         break;
2637
2638     case WIMAXASNCP_TLV_BITFLAGS16:
2639         add_reg_info(
2640             &tlv->hf_value, name, abbrev, FT_UINT16, BASE_HEX, blurb);
2641         break;
2642
2643     case WIMAXASNCP_TLV_BITFLAGS32:
2644         add_reg_info(
2645             &tlv->hf_value, name, abbrev, FT_UINT32, BASE_HEX, blurb);
2646         break;
2647
2648     case WIMAXASNCP_TLV_ID:
2649         g_free(name);
2650         g_free(abbrev);
2651
2652         name = "IPv4 Address";
2653
2654         abbrev = alnumerize(
2655             g_strdup_printf("wimaxasncp.tlv.%s.ipv4_value", tlv->name));
2656
2657         add_reg_info(
2658             &tlv->hf_ipv4, name, abbrev, FT_IPv4, BASE_NONE, blurb);
2659
2660         name = "IPv6 Address";
2661
2662         abbrev = alnumerize(
2663             g_strdup_printf("wimaxasncp.tlv.%s.ipv6_value", tlv->name));
2664
2665         add_reg_info(
2666             &tlv->hf_ipv6, name, abbrev, FT_IPv6, BASE_NONE, blurb);
2667
2668         name = "BS ID";
2669
2670         abbrev = alnumerize(
2671             g_strdup_printf("wimaxasncp.tlv.%s.bsid_value", tlv->name));
2672
2673         add_reg_info(
2674             &tlv->hf_bsid, name, abbrev, FT_ETHER, BASE_NONE, blurb);
2675
2676         break;
2677
2678     case WIMAXASNCP_TLV_HEX8:
2679         add_reg_info(
2680             &tlv->hf_value, name, abbrev, FT_UINT8, BASE_HEX, blurb);
2681         break;
2682
2683     case WIMAXASNCP_TLV_HEX16:
2684         add_reg_info(
2685             &tlv->hf_value, name, abbrev, FT_UINT16, BASE_HEX, blurb);
2686         break;
2687
2688     case WIMAXASNCP_TLV_HEX32:
2689         add_reg_info(
2690             &tlv->hf_value, name, abbrev, FT_UINT32, BASE_HEX, blurb);
2691         break;
2692
2693     case WIMAXASNCP_TLV_DEC8:
2694         add_reg_info(
2695             &tlv->hf_value, name, abbrev, FT_UINT8, BASE_DEC, blurb);
2696         break;
2697
2698     case WIMAXASNCP_TLV_DEC16:
2699         add_reg_info(
2700             &tlv->hf_value, name, abbrev, FT_UINT16, BASE_DEC, blurb);
2701         break;
2702
2703     case WIMAXASNCP_TLV_DEC32:
2704         add_reg_info(
2705             &tlv->hf_value, name, abbrev, FT_UINT32, BASE_DEC, blurb);
2706         break;
2707
2708     case WIMAXASNCP_TLV_IP_ADDRESS:
2709         g_free(name);
2710         g_free(abbrev);
2711
2712         name = "IPv4 Address";
2713
2714         abbrev = alnumerize(
2715             g_strdup_printf("wimaxasncp.tlv.%s.ipv4_value", tlv->name));
2716
2717         add_reg_info(
2718             &tlv->hf_ipv4, name, abbrev, FT_IPv4, BASE_NONE, blurb);
2719
2720         name = "IPv6 Address";
2721
2722         abbrev = alnumerize(
2723             g_strdup_printf("wimaxasncp.tlv.%s.ipv6_value", tlv->name));
2724
2725         add_reg_info(
2726             &tlv->hf_ipv6, name, abbrev, FT_IPv6, BASE_NONE, blurb);
2727
2728         break;
2729
2730     case WIMAXASNCP_TLV_IPV4_ADDRESS:
2731         add_reg_info(
2732             &tlv->hf_value, name, abbrev, FT_IPv4, BASE_NONE, blurb);
2733         break;
2734
2735     case WIMAXASNCP_TLV_PROTOCOL_LIST:
2736         add_reg_info(
2737             &tlv->hf_value, name, abbrev, FT_BYTES, BASE_NONE, blurb);
2738
2739         blurb = g_strdup_printf("value component for type=%u", tlv->type);
2740
2741         name = "Protocol";
2742
2743         abbrev = alnumerize(
2744             g_strdup_printf("wimaxasncp.tlv.%s.value.protocol", tlv->name));
2745
2746         add_reg_info(
2747             &tlv->hf_protocol, name, abbrev, FT_UINT16, BASE_DEC, blurb);
2748
2749         break;
2750
2751     case WIMAXASNCP_TLV_PORT_RANGE_LIST:
2752         add_reg_info(
2753             &tlv->hf_value, name, abbrev, FT_BYTES, BASE_NONE, blurb);
2754
2755         blurb = g_strdup_printf("value component for type=%u", tlv->type);
2756
2757         name = "Port Low";
2758
2759         abbrev = alnumerize(
2760             g_strdup_printf("wimaxasncp.tlv.%s.value.port_low", tlv->name));
2761
2762         add_reg_info(
2763             &tlv->hf_port_low, name, abbrev, FT_UINT16, BASE_DEC, blurb);
2764
2765         name = "Port High";
2766
2767         abbrev = alnumerize(
2768             g_strdup_printf("wimaxasncp.tlv.%s.value.port_high", tlv->name));
2769
2770         add_reg_info(
2771             &tlv->hf_port_high, name, abbrev, FT_UINT16, BASE_DEC, blurb);
2772
2773         break;
2774
2775     case WIMAXASNCP_TLV_IP_ADDRESS_MASK_LIST:
2776         add_reg_info(
2777             &tlv->hf_value, name, abbrev, FT_BYTES, BASE_NONE, blurb);
2778
2779         blurb = g_strdup_printf("value component for type=%u", tlv->type);
2780
2781         name = "IPv4 Address";
2782
2783         abbrev = alnumerize(
2784             g_strdup_printf("wimaxasncp.tlv.%s.value.ipv4", tlv->name));
2785
2786         add_reg_info(
2787             &tlv->hf_ipv4, name, abbrev, FT_IPv4, BASE_NONE, blurb);
2788
2789         name = "IPv4 Mask";
2790
2791         abbrev = alnumerize(
2792             g_strdup_printf("wimaxasncp.tlv.%s.value.ipv4_mask", tlv->name));
2793
2794         add_reg_info(
2795             &tlv->hf_ipv4_mask, name, abbrev, FT_IPv4, BASE_NONE, blurb);
2796
2797         name = "IPv6 Address";
2798
2799         abbrev = alnumerize(
2800             g_strdup_printf("wimaxasncp.tlv.%s.value.ipv6", tlv->name));
2801
2802         add_reg_info(
2803             &tlv->hf_ipv6, name, abbrev, FT_IPv6, BASE_NONE, blurb);
2804
2805         name = "IPv6 Mask";
2806
2807         abbrev = alnumerize(
2808             g_strdup_printf("wimaxasncp.tlv.%s.value.ipv6_mask", tlv->name));
2809
2810         add_reg_info(
2811             &tlv->hf_ipv6_mask, name, abbrev, FT_IPv6, BASE_NONE, blurb);
2812
2813         break;
2814
2815     case WIMAXASNCP_TLV_VENDOR_SPECIFIC:
2816         add_reg_info(
2817             &tlv->hf_value, name, abbrev, FT_BYTES, BASE_NONE, blurb);
2818
2819         blurb = g_strdup_printf("value component for type=%u", tlv->type);
2820
2821         name = "Vendor ID";
2822
2823         abbrev = alnumerize(
2824             g_strdup_printf("wimaxasncp.tlv.%s.value.vendor_id", tlv->name));
2825
2826         add_reg_info(
2827             &tlv->hf_vendor_id, name, abbrev, FT_UINT24, BASE_DEC, blurb);
2828
2829         name = "Rest of Info";
2830
2831         abbrev = alnumerize(
2832             g_strdup_printf(
2833                 "wimaxasncp.tlv.%s.value.vendor_rest_of_info", tlv->name));
2834
2835         add_reg_info(
2836             &tlv->hf_vendor_rest_of_info, name, abbrev, FT_BYTES, BASE_NONE,
2837             blurb);
2838
2839         break;
2840
2841     case WIMAXASNCP_TLV_EAP:
2842         blurb = g_strdup_printf("EAP payload embedded in %s", name);
2843
2844         add_reg_info(
2845             &tlv->hf_value, name, abbrev, FT_BYTES, BASE_NONE, blurb);
2846         break;
2847
2848
2849     default:
2850         add_reg_info(
2851             &tlv->hf_value, name, abbrev, FT_BYTES, BASE_NONE, blurb);
2852
2853         if (debug_enabled)
2854         {
2855             g_print(
2856                 "fix-me: unknown decoder: %d\n", tlv->decoder);
2857         }
2858
2859         break;
2860     }
2861 }
2862
2863 /* ========================================================================= */
2864 /* Register the protocol fields and subtrees with Wireshark */
2865 static void
2866 register_wimaxasncp_fields(const char* unused _U_)
2867 {
2868     gboolean debug_parser;
2869     gboolean dump_dict;
2870     gchar *dir;
2871     gchar* dict_error;
2872
2873     /* ------------------------------------------------------------------------
2874      * List of header fields
2875      * ------------------------------------------------------------------------
2876      */
2877
2878     static hf_register_info hf_base[] = {
2879             {
2880                 &hf_wimaxasncp_version,      /* ID */
2881                 {
2882                     "Version",               /* FIELDNAME */
2883                     "wimaxasncp.version",    /* PROTOABBREV.FIELDABBRE */
2884                     FT_UINT8,                /* FIELDTYPE */
2885                     BASE_DEC,                /* FIELDBASE */
2886                     NULL,                    /* FIELDCONVERT */
2887                     0x0,                     /* BITMASK */
2888                     NULL,                      /* FIELDDESCR */
2889                     HFILL                    /* HFILL */
2890                 }
2891             },
2892             {
2893                 &hf_wimaxasncp_flags,
2894                 {
2895                     "Flags",
2896                     "wimaxasncp.flags",
2897                     FT_UINT8,
2898                     BASE_HEX,
2899                     NULL,
2900                     0xff,
2901                     NULL,
2902                     HFILL
2903                 }
2904             },
2905             {
2906                 &hf_wimaxasncp_function_type,
2907                 {
2908                     "Function Type",
2909                     "wimaxasncp.function_type",
2910                     FT_UINT8,
2911                     BASE_DEC,
2912                     NULL,
2913                     0x0,
2914                     NULL,
2915                     HFILL
2916                 }
2917             },
2918             {
2919                 &hf_wimaxasncp_op_id,
2920                 {
2921                     "OP ID",
2922                     "wimaxasncp.opid",
2923                     FT_UINT8,
2924                     BASE_HEX,
2925                     VALS(wimaxasncp_op_id_vals),
2926                     0xE0,
2927                     NULL,
2928                     HFILL
2929                 }
2930             },
2931             {
2932                 &hf_wimaxasncp_message_type,
2933                 {
2934                     "Message Type",
2935                     "wimaxasncp.message_type",
2936                     FT_UINT8,
2937                     BASE_HEX,
2938                     NULL,
2939                     0x1F,
2940                     NULL,
2941                     HFILL
2942                 }
2943             },
2944             {
2945                 &hf_wimaxasncp_qos_msg,
2946                 {
2947                     "Message Type",
2948                     "wimaxasncp.qos_msg",
2949                     FT_UINT8,
2950                     BASE_HEX,
2951                     NULL,
2952                     0x1F,
2953                     NULL,
2954                     HFILL
2955                 }
2956             },
2957             {
2958                 &hf_wimaxasncp_ho_control_msg,
2959                 {
2960                     "Message Type",
2961                     "wimaxasncp.ho_control_msg",
2962                     FT_UINT8,
2963                     BASE_HEX,
2964                     NULL,
2965                     0x1F,
2966                     NULL,
2967                     HFILL
2968                 }
2969             },
2970             {
2971                 &hf_wimaxasncp_data_path_control_msg,
2972                 {
2973                     "Message Type",
2974                     "wimaxasncp.data_path_control_msg",
2975                     FT_UINT8,
2976                     BASE_HEX,
2977                     NULL,
2978                     0x1F,
2979                     NULL,
2980                     HFILL
2981                 }
2982             },
2983             {
2984                 &hf_wimaxasncp_context_delivery_msg,
2985                 {
2986                     "Message Type",
2987                     "wimaxasncp.context_delivery_msg",
2988                     FT_UINT8,
2989                     BASE_HEX,
2990                     NULL,
2991                     0x1F,
2992                     NULL,
2993                     HFILL
2994                 }
2995             },
2996             {
2997                 &hf_wimaxasncp_r3_mobility_msg,
2998                 {
2999                     "Message Type",
3000                     "wimaxasncp.r3_mobility_msg",
3001                     FT_UINT8,
3002                     BASE_HEX,
3003                     NULL,
3004                     0x1F,
3005                     NULL,
3006                     HFILL
3007                 }
3008             },
3009             {
3010                 &hf_wimaxasncp_paging_msg,
3011                 {
3012                     "Message Type",
3013                     "wimaxasncp.paging_msg",
3014                     FT_UINT8,
3015                     BASE_HEX,
3016                     NULL,
3017                     0x1F,
3018                     NULL,
3019                     HFILL
3020                 }
3021             },
3022             {
3023                 &hf_wimaxasncp_rrm_msg,
3024                 {
3025                     "Message Type",
3026                     "wimaxasncp.rrm_msg",
3027                     FT_UINT8,
3028                     BASE_HEX,
3029                     NULL,
3030                     0x1F,
3031                     NULL,
3032                     HFILL
3033                 }
3034             },
3035             {
3036                 &hf_wimaxasncp_authentication_msg,
3037                 {
3038                     "Message Type",
3039                     "wimaxasncp.authentication_msg",
3040                     FT_UINT8,
3041                     BASE_HEX,
3042                     NULL,
3043                     0x1F,
3044                     NULL,
3045                     HFILL
3046                 }
3047             },
3048             {
3049                 &hf_wimaxasncp_ms_state_msg,
3050                 {
3051                     "Message Type",
3052                     "wimaxasncp.ms_state_msg",
3053                     FT_UINT8,
3054                     BASE_HEX,
3055                     NULL,
3056                     0x1F,
3057                     NULL,
3058                     HFILL
3059                 }
3060             },
3061             {
3062                 &hf_wimaxasncp_reauthentication_msg,
3063                 {
3064                     "Message Type",
3065                     "wimaxasncp.reauthentication_msg",
3066                     FT_UINT8,
3067                     BASE_HEX,
3068                     NULL,
3069                     0x1F,
3070                     NULL,
3071                     HFILL
3072                 }
3073             },
3074             {
3075                 &hf_wimaxasncp_session_msg,
3076                 {
3077                     "Message Type",
3078                     "wimaxasncp.session_msg",
3079                     FT_UINT8,
3080                     BASE_HEX,
3081                     NULL,
3082                     0x1F,
3083                     NULL,
3084                     HFILL
3085                 }
3086             },
3087             {
3088                 &hf_wimaxasncp_length,
3089                 {
3090                     "Length",
3091                     "wimaxasncp.length",
3092                     FT_UINT16,
3093                     BASE_DEC,
3094                     NULL,
3095                     0x0,
3096                     NULL,
3097                     HFILL
3098                 }
3099             },
3100             {
3101                 &hf_wimaxasncp_msid,
3102                 {
3103                     "MSID",
3104                     "wimaxasncp.msid",
3105                     FT_ETHER,
3106                     BASE_NONE,
3107                     NULL,
3108                     0x0,
3109                     NULL,
3110                     HFILL
3111                 }
3112             },
3113             {
3114                 &hf_wimaxasncp_reserved1,
3115                 {
3116                     "Reserved",
3117                     "wimaxasncp.reserved1",
3118                     FT_UINT32,
3119                     BASE_HEX,
3120                     NULL,
3121                     0x0,
3122                     NULL,
3123                     HFILL
3124                 }
3125             },
3126             {
3127                 &hf_wimaxasncp_transaction_id,
3128                 {
3129                     "Transaction ID",
3130                     "wimaxasncp.transaction_id",
3131                     FT_UINT16,
3132                     BASE_HEX,
3133                     NULL,
3134                     0x0,
3135                     NULL,
3136                     HFILL
3137                 }
3138             },
3139             {
3140                 &hf_wimaxasncp_reserved2,
3141                 {
3142                     "Reserved",
3143                     "wimaxasncp.reserved2",
3144                     FT_UINT16,
3145                     BASE_HEX,
3146                     NULL,
3147                     0x0,
3148                     NULL,
3149                     HFILL
3150                 }
3151             },
3152             {
3153                 &hf_wimaxasncp_tlv,
3154                 {
3155                     "TLV",
3156                     "wimaxasncp.tlv",
3157                     FT_BYTES,
3158                     BASE_NONE,
3159                     NULL,
3160                     0x0,
3161                     NULL,
3162                     HFILL
3163                 }
3164             },
3165             {
3166                 &hf_wimaxasncp_tlv_type,
3167                 {
3168                     "Type",
3169                     "wimaxasncp.tlv.type",
3170                     FT_UINT16,
3171                     BASE_DEC,
3172                     NULL,
3173                     0x0,
3174                     NULL,
3175                     HFILL
3176                 }
3177             },
3178             {
3179                 &hf_wimaxasncp_tlv_length,
3180                 {
3181                     "Length",
3182                     "wimaxasncp.tlv.length",
3183                     FT_UINT16,
3184                     BASE_DEC,
3185                     NULL,
3186                     0x0,
3187                     NULL,
3188                     HFILL
3189                 }
3190             },
3191             {
3192                 &hf_wimaxasncp_tlv_value_bytes,
3193                 {
3194                     "Value",
3195                     "wimaxasncp.tlv_value_bytes",
3196                     FT_BYTES,
3197                     BASE_NONE,
3198                     NULL,
3199                     0x0,
3200                     NULL,
3201                     HFILL
3202                 }
3203             },
3204             {
3205                 &hf_wimaxasncp_tlv_value_bitflags8,
3206                 {
3207                     "Value",
3208                     "wimaxasncp.tlv_value_bitflags8",
3209                     FT_UINT8,
3210                     BASE_HEX,
3211                     NULL,
3212                     0xff,
3213                     NULL,
3214                     HFILL
3215                 }
3216             },
3217             {
3218                 &hf_wimaxasncp_tlv_value_bitflags16,
3219                 {
3220                     "Value",
3221                     "wimaxasncp.tlv_value_bitflags16",
3222                     FT_UINT16,
3223                     BASE_HEX,
3224                     NULL,
3225                     0xffff,
3226                     NULL,
3227                     HFILL
3228                 }
3229             },
3230             {
3231                 &hf_wimaxasncp_tlv_value_bitflags32,
3232                 {
3233                     "Value",
3234                     "wimaxasncp.tlv_value_bitflags32",
3235                     FT_UINT32,
3236                     BASE_HEX,
3237                     NULL,
3238                     0xffffffff,
3239                     NULL,
3240                     HFILL
3241                 }
3242             },
3243             {
3244                 &hf_wimaxasncp_tlv_value_protocol,
3245                 {
3246                     "Value",
3247                     "wimaxasncp.tlv_value_protocol",
3248                     FT_UINT16,
3249                     BASE_DEC,
3250                     NULL,
3251                     0x0,
3252                     NULL,
3253                     HFILL
3254                 }
3255             },
3256             {
3257                 &hf_wimaxasncp_tlv_value_vendor_id,
3258                 {
3259                     "Vendor ID",
3260                     "wimaxasncp.tlv_value_vendor_id",
3261                     FT_UINT24,
3262                     BASE_DEC,
3263                     NULL,
3264                     0x0,
3265                     NULL,
3266                     HFILL
3267                 }
3268             }
3269         };
3270
3271     /* ------------------------------------------------------------------------
3272      * Protocol subtree array
3273      * ------------------------------------------------------------------------
3274      */
3275
3276     static gint *ett_base[] = {
3277             &ett_wimaxasncp,
3278             &ett_wimaxasncp_flags,
3279             &ett_wimaxasncp_tlv,
3280             &ett_wimaxasncp_tlv_value_bitflags8,
3281             &ett_wimaxasncp_tlv_value_bitflags16,
3282             &ett_wimaxasncp_tlv_value_bitflags32,
3283             &ett_wimaxasncp_tlv_protocol_list,
3284             &ett_wimaxasncp_tlv_port_range_list,
3285             &ett_wimaxasncp_tlv_ip_address_mask_list,
3286             &ett_wimaxasncp_tlv_ip_address_mask,
3287             &ett_wimaxasncp_tlv_eap,
3288             &ett_wimaxasncp_tlv_vendor_specific_information_field
3289     };
3290
3291     /* ------------------------------------------------------------------------
3292      * load the XML dictionary
3293      * ------------------------------------------------------------------------
3294      */
3295
3296     debug_parser = getenv("WIRESHARK_DEBUG_WIMAXASNCP_DICT_PARSER") != NULL;
3297     dump_dict    = getenv("WIRESHARK_DUMP_WIMAXASNCP_DICT") != NULL;
3298
3299     dir = ep_strdup_printf(
3300         "%s" G_DIR_SEPARATOR_S "wimaxasncp",
3301         get_datafile_dir());
3302
3303     wimaxasncp_dict =
3304         wimaxasncp_dict_scan(dir, "dictionary.xml", debug_parser, &dict_error);
3305
3306     if (dict_error)
3307     {
3308         report_failure("wimaxasncp - %s", dict_error);
3309         g_free(dict_error);
3310     }
3311
3312     if (wimaxasncp_dict && dump_dict)
3313     {
3314         wimaxasncp_dict_print(stdout, wimaxasncp_dict);
3315     }
3316
3317     /* ------------------------------------------------------------------------
3318      * build the hf and ett dictionary entries
3319      * ------------------------------------------------------------------------
3320      */
3321
3322     wimaxasncp_build_dict.hf =
3323         g_array_new(FALSE, TRUE, sizeof(hf_register_info));
3324
3325     g_array_append_vals(
3326         wimaxasncp_build_dict.hf, hf_base, array_length(hf_base));
3327
3328     wimaxasncp_build_dict.ett =
3329         g_array_new(FALSE, TRUE, sizeof(gint*));
3330
3331     g_array_append_vals(
3332         wimaxasncp_build_dict.ett, ett_base, array_length(ett_base));
3333
3334     if (wimaxasncp_dict)
3335     {
3336         wimaxasncp_dict_tlv_t *tlv;
3337
3338         /* For each TLV found in XML file */
3339         for (tlv = wimaxasncp_dict->tlvs; tlv; tlv = tlv->next)
3340         {
3341             if (tlv->enums)
3342             {
3343                 /* Create array for enums */
3344                 wimaxasncp_dict_enum_t *e;
3345                 GArray* array = g_array_new(TRUE, TRUE, sizeof(value_string));
3346
3347                 /* Copy each entry into value_string array */
3348                 for (e = tlv->enums; e; e = e->next)
3349                 {
3350                     value_string item = { e->code, e->name };
3351                     g_array_append_val(array, item);
3352                 }
3353
3354                 /* Set enums to use with this TLV */
3355                 tlv->enum_vs = (value_string*)(void*)array->data;
3356             }
3357
3358             add_tlv_reg_info(tlv);
3359         }
3360     }
3361
3362     /* add an entry for unknown TLVs */
3363     add_tlv_reg_info(&wimaxasncp_tlv_not_found);
3364
3365     /* The following debug will only be printed if the debug_enabled variable
3366      * is set programmatically.  Setting the value via preferences will not
3367      * work as it will be set too late to affect this code path.
3368      */
3369     if (debug_enabled)
3370     {
3371         if (wimaxasncp_dict)
3372         {
3373             wimaxasncp_dict_tlv_t *tlv;
3374
3375             for (tlv = wimaxasncp_dict->tlvs; tlv; tlv = tlv->next)
3376             {
3377                 printf(
3378                     "%s\n"
3379                     "  type                   = %d\n"
3380                     "  description            = %s\n"
3381                     "  decoder                = %s\n"
3382                     "  hf_root                = %d\n"
3383                     "  hf_value               = %d\n"
3384                     "  hf_ipv4                = %d\n"
3385                     "  hf_ipv6                = %d\n"
3386                     "  hf_bsid                = %d\n"
3387                     "  hf_protocol            = %d\n"
3388                     "  hf_port_low            = %d\n"
3389                     "  hf_port_high           = %d\n"
3390                     "  hf_ipv4_mask           = %d\n"
3391                     "  hf_ipv6_mask           = %d\n"
3392                     "  hf_vendor_id           = %d\n"
3393                     "  hf_vendor_rest_of_info = %d\n",
3394                     tlv->name,
3395                     tlv->type,
3396                     tlv->description,
3397                     val_to_str(
3398                         tlv->decoder, wimaxasncp_decode_type_vals, "Unknown"),
3399                     tlv->hf_root,
3400                     tlv->hf_value,
3401                     tlv->hf_ipv4,
3402                     tlv->hf_ipv6,
3403                     tlv->hf_bsid,
3404                     tlv->hf_protocol,
3405                     tlv->hf_port_low,
3406                     tlv->hf_port_high,
3407                     tlv->hf_ipv4_mask,
3408                     tlv->hf_ipv6_mask,
3409                     tlv->hf_vendor_id,
3410                     tlv->hf_vendor_rest_of_info);
3411             }
3412         }
3413     }
3414
3415         /* Required function calls to register the header fields and subtrees
3416          * used */
3417     proto_register_field_array(
3418         proto_wimaxasncp,
3419         (hf_register_info*)(void *)wimaxasncp_build_dict.hf->data,
3420         wimaxasncp_build_dict.hf->len);
3421
3422     proto_register_subtree_array(
3423         (gint**)(void *)wimaxasncp_build_dict.ett->data,
3424         wimaxasncp_build_dict.ett->len);
3425 }
3426
3427
3428
3429
3430 /* ========================================================================= */
3431 /* Register the protocol with Wireshark */
3432
3433 /* this format is require because a script is used to build the C function
3434    that calls all the protocol registration.
3435 */
3436
3437 void
3438 proto_register_wimaxasncp(void)
3439 {
3440     module_t *wimaxasncp_module;
3441
3442     /* ------------------------------------------------------------------------
3443      * complete registration
3444      * ------------------------------------------------------------------------
3445      */
3446
3447         /* Register the protocol name and description */
3448     proto_wimaxasncp = proto_register_protocol(
3449             "WiMAX ASN Control Plane Protocol",
3450             "WiMAX ASN CP",
3451             "wimaxasncp");
3452
3453
3454         /* Register this dissector by name */
3455     new_register_dissector("wimaxasncp", dissect_wimaxasncp, proto_wimaxasncp);
3456
3457         /* Register preferences module (See Section 2.6 for more on
3458          * preferences) */
3459     wimaxasncp_module = prefs_register_protocol(
3460             proto_wimaxasncp,
3461             proto_reg_handoff_wimaxasncp);
3462
3463         /* Register preferences */
3464     prefs_register_bool_preference(
3465             wimaxasncp_module,
3466             "show_transaction_id_d_bit",
3467             "Show transaction ID direction bit",
3468             "Show transaction ID direction bit separately from the rest of "
3469             "the transaction ID field.",
3470             &show_transaction_id_d_bit);
3471
3472     prefs_register_bool_preference(
3473             wimaxasncp_module,
3474             "debug_enabled",
3475             "Enable debug output",
3476             "Print debug output to the console.",
3477             &debug_enabled);
3478
3479     prefs_register_uint_preference(
3480         wimaxasncp_module,
3481         "udp.wimax_port",
3482         "UDP Port for WiMAX ASN Control Plane Protocol",
3483         "Set UDP port for WiMAX ASN Control Plane Protocol",
3484         10, &global_wimaxasncp_udp_port);
3485
3486     prefs_register_enum_preference(
3487         wimaxasncp_module,
3488         "nwg_version",
3489         "NWG Version",
3490         "Version of the NWG that the R6 protocol complies with",
3491         &global_wimaxasncp_nwg_ver,
3492         wimaxasncp_nwg_versions,
3493         FALSE);
3494
3495     proto_register_prefix("wimaxasncp", register_wimaxasncp_fields);
3496 }
3497
3498 /* ========================================================================= */
3499 /* If this dissector uses sub-dissector registration add a registration
3500    routine.  This exact format is required because a script is used to find
3501    these routines and create the code that calls these routines.
3502
3503    This function is also called by preferences whenever "Apply" is pressed
3504    (see prefs_register_protocol above) so it should accommodate being called
3505    more than once.
3506 */
3507 void
3508 proto_reg_handoff_wimaxasncp(void)
3509 {
3510     static gboolean inited = FALSE;
3511     static dissector_handle_t wimaxasncp_handle;
3512     static int currentPort = -1;
3513
3514     if (!inited)
3515     {
3516
3517         /*  Use new_create_dissector_handle() to indicate that
3518          *  dissect_wimaxasncp() returns the number of bytes it dissected (or
3519          *  0 if it thinks the packet does not belong to WiMAX ASN Control
3520          *  Plane).
3521          */
3522         wimaxasncp_handle = new_create_dissector_handle(
3523              dissect_wimaxasncp,
3524              proto_wimaxasncp);
3525
3526
3527         inited = TRUE;
3528     }
3529
3530     if (currentPort != -1)
3531     {
3532         /* Remove any previous registered port */
3533         dissector_delete_uint("udp.port", currentPort, wimaxasncp_handle);
3534     }
3535
3536     /* Add the new one from preferences */
3537     currentPort = global_wimaxasncp_udp_port;
3538     dissector_add_uint("udp.port", currentPort, wimaxasncp_handle);
3539
3540     /* Find the EAP dissector */
3541     eap_handle = find_dissector("eap");
3542 }
3543