nexmon – Blame information for rev 1

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