2e17c8cd46872ed4f7478252c994e6cd12426939
[obnox/wireshark/wip.git] / plugins / docsis / packet-docsis.c
1 /* packet-docsis.c
2  * Routines for docsis dissection
3  * Copyright 2002, Anand V. Narwani <anand[AT]narwani.org>
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
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.
15  *
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.
20  *
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24  */
25
26
27 /* This code is based on the DOCSIS 1.1 specification available at:
28  * http://www.cablemodem.com/specifications/specifications11.html
29  *
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
33  *
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.
39  *
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.
46  */
47
48 #ifdef HAVE_CONFIG_H
49 # include "config.h"
50 #endif
51
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
55
56 #include <epan/packet.h>
57
58 #include "packet-docsis.h"
59
60 #define FCTYPE_PACKET 0x00
61 #define FCTYPE_ATMPDU 0x01
62 #define FCTYPE_RESRVD 0x02
63 #define FCTYPE_MACSPC 0x03
64
65 #define EH_NULL_CONFIG 0
66 #define EH_REQUEST 1
67 #define EH_ACK_REQ 2
68 #define EH_BP_UP 3
69 #define EH_BP_DOWN 4
70 #define EH_SFLOW_HDR_DOWN 5
71 #define EH_SFLOW_HDR_UP 6
72 #define EH_RESERVED_7 7
73 #define EH_RESERVED_8 8
74 #define EH_RESERVED_9 9
75 #define EH_RESERVED_10 10
76 #define EH_RESERVED_11 11
77 #define EH_RESERVED_12 12
78 #define EH_RESERVED_13 13
79 #define EH_RESERVED_14 14
80 #define EH_EXTENDED 15
81
82 /* Initialize the protocol and registered fields */
83 static int proto_docsis = -1;
84 static int hf_docsis_fctype = -1;
85 static int hf_docsis_machdr_fcparm = -1;
86 static int hf_docsis_fcparm = -1;
87 static int hf_docsis_ehdron = -1;
88 static int hf_docsis_concat_cnt = -1;
89 static int hf_docsis_macparm = -1;
90 static int hf_docsis_ehdrlen = -1;
91 static int hf_docsis_lensid = -1;
92 static int hf_docsis_eh_type = -1;
93 static int hf_docsis_eh_len = -1;
94 static int hf_docsis_eh_val = -1;
95 static int hf_docsis_frag_rsvd = -1;
96 static int hf_docsis_frag_first = -1;
97 static int hf_docsis_frag_last = -1;
98 static int hf_docsis_frag_seq = -1;
99 static int hf_docsis_sid = -1;
100 static int hf_docsis_mini_slots = -1;
101 static int hf_docsis_hcs = -1;
102 static int hf_docsis_bpi_en = -1;
103 static int hf_docsis_toggle_bit = -1;
104 static int hf_docsis_key_seq = -1;
105 static int hf_docsis_ehdr_ver = -1;
106 static int hf_docsis_said = -1;
107 static int hf_docsis_ehdr_phsi = -1;
108 static int hf_docsis_ehdr_qind = -1;
109 static int hf_docsis_ehdr_grants = -1;
110 static int hf_docsis_reserved = -1;
111
112 static dissector_handle_t docsis_handle;
113 static dissector_handle_t eth_withoutfcs_handle;
114 static dissector_handle_t data_handle;
115 static dissector_handle_t docsis_mgmt_handle;
116 static dissector_table_t docsis_dissector_table;
117
118 /* Initialize the subtree pointers */
119 static gint ett_docsis = -1;
120 static gint ett_ehdr = -1;
121
122 static const value_string fctype_vals[] = {
123   {FCTYPE_PACKET, "Packet PDU"},
124   {FCTYPE_ATMPDU, "ATM PDU"},
125   {FCTYPE_RESRVD, "Reserved"},
126   {FCTYPE_MACSPC, "MAC Specific"},
127   {0, NULL}
128 };
129
130 static const value_string eh_type_vals[] = {
131   {0, "NULL Configuration Parameter"},
132   {EH_REQUEST, "Request"},
133   {EH_ACK_REQ, "Acknowledgement Requested"},
134   {EH_BP_UP, "Upstream Privacy Element"},
135   {EH_BP_DOWN, "Downstream  Privacy Element"},
136   {EH_SFLOW_HDR_UP, "Service Flow EH; PHS Header Upstream"},
137   {EH_SFLOW_HDR_DOWN, "Service Flow EH; PHS Header Downstream"},
138   {EH_RESERVED_7, "Reserved"},
139   {EH_RESERVED_8, "Reserved"},
140   {EH_RESERVED_9, "Reserved"},
141   {EH_RESERVED_10, "Reserved"},
142   {EH_RESERVED_10, "Reserved"},
143   {EH_RESERVED_11, "Reserved"},
144   {EH_RESERVED_12, "Reserved"},
145   {EH_RESERVED_13, "Reserved"},
146   {EH_RESERVED_14, "Reserved"},
147   {EH_EXTENDED, "Extended"},
148   {0, NULL}
149 };
150
151 static const value_string fcparm_vals[] = {
152   {0x0, "Timing Header"},
153   {0x1, "Mac Management Message"},
154   {0x2, "Request Frame"},
155   {0x3, "Fragmentation Header"},
156   {0x1C, "Concatenation Header"},
157   {0, NULL}
158 };
159
160 static const true_false_string ehdron_tfs = {
161   "Extended Header Present",
162   "Extended Header Absent"
163 };
164
165 static const true_false_string ena_dis_tfs = {
166   "Enabled",
167   "Disabled"
168 };
169
170 static const true_false_string qind_tfs = {
171   "Rate overrun",
172   "Rate non-overrun"
173 };
174
175 static const true_false_string odd_even_tfs = {
176   "Odd Key",
177   "Even Key",
178 };
179
180 /* Code to actually dissect the packets */
181 /* Code to Dissect the extended header */
182 static void
183 dissect_ehdr (tvbuff_t * tvb, proto_tree * tree, gboolean isfrag)
184 {
185   proto_tree *ehdr_tree;
186   proto_item *it, *item;
187   gint ehdrlen;
188   int pos;
189   guint8 type;
190   guint8 len;
191   guint8 val;
192   guint8 mini_slots;
193   guint16 sid;
194
195   ehdrlen = tvb_get_guint8 (tvb, 1);
196   pos = 4;
197
198   it = proto_tree_add_text (tree, tvb, pos, ehdrlen, "Extended Header");
199   ehdr_tree = proto_item_add_subtree (it, ett_ehdr);
200   while (pos < ehdrlen + 4)
201     {
202       type = (tvb_get_guint8 (tvb, pos) & 0xF0);
203       len = (tvb_get_guint8 (tvb, pos) & 0x0F);
204       if ((((type >> 4) & 0x0F)== 6) && (len == 2)) 
205         {
206           item = proto_tree_add_item(ehdr_tree, hf_docsis_eh_type, tvb, pos, 1, FALSE);
207                   PROTO_ITEM_SET_HIDDEN(item);
208                   proto_tree_add_text(ehdr_tree, tvb, pos, 1, "0110 ....  = Unsolicited Grant Sync EHDR Sub-Element" );
209         }
210       else
211         proto_tree_add_item (ehdr_tree, hf_docsis_eh_type, tvb, pos, 1, FALSE);
212       proto_tree_add_item (ehdr_tree, hf_docsis_eh_len, tvb, pos, 1, FALSE);
213       switch ((type >> 4) & 0x0F)
214         {
215         case EH_REQUEST:
216           if (len == 3)
217             {
218               mini_slots = tvb_get_guint8 (tvb, pos + 1);
219               sid = tvb_get_ntohs (tvb, pos + 2);
220               proto_tree_add_uint (ehdr_tree, hf_docsis_mini_slots, tvb,
221                                    pos + 1, 1, mini_slots);
222               proto_tree_add_uint (ehdr_tree, hf_docsis_sid, tvb, pos + 2, 2,
223                                    sid);
224             }
225           else
226             {
227               THROW (ReportedBoundsError);
228             }
229           break;
230         case EH_ACK_REQ:
231           if (len == 2)
232             {
233               sid = tvb_get_ntohs (tvb, pos + 1);
234               proto_tree_add_uint (ehdr_tree, hf_docsis_sid, tvb, pos + 2, 2,
235                                    sid);
236             }
237           else
238             {
239               THROW (ReportedBoundsError);
240             }
241         case EH_BP_UP:
242           proto_tree_add_item (ehdr_tree, hf_docsis_key_seq, tvb, pos + 1, 1,
243                                FALSE);
244           proto_tree_add_item (ehdr_tree, hf_docsis_ehdr_ver, tvb, pos + 1, 1,
245                                FALSE);
246           proto_tree_add_item (ehdr_tree, hf_docsis_bpi_en, tvb, pos + 2, 1,
247                                FALSE);
248           proto_tree_add_item (ehdr_tree, hf_docsis_toggle_bit, tvb, pos + 2,
249                                1, FALSE);
250           proto_tree_add_item (ehdr_tree, hf_docsis_sid, tvb, pos + 2, 2,
251                                FALSE);
252           proto_tree_add_item (ehdr_tree, hf_docsis_mini_slots, tvb, pos + 4,
253                                1, FALSE);
254           if (isfrag)
255             {
256               proto_tree_add_item (ehdr_tree, hf_docsis_frag_rsvd, tvb, pos+5,
257                                   1, FALSE);
258               proto_tree_add_item (ehdr_tree, hf_docsis_frag_first, tvb, pos+5,
259                                   1, FALSE);
260               proto_tree_add_item (ehdr_tree, hf_docsis_frag_last, tvb, pos+5,
261                                   1, FALSE);
262               proto_tree_add_item (ehdr_tree, hf_docsis_frag_seq, tvb, pos+5,
263                                   1, FALSE);
264             }
265           break;
266         case EH_BP_DOWN:
267           proto_tree_add_item (ehdr_tree, hf_docsis_key_seq, tvb, pos + 1, 1,
268                                FALSE);
269           proto_tree_add_item (ehdr_tree, hf_docsis_ehdr_ver, tvb, pos + 1, 1,
270                                FALSE);
271           proto_tree_add_item (ehdr_tree, hf_docsis_bpi_en, tvb, pos + 2, 1,
272                                FALSE);
273           proto_tree_add_item (ehdr_tree, hf_docsis_toggle_bit, tvb, pos + 2,
274                                1, FALSE);
275           proto_tree_add_item (ehdr_tree, hf_docsis_said, tvb, pos + 2, 2,
276                                FALSE);
277           proto_tree_add_item (ehdr_tree, hf_docsis_reserved, tvb, pos + 4, 1,
278                                FALSE);
279           break;
280         case EH_SFLOW_HDR_DOWN:
281         case EH_SFLOW_HDR_UP:
282           val = tvb_get_guint8 (tvb, pos+1);
283           if (val == 0)
284           {
285             item = proto_tree_add_item(ehdr_tree, hf_docsis_ehdr_phsi, tvb, pos+1, 1, FALSE);
286                 PROTO_ITEM_SET_HIDDEN(item);
287             proto_tree_add_text (ehdr_tree, tvb, pos+1, 1, "0000 0000 = No PHS on current packet" );
288           }
289           else
290             proto_tree_add_item(ehdr_tree, hf_docsis_ehdr_phsi, tvb, pos+1, 1, FALSE);
291
292           if (len == 2) 
293           {
294             proto_tree_add_item (ehdr_tree, hf_docsis_ehdr_qind, tvb, pos+2, 1, FALSE);
295             proto_tree_add_item (ehdr_tree, hf_docsis_ehdr_grants, tvb, pos+2, 1, FALSE);
296           }
297           break;
298         default:
299           if (len > 0)
300             proto_tree_add_item (ehdr_tree, hf_docsis_eh_val, tvb, pos + 1,
301                                   len, FALSE);
302         }
303       pos += len + 1;
304     }
305
306   return;
307 }
308
309
310 static void
311 dissect_docsis (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
312 {
313   guint8 fc;
314   guint8 fctype;
315   guint8 fcparm;
316   guint8 ehdron;
317   gint mac_parm;
318   gint hdrlen;
319   guint16 len_sid;
320   tvbuff_t *next_tvb, *mgt_tvb;
321   gint pdulen, captured_length;
322   gint framelen;
323   gboolean isfrag = FALSE;
324   gint oldconcatlen;
325
326 /* Set up structures needed to add the protocol subtree and manage it */
327   proto_item *ti;
328   proto_tree *docsis_tree;
329 /* concatlen and concatpos are declared static to allow for recursive calls to
330  * the dissect_docsis routine when dissecting Concatenated frames
331  */
332   static gint concatlen;
333   static gint concatpos;
334
335 /* Extract important fields */
336   fc = tvb_get_guint8 (tvb, 0); /* Frame Control Byte */
337   fctype = (fc >> 6) & 0x03;    /* Frame Control Type:  2 MSB Bits */
338   fcparm = (fc >> 1) & 0x1F;    /* Frame Control Parameter: Next 5 Bits */
339   ehdron = (fc & 0x01);         /* Extended Header Bit: LSB */
340
341   mac_parm = tvb_get_guint8 (tvb, 1);   /* Mac Parm */
342   len_sid = tvb_get_ntohs (tvb, 2);     /* Length Or SID */
343
344 /* set Header length based on presence of Extended header */
345   if (ehdron == 0x00)
346     hdrlen = 6;
347   else
348     hdrlen = 6 + mac_parm;
349
350 /* Captured PDU Length is based on the length of the header */
351   captured_length = tvb_length_remaining (tvb, hdrlen);
352
353 /* If this is a Request Frame, then pdulen is 0 and framelen is 6 */
354   if ((fctype == FCTYPE_MACSPC) && fcparm == 0x02)
355     {
356       pdulen = 0;
357       framelen = 6;
358     }
359   else
360     {
361       framelen = 6 + len_sid;
362       pdulen = len_sid - (mac_parm + 2);
363     }
364
365 /* if this is a concatenated frame setup the length of the concatenated
366  * frame and set the position to the first byte of the first frame */
367   if ((fctype == FCTYPE_MACSPC) && (fcparm == 0x1c))
368     {
369       concatlen = len_sid;
370       concatpos = 6;
371     }
372
373 /* Make entries in Protocol column and Info column on summary display */
374   if (check_col (pinfo->cinfo, COL_PROTOCOL))
375     col_set_str (pinfo->cinfo, COL_PROTOCOL, "DOCSIS");
376
377   if (check_col (pinfo->cinfo, COL_INFO))
378     {
379       col_clear (pinfo->cinfo, COL_INFO);
380       switch (fctype)
381         {
382         case FCTYPE_PACKET:
383           col_set_str (pinfo->cinfo, COL_INFO, "Packet PDU");
384           break;
385         case FCTYPE_ATMPDU:
386           col_set_str (pinfo->cinfo, COL_INFO, "ATM PDU");
387           break;
388         case FCTYPE_RESRVD:
389           col_set_str (pinfo->cinfo, COL_INFO, "Reserved PDU");
390           break;
391         case FCTYPE_MACSPC:
392           if (fcparm == 0x02)
393             col_add_fstr (pinfo->cinfo, COL_INFO,
394                           "Request Frame SID = %u Mini Slots = %u", len_sid,
395                           mac_parm);
396           else if (fcparm == 0x03)
397             col_set_str (pinfo->cinfo, COL_INFO, "Fragmented Frame");
398           else
399             col_set_str (pinfo->cinfo, COL_INFO, "Mac Specific");
400           break;
401         }                       /* switch */
402     }                           /* if */
403
404 /* In the interest of speed, if "tree" is NULL, don't do any work not
405    necessary to generate protocol tree items. */
406   if (tree)
407     {
408       ti = proto_tree_add_protocol_format (tree, proto_docsis, tvb, 0,
409                                            hdrlen, "DOCSIS");
410       docsis_tree = proto_item_add_subtree (ti, ett_docsis);
411
412 /* add an item to the subtree, see section 1.6 for more information */
413       proto_tree_add_item (docsis_tree, hf_docsis_fctype, tvb, 0, 1, FALSE);
414       switch (fctype)
415         {
416         case FCTYPE_PACKET:
417         case FCTYPE_ATMPDU:
418         case FCTYPE_RESRVD:
419           proto_tree_add_item (docsis_tree, hf_docsis_fcparm, tvb, 0, 1,
420                                FALSE);
421           proto_tree_add_item (docsis_tree, hf_docsis_ehdron, tvb, 0, 1,
422                                FALSE);
423           if (ehdron == 0x01)
424             {
425               proto_tree_add_item (docsis_tree, hf_docsis_ehdrlen, tvb, 1, 1,
426                                    FALSE);
427               proto_tree_add_item (docsis_tree, hf_docsis_lensid, tvb, 2, 2,
428                                    FALSE);
429               dissect_ehdr (tvb, docsis_tree, isfrag);
430               proto_tree_add_item (docsis_tree, hf_docsis_hcs, tvb,
431                                    4 + mac_parm, 2, FALSE);
432             }
433           else
434             {
435               proto_tree_add_item (docsis_tree, hf_docsis_macparm, tvb, 1, 1,
436                                    FALSE);
437               proto_tree_add_item (docsis_tree, hf_docsis_lensid, tvb, 2, 2,
438                                    FALSE);
439               proto_tree_add_item (docsis_tree, hf_docsis_hcs, tvb, 4, 2,
440                                    FALSE);
441             }
442           break;
443         case FCTYPE_MACSPC:
444           proto_tree_add_item (docsis_tree, hf_docsis_machdr_fcparm, tvb, 0,
445                                1, FALSE);
446           proto_tree_add_item (docsis_tree, hf_docsis_ehdron, tvb, 0, 1,
447                                FALSE);
448           /* Decode for a Request Frame.  No extended header */
449           if (fcparm == 0x02)
450             {
451               proto_tree_add_uint (docsis_tree, hf_docsis_mini_slots, tvb, 1,
452                                    1, mac_parm);
453               proto_tree_add_uint (docsis_tree, hf_docsis_sid, tvb, 2, 2,
454                                    len_sid);
455               proto_tree_add_item (docsis_tree, hf_docsis_hcs, tvb, 4, 2,
456                                    FALSE);
457               break;
458             }
459           /* Check if this is a fragmentation header */
460           if (fcparm == 0x03)
461             {
462               isfrag = TRUE;
463             }
464           /* Decode for a Concatenated Header.  No Extended Header */
465           if (fcparm == 0x1c)
466             {
467               proto_item_append_text (ti, " (Concatenated Header)");
468               proto_tree_add_item (docsis_tree, hf_docsis_concat_cnt, tvb, 1,
469                                    1, FALSE);
470               proto_tree_add_item (docsis_tree, hf_docsis_lensid, tvb, 2, 2,
471                                    FALSE);
472               proto_tree_add_item (docsis_tree, hf_docsis_hcs, tvb, 4, 2,
473                                    FALSE);
474               break;
475             }
476           /* If Extended header is present then decode it */
477           if (ehdron == 0x01)
478             {
479               proto_tree_add_item (docsis_tree, hf_docsis_ehdrlen, tvb, 1, 1,
480                                    FALSE);
481               proto_tree_add_item (docsis_tree, hf_docsis_lensid, tvb, 2, 2,
482                                    FALSE);
483               dissect_ehdr (tvb, docsis_tree, isfrag);
484               proto_tree_add_item (docsis_tree, hf_docsis_hcs, tvb,
485                                    4 + mac_parm, 2, FALSE);
486               break;
487             }
488           /* default case for all other Mac Frame Types */
489           proto_tree_add_item (docsis_tree, hf_docsis_macparm, tvb, 1, 1,
490                                FALSE);
491           proto_tree_add_item (docsis_tree, hf_docsis_lensid, tvb, 2, 2,
492                                FALSE);
493           proto_tree_add_item (docsis_tree, hf_docsis_hcs, tvb, 4, 2, FALSE);
494           break;
495         }
496     }
497
498 /* If this protocol has a sub-dissector call it here, see section 1.8 */
499   switch (fctype)
500     {
501     case FCTYPE_PACKET:
502       if (pdulen >= 0)
503         {
504           if (pdulen > 0)
505             {
506               next_tvb = tvb_new_subset (tvb, hdrlen, captured_length, pdulen);
507               call_dissector (eth_withoutfcs_handle, next_tvb, pinfo, tree);
508             }
509           if (concatlen > 0)
510             {
511               concatlen = concatlen - framelen;
512               concatpos += framelen;
513             }
514         }
515       break;
516     case FCTYPE_MACSPC:
517       switch (fcparm)
518         {
519         case 0x00:
520         case 0x01:
521           if (pdulen > 0)
522             {
523               mgt_tvb = tvb_new_subset (tvb, hdrlen, captured_length, pdulen);
524               call_dissector (docsis_mgmt_handle, mgt_tvb, pinfo, tree);
525             }
526           if (concatlen > 0)
527             {
528               concatlen = concatlen - framelen;
529               concatpos += framelen;
530             }
531           break;
532         case 0x02:
533           /* Don't do anything for a Request Frame */
534           break;
535         case 0x03:
536           /* For Fragmentation Frames simply dissect using the data
537            * dissector as we don't handle them yet
538            */
539           if (pdulen > 0)
540             {
541               mgt_tvb = tvb_new_subset (tvb, hdrlen, captured_length, pdulen);
542               call_dissector (data_handle, mgt_tvb, pinfo, tree);
543             }
544           if (concatlen > 0)
545             {
546               concatlen = concatlen - framelen;
547               concatpos += framelen;
548             }
549           break;
550         case 0x1c:
551           /* call the docsis dissector on the same frame
552            * to dissect DOCSIS frames within the concatenated
553            * frame.  concatpos and concatlen are declared
554            * static and are decremented and incremented
555            * respectively when the inner
556            * docsis frames are dissected. */
557           while (concatlen > 0)
558             {
559               oldconcatlen = concatlen;
560               next_tvb = tvb_new_subset (tvb, concatpos, -1, concatlen);
561               call_dissector (docsis_handle, next_tvb, pinfo, tree);
562               if (oldconcatlen <= concatlen)
563                 THROW(ReportedBoundsError);
564             }
565           concatlen = 0;
566           concatpos = 0;
567           if (check_col (pinfo->cinfo, COL_INFO))
568             col_set_str (pinfo->cinfo, COL_INFO, "Concatenated Frame");
569           break;
570         }
571       break;
572     }
573 }
574
575
576 /* Register the protocol with Wireshark */
577
578 /* this format is require because a script is used to build the C function
579    that calls all the protocol registration.
580 */
581
582
583 void
584 proto_register_docsis (void)
585 {
586
587 /* Setup list of header fields  See Section 1.6.1 for details*/
588   static hf_register_info hf[] = {
589     {&hf_docsis_fctype,
590      {"FCType", "docsis.fctype",
591       FT_UINT8, BASE_HEX, VALS (fctype_vals), 0xC0,
592       "Frame Control Type", HFILL}
593      },
594     {&hf_docsis_fcparm,
595      {"FCParm", "docsis.fcparm",
596       FT_UINT8, BASE_DEC, NULL, 0x3E,
597       "Parameter Field", HFILL}
598      },
599     {&hf_docsis_machdr_fcparm,
600      {"FCParm", "docsis.fcparm",
601       FT_UINT8, BASE_HEX, VALS (fcparm_vals), 0x3E,
602       "Parameter Field", HFILL}
603      },
604     {&hf_docsis_ehdron,
605      {"EHDRON", "docsis.ehdron",
606       FT_BOOLEAN, 8, TFS (&ehdron_tfs), 0x01,
607       "Extended Header Presence", HFILL}
608      },
609     {&hf_docsis_macparm,
610      {"MacParm", "docsis.macparm",
611       FT_UINT8, BASE_HEX, NULL, 0x0,
612       "Mac Parameter Field", HFILL}
613      },
614     {&hf_docsis_concat_cnt,
615      {"Number of Concatenated Frames", "docsis.macparm",
616       FT_UINT8, BASE_DEC, NULL, 0x0,
617       "Number of Concatenated Frames", HFILL}
618      },
619     {&hf_docsis_ehdrlen,
620      {"Extended Header Length (bytes)", "docsis.macparm",
621       FT_UINT8, BASE_DEC, NULL, 0x0,
622       "Mac Parameter Field", HFILL}
623      },
624     {&hf_docsis_lensid,
625      {"Length after HCS (bytes)", "docsis.lensid",
626       FT_UINT16, BASE_DEC, NULL, 0x0,
627       "Length or SID", HFILL}
628      },
629     {&hf_docsis_eh_type,
630      {"Type", "docsis.ehdr.type",
631       FT_UINT8, BASE_DEC, VALS (eh_type_vals), 0xF0,
632       "TLV Type", HFILL}
633      },
634     {&hf_docsis_eh_len,
635      {"Length", "docsis.ehdr.len",
636       FT_UINT8, BASE_DEC, NULL, 0x0F,
637       "TLV Len", HFILL}
638      },
639     {&hf_docsis_eh_val,
640      {"Value", "docsis.ehdr.value",
641       FT_BYTES, BASE_HEX, NULL, 0x0,
642       "TLV Value", HFILL}
643      },
644     {&hf_docsis_frag_rsvd,
645      {"Reserved", "docsis.frag_rsvd",
646       FT_UINT8, BASE_DEC, NULL, 0xC0,
647       "Reserved", HFILL}
648      },
649     {&hf_docsis_frag_first,
650      {"First Frame", "docsis.frag_first",
651       FT_BOOLEAN, 8, NULL, 0x20,
652       "First Frame", HFILL}
653      },
654     {&hf_docsis_frag_last,
655      {"Last Frame", "docsis.frag_last",
656       FT_BOOLEAN, 8, NULL, 0x10,
657       "Last Frame", HFILL}
658      },
659     {&hf_docsis_frag_seq,
660      {"Fragmentation Sequence #", "docsis.frag_seq",
661       FT_UINT8, BASE_DEC, NULL, 0x0F,
662       "Fragmentation Sequence Number", HFILL}
663      },
664     {&hf_docsis_sid,
665      {"SID", "docsis.ehdr.sid",
666       FT_UINT16, BASE_DEC, NULL, 0x3FFF,
667       "Service Identifier", HFILL}
668      },
669     {&hf_docsis_said,
670      {"SAID", "docsis.ehdr.said",
671       FT_UINT16, BASE_DEC, NULL, 0x3FFF,
672       "Security Association Identifier", HFILL}
673      },
674     {&hf_docsis_reserved,
675      {"Reserved", "docsis.ehdr.rsvd",
676       FT_UINT8, BASE_HEX, NULL, 0x3FFF,
677       "Reserved Byte", HFILL}
678      },
679     {&hf_docsis_mini_slots,
680      {"MiniSlots", "docsis.ehdr.minislots",
681       FT_UINT8, BASE_DEC, NULL, 0x0,
682       "Mini Slots Requested", HFILL}
683      },
684     {&hf_docsis_key_seq,
685      {"Key Sequence", "docsis.ehdr.keyseq",
686       FT_UINT8, BASE_DEC, NULL, 0xF0,
687       "Key Sequence", HFILL}
688      },
689     {&hf_docsis_ehdr_ver,
690      {"Version", "docsis.ehdr.ver",
691       FT_UINT8, BASE_DEC, NULL, 0x0F,
692       "Version", HFILL}
693      },
694     {&hf_docsis_ehdr_phsi,
695      {"Payload Header Suppression Index", "docsis.ehdr.phsi",
696       FT_UINT8, BASE_DEC, NULL, 0x0,
697       "Payload Header Suppression Index", HFILL}
698      },
699     {&hf_docsis_ehdr_qind,
700      {"Queue Indicator", "docsis.ehdr.qind",
701       FT_BOOLEAN, 8, TFS(&qind_tfs), 0x80,
702       "Queue Indicator", HFILL}
703      },
704     {&hf_docsis_ehdr_grants,
705      {"Active Grants", "docsis.ehdr.act_grants",
706       FT_UINT8, BASE_DEC, NULL, 0x7F,
707       "Active Grants", HFILL}
708      },
709     {&hf_docsis_hcs,
710      {"Header check sequence", "docsis.hcs",
711       FT_UINT16, BASE_HEX, NULL, 0x0,
712       "Header check sequence", HFILL},
713      },
714     {&hf_docsis_bpi_en,
715      {"Encryption", "docsis.bpi_en",
716       FT_BOOLEAN, 8, TFS (&ena_dis_tfs), 0x80,
717       "BPI Enable", HFILL},
718      },
719     {&hf_docsis_toggle_bit,
720      {"Toggle", "docsis.toggle_bit",
721       FT_BOOLEAN, 8, TFS (&odd_even_tfs), 0x40,
722       "Toggle", HFILL},
723      },
724
725   };
726
727 /* Setup protocol subtree array */
728   static gint *ett[] = {
729     &ett_docsis,
730     &ett_ehdr,
731   };
732
733   docsis_dissector_table = register_dissector_table ("docsis",
734                                                      "DOCSIS Encapsulation Type",
735                                                      FT_UINT8, BASE_DEC);
736
737 /* Register the protocol name and description */
738   proto_docsis = proto_register_protocol ("DOCSIS 1.1", "DOCSIS", "docsis");
739
740 /* Required function calls to register the header fields and subtrees used */
741   proto_register_field_array (proto_docsis, hf, array_length (hf));
742   proto_register_subtree_array (ett, array_length (ett));
743
744   register_dissector ("docsis", dissect_docsis, proto_docsis);
745 }
746
747
748 /* If this dissector uses sub-dissector registration add a registration routine.
749    This format is required because a script is used to find these routines and
750    create the code that calls these routines.
751 */
752 void
753 proto_reg_handoff_docsis (void)
754 {
755
756
757   docsis_handle = find_dissector ("docsis");
758   data_handle = find_dissector ("data");
759   dissector_add ("wtap_encap", WTAP_ENCAP_DOCSIS, docsis_handle);
760
761   docsis_mgmt_handle = find_dissector ("docsis_mgmt");
762   eth_withoutfcs_handle = find_dissector ("eth_withoutfcs");
763 }