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