From Yi Zhang:
[obnox/wireshark/wip.git] / plugins / docsis / packet-dcd.c
1 /* packet-dcd.c
2  * Routines for DCD Message dissection
3  * Copyright 2004, Darryl Hymel <darryl.hymel[AT]arrisi.com>
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 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include <epan/packet.h>
31
32 #define DCD_DOWN_CLASSIFIER 23
33 #define DCD_DSG_RULE 50
34 #define DCD_DSG_CONFIG 51
35
36 /* Define Downstrean Classifier subtypes
37  * These are subtype of DCD_DOWN_CLASSIFIER (23)
38  */
39
40 #define DCD_CFR_ID 2
41 #define DCD_CFR_RULE_PRI 5
42 #define DCD_CFR_IP_CLASSIFIER 9
43
44 /* Define IP Classifier sub-subtypes
45  * These are subtypes of DCD_CFR_IP_CLASSIFIER (23.9)
46  */
47 #define DCD_CFR_IP_SOURCE_ADDR 3
48 #define DCD_CFR_IP_SOURCE_MASK 4
49 #define DCD_CFR_IP_DEST_ADDR 5
50 #define DCD_CFR_IP_DEST_MASK 6
51 #define DCD_CFR_TCPUDP_SRCPORT_START 7
52 #define DCD_CFR_TCPUDP_SRCPORT_END 8
53 #define DCD_CFR_TCPUDP_DSTPORT_START 9
54 #define DCD_CFR_TCPUDP_DSTPORT_END 10
55
56 /* Define DSG Rule subtypes
57  * These are subtype of DCD_DSG_RULE (50)
58  */
59
60 #define DCD_RULE_ID 1
61 #define DCD_RULE_PRI 2
62 #define DCD_RULE_UCID_RNG 3
63 #define DCD_RULE_CLIENT_ID 4
64 #define DCD_RULE_TUNL_ADDR 5
65 #define DCD_RULE_CFR_ID 6
66 #define DCD_RULE_VENDOR_SPEC 43
67 /* Define DSG Rule Client ID sub-subtypes
68  * These are subtypes of DCD_RULE_CLIENT_ID (50.4)
69  */
70 #define DCD_CLID_BCAST_ID 1
71 #define DCD_CLID_KNOWN_MAC_ADDR 2
72 #define DCD_CLID_CA_SYS_ID 3
73 #define DCD_CLID_APP_ID 4
74
75 /* Define DSG Configuration subtypes
76  * These are subtype of DCD_DSG_CONFIG (51)
77  */
78
79 #define DCD_CFG_CHAN_LST 1
80 #define DCD_CFG_TDSG1 2
81 #define DCD_CFG_TDSG2 3
82 #define DCD_CFG_TDSG3 4
83 #define DCD_CFG_TDSG4 5
84 #define DCD_CFG_VENDOR_SPEC 43
85
86 /* Initialize the protocol and registered fields */
87 static int proto_docsis_dcd = -1;
88
89 static int hf_docsis_dcd_config_ch_cnt = -1;
90 static int hf_docsis_dcd_num_of_frag = -1;
91 static int hf_docsis_dcd_frag_sequence_num = -1;
92 static int hf_docsis_dcd_cfr_id = -1;
93 static int hf_docsis_dcd_cfr_rule_pri = -1;
94 static int hf_docsis_dcd_cfr_ip_source_addr = -1;
95 static int hf_docsis_dcd_cfr_ip_source_mask = -1;
96 static int hf_docsis_dcd_cfr_ip_dest_addr = -1;
97 static int hf_docsis_dcd_cfr_ip_dest_mask = -1;
98 static int hf_docsis_dcd_cfr_tcpudp_srcport_start = -1;
99 static int hf_docsis_dcd_cfr_tcpudp_srcport_end = -1;
100 static int hf_docsis_dcd_cfr_tcpudp_dstport_start = -1;
101 static int hf_docsis_dcd_cfr_tcpudp_dstport_end = -1;
102 static int hf_docsis_dcd_rule_id = -1;
103 static int hf_docsis_dcd_rule_pri = -1;
104 static int hf_docsis_dcd_rule_ucid_list = -1;
105 static int hf_docsis_dcd_clid_bcast_id = -1;
106 static int hf_docsis_dcd_clid_known_mac_addr = -1;
107 static int hf_docsis_dcd_clid_ca_sys_id = -1;
108 static int hf_docsis_dcd_clid_app_id = -1;
109 static int hf_docsis_dcd_rule_tunl_addr = -1;
110 static int hf_docsis_dcd_rule_cfr_id = -1;
111 static int hf_docsis_dcd_rule_vendor_spec = -1;
112 static int hf_docsis_dcd_cfg_chan = -1;
113 static int hf_docsis_dcd_cfg_tdsg1 = -1;
114 static int hf_docsis_dcd_cfg_tdsg2 = -1;
115 static int hf_docsis_dcd_cfg_tdsg3 = -1;
116 static int hf_docsis_dcd_cfg_tdsg4 = -1;
117 static int hf_docsis_dcd_cfg_vendor_spec = -1;
118
119 /* Initialize the subtree pointers */
120 static gint ett_docsis_dcd = -1;
121 static gint ett_docsis_dcd_cfr = -1;
122 static gint ett_docsis_dcd_cfr_ip = -1;
123 static gint ett_docsis_dcd_rule = -1;
124 static gint ett_docsis_dcd_clid = -1;
125 static gint ett_docsis_dcd_cfg = -1;
126
127 /* Code to actually dissect the packets */
128 static void
129 dissect_dcd_dsg_cfg (tvbuff_t * tvb, proto_tree * tree, int start, guint16 len)
130 {
131   guint8 type, length;
132   proto_item *dcd_item;
133   proto_tree *dcd_tree;
134   int pos;
135    
136   pos = start;
137   dcd_item = proto_tree_add_text ( tree, tvb, start, len, "51 DCD DSG Config Encodings (Length = %u)", len);
138   dcd_tree = proto_item_add_subtree ( dcd_item , ett_docsis_dcd_cfg);
139   
140   while ( pos < ( start + len) ) 
141     {
142         type = tvb_get_guint8 (tvb, pos++);
143         length = tvb_get_guint8 (tvb, pos++);
144         
145         switch (type)
146           {
147             case DCD_CFG_CHAN_LST:
148               if (length == 4)
149                 {
150                   proto_tree_add_item (dcd_tree, hf_docsis_dcd_cfg_chan, tvb,
151                                        pos, length, ENC_BIG_ENDIAN);
152                 }
153               else
154                 {
155                   THROW (ReportedBoundsError);
156                 }
157               break;
158             case DCD_CFG_TDSG1:
159               if (length == 2)
160                 {
161                   proto_tree_add_item (dcd_tree, hf_docsis_dcd_cfg_tdsg1, tvb,
162                                    pos, length, ENC_BIG_ENDIAN);
163                 }
164               else 
165                 {
166                   THROW (ReportedBoundsError);
167                 }
168               break;
169             case DCD_CFG_TDSG2:
170               if (length == 2)
171                 {
172                   proto_tree_add_item (dcd_tree, hf_docsis_dcd_cfg_tdsg2, tvb,
173                                    pos, length, ENC_BIG_ENDIAN);
174                 }
175               else 
176                 {
177                   THROW (ReportedBoundsError);
178                 }
179               break;
180             case DCD_CFG_TDSG3:
181               if (length == 2)
182                 {
183                   proto_tree_add_item (dcd_tree, hf_docsis_dcd_cfg_tdsg3, tvb,
184                                    pos, length, ENC_BIG_ENDIAN);
185                 }
186               else 
187                 {
188                   THROW (ReportedBoundsError);
189                 }
190               break;
191             case DCD_CFG_TDSG4:
192               if (length == 2)
193                 {
194                   proto_tree_add_item (dcd_tree, hf_docsis_dcd_cfg_tdsg4, tvb,
195                                    pos, length, ENC_BIG_ENDIAN);
196                 }
197               else 
198                 {
199                   THROW (ReportedBoundsError);
200                 }
201               break;
202             case DCD_CFG_VENDOR_SPEC:
203                   proto_tree_add_item (dcd_tree, hf_docsis_dcd_cfg_vendor_spec, tvb,
204                                    pos, length, ENC_NA);
205               break;
206
207             }
208           pos = pos + length;
209       }
210 }
211 static void
212 dissect_dcd_down_classifier_ip (tvbuff_t * tvb, proto_tree * tree, int start, guint16 len)
213 {
214   guint8 type, length;
215   proto_item *dcd_item;
216   proto_tree *dcd_tree;
217   int pos;
218    
219   pos = start;
220   dcd_item = proto_tree_add_text ( tree, tvb, start, len, "23.9 DCD_CFR_IP Encodings (Length = %u)", len);
221   dcd_tree = proto_item_add_subtree ( dcd_item , ett_docsis_dcd_cfr_ip);
222   
223   while ( pos < ( start + len) ) 
224     {
225         type = tvb_get_guint8 (tvb, pos++);
226         length = tvb_get_guint8 (tvb, pos++);
227         
228         switch (type)
229           {
230             case DCD_CFR_IP_SOURCE_ADDR:
231               if (length == 4)
232                 {
233                   proto_tree_add_item (dcd_tree, hf_docsis_dcd_cfr_ip_source_addr, tvb,
234                                        pos, length, ENC_BIG_ENDIAN);
235                 }
236               else
237                 {
238                   THROW (ReportedBoundsError);
239                 }
240               break;
241             case DCD_CFR_IP_SOURCE_MASK:
242               if (length == 4)
243                 {
244                   proto_tree_add_item (dcd_tree, hf_docsis_dcd_cfr_ip_source_mask, tvb,
245                                        pos, length, ENC_BIG_ENDIAN);
246                 }
247               else
248                 {
249                   THROW (ReportedBoundsError);
250                 }
251               break;
252             case DCD_CFR_IP_DEST_ADDR:
253               if (length == 4)
254                 {
255                   proto_tree_add_item (dcd_tree, hf_docsis_dcd_cfr_ip_dest_addr, tvb,
256                                        pos, length, ENC_BIG_ENDIAN);
257                 }
258               else
259                 {
260                   THROW (ReportedBoundsError);
261                 }
262                 break;
263             case DCD_CFR_IP_DEST_MASK:
264               if (length == 4)
265                 {
266                   proto_tree_add_item (dcd_tree, hf_docsis_dcd_cfr_ip_dest_mask, tvb,
267                                        pos, length, ENC_BIG_ENDIAN);
268                 }
269               else
270                 {
271                   THROW (ReportedBoundsError);
272                 }
273                 break;
274             case DCD_CFR_TCPUDP_SRCPORT_START:
275               if (length == 2)
276                 {
277                   proto_tree_add_item (dcd_tree, hf_docsis_dcd_cfr_tcpudp_srcport_start, tvb,
278                                        pos, length, ENC_BIG_ENDIAN);
279                 }
280               else
281                 {
282                   THROW (ReportedBoundsError);
283                 }
284                 break;
285             case DCD_CFR_TCPUDP_SRCPORT_END:
286               if (length == 2)
287                 {
288                   proto_tree_add_item (dcd_tree, hf_docsis_dcd_cfr_tcpudp_srcport_end, tvb,
289                                        pos, length, ENC_BIG_ENDIAN);
290                 }
291               else
292                 {
293                   THROW (ReportedBoundsError);
294                 }
295                 break;
296             case DCD_CFR_TCPUDP_DSTPORT_START:
297               if (length == 2)
298                 {
299                   proto_tree_add_item (dcd_tree, hf_docsis_dcd_cfr_tcpudp_dstport_start, tvb,
300                                        pos, length, ENC_BIG_ENDIAN);
301                 }
302               else
303                 {
304                   THROW (ReportedBoundsError);
305                 }
306                 break;
307             case DCD_CFR_TCPUDP_DSTPORT_END:
308               if (length == 2)
309                 {
310                   proto_tree_add_item (dcd_tree, hf_docsis_dcd_cfr_tcpudp_dstport_end, tvb,
311                                        pos, length, ENC_BIG_ENDIAN);
312                 }
313               else
314                 {
315                   THROW (ReportedBoundsError);
316                 }
317                 break;
318             }
319           pos = pos + length;
320       }
321 }
322 static void
323 dissect_dcd_clid (tvbuff_t * tvb, proto_tree * tree, int start, guint16 len)
324 {
325   guint8 type, length;
326   proto_item *dcd_item;
327   proto_tree *dcd_tree;
328   int pos;
329    
330   pos = start;
331   dcd_item = proto_tree_add_text ( tree, tvb, start, len, "50.4 DCD Rule ClientID Encodings (Length = %u)", len);
332   dcd_tree = proto_item_add_subtree ( dcd_item , ett_docsis_dcd_clid);
333   
334   while ( pos < ( start + len) ) 
335     {
336         type = tvb_get_guint8 (tvb, pos++);
337         length = tvb_get_guint8 (tvb, pos++);
338         
339         switch (type)
340           {
341                 case DCD_CLID_BCAST_ID:
342                         if (length == 2)
343                         {
344                                 proto_tree_add_item(dcd_tree, hf_docsis_dcd_clid_bcast_id, tvb, pos, length, ENC_BIG_ENDIAN);
345                         }
346                         else
347                         {
348                                 THROW (ReportedBoundsError);
349                         }
350                         break;
351             case DCD_CLID_KNOWN_MAC_ADDR:
352               if (length == 6)
353                 {
354                   proto_tree_add_item (dcd_tree, hf_docsis_dcd_clid_known_mac_addr, tvb,
355                                        pos, length, ENC_NA);
356                 }
357               else
358                 {
359                   THROW (ReportedBoundsError);
360                 }
361               break;
362             case DCD_CLID_CA_SYS_ID:
363               if (length == 2)
364                 {
365                   proto_tree_add_item (dcd_tree, hf_docsis_dcd_clid_ca_sys_id, tvb,
366                                        pos, length, ENC_BIG_ENDIAN);
367                 }
368               else
369                 {
370                   THROW (ReportedBoundsError);
371                 }
372               break;
373             case DCD_CLID_APP_ID:
374               if (length == 2)
375                 {
376                   proto_tree_add_item (dcd_tree, hf_docsis_dcd_clid_app_id, tvb,
377                                        pos, length, ENC_BIG_ENDIAN);
378                 }
379               else
380                 {
381                   THROW (ReportedBoundsError);
382                 }
383                 break;
384             }
385           pos = pos + length;
386       }
387 }
388 static void
389 dissect_dcd_dsg_rule (tvbuff_t * tvb, proto_tree * tree, int start, guint16 len)
390 {
391   guint8 type, length;
392   proto_item *dcd_item;
393   proto_tree *dcd_tree;
394   int pos;
395    
396   pos = start;
397   dcd_item = proto_tree_add_text ( tree, tvb, start, len, "50 DCD DSG Rule Encodings (Length = %u)", len);
398   dcd_tree = proto_item_add_subtree ( dcd_item , ett_docsis_dcd_rule);
399   
400   while ( pos < ( start + len) ) 
401     {
402         type = tvb_get_guint8 (tvb, pos++);
403         length = tvb_get_guint8 (tvb, pos++);
404         
405         switch (type)
406           {
407             case DCD_RULE_ID:
408               if (length == 1)
409                 {
410                   proto_tree_add_item (dcd_tree, hf_docsis_dcd_rule_id, tvb,
411                                        pos, length, ENC_BIG_ENDIAN);
412                 }
413               else
414                 {
415                   THROW (ReportedBoundsError);
416                 }
417               break;
418             case DCD_RULE_PRI:
419               if (length == 1)
420                 {
421                   proto_tree_add_item (dcd_tree, hf_docsis_dcd_rule_pri, tvb,
422                                    pos, length, ENC_BIG_ENDIAN);
423                 }
424               else 
425                 {
426                   THROW (ReportedBoundsError);
427                 }
428               break;
429             case DCD_RULE_UCID_RNG:
430                   proto_tree_add_item (dcd_tree, hf_docsis_dcd_rule_ucid_list, tvb,
431                                    pos, length, ENC_NA);
432               break;
433             case DCD_RULE_CLIENT_ID:
434               dissect_dcd_clid (tvb , dcd_tree , pos , length );
435               break;
436             case DCD_RULE_TUNL_ADDR:
437               if (length == 6)
438                 {
439                   proto_tree_add_item (dcd_tree, hf_docsis_dcd_rule_tunl_addr, tvb,
440                                    pos, length, ENC_NA);
441                 }
442               else 
443                 {
444                   THROW (ReportedBoundsError);
445                 }
446               break;
447             case DCD_RULE_CFR_ID:
448               if (length == 2)
449                 {
450                   proto_tree_add_item (dcd_tree, hf_docsis_dcd_rule_cfr_id, tvb,
451                                    pos, length, ENC_BIG_ENDIAN);
452                 }
453               else 
454                 {
455                   THROW (ReportedBoundsError);
456                 }
457               break;
458             case DCD_RULE_VENDOR_SPEC:
459                   proto_tree_add_item (dcd_tree, hf_docsis_dcd_rule_vendor_spec, tvb,
460                                    pos, length, ENC_NA);
461               break;
462
463             }
464           pos = pos + length;
465       }
466 }
467 static void
468 dissect_dcd_down_classifier (tvbuff_t * tvb, proto_tree * tree, int start, guint16 len)
469 {
470   guint8 type, length;
471   proto_item *dcd_item;
472   proto_tree *dcd_tree;
473   int pos;
474    
475   pos = start;
476   dcd_item = proto_tree_add_text ( tree, tvb, start, len, "23 DCD_CFR Encodings (Length = %u)", len);
477   dcd_tree = proto_item_add_subtree ( dcd_item , ett_docsis_dcd_cfr);
478   
479   while ( pos < ( start + len) ) 
480     {
481         type = tvb_get_guint8 (tvb, pos++);
482         length = tvb_get_guint8 (tvb, pos++);
483         
484         switch (type)
485           {
486             case DCD_CFR_ID:
487               if (length == 2)
488                 {
489                   proto_tree_add_item (dcd_tree, hf_docsis_dcd_cfr_id, tvb,
490                                        pos, length, ENC_BIG_ENDIAN);
491                 }
492               else
493                 {
494                   THROW (ReportedBoundsError);
495                 }
496               break;
497             case DCD_CFR_RULE_PRI:
498               if (length == 1)
499                 {
500                   proto_tree_add_item (dcd_tree, hf_docsis_dcd_cfr_rule_pri, tvb,
501                                    pos, length, ENC_BIG_ENDIAN);
502                 }
503               else 
504                 {
505                   THROW (ReportedBoundsError);
506                 }
507               break;
508             case DCD_CFR_IP_CLASSIFIER:
509               dissect_dcd_down_classifier_ip (tvb , dcd_tree , pos , length );
510               break;
511
512             }
513           pos = pos + length;
514       }
515 }
516 static void
517 dissect_dcd (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
518 {
519   guint16 pos;
520   guint8 type, length;
521   proto_tree *dcd_tree;
522   proto_item *dcd_item;
523   guint16 len;
524
525   len = tvb_length_remaining (tvb, 0);
526
527   col_set_str(pinfo->cinfo, COL_INFO, "DCD Message: ");
528
529   if (tree)
530     {
531       dcd_item =
532         proto_tree_add_protocol_format (tree, proto_docsis_dcd, tvb, 0,
533                                         tvb_length_remaining (tvb, 0),
534                                         "DCD Message");
535       dcd_tree = proto_item_add_subtree (dcd_item, ett_docsis_dcd);
536       proto_tree_add_item (dcd_tree, hf_docsis_dcd_config_ch_cnt, tvb, 0, 1, ENC_BIG_ENDIAN);
537       proto_tree_add_item (dcd_tree, hf_docsis_dcd_num_of_frag, tvb, 1, 1, ENC_BIG_ENDIAN);
538       proto_tree_add_item (dcd_tree, hf_docsis_dcd_frag_sequence_num, tvb, 2, 1, ENC_BIG_ENDIAN);
539
540       pos = 3;
541       while (pos < len)
542         {
543           type = tvb_get_guint8 (tvb, pos++);
544           length = tvb_get_guint8 (tvb, pos++);
545           switch (type)
546             {
547             case DCD_DOWN_CLASSIFIER:
548               dissect_dcd_down_classifier (tvb , dcd_tree , pos , length );
549               break;
550             case DCD_DSG_RULE:
551               dissect_dcd_dsg_rule (tvb , dcd_tree , pos , length );
552               break;
553             case DCD_DSG_CONFIG:
554               dissect_dcd_dsg_cfg (tvb , dcd_tree , pos , length );
555               break;
556             }                   /* switch(type) */
557           pos = pos + length;
558         }                       /* while (pos < len) */
559     }                           /* if (tree) */
560
561 }
562 /* Register the protocol with Wireshark */
563
564 /* this format is require because a script is used to build the C function
565    that calls all the protocol registration.
566 */
567
568
569 void
570 proto_register_docsis_dcd (void)
571 {
572 /* Setup list of header fields  See Section 1.6.1 for details*/
573   static hf_register_info hf[] = {
574     {&hf_docsis_dcd_config_ch_cnt,
575       {
576       "Configuration Change Count", 
577       "docsis_dcd.config_ch_cnt",
578       FT_UINT8, BASE_DEC, NULL, 0x0,
579       NULL, 
580       HFILL
581       }
582     },
583     {&hf_docsis_dcd_num_of_frag,
584       {
585       "Number of Fragments", 
586       "docsis_dcd.num_of_frag",
587       FT_UINT8, BASE_DEC, NULL, 0x0,
588       NULL, 
589       HFILL
590       }
591     },
592     {&hf_docsis_dcd_frag_sequence_num,
593       {
594       "Fragment Sequence Number", 
595       "docsis_dcd.frag_sequence_num",
596       FT_UINT8, BASE_DEC, NULL, 0x0,
597       NULL, 
598       HFILL
599       }
600     },
601     {&hf_docsis_dcd_cfr_id,
602       {
603       "Downstream Classifier Id", 
604       "docsis_dcd.cfr_id",
605       FT_UINT16, BASE_DEC, NULL, 0x0,
606       NULL, 
607       HFILL
608       }
609     },
610     {&hf_docsis_dcd_cfr_rule_pri,
611       {
612       "Downstream Classifier Rule Priority", 
613       "docsis_dcd.cfr_rule_pri",
614       FT_UINT8, BASE_DEC, NULL, 0x0,
615       NULL, 
616       HFILL
617       }
618     },
619     {&hf_docsis_dcd_cfr_ip_source_addr,
620       {
621       "Downstream Classifier IP Source Address", 
622       "docsis_dcd.cfr_ip_source_addr",
623       FT_IPv4, BASE_NONE, NULL, 0x0,
624       NULL, 
625       HFILL
626       }
627     },
628     {&hf_docsis_dcd_cfr_ip_source_mask,
629       {
630       "Downstream Classifier IP Source Mask", 
631       "docsis_dcd.cfr_ip_source_mask",
632       FT_IPv4, BASE_NONE, NULL, 0x0,
633       NULL, 
634       HFILL
635       }
636     },
637     {&hf_docsis_dcd_cfr_ip_dest_addr,
638       {
639       "Downstream Classifier IP Destination Address", 
640       "docsis_dcd.cfr_ip_dest_addr",
641       FT_IPv4, BASE_NONE, NULL, 0x0,
642       NULL, 
643       HFILL
644       }
645     },
646     {&hf_docsis_dcd_cfr_ip_dest_mask,
647       {
648       "Downstream Classifier IP Destination Mask", 
649       "docsis_dcd.cfr_ip_dest_mask",
650       FT_IPv4, BASE_NONE, NULL, 0x0,
651       "Downstream Classifier IP Destination Address", 
652       HFILL
653       }
654     },
655     {&hf_docsis_dcd_cfr_tcpudp_srcport_start,
656       {
657       "Downstream Classifier IP TCP/UDP Source Port Start", 
658       "docsis_dcd.cfr_ip_tcpudp_srcport_start",
659       FT_UINT16, BASE_DEC, NULL, 0x0,
660       NULL, 
661       HFILL
662       }
663     },
664     {&hf_docsis_dcd_cfr_tcpudp_srcport_end,
665       {
666       "Downstream Classifier IP TCP/UDP Source Port End", 
667       "docsis_dcd.cfr_ip_tcpudp_srcport_end",
668       FT_UINT16, BASE_DEC, NULL, 0x0,
669       NULL, 
670       HFILL
671       }
672     },
673     {&hf_docsis_dcd_cfr_tcpudp_dstport_start,
674       {
675       "Downstream Classifier IP TCP/UDP Destination Port Start", 
676       "docsis_dcd.cfr_ip_tcpudp_dstport_start",
677       FT_UINT16, BASE_DEC, NULL, 0x0,
678       NULL, 
679       HFILL
680       }
681     },
682     {&hf_docsis_dcd_cfr_tcpudp_dstport_end,
683       {
684       "Downstream Classifier IP TCP/UDP Destination Port End", 
685       "docsis_dcd.cfr_ip_tcpudp_dstport_end",
686       FT_UINT16, BASE_DEC, NULL, 0x0,
687       NULL, 
688       HFILL
689       }
690     },
691     {&hf_docsis_dcd_rule_id,
692       {
693       "DSG Rule Id", 
694       "docsis_dcd.rule_id",
695       FT_UINT8, BASE_DEC, NULL, 0x0,
696       NULL, 
697       HFILL
698       }
699     },
700     {&hf_docsis_dcd_rule_pri,
701       {
702       "DSG Rule Priority", 
703       "docsis_dcd.rule_pri",
704       FT_UINT8, BASE_DEC, NULL, 0x0,
705       NULL, 
706       HFILL
707       }
708     },
709     {&hf_docsis_dcd_rule_ucid_list,
710       {
711       "DSG Rule UCID Range", 
712       "docsis_dcd.rule_ucid_list",
713       FT_BYTES, BASE_NONE, NULL, 0x0,
714       NULL, 
715       HFILL
716       }
717     },
718         {&hf_docsis_dcd_clid_bcast_id,
719                 {
720                         "DSG Rule Client ID Broadcast ID",
721                         "docsis_dcd.clid_bcast_id",
722                         FT_UINT16, BASE_DEC, NULL, 0x0,
723                         NULL,
724                         HFILL
725                 }
726         },
727     {&hf_docsis_dcd_clid_known_mac_addr,
728       {
729       "DSG Rule Client ID Known MAC Address", 
730       "docsis_dcd.clid_known_mac_addr",
731       FT_ETHER, BASE_NONE, NULL, 0x0,
732       NULL, 
733       HFILL
734       }
735     },
736     {&hf_docsis_dcd_clid_ca_sys_id,
737       {
738       "DSG Rule Client ID CA System ID", 
739       "docsis_dcd.clid_ca_sys_id",
740       FT_UINT16, BASE_DEC, NULL, 0x0,
741       NULL, 
742       HFILL
743       }
744     },
745     {&hf_docsis_dcd_clid_app_id,
746       {
747       "DSG Rule Client ID Application ID", 
748       "docsis_dcd.clid_app_id",
749       FT_UINT16, BASE_DEC, NULL, 0x0,
750       NULL, 
751       HFILL
752       }
753     },
754     {&hf_docsis_dcd_rule_tunl_addr,
755       {
756       "DSG Rule Tunnel MAC Address", 
757       "docsis_dcd.rule_tunl_addr",
758       FT_ETHER, BASE_NONE, NULL, 0x0,
759       NULL, 
760       HFILL
761       }
762     },
763     {&hf_docsis_dcd_rule_cfr_id,
764       {
765       "DSG Rule Classifier ID", 
766       "docsis_dcd.rule_cfr_id",
767       FT_UINT16, BASE_DEC, NULL, 0x0,
768       NULL, 
769       HFILL
770       }
771     },
772     {&hf_docsis_dcd_rule_vendor_spec,
773       {
774       "DSG Rule Vendor Specific Parameters", 
775       "docsis_dcd.rule_vendor_spec",
776       FT_BYTES, BASE_NONE, NULL, 0x0,
777       NULL, 
778       HFILL
779       }
780     },
781     {&hf_docsis_dcd_cfg_chan,
782       {
783       "DSG Configuration Channel", 
784       "docsis_dcd.cfg_chan",
785       FT_UINT32, BASE_DEC, NULL, 0x0,
786       NULL, 
787       HFILL
788       }
789     },
790     {&hf_docsis_dcd_cfg_tdsg1,
791       {
792       "DSG Initialization Timeout (Tdsg1)", 
793       "docsis_dcd.cfg_tdsg1",
794       FT_UINT16, BASE_DEC, NULL, 0x0,
795       NULL, 
796       HFILL
797       }
798     },
799     {&hf_docsis_dcd_cfg_tdsg2,
800       {
801       "DSG Operational Timeout (Tdsg2)", 
802       "docsis_dcd.cfg_tdsg2",
803       FT_UINT16, BASE_DEC, NULL, 0x0,
804       NULL, 
805       HFILL
806       }
807     },
808     {&hf_docsis_dcd_cfg_tdsg3,
809       {
810       "DSG Two-Way Retry Timer (Tdsg3)", 
811       "docsis_dcd.cfg_tdsg3",
812       FT_UINT16, BASE_DEC, NULL, 0x0,
813       NULL, 
814       HFILL
815       }
816     },
817     {&hf_docsis_dcd_cfg_tdsg4,
818       {
819       "DSG One-Way Retry Timer (Tdsg4)", 
820       "docsis_dcd.cfg_tdsg4",
821       FT_UINT16, BASE_DEC, NULL, 0x0,
822       NULL, 
823       HFILL
824       }
825     },
826     {&hf_docsis_dcd_cfg_vendor_spec,
827       {
828       "DSG Configuration Vendor Specific Parameters", 
829       "docsis_dcd.cfg_vendor_spec",
830       FT_BYTES, BASE_NONE, NULL, 0x0,
831       NULL, 
832       HFILL
833       }
834     },
835
836   };
837
838 /* Setup protocol subtree array */
839   static gint *ett[] = {
840     &ett_docsis_dcd,
841     &ett_docsis_dcd_cfr,
842     &ett_docsis_dcd_cfr_ip,
843     &ett_docsis_dcd_rule,
844     &ett_docsis_dcd_clid,
845     &ett_docsis_dcd_cfg,
846   };
847
848 /* Register the protocol name and description */
849   proto_docsis_dcd =
850     proto_register_protocol ("DOCSIS Downstream Channel Descriptor",
851                              "DOCSIS DCD", "docsis_dcd");
852
853 /* Required function calls to register the header fields and subtrees used */
854   proto_register_field_array (proto_docsis_dcd, hf, array_length (hf));
855   proto_register_subtree_array (ett, array_length (ett));
856
857   register_dissector ("docsis_dcd", dissect_dcd, proto_docsis_dcd);
858 }
859
860
861 /* If this dissector uses sub-dissector registration add a registration routine.
862    This format is required because a script is used to find these routines and
863    create the code that calls these routines.
864 */
865 void
866 proto_reg_handoff_docsis_dcd (void)
867 {
868   dissector_handle_t docsis_dcd_handle;
869
870   docsis_dcd_handle = find_dissector ("docsis_dcd");
871   dissector_add_uint ("docsis_mgmt", 0x20, docsis_dcd_handle);
872
873 }