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