1 /* packet-m2m.c
2  * Routines for WiMax MAC to MAC TLV packet disassembly
3  *
4  * Copyright (c) 2007 by Intel Corporation.
5  *
6  * Author: Lu Pan <lu.pan@intel.com>
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1999 Gerald Combs
11  *
12  * SPDX-License-Identifier: GPL-2.0-or-later
13  */
14 
15 /* Include files */
16 
17 #include "config.h"
18 
19 #include <epan/packet.h>
20 #include <epan/reassemble.h>
21 #include <epan/etypes.h>
22 #include <epan/expert.h>
23 #include "wimax_tlv.h"
24 
25 /* forward reference */
26 void proto_reg_handoff_m2m(void);
27 void proto_register_m2m(void);
28 static void fch_burst_decoder(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, packet_info *pinfo);
29 static void cdma_code_decoder(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, packet_info *pinfo);
30 static void pdu_burst_decoder(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, packet_info *pinfo, gint burst_number, gint frag_type, gint frag_number);
31 static void fast_feedback_burst_decoder(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, packet_info *pinfo);
32 static void harq_ack_bursts_decoder(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, packet_info *pinfo);
33 static void physical_attributes_decoder(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, packet_info *pinfo);
34 static void extended_tlv_decoder(packet_info *pinfo);
35 void proto_tree_add_tlv(tlv_info_t *self, tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, gint hf, guint encoding);
36 
37 /* Global variables */
38 static dissector_handle_t wimax_cdma_code_burst_handle;
39 static dissector_handle_t wimax_ffb_burst_handle;
40 static dissector_handle_t wimax_fch_burst_handle;
41 static dissector_handle_t wimax_hack_burst_handle;
42 static dissector_handle_t wimax_pdu_burst_handle;
43 static dissector_handle_t wimax_phy_attributes_burst_handle;
44 
45 static reassembly_table pdu_reassembly_table;
46 
47 static gint proto_m2m    = -1;
48 
49 static gint ett_m2m      = -1;
50 static gint ett_m2m_tlv  = -1;
51 static gint ett_m2m_fch  = -1;
52 static gint ett_m2m_cdma = -1;
53 static gint ett_m2m_ffb  = -1;
54 
55 /* TLV types (rev:0.2) */
56 #define TLV_PROTO_VER		 1
57 #define TLV_FRAME_NUM		 2
58 #define TLV_BURST_NUM		 3
59 #define TLV_FRAG_TYPE		 4
60 #define TLV_FRAG_NUM		 5
61 #define TLV_CDMA_CODE		 7
62 #define TLV_FCH_BURST		 8
63 #define TLV_PDU_BURST		 9
64 #define TLV_FAST_FB		10
65 #define TLV_CRC16_STATUS	11
66 #define TLV_BURST_POWER		12
67 #define TLV_BURST_CINR		13
68 #define TLV_PREAMBLE		14
69 #define TLV_HARQ_ACK_BURST	15
70 #define TLV_PHY_ATTRIBUTES	16
71 #define TLV_EXTENDED_TLV	255
72 
73 /* TLV names */
74 static const value_string tlv_name[] =
75 {
76 	{ TLV_PROTO_VER,      "Protocol Version" },
77 	{ TLV_FRAME_NUM,      "Frame Number" },
78 	{ TLV_BURST_NUM,      "Burst Number" },
79 	{ TLV_FRAG_TYPE,      "Fragment Type" },
80 	{ TLV_FRAG_NUM,	      "Fragment Number" },
81 	{ TLV_CDMA_CODE,      "CDMA Attribute" },
82 	{ TLV_FCH_BURST,      "FCH Burst" },
83 	{ TLV_PDU_BURST,      "PDU Burst" },
84 	{ TLV_FAST_FB,	      "Fast Feedback Burst" },
85 	{ TLV_CRC16_STATUS,   "CRC16 Status" },
86 	{ TLV_BURST_POWER,    " Burst Power" },
87 	{ TLV_BURST_CINR,     "Burst CINR" },
88 	{ TLV_PREAMBLE,	      "Preamble" },
89 	{ TLV_HARQ_ACK_BURST, "HARQ ACK Bursts" },
90 	{ TLV_PHY_ATTRIBUTES, "PDU Burst Physical Attributes" },
91 	{ TLV_EXTENDED_TLV,   "Extended TLV" },
92 	{ 0, NULL }
93 };
94 
95 /* TLV Fragment types */
96 #define TLV_NO_FRAG     0
97 #define TLV_FIRST_FRAG  1
98 #define TLV_MIDDLE_FRAG 2
99 #define TLV_LAST_FRAG   3
100 
101 /* TLV Fragment Type names */
102 static const value_string tlv_frag_type_name[] =
103 {
104 	{ TLV_NO_FRAG,	   "No TLV Fragment" },
105 	{ TLV_FIRST_FRAG,  "First TLV Fragment" },
106 	{ TLV_MIDDLE_FRAG, "Middle TLV Fragment" },
107 	{ TLV_LAST_FRAG,   "Last TLV Fragment" },
108 	{ 0, NULL }
109 };
110 
111 /* TLV CRC16 Status */
112 static const value_string tlv_crc16_status[] =
113 {
114 	{ 0, "No CRC-16 in burst" },
115 	{ 1, "Good CRC-16 in burst" },
116 	{ 2, "Bad CRC-16 in burst" },
117 	{ 0, NULL }
118 };
119 
120 static gint hf_m2m_sequence_number = -1;
121 static gint hf_m2m_frame_number = -1;
122 static gint hf_m2m_tlv_count = -1;
123 
124 static gint hf_m2m_type = -1;
125 static gint hf_m2m_len = -1;
126 static gint hf_m2m_len_size = -1;
127 /* static gint hf_m2m_value_bytes = -1; */
128 static gint hf_wimax_invalid_tlv = -1;
129 static gint hf_m2m_value_protocol_vers_uint8 = -1;
130 static gint hf_m2m_value_burst_num_uint8 = -1;
131 static gint hf_m2m_value_frag_type_uint8 = -1;
132 static gint hf_m2m_value_frag_num_uint8 = -1;
133 static gint hf_m2m_value_pdu_burst = -1;
134 static gint hf_m2m_value_fast_fb = -1;
135 static gint hf_m2m_value_fch_burst_uint24 = -1;
136 static gint hf_m2m_value_cdma_code_uint24 = -1;
137 static gint hf_m2m_value_crc16_status_uint8 = -1;
138 static gint hf_m2m_value_burst_power_uint16 = -1;
139 static gint hf_m2m_value_burst_cinr_uint16 = -1;
140 static gint hf_m2m_value_preamble_uint16 = -1;
141 static gint hf_m2m_value_harq_ack_burst_bytes = -1;
142 static gint hf_m2m_phy_attributes = -1;
143 
144 static expert_field ei_m2m_unexpected_length = EI_INIT;
145 
146 
147 /* WiMax MAC to MAC protocol dissector */
dissect_m2m(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)148 static int dissect_m2m(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
149 {
150 	proto_item *ti = NULL;
151 	proto_item *m2m_item = NULL;
152 	proto_tree *m2m_tree = NULL;
153 	proto_tree *tlv_tree = NULL;
154 	gint burst_number = 0;
155 	gint length, offset = 0;
156 	gint tlv_count;
157 	gint tlv_type, tlv_len, tlv_offset, tlv_value;
158 	gint tlv_frag_type = 0;
159 	gint tlv_frag_number = 0;
160 	tlv_info_t m2m_tlv_info;
161 	gint hf;
162 	guint encoding;
163 	guint frame_number;
164 	int expected_len;
165 
166 	/* display the M2M protocol name */
167 	col_set_str(pinfo->cinfo, COL_PROTOCOL, "WiMax");
168 
169 	/* Clear out stuff in the info column */
170 	col_clear(pinfo->cinfo, COL_INFO);
171 
172 
173 	{	/* we are being asked for details */
174 		m2m_item = proto_tree_add_item(tree, proto_m2m, tvb, 0, -1, ENC_NA);
175 		m2m_tree = proto_item_add_subtree(m2m_item, ett_m2m);
176 		/* get the tvb reported length */
177 		length =  tvb_reported_length(tvb);
178 		/* add the size info */
179 		/*
180 		proto_item_append_text(m2m_item, " (%u bytes) - Packet Sequence Number,Number of TLVs", length);
181 		*/
182 		proto_item_append_text(m2m_item, " (%u bytes)", length);
183 		/* display the sequence number */
184 		proto_tree_add_item(m2m_tree, hf_m2m_sequence_number, tvb, offset, 2, ENC_BIG_ENDIAN);
185 		offset += 2;
186 		/* display the TLV count */
187 		proto_tree_add_item(m2m_tree, hf_m2m_tlv_count, tvb, offset, 2, ENC_BIG_ENDIAN);
188 		tlv_count = tvb_get_ntohs(tvb, offset);
189 		offset += 2;
190 		/* parses the TLVs within current packet */
191 		while ( tlv_count > 0)
192 		{	/* init MAC to MAC TLV information */
193 			init_tlv_info(&m2m_tlv_info, tvb, offset);
194 			/* get the TLV type */
195 			tlv_type = get_tlv_type(&m2m_tlv_info);
196 			/* get the TLV length */
197 			tlv_len = get_tlv_length(&m2m_tlv_info);
198 			if(tlv_type == -1 || tlv_len > 64000 || tlv_len < 1)
199 			{	/* invalid tlv info */
200 				col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", "M2M TLV error");
201 				/* display the invalid TLV in HEX */
202 				proto_tree_add_item(m2m_tree, hf_wimax_invalid_tlv, tvb, offset, (length - offset), ENC_NA);
203 				break;
204 			}
205 			/* get the TLV value offset */
206 			tlv_offset = get_tlv_value_offset(&m2m_tlv_info);
207 			/* display TLV type */
208 			ti = proto_tree_add_protocol_format(m2m_tree, proto_m2m, tvb, offset, (tlv_len + tlv_offset), "%s", val_to_str(tlv_type, tlv_name, "Unknown TLV"));
209 			/* add TLV subtree */
210 			tlv_tree = proto_item_add_subtree(ti, ett_m2m_tlv);
211 			/* update the offset */
212 			offset += tlv_offset;
213 			/* add the size info */
214 			/* decode TLV content (TLV value) */
215 			expected_len = 0;
216 			hf = 0;
217 			encoding = ENC_NA;
218 			switch (tlv_type)
219 			{
220 				case TLV_PROTO_VER:
221 					/* get the protocol version */
222 					tlv_value = tvb_get_guint8( tvb, offset );
223 					/* add the description */
224 					proto_item_append_text(ti, ": %d", tlv_value);
225 					hf = hf_m2m_value_protocol_vers_uint8;
226 					encoding = ENC_BIG_ENDIAN;
227 					expected_len = 1;
228 				break;
229 
230 				case TLV_BURST_NUM:
231 					/* get the burst number */
232 					burst_number = tvb_get_guint8( tvb, offset );
233 					/* add the description */
234 					proto_item_append_text(ti, ": %d", burst_number);
235 					hf = hf_m2m_value_burst_num_uint8;
236 					encoding = ENC_BIG_ENDIAN;
237 					expected_len = 1;
238 				break;
239 
240 				case TLV_FRAG_TYPE:
241 					/* add the description */
242 					tlv_frag_type = tvb_get_guint8( tvb, offset );
243 					proto_item_append_text(ti, ": %s", val_to_str(tlv_frag_type, tlv_frag_type_name, "Unknown"));
244 					hf = hf_m2m_value_frag_type_uint8;
245 					encoding = ENC_BIG_ENDIAN;
246 					expected_len = 1;
247 				break;
248 
249 				case TLV_FRAG_NUM:
250 					/* get the fragment number */
251 					tlv_frag_number = tvb_get_guint8( tvb, offset );
252 					/* add the description */
253 					proto_item_append_text(ti, ": %d", tlv_frag_number);
254 					hf = hf_m2m_value_frag_num_uint8;
255 					encoding = ENC_BIG_ENDIAN;
256 					expected_len = 1;
257 				break;
258 
259 				case TLV_PDU_BURST:
260 					/* display PDU Burst length info */
261 					proto_item_append_text(ti, " (%u bytes)", tlv_len);
262 					/* decode and display the PDU Burst */
263 					pdu_burst_decoder(tree, tvb, offset, tlv_len, pinfo, burst_number, tlv_frag_type, tlv_frag_number);
264 					hf = hf_m2m_value_pdu_burst;
265 					encoding = ENC_NA;
266 				break;
267 
268 				case TLV_FAST_FB:
269 					/* display the Fast Feedback Burst length info */
270 					proto_item_append_text(ti, " (%u bytes)", tlv_len);
271 					/* decode and display the Fast Feedback Burst */
272 					fast_feedback_burst_decoder(tree, tvb, offset, tlv_len, pinfo);
273 					hf = hf_m2m_value_fast_fb;
274 					encoding = ENC_NA;
275 				break;
276 
277 				case TLV_FRAME_NUM:
278 					/* get the frame number */
279 					frame_number = tvb_get_ntoh24( tvb, offset );
280 					/* add the description */
281 					proto_tree_add_item(tlv_tree, hf_m2m_frame_number, tvb, offset, 3, ENC_BIG_ENDIAN);
282 					proto_item_append_text(ti, ": %d", frame_number);
283 				break;
284 
285 				case TLV_FCH_BURST:
286 					/* add the description */
287 					tlv_value = tvb_get_ntoh24( tvb, offset );
288 					proto_item_append_text(ti, ": 0x%X", tlv_value);
289 					/* decode and display the TLV FCH burst */
290 					fch_burst_decoder(tree, tvb, offset, tlv_len, pinfo);
291 					hf = hf_m2m_value_fch_burst_uint24;
292 					encoding = ENC_BIG_ENDIAN;
293 					expected_len = 3;
294 				break;
295 
296 				case TLV_CDMA_CODE:
297 					/* add the description */
298 					tlv_value = tvb_get_ntoh24( tvb, offset );
299 					proto_item_append_text(ti, ": 0x%X", tlv_value);
300 					/* decode and display the CDMA Code */
301 					cdma_code_decoder(tree, tvb, offset, tlv_len, pinfo);
302 					hf = hf_m2m_value_cdma_code_uint24;
303 					encoding = ENC_BIG_ENDIAN;
304 					expected_len = 3;
305 				break;
306 
307 				case TLV_CRC16_STATUS:
308 					/* add the description */
309 					tlv_value = tvb_get_guint8( tvb, offset );
310 					proto_item_append_text(ti, ": %s", val_to_str(tlv_value, tlv_crc16_status, "Unknown"));
311 					hf = hf_m2m_value_crc16_status_uint8;
312 					encoding = ENC_BIG_ENDIAN;
313 					expected_len = 1;
314 				break;
315 
316 				case TLV_BURST_POWER:
317 					/* add the description */
318 					tlv_value = tvb_get_ntohs( tvb, offset );
319 					proto_item_append_text(ti, ": %d", tlv_value);
320 					hf = hf_m2m_value_burst_power_uint16;
321 					encoding = ENC_BIG_ENDIAN;
322 					expected_len = 2;
323 				break;
324 
325 				case TLV_BURST_CINR:
326 					/* add the description */
327 					tlv_value = tvb_get_ntohs( tvb, offset );
328 					proto_item_append_text(ti, ": 0x%X", tlv_value);
329 					hf = hf_m2m_value_burst_cinr_uint16;
330 					encoding = ENC_BIG_ENDIAN;
331 					expected_len = 2;
332 				break;
333 
334 				case TLV_PREAMBLE:
335 					/* add the description */
336 					tlv_value = tvb_get_ntohs( tvb, offset );
337 					proto_item_append_text(ti, ": 0x%X", tlv_value);
338 					hf = hf_m2m_value_preamble_uint16;
339 					encoding = ENC_BIG_ENDIAN;
340 					expected_len = 2;
341 				break;
342 
343 				case TLV_HARQ_ACK_BURST:
344 					/* display the Burst length info */
345 					proto_item_append_text(ti, " (%u bytes)", tlv_len);
346 					/* decode and display the HARQ ACK Bursts */
347 					harq_ack_bursts_decoder(tree, tvb, offset, tlv_len, pinfo);
348 					hf = hf_m2m_value_harq_ack_burst_bytes;
349 					encoding = ENC_NA;
350 				break;
351 
352 				case TLV_PHY_ATTRIBUTES:
353 					/* display the Burst length info */
354 					proto_item_append_text(ti, " (%u bytes)", tlv_len);
355 					/* decode and display the PDU Burst Physical Attributes */
356 					physical_attributes_decoder(tree, tvb, offset, tlv_len, pinfo);
357 					hf = hf_m2m_phy_attributes;
358 					encoding = ENC_NA;
359 				break;
360 
361 				case TLV_EXTENDED_TLV:
362 					/* display the Burst length info */
363 					proto_item_append_text(ti, " (%u bytes)", tlv_len);
364 					/* decode and display the Extended TLV */
365 					extended_tlv_decoder(pinfo);
366 				break;
367 
368 				default:
369 					/* update the info column */
370 					col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", "Unknown TLV Type");
371 				break;
372 			}
373 			/* expand the TLV detail */
374 			if (hf) {
375 				if (offset - tlv_offset == expected_len) {
376 					proto_tree_add_tlv(&m2m_tlv_info, tvb, offset - tlv_offset, pinfo, tlv_tree, hf, encoding);
377 				} else {
378 					expert_add_info_format(pinfo, NULL, &ei_m2m_unexpected_length, "Expected length %d, got %d.", expected_len, offset - tlv_offset);
379 				}
380 			}
381 			offset += tlv_len;
382 			/* update tlv_count */
383 			tlv_count--;
384 		}
385 	}
386 	return tvb_captured_length(tvb);
387 }
388 
389 /* Decode and display the FCH burst */
fch_burst_decoder(proto_tree * tree,tvbuff_t * tvb,gint offset,gint length,packet_info * pinfo)390 static void fch_burst_decoder(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, packet_info *pinfo)
391 {
392 	if(wimax_fch_burst_handle)
393 	{	/* call FCH dissector */
394 		call_dissector(wimax_fch_burst_handle, tvb_new_subset_length(tvb, offset, length), pinfo, tree);
395 	}
396 	else	/* display FCH info */
397 	{	/* update the info column */
398 		col_append_str(pinfo->cinfo, COL_INFO, "FCH Burst: DL Frame Prefix");
399 	}
400 }
401 
402 /* Decode and display the CDMA Code Attribute */
cdma_code_decoder(proto_tree * tree,tvbuff_t * tvb,gint offset,gint length,packet_info * pinfo)403 static void cdma_code_decoder(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, packet_info *pinfo)
404 {
405 	if(wimax_cdma_code_burst_handle)
406 	{	/* call CDMA dissector */
407 		call_dissector(wimax_cdma_code_burst_handle, tvb_new_subset_length(tvb, offset, length), pinfo, tree);
408 	}
409 	else	/* display CDMA Code Attribute info */
410 	{	/* update the info column */
411 		col_append_str(pinfo->cinfo, COL_INFO, "CDMA Code Attribute");
412 	}
413 }
414 
415 /* Decode and display the PDU Burst */
pdu_burst_decoder(proto_tree * tree,tvbuff_t * tvb,gint offset,gint length,packet_info * pinfo,gint burst_number,gint frag_type,gint frag_number)416 static void pdu_burst_decoder(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, packet_info *pinfo, gint burst_number, gint frag_type, gint frag_number)
417 {
418 	fragment_head *pdu_frag;
419 	tvbuff_t *pdu_tvb = NULL;
420 
421 	/* update the info column */
422 	switch (frag_type)
423 	{
424 		case TLV_FIRST_FRAG:
425 			col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "First TLV Fragment (%d)", frag_number);
426 		break;
427 		case TLV_LAST_FRAG:
428 			col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Last TLV Fragment (%d)", frag_number);
429 		break;
430 		case TLV_MIDDLE_FRAG:
431 			col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Middle TLV Fragment %d", frag_number);
432 		break;
433 	}
434 	if(frag_type == TLV_NO_FRAG)
435 	{	/* not fragmented PDU */
436 		pdu_tvb =  tvb_new_subset_length(tvb, offset, length);
437 	}
438 	else	/* fragmented PDU */
439 	{	/* add the fragment */
440 		pdu_frag = fragment_add_seq(&pdu_reassembly_table, tvb, offset, pinfo, burst_number, NULL, frag_number - 1, length, ((frag_type==TLV_LAST_FRAG)?0:1), 0);
441 		if(pdu_frag && frag_type == TLV_LAST_FRAG)
442 		{
443 			/* create the new tvb for defragmented frame */
444 			pdu_tvb = tvb_new_chain(tvb, pdu_frag->tvb_data);
445 			/* add the defragmented data to the data source list */
446 			add_new_data_source(pinfo, pdu_tvb, "Reassembled WiMax PDU Frame");
447 		}
448 		else
449 		{
450 			pdu_tvb = NULL;
451 			if(frag_type == TLV_LAST_FRAG)
452 			{	/* update the info column */
453 				col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", "Incomplete PDU frame");
454 			}
455 		}
456 	}
457 	/* process the defragmented PDU burst */
458 	if(pdu_tvb)
459 	{
460 		if(wimax_pdu_burst_handle)
461 		{/* decode and display PDU Burst */
462 			call_dissector(wimax_pdu_burst_handle, pdu_tvb, pinfo, tree);
463 		}
464 		else	/* display PDU Burst info */
465 		{	/* update the info column */
466 			col_append_str(pinfo->cinfo, COL_INFO, "PDU Burst");
467 		}
468 	}
469 }
470 
471 /* Decode and display the Fast Feedback Burst */
fast_feedback_burst_decoder(proto_tree * tree,tvbuff_t * tvb,gint offset,gint length,packet_info * pinfo)472 static void fast_feedback_burst_decoder(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, packet_info *pinfo)
473 {
474 	if(wimax_ffb_burst_handle)
475 	{	/* display the TLV Fast Feedback Burst dissector info */
476 		call_dissector(wimax_ffb_burst_handle, tvb_new_subset_length(tvb, offset, length), pinfo, tree);
477 	}
478 	else	/* display the Fast Feedback Burst info */
479 	{	/* update the info column */
480 		col_append_str(pinfo->cinfo, COL_INFO, "Fast Feedback Burst");
481 	}
482 }
483 
harq_ack_bursts_decoder(proto_tree * tree,tvbuff_t * tvb,gint offset,gint length,packet_info * pinfo)484 static void harq_ack_bursts_decoder(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, packet_info *pinfo)
485 {
486 	if(wimax_hack_burst_handle)
487 	{	/* call the TLV HARQ ACK Bursts dissector */
488 		call_dissector(wimax_hack_burst_handle, tvb_new_subset_length(tvb, offset, length), pinfo, tree);
489 	}
490 	else	/* display the TLV HARQ ACK Bursts info */
491 	{	/* update the info column */
492 		col_append_str(pinfo->cinfo, COL_INFO, "HARQ ACK Bursts");
493 	}
494 }
495 
physical_attributes_decoder(proto_tree * tree,tvbuff_t * tvb,gint offset,gint length,packet_info * pinfo)496 static void physical_attributes_decoder(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, packet_info *pinfo)
497 {
498 	if(wimax_phy_attributes_burst_handle)
499 	{	/* call the TLV PDU Burst Physical Attributes dissector */
500 		call_dissector(wimax_phy_attributes_burst_handle, tvb_new_subset_length(tvb, offset, length), pinfo, tree);
501 	}
502 	else	/* display the TLV PDU Burst Physical Attributes info */
503 	{	/* update the info column */
504 		col_append_str(pinfo->cinfo, COL_INFO, "PHY-attr");
505 	}
506 }
507 
extended_tlv_decoder(packet_info * pinfo)508 static void extended_tlv_decoder(packet_info *pinfo)
509 {
510 	/* display the Extended TLV info */
511 	/* update the info column */
512 	col_append_str(pinfo->cinfo, COL_INFO, "Extended TLV");
513 }
514 
515 /* Display the raw WiMax TLV */
proto_tree_add_tlv(tlv_info_t * self,tvbuff_t * tvb,guint offset,packet_info * pinfo,proto_tree * tree,gint hf,guint encoding)516 void proto_tree_add_tlv(tlv_info_t *self, tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, gint hf, guint encoding)
517 {
518 	guint tlv_offset;
519 	gint tlv_type, tlv_len;
520 
521 	/* make sure the TLV information is valid */
522 	if(!self->valid)
523 	{	/* invalid TLV info */
524 		col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Invalid TLV");
525 		return;
526 	}
527 	tlv_offset = offset;
528 	/* display TLV type */
529 	proto_tree_add_item(tree, hf_m2m_type, tvb, tlv_offset, 1, ENC_BIG_ENDIAN);
530 	tlv_offset++;
531 	/* check the TLV length type */
532 	if( self->length_type )
533 	{	/* multiple bytes TLV length */
534 		/* display the length of the TLV length with MSB */
535 		proto_tree_add_item(tree, hf_m2m_len_size, tvb, tlv_offset, 1, ENC_BIG_ENDIAN);
536 		tlv_offset++;
537 		if(self->size_of_length)
538 			/* display the multiple byte TLV length */
539 			proto_tree_add_item(tree, hf_m2m_len, tvb, tlv_offset, self->size_of_length, ENC_BIG_ENDIAN);
540 		else
541 			return;
542 	}
543 	else	/* display the single byte TLV length */
544 		proto_tree_add_item(tree, hf_m2m_len, tvb, tlv_offset, 1, ENC_BIG_ENDIAN);
545 
546 	tlv_type = get_tlv_type(self);
547 	/* Display Frame Number as special case for filter */
548 	if ( tlv_type == TLV_FRAME_NUM )
549 	{
550 		return;
551 	}
552 
553 	/* get the TLV length */
554 	tlv_len = get_tlv_length(self);
555 	proto_tree_add_item(tree, hf, tvb, (offset + self->value_offset), tlv_len, encoding);
556 }
557 
558 /* Register Wimax Mac to Mac Protocol */
proto_register_m2m(void)559 void proto_register_m2m(void)
560 {
561 	/* M2M TLV display */
562 	static hf_register_info hf[] =
563 	{
564 		{
565 			&hf_m2m_sequence_number,
566 			{
567 				"Packet Sequence Number", "m2m.seq_number",
568 				FT_UINT16, BASE_DEC, NULL, 0x0,
569 				NULL, HFILL
570 			}
571 		},
572 		{
573 			&hf_m2m_frame_number,
574 			{
575 				"Value", "m2m.frame_number",
576 				FT_UINT24, BASE_DEC, NULL, 0x0,
577 				NULL, HFILL
578 			}
579 		},
580 		{
581 			&hf_m2m_tlv_count,
582 			{
583 				"Number of TLVs in the packet", "m2m.tlv_count",
584 				FT_UINT16, BASE_DEC, NULL, 0x0,
585 				NULL, HFILL
586 			}
587 		}
588 	};
589 
590 	/* WiMax TLV display */
591 	static hf_register_info hf_tlv[] =
592 	{
593 		{
594 			&hf_m2m_type,
595 			{
596 				"Type", "m2m.tlv_type",
597 				FT_UINT8, BASE_DEC, NULL, 0x0,
598 				NULL, HFILL
599 			}
600 		},
601 		{
602 			&hf_m2m_len,
603 			{
604 				"Length", "m2m.tlv_len",
605 				FT_UINT8, BASE_DEC, NULL, 0x0,
606 				NULL, HFILL
607 			}
608 		},
609 		{
610 			&hf_m2m_len_size,
611 			{
612 				"Length Size", "m2m.tlv_len_size",
613 				FT_UINT8, BASE_HEX, NULL, 0x0,
614 				NULL, HFILL
615 			}
616 		},
617 #if 0
618 		{
619 			&hf_m2m_value_bytes,
620 			{
621 				"Value (hex)", "m2m.multibyte_tlv_value",
622 				FT_BYTES, BASE_NONE, NULL, 0x0,
623 				NULL, HFILL
624 			}
625 		},
626 #endif
627 		{
628 			&hf_m2m_value_protocol_vers_uint8,
629 			{
630 				"Value", "m2m.protocol_vers_tlv_value",
631 				FT_UINT8, BASE_DEC, NULL, 0x0,
632 				NULL, HFILL
633 			}
634 		},
635 		{
636 			&hf_m2m_value_burst_num_uint8,
637 			{
638 				"Value", "m2m.burst_num_tlv_value",
639 				FT_UINT8, BASE_DEC, NULL, 0x0,
640 				NULL, HFILL
641 			}
642 		},
643 		{
644 			&hf_m2m_value_frag_type_uint8,
645 			{
646 				"Value", "m2m.frag_type_tlv_value",
647 				FT_UINT8, BASE_DEC, NULL, 0x0,
648 				NULL, HFILL
649 			}
650 		},
651 		{
652 			&hf_m2m_value_frag_num_uint8,
653 			{
654 				"Value", "m2m.frag_num_tlv_value",
655 				FT_UINT8, BASE_DEC, NULL, 0x0,
656 				NULL, HFILL
657 			}
658 		},
659 		{
660 			&hf_m2m_value_pdu_burst,
661 			{
662 				"Value (hex)", "m2m.pdu_burst_tlv_value",
663 				FT_BYTES, BASE_NONE, NULL, 0x0,
664 				NULL, HFILL
665 			}
666 		},
667 		{
668 			&hf_m2m_value_fast_fb,
669 			{
670 				"Value (hex)", "m2m.fast_fb_tlv_value",
671 				FT_BYTES, BASE_NONE, NULL, 0x0,
672 				NULL, HFILL
673 			}
674 		},
675 		{
676 			&hf_m2m_value_fch_burst_uint24,
677 			{
678 				"Value", "m2m.fch_burst_tlv_value",
679 				FT_UINT24, BASE_DEC, NULL, 0x0,
680 				NULL, HFILL
681 			}
682 		},
683 		{
684 			&hf_m2m_value_cdma_code_uint24,
685 			{
686 				"Value", "m2m.cdma_code_tlv_value",
687 				FT_UINT24, BASE_DEC, NULL, 0x0,
688 				NULL, HFILL
689 			}
690 		},
691 		{
692 			&hf_m2m_value_crc16_status_uint8,
693 			{
694 				"Value", "m2m.crc16_status_tlv_value",
695 				FT_UINT8, BASE_DEC, NULL, 0x0,
696 				NULL, HFILL
697 			}
698 		},
699 		{
700 			&hf_m2m_value_burst_power_uint16,
701 			{
702 				"Value", "m2m.burst_power_tlv_value",
703 				FT_UINT16, BASE_DEC, NULL, 0x0,
704 				NULL, HFILL
705 			}
706 		},
707 		{
708 			&hf_m2m_value_burst_cinr_uint16,
709 			{
710 				"Value", "m2m.burst_cinr_tlv_value",
711 				FT_UINT16, BASE_DEC, NULL, 0x0,
712 				NULL, HFILL
713 			}
714 		},
715 		{
716 			&hf_m2m_value_preamble_uint16,
717 			{
718 				"Value", "m2m.preamble_tlv_value",
719 				FT_UINT16, BASE_DEC, NULL, 0x0,
720 				NULL, HFILL
721 			}
722 		},
723 		{
724 			&hf_m2m_value_harq_ack_burst_bytes,
725 			{
726 				"Value (hex)", "m2m.harq_ack_burst_tlv_value",
727 				FT_BYTES, BASE_NONE, NULL, 0x0,
728 				NULL, HFILL
729 			}
730 		},
731 		{
732 			&hf_m2m_phy_attributes,
733 			{
734 				"Value (hex)", "m2m.phy_attributes",
735 				FT_BYTES, BASE_NONE, NULL, 0x0,
736 				NULL, HFILL
737 			}
738 		},
739 		{
740 			&hf_wimax_invalid_tlv,
741 			{
742 				"Invalid TLV (hex)", "m2m.invalid_tlv",
743 				FT_BYTES, BASE_NONE, NULL, 0x0,
744 				NULL, HFILL
745 			}
746 		}
747 	};
748 
749 	static gint *ett[] =
750 		{
751 			&ett_m2m,
752 			&ett_m2m_tlv,
753 			&ett_m2m_fch,
754 			&ett_m2m_cdma,
755 			&ett_m2m_ffb,
756 		};
757 
758 	static ei_register_info ei[] = {
759 		{ &ei_m2m_unexpected_length, { "m2m.unexpected_length", PI_MALFORMED, PI_ERROR, "Unexpected length", EXPFILL }},
760 	};
761 
762 	expert_module_t* expert_m2m;
763 
764 	proto_m2m = proto_register_protocol (
765 		"WiMax Mac to Mac Packet", /* name       */
766 		"M2M  (m2m)",              /* short name */
767 		"m2m"                      /* abbrev     */
768 		);
769 
770 	proto_register_field_array(proto_m2m, hf, array_length(hf));
771 	proto_register_field_array(proto_m2m, hf_tlv, array_length(hf_tlv));
772 	proto_register_subtree_array(ett, array_length(ett));
773 	expert_m2m = expert_register_protocol(proto_m2m);
774 	expert_register_field_array(expert_m2m, ei, array_length(ei));
775 
776 	/* Register reassembly table */
777 	reassembly_table_register(&pdu_reassembly_table,
778 	    &addresses_reassembly_table_functions);
779 }
780 
781 /* Register Wimax Mac to Mac Protocol handler */
proto_reg_handoff_m2m(void)782 void proto_reg_handoff_m2m(void)
783 {
784 	dissector_handle_t m2m_handle;
785 
786 	m2m_handle = create_dissector_handle(dissect_m2m, proto_m2m);
787 	dissector_add_uint("ethertype", ETHERTYPE_WMX_M2M, m2m_handle);
788 
789 	/* find the wimax handlers */
790 	wimax_cdma_code_burst_handle      = find_dissector("wimax_cdma_code_burst_handler");
791 	wimax_fch_burst_handle            = find_dissector("wimax_fch_burst_handler");
792 	wimax_ffb_burst_handle            = find_dissector("wimax_ffb_burst_handler");
793 	wimax_hack_burst_handle           = find_dissector("wimax_hack_burst_handler");
794 	wimax_pdu_burst_handle            = find_dissector("wimax_pdu_burst_handler");
795 	wimax_phy_attributes_burst_handle = find_dissector("wimax_phy_attributes_burst_handler");
796 }
797 
798 /*
799  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
800  *
801  * Local variables:
802  * c-basic-offset: 8
803  * tab-width: 8
804  * indent-tabs-mode: t
805  * End:
806  *
807  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
808  * :indentSize=8:tabSize=8:noTabs=false:
809  */
810