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