Revert "In get_unicode_or_ascii_string(), check if the length is odd/even, not the...
[wireshark-wip.git] / plugins / docsis / packet-docsis.c
blob2afb39f737a1a820751afeb1ec35861a8083c2f0
1 /* packet-docsis.c
2 * Routines for docsis dissection
3 * Copyright 2002, Anand V. Narwani <anand[AT]narwani.org>
5 * $Id$
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 /* This code is based on the DOCSIS 1.1 specification available at:
28 * http://www.cablemodem.com/specifications/specifications11.html
30 * DOCSIS Captures can be facilitated using the Cable Monitor Feature
31 * available on Cisco Cable Modem Termination Systems :
32 * http://www.cisco.com/univercd/cc/td/doc/product/cable/cab_rout/cmtsfg/ufg_cmon.htm
34 * This dissector depends on the presence of a DOCSIS enapsulation type.
35 * There is no simple way to distinguish DOCSIS Frames from Ethernet frames,
36 * since the frames are copied from the RF interface on the CMTS to
37 * a Fast Ethernet interface; thus a preference was needed to enable
38 * the DOCSIS encapsulation type.
40 * The current CVS version of libpcap allows a link-layer header type to
41 * be specified for some interfaces on some platforms; for Ethernet
42 * interfaces, it allows DOCSIS to be specified. If an Ethernet capture
43 * is done with a link-layer type of DOCSIS, the file will have a link-
44 * layer type of DLT_DOCSIS; Wireshark will treat the frames in that capture
45 * as DOCSIS frames.
48 #include "config.h"
50 #include <epan/packet.h>
51 #include <epan/exceptions.h>
53 #define FCTYPE_PACKET 0x00
54 #define FCTYPE_ATMPDU 0x01
55 #define FCTYPE_RESRVD 0x02
56 #define FCTYPE_MACSPC 0x03
58 #define EH_NULL_CONFIG 0
59 #define EH_REQUEST 1
60 #define EH_ACK_REQ 2
61 #define EH_BP_UP 3
62 #define EH_BP_DOWN 4
63 #define EH_SFLOW_HDR_DOWN 5
64 #define EH_SFLOW_HDR_UP 6
65 #define EH_BP_UP2 7
66 #define EH_DS_SERVICE 8
67 #define EH_RESERVED_9 9
68 #define EH_RESERVED_10 10
69 #define EH_RESERVED_11 11
70 #define EH_RESERVED_12 12
71 #define EH_RESERVED_13 13
72 #define EH_RESERVED_14 14
73 #define EH_EXTENDED 15
75 /* Initialize the protocol and registered fields */
76 static int proto_docsis = -1;
77 static int hf_docsis_fctype = -1;
78 static int hf_docsis_machdr_fcparm = -1;
79 static int hf_docsis_fcparm = -1;
80 static int hf_docsis_ehdron = -1;
81 static int hf_docsis_concat_cnt = -1;
82 static int hf_docsis_macparm = -1;
83 static int hf_docsis_ehdrlen = -1;
84 static int hf_docsis_lensid = -1;
85 static int hf_docsis_eh_type = -1;
86 static int hf_docsis_eh_len = -1;
87 static int hf_docsis_eh_val = -1;
88 static int hf_docsis_frag_rsvd = -1;
89 static int hf_docsis_frag_first = -1;
90 static int hf_docsis_frag_last = -1;
91 static int hf_docsis_frag_seq = -1;
92 static int hf_docsis_sid = -1;
93 static int hf_docsis_mini_slots = -1;
94 static int hf_docsis_hcs = -1;
95 static int hf_docsis_bpi_en = -1;
96 static int hf_docsis_toggle_bit = -1;
97 static int hf_docsis_key_seq = -1;
98 static int hf_docsis_ehdr_ver = -1;
99 static int hf_docsis_said = -1;
100 static int hf_docsis_ehdr_phsi = -1;
101 static int hf_docsis_ehdr_qind = -1;
102 static int hf_docsis_ehdr_grants = -1;
103 static int hf_docsis_reserved = -1;
104 static int hf_docsis_ehdr_ds_traffic_pri = -1;
105 static int hf_docsis_ehdr_ds_seq_chg_cnt = -1;
106 static int hf_docsis_ehdr_ds_dsid = -1;
107 static int hf_docsis_ehdr_ds_pkt_seq_num = -1;
108 static int hf_docsis_ehdr_bpup2_bpi_en = -1;
109 static int hf_docsis_ehdr_bpup2_toggle_bit = -1;
110 static int hf_docsis_ehdr_bpup2_key_seq = -1;
111 static int hf_docsis_ehdr_bpup2_ver = -1;
112 static int hf_docsis_ehdr_bpup2_sid = -1;
113 static dissector_handle_t docsis_handle;
114 static dissector_handle_t eth_withoutfcs_handle;
115 static dissector_handle_t data_handle;
116 static dissector_handle_t docsis_mgmt_handle;
117 #if 0
118 static dissector_table_t docsis_dissector_table;
119 #endif
121 /* Initialize the subtree pointers */
122 static gint ett_docsis = -1;
123 static gint ett_ehdr = -1;
125 static const value_string fctype_vals[] = {
126 {FCTYPE_PACKET, "Packet PDU"},
127 {FCTYPE_ATMPDU, "ATM PDU"},
128 {FCTYPE_RESRVD, "Reserved"},
129 {FCTYPE_MACSPC, "MAC Specific"},
130 {0, NULL}
133 static const value_string eh_type_vals[] = {
134 {0, "NULL Configuration Parameter"},
135 {EH_REQUEST, "Request"},
136 {EH_ACK_REQ, "Acknowledgement Requested"},
137 {EH_BP_UP, "Upstream Privacy Element"},
138 {EH_BP_DOWN, "Downstream Privacy Element"},
139 {EH_SFLOW_HDR_UP, "Service Flow EH; PHS Header Upstream"},
140 {EH_SFLOW_HDR_DOWN, "Service Flow EH; PHS Header Downstream"},
141 {EH_BP_UP2, "Upstream Privacy with Multi Channel"},
142 {EH_DS_SERVICE, "Downstream Service"},
143 {EH_RESERVED_9, "Reserved"},
144 {EH_RESERVED_10, "Reserved"},
145 {EH_RESERVED_10, "Reserved"},
146 {EH_RESERVED_11, "Reserved"},
147 {EH_RESERVED_12, "Reserved"},
148 {EH_RESERVED_13, "Reserved"},
149 {EH_RESERVED_14, "Reserved"},
150 {EH_EXTENDED, "Extended"},
151 {0, NULL}
154 static const value_string fcparm_vals[] = {
155 {0x0, "Timing Header"},
156 {0x1, "Mac Management Message"},
157 {0x2, "Request Frame"},
158 {0x3, "Fragmentation Header"},
159 {0x1C, "Concatenation Header"},
160 {0, NULL}
163 static const true_false_string ehdron_tfs = {
164 "Extended Header Present",
165 "Extended Header Absent"
168 static const true_false_string ena_dis_tfs = {
169 "Enabled",
170 "Disabled"
173 static const true_false_string qind_tfs = {
174 "Rate overrun",
175 "Rate non-overrun"
178 static const true_false_string odd_even_tfs = {
179 "Odd Key",
180 "Even Key",
183 /* Code to actually dissect the packets */
184 /* Code to Dissect the extended header */
185 static void
186 dissect_ehdr (tvbuff_t * tvb, proto_tree * tree, gboolean isfrag)
188 proto_tree *ehdr_tree;
189 proto_item *it, *item;
190 gint ehdrlen;
191 int pos;
192 guint8 type;
193 guint8 len;
194 guint8 val;
195 guint8 mini_slots;
196 guint16 sid;
198 ehdrlen = tvb_get_guint8 (tvb, 1);
199 pos = 4;
201 it = proto_tree_add_text (tree, tvb, pos, ehdrlen, "Extended Header");
202 ehdr_tree = proto_item_add_subtree (it, ett_ehdr);
203 while (pos < ehdrlen + 4)
205 type = (tvb_get_guint8 (tvb, pos) & 0xF0);
206 len = (tvb_get_guint8 (tvb, pos) & 0x0F);
207 if ((((type >> 4) & 0x0F)== 6) && (len == 2))
209 item = proto_tree_add_item(ehdr_tree, hf_docsis_eh_type, tvb, pos, 1, ENC_BIG_ENDIAN);
210 PROTO_ITEM_SET_HIDDEN(item);
211 proto_tree_add_text(ehdr_tree, tvb, pos, 1, "0110 .... = Unsolicited Grant Sync EHDR Sub-Element" );
213 else
214 proto_tree_add_item (ehdr_tree, hf_docsis_eh_type, tvb, pos, 1, ENC_BIG_ENDIAN);
215 proto_tree_add_item (ehdr_tree, hf_docsis_eh_len, tvb, pos, 1, ENC_BIG_ENDIAN);
216 switch ((type >> 4) & 0x0F)
218 case EH_REQUEST:
219 if (len == 3)
221 mini_slots = tvb_get_guint8 (tvb, pos + 1);
222 sid = tvb_get_ntohs (tvb, pos + 2);
223 proto_tree_add_uint (ehdr_tree, hf_docsis_mini_slots, tvb,
224 pos + 1, 1, mini_slots);
225 proto_tree_add_uint (ehdr_tree, hf_docsis_sid, tvb, pos + 2, 2,
226 sid);
228 else
230 THROW (ReportedBoundsError);
232 break;
233 case EH_ACK_REQ:
234 if (len == 2)
236 sid = tvb_get_ntohs (tvb, pos + 1);
237 proto_tree_add_uint (ehdr_tree, hf_docsis_sid, tvb, pos + 2, 2,
238 sid);
240 else
242 THROW (ReportedBoundsError);
244 case EH_BP_UP:
245 proto_tree_add_item (ehdr_tree, hf_docsis_key_seq, tvb, pos + 1, 1,
246 ENC_BIG_ENDIAN);
247 proto_tree_add_item (ehdr_tree, hf_docsis_ehdr_ver, tvb, pos + 1, 1,
248 ENC_BIG_ENDIAN);
249 proto_tree_add_item (ehdr_tree, hf_docsis_bpi_en, tvb, pos + 2, 1,
250 ENC_BIG_ENDIAN);
251 proto_tree_add_item (ehdr_tree, hf_docsis_toggle_bit, tvb, pos + 2,
252 1, ENC_BIG_ENDIAN);
253 proto_tree_add_item (ehdr_tree, hf_docsis_sid, tvb, pos + 2, 2,
254 ENC_BIG_ENDIAN);
255 proto_tree_add_item (ehdr_tree, hf_docsis_mini_slots, tvb, pos + 4,
256 1, ENC_BIG_ENDIAN);
257 if (isfrag)
259 proto_tree_add_item (ehdr_tree, hf_docsis_frag_rsvd, tvb, pos+5,
260 1, ENC_BIG_ENDIAN);
261 proto_tree_add_item (ehdr_tree, hf_docsis_frag_first, tvb, pos+5,
262 1, ENC_BIG_ENDIAN);
263 proto_tree_add_item (ehdr_tree, hf_docsis_frag_last, tvb, pos+5,
264 1, ENC_BIG_ENDIAN);
265 proto_tree_add_item (ehdr_tree, hf_docsis_frag_seq, tvb, pos+5,
266 1, ENC_BIG_ENDIAN);
268 break;
269 case EH_BP_DOWN:
270 proto_tree_add_item (ehdr_tree, hf_docsis_key_seq, tvb, pos + 1, 1,
271 ENC_BIG_ENDIAN);
272 proto_tree_add_item (ehdr_tree, hf_docsis_ehdr_ver, tvb, pos + 1, 1,
273 ENC_BIG_ENDIAN);
274 proto_tree_add_item (ehdr_tree, hf_docsis_bpi_en, tvb, pos + 2, 1,
275 ENC_BIG_ENDIAN);
276 proto_tree_add_item (ehdr_tree, hf_docsis_toggle_bit, tvb, pos + 2,
277 1, ENC_BIG_ENDIAN);
278 proto_tree_add_item (ehdr_tree, hf_docsis_said, tvb, pos + 2, 2,
279 ENC_BIG_ENDIAN);
280 proto_tree_add_item (ehdr_tree, hf_docsis_reserved, tvb, pos + 4, 1,
281 ENC_BIG_ENDIAN);
282 break;
283 case EH_SFLOW_HDR_DOWN:
284 case EH_SFLOW_HDR_UP:
285 val = tvb_get_guint8 (tvb, pos+1);
286 if (val == 0)
288 item = proto_tree_add_item(ehdr_tree, hf_docsis_ehdr_phsi, tvb, pos+1, 1, ENC_BIG_ENDIAN);
289 PROTO_ITEM_SET_HIDDEN(item);
290 proto_tree_add_text (ehdr_tree, tvb, pos+1, 1, "0000 0000 = No PHS on current packet" );
292 else
293 proto_tree_add_item(ehdr_tree, hf_docsis_ehdr_phsi, tvb, pos+1, 1, ENC_BIG_ENDIAN);
295 if (len == 2)
297 proto_tree_add_item (ehdr_tree, hf_docsis_ehdr_qind, tvb, pos+2, 1, ENC_BIG_ENDIAN);
298 proto_tree_add_item (ehdr_tree, hf_docsis_ehdr_grants, tvb, pos+2, 1, ENC_BIG_ENDIAN);
300 break;
301 case EH_BP_UP2:
302 proto_tree_add_item (ehdr_tree, hf_docsis_ehdr_bpup2_key_seq, tvb, pos + 1, 1,
303 ENC_BIG_ENDIAN);
304 proto_tree_add_item (ehdr_tree, hf_docsis_ehdr_bpup2_ver, tvb, pos + 1, 1,
305 ENC_BIG_ENDIAN);
306 proto_tree_add_item (ehdr_tree, hf_docsis_ehdr_bpup2_bpi_en, tvb, pos + 2, 1,
307 ENC_BIG_ENDIAN);
308 proto_tree_add_item (ehdr_tree, hf_docsis_ehdr_bpup2_toggle_bit, tvb, pos + 2,
309 1, ENC_BIG_ENDIAN);
310 proto_tree_add_item (ehdr_tree, hf_docsis_ehdr_bpup2_sid, tvb, pos + 2, 2,
311 ENC_BIG_ENDIAN);
312 break;
313 case EH_DS_SERVICE:
314 proto_tree_add_item(ehdr_tree, hf_docsis_ehdr_ds_traffic_pri, tvb, pos+1, 1, FALSE);
316 if (len == 3)
318 proto_tree_add_item (ehdr_tree, hf_docsis_ehdr_ds_dsid, tvb, pos+1, 3, FALSE);
321 if (len == 5)
323 proto_tree_add_item (ehdr_tree, hf_docsis_ehdr_ds_seq_chg_cnt, tvb, pos+1, 1, FALSE);
324 proto_tree_add_item (ehdr_tree, hf_docsis_ehdr_ds_dsid, tvb, pos+1, 3, FALSE);
325 proto_tree_add_item (ehdr_tree, hf_docsis_ehdr_ds_pkt_seq_num, tvb, pos+4, 2, FALSE);
328 break;
329 default:
330 if (len > 0)
331 proto_tree_add_item (ehdr_tree, hf_docsis_eh_val, tvb, pos + 1,
332 len, ENC_NA);
334 pos += len + 1;
337 return;
341 static void
342 dissect_docsis (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
344 guint8 fc;
345 guint8 fctype;
346 guint8 fcparm;
347 guint8 ehdron;
348 gint mac_parm;
349 gint hdrlen;
350 guint16 len_sid;
351 tvbuff_t *next_tvb, *mgt_tvb;
352 gint pdulen, captured_length;
353 gint framelen;
354 gboolean isfrag = FALSE;
355 gint oldconcatlen;
357 /* Set up structures needed to add the protocol subtree and manage it */
358 proto_item *ti;
359 proto_tree *docsis_tree;
360 /* concatlen and concatpos are declared static to allow for recursive calls to
361 * the dissect_docsis routine when dissecting Concatenated frames
363 static gint concatlen;
364 static gint concatpos;
366 /* Extract important fields */
367 fc = tvb_get_guint8 (tvb, 0); /* Frame Control Byte */
368 fctype = (fc >> 6) & 0x03; /* Frame Control Type: 2 MSB Bits */
369 fcparm = (fc >> 1) & 0x1F; /* Frame Control Parameter: Next 5 Bits */
370 ehdron = (fc & 0x01); /* Extended Header Bit: LSB */
372 mac_parm = tvb_get_guint8 (tvb, 1); /* Mac Parm */
373 len_sid = tvb_get_ntohs (tvb, 2); /* Length Or SID */
375 /* set Header length based on presence of Extended header */
376 if (ehdron == 0x00)
377 hdrlen = 6;
378 else
379 hdrlen = 6 + mac_parm;
381 /* Captured PDU Length is based on the length of the header */
382 captured_length = tvb_length_remaining (tvb, hdrlen);
384 /* If this is a Request Frame, then pdulen is 0 and framelen is 6 */
385 if ((fctype == FCTYPE_MACSPC) && fcparm == 0x02)
387 pdulen = 0;
388 framelen = 6;
390 else
392 framelen = 6 + len_sid;
393 pdulen = len_sid - (mac_parm + 2);
396 /* if this is a concatenated frame setup the length of the concatenated
397 * frame and set the position to the first byte of the first frame */
398 if ((fctype == FCTYPE_MACSPC) && (fcparm == 0x1c))
400 concatlen = len_sid;
401 concatpos = 6;
404 /* Make entries in Protocol column and Info column on summary display */
405 col_set_str (pinfo->cinfo, COL_PROTOCOL, "DOCSIS");
407 switch (fctype)
409 case FCTYPE_PACKET:
410 col_set_str (pinfo->cinfo, COL_INFO, "Packet PDU");
411 break;
412 case FCTYPE_ATMPDU:
413 col_set_str (pinfo->cinfo, COL_INFO, "ATM PDU");
414 break;
415 case FCTYPE_RESRVD:
416 col_set_str (pinfo->cinfo, COL_INFO, "Reserved PDU");
417 break;
418 case FCTYPE_MACSPC:
419 if (fcparm == 0x02)
420 col_add_fstr (pinfo->cinfo, COL_INFO,
421 "Request Frame SID = %u Mini Slots = %u", len_sid,
422 mac_parm);
423 else if (fcparm == 0x03)
424 col_set_str (pinfo->cinfo, COL_INFO, "Fragmented Frame");
425 else
426 col_set_str (pinfo->cinfo, COL_INFO, "Mac Specific");
427 break;
428 } /* switch */
430 /* In the interest of speed, if "tree" is NULL, don't do any work not
431 necessary to generate protocol tree items. */
432 if (tree)
434 ti = proto_tree_add_protocol_format (tree, proto_docsis, tvb, 0,
435 hdrlen, "DOCSIS");
436 docsis_tree = proto_item_add_subtree (ti, ett_docsis);
438 /* add an item to the subtree, see section 1.6 for more information */
439 proto_tree_add_item (docsis_tree, hf_docsis_fctype, tvb, 0, 1, ENC_BIG_ENDIAN);
440 switch (fctype)
442 case FCTYPE_PACKET:
443 case FCTYPE_ATMPDU:
444 case FCTYPE_RESRVD:
445 proto_tree_add_item (docsis_tree, hf_docsis_fcparm, tvb, 0, 1,
446 ENC_BIG_ENDIAN);
447 proto_tree_add_item (docsis_tree, hf_docsis_ehdron, tvb, 0, 1,
448 ENC_BIG_ENDIAN);
449 if (ehdron == 0x01)
451 proto_tree_add_item (docsis_tree, hf_docsis_ehdrlen, tvb, 1, 1,
452 ENC_BIG_ENDIAN);
453 proto_tree_add_item (docsis_tree, hf_docsis_lensid, tvb, 2, 2,
454 ENC_BIG_ENDIAN);
455 dissect_ehdr (tvb, docsis_tree, isfrag);
456 proto_tree_add_item (docsis_tree, hf_docsis_hcs, tvb,
457 4 + mac_parm, 2, ENC_BIG_ENDIAN);
459 else
461 proto_tree_add_item (docsis_tree, hf_docsis_macparm, tvb, 1, 1,
462 ENC_BIG_ENDIAN);
463 proto_tree_add_item (docsis_tree, hf_docsis_lensid, tvb, 2, 2,
464 ENC_BIG_ENDIAN);
465 proto_tree_add_item (docsis_tree, hf_docsis_hcs, tvb, 4, 2,
466 ENC_BIG_ENDIAN);
468 break;
469 case FCTYPE_MACSPC:
470 proto_tree_add_item (docsis_tree, hf_docsis_machdr_fcparm, tvb, 0,
471 1, ENC_BIG_ENDIAN);
472 proto_tree_add_item (docsis_tree, hf_docsis_ehdron, tvb, 0, 1,
473 ENC_BIG_ENDIAN);
474 /* Decode for a Request Frame. No extended header */
475 if (fcparm == 0x02)
477 proto_tree_add_uint (docsis_tree, hf_docsis_mini_slots, tvb, 1,
478 1, mac_parm);
479 proto_tree_add_uint (docsis_tree, hf_docsis_sid, tvb, 2, 2,
480 len_sid);
481 proto_tree_add_item (docsis_tree, hf_docsis_hcs, tvb, 4, 2,
482 ENC_BIG_ENDIAN);
483 break;
485 /* Check if this is a fragmentation header */
486 if (fcparm == 0x03)
488 isfrag = TRUE;
490 /* Decode for a Concatenated Header. No Extended Header */
491 if (fcparm == 0x1c)
493 proto_item_append_text (ti, " (Concatenated Header)");
494 proto_tree_add_item (docsis_tree, hf_docsis_concat_cnt, tvb, 1,
495 1, ENC_BIG_ENDIAN);
496 proto_tree_add_item (docsis_tree, hf_docsis_lensid, tvb, 2, 2,
497 ENC_BIG_ENDIAN);
498 proto_tree_add_item (docsis_tree, hf_docsis_hcs, tvb, 4, 2,
499 ENC_BIG_ENDIAN);
500 break;
502 /* If Extended header is present then decode it */
503 if (ehdron == 0x01)
505 proto_tree_add_item (docsis_tree, hf_docsis_ehdrlen, tvb, 1, 1,
506 ENC_BIG_ENDIAN);
507 proto_tree_add_item (docsis_tree, hf_docsis_lensid, tvb, 2, 2,
508 ENC_BIG_ENDIAN);
509 dissect_ehdr (tvb, docsis_tree, isfrag);
510 proto_tree_add_item (docsis_tree, hf_docsis_hcs, tvb,
511 4 + mac_parm, 2, ENC_BIG_ENDIAN);
512 break;
514 /* default case for all other Mac Frame Types */
515 proto_tree_add_item (docsis_tree, hf_docsis_macparm, tvb, 1, 1,
516 ENC_BIG_ENDIAN);
517 proto_tree_add_item (docsis_tree, hf_docsis_lensid, tvb, 2, 2,
518 ENC_BIG_ENDIAN);
519 proto_tree_add_item (docsis_tree, hf_docsis_hcs, tvb, 4, 2, ENC_BIG_ENDIAN);
520 break;
524 /* If this protocol has a sub-dissector call it here, see section 1.8 */
525 switch (fctype)
527 case FCTYPE_PACKET:
528 case FCTYPE_RESRVD:
529 if (pdulen >= 0)
531 if (pdulen > 0)
533 next_tvb = tvb_new_subset (tvb, hdrlen, captured_length, pdulen);
534 call_dissector (eth_withoutfcs_handle, next_tvb, pinfo, tree);
536 if (concatlen > 0)
538 concatlen = concatlen - framelen;
539 concatpos += framelen;
542 break;
543 case FCTYPE_MACSPC:
544 switch (fcparm)
546 case 0x00:
547 case 0x01:
548 if (pdulen > 0)
550 mgt_tvb = tvb_new_subset (tvb, hdrlen, captured_length, pdulen);
551 call_dissector (docsis_mgmt_handle, mgt_tvb, pinfo, tree);
553 if (concatlen > 0)
555 concatlen = concatlen - framelen;
556 concatpos += framelen;
558 break;
559 case 0x02:
560 /* Don't do anything for a Request Frame */
561 break;
562 case 0x03:
563 /* For Fragmentation Frames simply dissect using the data
564 * dissector as we don't handle them yet
566 if (pdulen > 0)
568 mgt_tvb = tvb_new_subset (tvb, hdrlen, captured_length, pdulen);
569 call_dissector (data_handle, mgt_tvb, pinfo, tree);
571 if (concatlen > 0)
573 concatlen = concatlen - framelen;
574 concatpos += framelen;
576 break;
577 case 0x1c:
578 /* call the docsis dissector on the same frame
579 * to dissect DOCSIS frames within the concatenated
580 * frame. concatpos and concatlen are declared
581 * static and are decremented and incremented
582 * respectively when the inner
583 * docsis frames are dissected. */
584 while (concatlen > 0)
586 oldconcatlen = concatlen;
587 next_tvb = tvb_new_subset (tvb, concatpos, -1, concatlen);
588 call_dissector (docsis_handle, next_tvb, pinfo, tree);
589 if (oldconcatlen <= concatlen)
590 THROW(ReportedBoundsError);
592 concatlen = 0;
593 concatpos = 0;
594 col_set_str(pinfo->cinfo, COL_INFO, "Concatenated Frame");
595 break;
597 break;
602 /* Register the protocol with Wireshark */
604 /* this format is require because a script is used to build the C function
605 that calls all the protocol registration.
609 void
610 proto_register_docsis (void)
613 /* Setup list of header fields See Section 1.6.1 for details*/
614 static hf_register_info hf[] = {
615 {&hf_docsis_fctype,
616 {"FCType", "docsis.fctype",
617 FT_UINT8, BASE_HEX, VALS (fctype_vals), 0xC0,
618 "Frame Control Type", HFILL}
620 {&hf_docsis_fcparm,
621 {"FCParm", "docsis.fcparm",
622 FT_UINT8, BASE_DEC, NULL, 0x3E,
623 "Parameter Field", HFILL}
625 {&hf_docsis_machdr_fcparm,
626 {"FCParm", "docsis.fcparm",
627 FT_UINT8, BASE_HEX, VALS (fcparm_vals), 0x3E,
628 "Parameter Field", HFILL}
630 {&hf_docsis_ehdron,
631 {"EHDRON", "docsis.ehdron",
632 FT_BOOLEAN, 8, TFS (&ehdron_tfs), 0x01,
633 "Extended Header Presence", HFILL}
635 {&hf_docsis_macparm,
636 {"MacParm", "docsis.macparm",
637 FT_UINT8, BASE_HEX, NULL, 0x0,
638 "Mac Parameter Field", HFILL}
640 {&hf_docsis_concat_cnt,
641 {"Number of Concatenated Frames", "docsis.macparm",
642 FT_UINT8, BASE_DEC, NULL, 0x0,
643 NULL, HFILL}
645 {&hf_docsis_ehdrlen,
646 {"Extended Header Length (bytes)", "docsis.macparm",
647 FT_UINT8, BASE_DEC, NULL, 0x0,
648 "Mac Parameter Field", HFILL}
650 {&hf_docsis_lensid,
651 {"Length after HCS (bytes)", "docsis.lensid",
652 FT_UINT16, BASE_DEC, NULL, 0x0,
653 "Length or SID", HFILL}
655 {&hf_docsis_eh_type,
656 {"Type", "docsis.ehdr.type",
657 FT_UINT8, BASE_DEC, VALS (eh_type_vals), 0xF0,
658 "TLV Type", HFILL}
660 {&hf_docsis_eh_len,
661 {"Length", "docsis.ehdr.len",
662 FT_UINT8, BASE_DEC, NULL, 0x0F,
663 "TLV Len", HFILL}
665 {&hf_docsis_eh_val,
666 {"Value", "docsis.ehdr.value",
667 FT_BYTES, BASE_NONE, NULL, 0x0,
668 "TLV Value", HFILL}
670 {&hf_docsis_frag_rsvd,
671 {"Reserved", "docsis.frag_rsvd",
672 FT_UINT8, BASE_DEC, NULL, 0xC0,
673 NULL, HFILL}
675 {&hf_docsis_frag_first,
676 {"First Frame", "docsis.frag_first",
677 FT_BOOLEAN, 8, NULL, 0x20,
678 NULL, HFILL}
680 {&hf_docsis_frag_last,
681 {"Last Frame", "docsis.frag_last",
682 FT_BOOLEAN, 8, NULL, 0x10,
683 NULL, HFILL}
685 {&hf_docsis_frag_seq,
686 {"Fragmentation Sequence #", "docsis.frag_seq",
687 FT_UINT8, BASE_DEC, NULL, 0x0F,
688 "Fragmentation Sequence Number", HFILL}
690 {&hf_docsis_sid,
691 {"SID", "docsis.ehdr.sid",
692 FT_UINT16, BASE_DEC, NULL, 0x3FFF,
693 "Service Identifier", HFILL}
695 {&hf_docsis_said,
696 {"SAID", "docsis.ehdr.said",
697 FT_UINT16, BASE_DEC, NULL, 0x3FFF,
698 "Security Association Identifier", HFILL}
700 {&hf_docsis_reserved,
701 {"Reserved", "docsis.ehdr.rsvd",
702 FT_UINT8, BASE_HEX, NULL, 0x3FFF,
703 "Reserved Byte", HFILL}
705 {&hf_docsis_mini_slots,
706 {"MiniSlots", "docsis.ehdr.minislots",
707 FT_UINT8, BASE_DEC, NULL, 0x0,
708 "Mini Slots Requested", HFILL}
710 {&hf_docsis_key_seq,
711 {"Key Sequence", "docsis.ehdr.keyseq",
712 FT_UINT8, BASE_DEC, NULL, 0xF0,
713 NULL, HFILL}
715 {&hf_docsis_ehdr_ver,
716 {"Version", "docsis.ehdr.ver",
717 FT_UINT8, BASE_DEC, NULL, 0x0F,
718 NULL, HFILL}
720 {&hf_docsis_ehdr_phsi,
721 {"Payload Header Suppression Index", "docsis.ehdr.phsi",
722 FT_UINT8, BASE_DEC, NULL, 0x0,
723 NULL, HFILL}
725 {&hf_docsis_ehdr_qind,
726 {"Queue Indicator", "docsis.ehdr.qind",
727 FT_BOOLEAN, 8, TFS(&qind_tfs), 0x80,
728 NULL, HFILL}
730 {&hf_docsis_ehdr_grants,
731 {"Active Grants", "docsis.ehdr.act_grants",
732 FT_UINT8, BASE_DEC, NULL, 0x7F,
733 NULL, HFILL}
735 {&hf_docsis_ehdr_bpup2_key_seq,
736 {"Key Sequence", "docsis.ehdr.bpup2_keyseq",
737 FT_UINT8, BASE_DEC, NULL, 0xF0,
738 "NULL", HFILL}
740 {&hf_docsis_ehdr_bpup2_ver,
741 {"Version", "docsis.ehdr.bpup2_ver",
742 FT_UINT8, BASE_DEC, NULL, 0x0F,
743 "NULL", HFILL}
745 {&hf_docsis_ehdr_bpup2_bpi_en,
746 {"Encryption", "docsis.ehdr.bpup2_bpi_en",
747 FT_BOOLEAN, 8, TFS (&ena_dis_tfs), 0x80,
748 "BPI Enable", HFILL},
750 {&hf_docsis_ehdr_bpup2_toggle_bit,
751 {"Toggle", "docsis.ehdr.bpup2_toggle_bit",
752 FT_BOOLEAN, 8, TFS (&odd_even_tfs), 0x40,
753 "NULL", HFILL},
755 {&hf_docsis_ehdr_bpup2_sid,
756 {"SID", "docsis.ehdr.bpup2_sid",
757 FT_UINT16, BASE_DEC, NULL, 0x3FFF,
758 "Service Identifier", HFILL}
760 {&hf_docsis_ehdr_ds_traffic_pri,
761 {"DS Traffic Priority", "docsis.ehdr.ds_traffic_pri",
762 FT_UINT8, BASE_DEC, NULL, 0xE0,
763 "NULL", HFILL}
765 {&hf_docsis_ehdr_ds_seq_chg_cnt,
766 {"DS Sequence Change Count", "docsis.ehdr.ds_seq_chg_cnt",
767 FT_UINT8, BASE_DEC, NULL, 0x10,
768 "NULL", HFILL}
770 {&hf_docsis_ehdr_ds_dsid,
771 {"DS DSID", "docsis.ehdr.ds_dsid",
772 FT_UINT32, BASE_DEC, NULL, 0x0FFFFF,
773 "NULL", HFILL}
775 {&hf_docsis_ehdr_ds_pkt_seq_num,
776 {"DS Packet Sequence Number", "docsis.ehdr.ds_pkt_seq_num",
777 FT_UINT16, BASE_DEC, NULL, 0x0,
778 "NULL", HFILL}
780 {&hf_docsis_hcs,
781 {"Header check sequence", "docsis.hcs",
782 FT_UINT16, BASE_HEX, NULL, 0x0,
783 NULL, HFILL},
785 {&hf_docsis_bpi_en,
786 {"Encryption", "docsis.bpi_en",
787 FT_BOOLEAN, 8, TFS (&ena_dis_tfs), 0x80,
788 "BPI Enable", HFILL},
790 {&hf_docsis_toggle_bit,
791 {"Toggle", "docsis.toggle_bit",
792 FT_BOOLEAN, 8, TFS (&odd_even_tfs), 0x40,
793 NULL, HFILL},
798 /* Setup protocol subtree array */
799 static gint *ett[] = {
800 &ett_docsis,
801 &ett_ehdr,
804 #if 0
805 docsis_dissector_table = register_dissector_table ("docsis",
806 "DOCSIS Encapsulation Type",
807 FT_UINT8, BASE_DEC);
808 #endif
810 /* Register the protocol name and description */
811 proto_docsis = proto_register_protocol ("DOCSIS 1.1", "DOCSIS", "docsis");
813 /* Required function calls to register the header fields and subtrees used */
814 proto_register_field_array (proto_docsis, hf, array_length (hf));
815 proto_register_subtree_array (ett, array_length (ett));
817 register_dissector ("docsis", dissect_docsis, proto_docsis);
821 /* If this dissector uses sub-dissector registration add a registration routine.
822 This format is required because a script is used to find these routines and
823 create the code that calls these routines.
825 void
826 proto_reg_handoff_docsis (void)
829 docsis_handle = find_dissector ("docsis");
830 data_handle = find_dissector ("data");
831 dissector_add_uint ("wtap_encap", WTAP_ENCAP_DOCSIS, docsis_handle);
833 docsis_mgmt_handle = find_dissector ("docsis_mgmt");
834 eth_withoutfcs_handle = find_dissector ("eth_withoutfcs");