We always HAVE_CONFIG_H so don't bother checking whether we have it or not.
[metze/wireshark/wip.git] / plugins / wimax / msg_arq.c
1 /* msg_arq.c
2  * WiMax MAC Management ARQ Feedback, Discard, Reset Message decoders
3  *
4  * Copyright (c) 2007 by Intel Corporation.
5  *
6  * Author: John R. Underwood <junderx@yahoo.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 "moduleinfo.h"
34
35 #include <glib.h>
36 #include <epan/packet.h>
37 #include "crc.h"
38 #include "wimax_tlv.h"
39 #include "wimax_mac.h"
40
41 extern gint man_ofdma;
42
43 /* Forward reference */
44 void dissect_mac_mgmt_msg_arq_feedback_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
45 void dissect_mac_mgmt_msg_arq_discard_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
46 void dissect_mac_mgmt_msg_arq_reset_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
47
48 static gint proto_mac_mgmt_msg_arq_feedback_decoder = -1;
49 static gint proto_mac_mgmt_msg_arq_discard_decoder = -1;
50 static gint proto_mac_mgmt_msg_arq_reset_decoder = -1;
51
52 static gint ett_mac_mgmt_msg_arq_decoder = -1;
53
54 /* Setup protocol subtree array */
55 static gint *ett[] =
56 {
57         &ett_mac_mgmt_msg_arq_decoder,
58 };
59
60
61 /* ARQ fields */
62 static gint hf_arq_cid                  = -1;
63 static gint hf_arq_last                 = -1;
64 static gint hf_arq_ack_type             = -1;
65 static gint hf_ack_type_reserved        = -1;
66 static gint hf_arq_bsn                  = -1;
67 static gint hf_arq_num_ack_maps         = -1;
68 static gint hf_arq_selective_map        = -1;
69 static gint hf_arq_seq_format           = -1;
70 static gint hf_arq_0seq_ack_map         = -1;
71 static gint hf_arq_0seq1_len            = -1;
72 static gint hf_arq_0seq2_len            = -1;
73 static gint hf_arq_1seq_ack_map         = -1;
74 static gint hf_arq_1seq1_len            = -1;
75 static gint hf_arq_1seq2_len            = -1;
76 static gint hf_arq_1seq3_len            = -1;
77 static gint hf_arq_reserved             = -1;
78
79 static gint hf_arq_discard_cid          = -1;
80 static gint hf_arq_discard_reserved     = -1;
81 static gint hf_arq_discard_bsn          = -1;
82
83 static gint hf_arq_reset_cid            = -1;
84 static gint hf_arq_reset_type           = -1;
85 static gint hf_arq_reset_direction      = -1;
86 static gint hf_arq_reset_reserved       = -1;
87
88 static gint hf_arq_message_type = -1;
89
90 /* STRING RESOURCES */
91
92 static const true_false_string tfs_present = {
93         "present",
94         "absent"
95 };
96
97 static const true_false_string tfs_rng_req_aas_broadcast = {
98         "SS cannot receive broadcast messages",
99         "SS can receive broadcast messages"
100 };
101
102 static const true_false_string tfs_arq_last = {
103         "Last ARQ feedback IE in the list",
104         "More ARQ feedback IE in the list"
105 };
106
107 static const value_string vals_arq_ack_type[] = {
108         {0,                             "Selective ACK entry"},
109         {1,                             "Cumulative ACK entry"},
110         {2,                             "Cumulative with Selective ACK entry"},
111         {3,                             "Cumulative ACK with Block Sequence Ack entry"},
112         {0,                             NULL}
113 };
114
115 static const value_string vals_arq_reset_type[] = {
116         {0,                             "Original message from Initiator"},
117         {1,                             "Acknowledgment from Responder"},
118         {2,                             "Confirmation from Initiator"},
119         {3,                             "Reserved"},
120         {0,                             NULL}
121 };
122
123 static const value_string vals_arq_reset_direction[] = {
124         {0,                             "Uplink or downlink"},
125         {1,                             "Uplink"},
126         {2,                             "Downlink"},
127         {3,                             "Reserved"},
128         {0,                             NULL}
129 };
130
131 /* Register Wimax Mac Payload Protocol and Dissector */
132 void proto_register_mac_mgmt_msg_arq_feedback(void)
133 {
134         /* ARQ fields display */
135         static hf_register_info hf[] =
136         {
137                 /* TODO: Make three separate arq message types */
138                 {
139                         &hf_arq_message_type,
140                         {
141                                 "MAC Management Message Type", "wmx.macmgtmsgtype.arq",
142                                 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL
143                         }
144                 },
145                 {
146                         &hf_arq_ack_type,
147                         {
148                                 "ACK Type", "wmx.arq.ack_type",
149                                 FT_UINT8, BASE_DEC, VALS(vals_arq_ack_type), 0x60, NULL, HFILL
150                         }
151                 },
152                 {
153                         &hf_arq_bsn,
154                         {
155                                 "BSN", "wmx.arq.bsn",
156                                 FT_UINT16, BASE_DEC, NULL, 0x1FFC, NULL, HFILL
157                         }
158                 },
159                 {
160                         &hf_arq_cid,
161                         {
162                                 "Connection ID", "wmx.arq.cid",
163                                 FT_UINT16, BASE_DEC, NULL, 0x00, "The ID of the connection being referenced", HFILL
164                         }
165                 },
166                 {
167                         &hf_arq_discard_bsn,
168                         {
169                                 "BSN", "wmx.arq.discard_bsn",
170                                 FT_UINT16, BASE_DEC, NULL, 0x07FF, NULL, HFILL
171                         }
172                 },
173                 {
174                         &hf_arq_discard_cid,
175                         {
176                                 "Connection ID", "wmx.arq.discard_cid",
177                                 FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL
178                         }
179                 },
180                 {
181                         &hf_arq_discard_reserved,
182                         {
183                                 "Reserved", "wmx.arq.discard_reserved",
184                                 FT_UINT8, BASE_DEC, NULL, 0xF8, NULL, HFILL
185                         }
186                 },
187                 {
188                         &hf_arq_last,
189                         {
190                                 "LAST", "wmx.arq.last",
191                                 FT_BOOLEAN, 8, TFS(&tfs_arq_last), 0x80, NULL, HFILL
192                         }
193                 },
194                 {
195                         &hf_arq_num_ack_maps,
196                         {
197                                 "Number of ACK Maps", "wmx.arq.num_maps",
198                                 FT_UINT8, BASE_DEC, NULL, 0x03, NULL, HFILL
199                         }
200                 },
201                 {
202                         &hf_arq_reserved,
203                         {
204                                 "Reserved", "wmx.arq.reserved",
205                                 FT_UINT8, BASE_DEC, NULL, 0x01, NULL, HFILL
206                         }
207                 },
208                 {
209                         &hf_arq_reset_cid,
210                         {
211                                 "Connection ID", "wmx.arq.reset_cid",
212                                 FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL
213                         }
214                 },
215                 {
216                         &hf_arq_reset_direction,
217                         {
218                                 "Direction", "wmx.arq.reset_direction",
219                                 FT_UINT8, BASE_DEC, VALS(vals_arq_reset_direction), 0x30, NULL, HFILL
220                         }
221                 },
222                 {
223                         &hf_arq_reset_reserved,
224                         {
225                                 "Reserved", "wmx.arq.reset_reserved",
226                                 FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL
227                         }
228                 },
229                 {
230                         &hf_arq_reset_type,
231                         {
232                                 "Type", "wmx.arq.reset_type",
233                                 FT_UINT8, BASE_DEC, VALS(vals_arq_reset_type), 0xC0, NULL, HFILL
234                         }
235                 },
236                 {
237                         &hf_arq_selective_map,
238                         {
239                                 "Selective ACK Map", "wmx.arq.selective_map",
240                                 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL
241                         }
242                 },
243                 {
244                         &hf_arq_0seq_ack_map,
245                         {
246                                 "Sequence ACK Map", "wmx.arq.seq_ack_map",
247                                 FT_UINT8, BASE_HEX, NULL, 0x60, NULL, HFILL
248                         }
249                 },
250                 {
251                         &hf_arq_1seq_ack_map,
252                         {
253                                 "Sequence ACK Map", "wmx.arq.seq_ack_map",
254                                 FT_UINT8, BASE_HEX, NULL, 0x70, NULL, HFILL
255                         }
256                 },
257                 {
258                         &hf_arq_seq_format,
259                         {
260                                 "Sequence Format", "wmx.arq.seq_format",
261                                 FT_UINT8, BASE_DEC, NULL, 0x80, NULL, HFILL
262                         }
263                 },
264                 {
265                         &hf_arq_0seq1_len,
266                         {
267                                 "Sequence 1 Length", "wmx.arq.seq1_len",
268                                 FT_UINT16, BASE_DEC, NULL, 0x1F80, NULL, HFILL
269                         }
270                 },
271                 {
272                         &hf_arq_0seq2_len,
273                         {
274                                 "Sequence 2 Length", "wmx.arq.seq2_len",
275                                 FT_UINT16, BASE_DEC, NULL, 0x007E, NULL, HFILL
276                         }
277                 },
278                 {
279                         &hf_arq_1seq1_len,
280                         {
281                                 "Sequence 1 Length", "wmx.arq.seq1_len",
282                                 FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL
283                         }
284                 },
285                 {
286                         &hf_arq_1seq2_len,
287                         {
288                                 "Sequence 2 Length", "wmx.arq.seq2_len",
289                                 FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL
290                         }
291                 },
292                 {
293                         &hf_arq_1seq3_len,
294                         {
295                                 "Sequence 3 Length", "wmx.arq.seq3_len",
296                                 FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL
297                         }
298                 },
299                 {
300                         &hf_ack_type_reserved,
301                         {
302                                 "Reserved", "wmx.ack_type.reserved",
303                                 FT_UINT8, BASE_DEC, NULL, 0x03, NULL, HFILL
304                         }
305                 }
306         };
307
308         proto_mac_mgmt_msg_arq_feedback_decoder = proto_register_protocol (
309                 "WiMax ARQ Feedback/Discard/Reset Messages", /* name */
310                 "WiMax ARQ Feedback/Discard/Reset (arq)", /* short name */
311                 "wmx.arq" /* abbrev */
312                 );
313
314         proto_register_field_array(proto_mac_mgmt_msg_arq_feedback_decoder, hf, array_length(hf));
315         proto_register_subtree_array(ett, array_length(ett));
316 }
317
318 /* Register Wimax Mac Payload Protocol and Dissector */
319 void proto_register_mac_mgmt_msg_arq_discard(void)
320 {
321         proto_mac_mgmt_msg_arq_discard_decoder = proto_mac_mgmt_msg_arq_feedback_decoder;
322 }
323
324 /* Register Wimax Mac Payload Protocol and Dissector */
325 void proto_register_mac_mgmt_msg_arq_reset(void)
326 {
327         proto_mac_mgmt_msg_arq_reset_decoder = proto_mac_mgmt_msg_arq_feedback_decoder;
328 }
329
330 /* Decode ARQ-Feedback messages. */
331 void dissect_mac_mgmt_msg_arq_feedback_decoder(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
332 {
333         guint offset = 0;
334         guint arq_feedback_ie_count = 0;
335         guint arq_cid;
336         gboolean arq_last = FALSE;
337         guint arq_ack_type;
338         guint arq_bsn;
339         guint arq_num_ack_maps;
340         guint tvb_len, payload_type;
341         proto_item *arq_feedback_item = NULL;
342         proto_tree *arq_feedback_tree = NULL;
343         proto_item *arq_fb_item = NULL;
344         proto_tree *arq_fb_tree = NULL;
345         proto_item *ti = NULL;
346         guint i, seq_format;
347
348         /* Ensure the right payload type */
349         payload_type = tvb_get_guint8(tvb, offset);
350         if(payload_type != MAC_MGMT_MSG_ARQ_FEEDBACK)
351         {
352                 return;
353         }
354
355         if (tree)
356         {       /* we are being asked for details */
357
358                 /* Get the tvb reported length */
359                 tvb_len =  tvb_reported_length(tvb);
360                 /* display MAC payload type ARQ-Feedback */
361                 arq_feedback_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_arq_feedback_decoder, tvb, offset, tvb_len, "MAC Management Message, ARQ-Feedback (33)");
362                 /* add MAC ARQ Feedback subtree */
363                 arq_feedback_tree = proto_item_add_subtree(arq_feedback_item, ett_mac_mgmt_msg_arq_decoder);
364                 /* display the Message Type */
365                 proto_tree_add_item(arq_feedback_tree, hf_arq_message_type, tvb, offset, 1, ENC_BIG_ENDIAN);
366                 offset += 1;
367
368                 while(offset < tvb_len && !arq_last)
369                 {
370                         arq_feedback_ie_count++;
371                         arq_cid = tvb_get_ntohs(tvb, offset);
372                         arq_last = ((tvb_get_guint8(tvb, offset + 2) & 0x80) != 0);
373                         arq_ack_type = (tvb_get_guint8(tvb, offset + 2) & 0x60) >> 5;
374                         arq_bsn = (tvb_get_ntohs(tvb, offset + 2) & 0x1FFC) >> 2;
375                         arq_num_ack_maps = 1 + (tvb_get_guint8(tvb, offset + 3) & 0x03);
376
377                         arq_fb_item = proto_tree_add_protocol_format(arq_feedback_tree, proto_mac_mgmt_msg_arq_feedback_decoder, tvb, offset, tvb_len, "ARQ_Feedback_IE");
378                         proto_item_append_text(arq_fb_item, ", CID: %u, %s ARQ feedback IE, %s, BSN: %u",
379                                 arq_cid, arq_last ? "Last" : "More", val_to_str(arq_ack_type, vals_arq_ack_type, ""), arq_bsn);
380                         if (arq_ack_type != ARQ_CUMULATIVE_ACK_ENTRY) {
381                                 proto_item_append_text(arq_fb_item, ", %u ACK Map(s)", arq_num_ack_maps);
382                         }
383                         /* add ARQ Feedback IE subtree */
384                         arq_fb_tree = proto_item_add_subtree(arq_fb_item, ett_mac_mgmt_msg_arq_decoder);
385                         proto_tree_add_item(arq_fb_tree, hf_arq_cid, tvb, offset, 2, ENC_BIG_ENDIAN);
386                         proto_tree_add_item(arq_fb_tree, hf_arq_last, tvb, offset + 2, 1, ENC_BIG_ENDIAN);
387                         proto_tree_add_item(arq_fb_tree, hf_arq_ack_type, tvb, offset + 2, 1, ENC_BIG_ENDIAN);
388                         proto_tree_add_item(arq_fb_tree, hf_arq_bsn, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
389                         if (arq_ack_type != ARQ_CUMULATIVE_ACK_ENTRY) {
390                                 ti = proto_tree_add_item(arq_fb_tree, hf_arq_num_ack_maps, tvb, offset + 3, 1, ENC_BIG_ENDIAN);
391                                 proto_item_append_text(ti, " (%d map(s))", arq_num_ack_maps);
392                                 offset += 2;
393
394                                 for (i = 0; i < arq_num_ack_maps; i++) {
395                                         /* Each ACK Map is 16 bits. */
396                                         offset += 2;
397                                         if (arq_ack_type != 3) {
398                                                 proto_tree_add_item(arq_fb_tree, hf_arq_selective_map, tvb, offset, 2, ENC_BIG_ENDIAN);
399                                         } else {
400                                                 proto_tree_add_item(arq_fb_tree, hf_arq_seq_format, tvb, offset, 1, ENC_BIG_ENDIAN);
401                                                 seq_format = (tvb_get_guint8(tvb, offset) & 0x80) >> 7;
402                                                 if (seq_format == 0) {
403                                                         proto_tree_add_item(arq_fb_tree, hf_arq_0seq_ack_map, tvb, offset, 1, ENC_BIG_ENDIAN);
404                                                         proto_tree_add_item(arq_fb_tree, hf_arq_0seq1_len, tvb, offset, 2, ENC_BIG_ENDIAN);
405                                                         proto_tree_add_item(arq_fb_tree, hf_arq_0seq2_len, tvb, offset, 2, ENC_BIG_ENDIAN);
406                                                         proto_tree_add_item(arq_fb_tree, hf_arq_reserved, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
407                                                 } else {
408                                                         proto_tree_add_item(arq_fb_tree, hf_arq_1seq_ack_map, tvb, offset, 1, ENC_BIG_ENDIAN);
409                                                         proto_tree_add_item(arq_fb_tree, hf_arq_1seq1_len, tvb, offset, 1, ENC_BIG_ENDIAN);
410                                                         proto_tree_add_item(arq_fb_tree, hf_arq_1seq2_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
411                                                         proto_tree_add_item(arq_fb_tree, hf_arq_1seq3_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
412                                                 }
413                                         }
414                                 }
415                         } else {
416                                 /* Number of ACK Maps bits are reserved when ACK TYPE == 1 */
417                                 proto_tree_add_item(arq_fb_tree, hf_ack_type_reserved, tvb, offset + 3, 1, ENC_BIG_ENDIAN);
418                                 /* update the offset */
419                                 offset += 2;
420                         }
421                         /* update the offset */
422                         offset += 2;
423                 }
424                 proto_item_append_text(arq_feedback_item, ", %u ARQ_feedback_IE(s)", arq_feedback_ie_count);
425         }
426 }
427
428 /* Decode ARQ-Discard messages. */
429 void dissect_mac_mgmt_msg_arq_discard_decoder(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
430 {
431         guint tvb_len, payload_type;
432         proto_item *arq_discard_item = NULL;
433         proto_tree *arq_discard_tree = NULL;
434
435         /* Ensure the right payload type */
436         payload_type = tvb_get_guint8(tvb, 0);
437         if(payload_type != MAC_MGMT_MSG_ARQ_DISCARD)
438         {
439                 return;
440         }
441
442         if (tree)
443         {       /* we are being asked for details */
444
445                 /* Get the tvb reported length */
446                 tvb_len =  tvb_reported_length(tvb);
447                 /* display MAC payload type ARQ-Discard */
448                 arq_discard_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_arq_discard_decoder, tvb, 0, tvb_len, "MAC Management Message, ARQ-Discard (34)");
449                 /* add MAC ARQ Discard subtree */
450                 arq_discard_tree = proto_item_add_subtree(arq_discard_item, ett_mac_mgmt_msg_arq_decoder);
451                 /* display the Message Type */
452                 proto_tree_add_item(arq_discard_tree, hf_arq_message_type, tvb, 0, 1, ENC_BIG_ENDIAN);
453
454                 proto_tree_add_item(arq_discard_tree, hf_arq_discard_cid, tvb, 1, 2, ENC_BIG_ENDIAN);
455                 proto_tree_add_item(arq_discard_tree, hf_arq_discard_reserved, tvb, 3, 1, ENC_BIG_ENDIAN);
456                 proto_tree_add_item(arq_discard_tree, hf_arq_discard_bsn, tvb, 3, 2, ENC_BIG_ENDIAN);
457         }
458 }
459
460 /* Decode ARQ-Reset messages. */
461 void dissect_mac_mgmt_msg_arq_reset_decoder(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
462 {
463         guint tvb_len, payload_type;
464         proto_item *arq_reset_item = NULL;
465         proto_tree *arq_reset_tree = NULL;
466
467         /* Ensure the right payload type */
468         payload_type = tvb_get_guint8(tvb, 0);
469         if(payload_type != MAC_MGMT_MSG_ARQ_RESET)
470         {
471                 return;
472         }
473
474         if (tree)
475         {       /* we are being asked for details */
476
477                 /* Get the tvb reported length */
478                 tvb_len =  tvb_reported_length(tvb);
479                 /* display MAC payload type ARQ-Reset */
480                 arq_reset_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_arq_reset_decoder, tvb, 0, tvb_len, "MAC Management Message, ARQ-Reset (35)");
481                 /* add MAC ARQ Reset subtree */
482                 arq_reset_tree = proto_item_add_subtree(arq_reset_item, ett_mac_mgmt_msg_arq_decoder);
483                 /* display the Message Type */
484                 proto_tree_add_item(arq_reset_tree, hf_arq_message_type, tvb, 0, 1, ENC_BIG_ENDIAN);
485
486                 proto_tree_add_item(arq_reset_tree, hf_arq_reset_cid, tvb, 1, 2, ENC_BIG_ENDIAN);
487                 proto_tree_add_item(arq_reset_tree, hf_arq_reset_type, tvb, 3, 1, ENC_BIG_ENDIAN);
488                 proto_tree_add_item(arq_reset_tree, hf_arq_reset_direction, tvb, 3, 1, ENC_BIG_ENDIAN);
489                 proto_tree_add_item(arq_reset_tree, hf_arq_reset_reserved, tvb, 3, 1, ENC_BIG_ENDIAN);
490         }
491 }
492