Use ENC_NA as proto_tree_add_item() encoding arg for FT_ETHER hf[] field type.
[obnox/wireshark/wip.git] / plugins / docsis / packet-bpkmattr.c
1 /* packet-bpkmattr.c
2  * Routines for Baseline Privacy Key Management Attributes 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 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <epan/packet.h>
31
32 /* BPKM Attributes defined in:
33  * http://www.cablemodem.com/downloads/specs/SP-BPI+_I10-030730.pdf
34  */
35 #define BPKM_RESERVED 0
36 #define BPKM_SERIAL_NUM 1
37 #define BPKM_MANUFACTURER_ID 2
38 #define BPKM_MAC_ADDR 3
39 #define BPKM_RSA_PUB_KEY 4
40 #define BPKM_CM_ID 5
41 #define BPKM_DISPLAY_STR 6
42 #define BPKM_AUTH_KEY 7
43 #define BPKM_TEK 8
44 #define BPKM_KEY_LIFETIME 9
45 #define BPKM_KEY_SEQ_NUM 10
46 #define BPKM_HMAC_DIGEST 11
47 #define BPKM_SAID 12
48 #define BPKM_TEK_PARAM 13
49 #define BPKM_OBSOLETED 14
50 #define BPKM_CBC_IV 15
51 #define BPKM_ERROR_CODE 16
52 #define BPKM_CA_CERT 17
53 #define BPKM_CM_CERT 18
54 #define BPKM_SEC_CAPABILITIES 19
55 #define BPKM_CRYPTO_SUITE 20
56 #define BPKM_CRYPTO_SUITE_LIST 21
57 #define BPKM_BPI_VERSION 22
58 #define BPKM_SA_DESCRIPTOR 23
59 #define BPKM_SA_TYPE 24
60 #define BPKM_SA_QUERY 25
61 #define BPKM_SA_QUERY_TYPE 26
62 #define BPKM_IP_ADDRESS 27
63 #define BPKM_DNLD_PARAMS 28
64 #define BPKM_VENDOR_DEFINED 127
65
66 /* Initialize the protocol and registered fields */
67 static int proto_docsis_bpkmattr = -1;
68 static int hf_docsis_bpkmattr_serial_num = -1;
69 static int hf_docsis_bpkmattr_manf_id = -1;
70 static int hf_docsis_bpkmattr_mac_addr = -1;
71 static int hf_docsis_bpkmattr_rsa_pub_key = -1;
72 static int hf_docsis_bpkmattr_cm_id = -1;
73 static int hf_docsis_bpkmattr_display_str = -1;
74 static int hf_docsis_bpkmattr_auth_key = -1;
75 static int hf_docsis_bpkmattr_tek = -1;
76 static int hf_docsis_bpkmattr_key_life = -1;
77 static int hf_docsis_bpkmattr_key_seq = -1;
78 static int hf_docsis_bpkmattr_hmac_digest = -1;
79 static int hf_docsis_bpkmattr_said = -1;
80 static int hf_docsis_bpkmattr_tek_params = -1;
81 static int hf_docsis_bpkmattr_cbc_iv = -1;
82 static int hf_docsis_bpkmattr_error_code = -1;
83 static int hf_docsis_bpkmattr_vendor_def = -1;
84 static int hf_docsis_bpkmattr_ca_cert = -1;
85 static int hf_docsis_bpkmattr_cm_cert = -1;
86 static int hf_docsis_bpkmattr_security_cap = -1;
87 static int hf_docsis_bpkmattr_crypto_suite = -1;
88 static int hf_docsis_bpkmattr_crypto_suite_list = -1;
89 static int hf_docsis_bpkmattr_bpi_version = -1;
90 static int hf_docsis_bpkmattr_sa_descr = -1;
91 static int hf_docsis_bpkmattr_sa_type = -1;
92 static int hf_docsis_bpkmattr_sa_query = -1;
93 static int hf_docsis_bpkmattr_sa_query_type = -1;
94 static int hf_docsis_bpkmattr_ip_address = -1;
95 static int hf_docsis_bpkmattr_download_param = -1;
96
97
98
99 /* Initialize the subtree pointers */
100 static gint ett_docsis_bpkmattr = -1;
101 static gint ett_docsis_bpkmattr_cmid = -1;
102 static gint ett_docsis_bpkmattr_scap = -1;
103 static gint ett_docsis_bpkmattr_tekp = -1;
104 static gint ett_docsis_bpkmattr_sadsc = -1;
105 static gint ett_docsis_bpkmattr_saqry = -1;
106 static gint ett_docsis_bpkmattr_dnld = -1;
107
108
109 static const value_string error_code_vals[] = {
110   {0, "no information"},
111   {1, "Unauthorized CM"},
112   {2, "Unauthorized SAID"},
113   {3, "Unsolicited"},
114   {4, "Invalid Key Sequence Number"},
115   {5, "Key Request authentication failure"},
116   {6, "Permanent Authorization Failure"},
117   {7, "Not authorized for requested downstream traffic flow"},
118   {8, "Downstream traffic flow not mapped to BPI+ SAID"},
119   {9, "Time of day not acquired"},
120   {0, NULL},
121 };
122
123 static const value_string crypto_suite_attr_vals[] = {
124   {0x0100, "CBC Mode, 56 Bit DES & no Data Authentication"},
125   {0x0200, "CBC Mode, 40 Bit DES & no Data Authentication"},
126   {0, NULL},
127 };
128
129 static const value_string bpi_ver_vals[] = {
130   {0, "Reserved"},
131   {1, "BPI+"},
132   {0, NULL},
133 };
134
135 /* Code to actually dissect the packets */
136
137 /* The dissect_attrs() function does the actual work to dissect the
138  * attributes.  It's called recursively, to dissect embedded attributes
139  */
140 static void
141 dissect_attrs (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
142 {
143   guint8 type;
144   guint16 length;
145   int pos = 0;
146   gint total_len;
147   proto_item *cmid_it, *tekp_it, *scap_it;
148   proto_item *saqry_it, *dnld_it, *sadsc_it;
149   proto_tree *cmid_tree, *tekp_tree, *scap_tree;
150   proto_tree *saqry_tree, *dnld_tree, *sadsc_tree;
151   tvbuff_t *cmid_tvb, *tekp_tvb, *scap_tvb;
152   tvbuff_t *saqry_tvb, *dnld_tvb, *sadsc_tvb;
153
154   total_len = tvb_reported_length_remaining (tvb, 0);
155   while (pos < total_len)
156     {
157       type = tvb_get_guint8 (tvb, pos++);
158       length = tvb_get_ntohs (tvb, pos);
159       pos += 2;
160       switch (type)
161         {
162         case BPKM_RESERVED:
163           break;
164         case BPKM_SERIAL_NUM:
165           proto_tree_add_item (tree, hf_docsis_bpkmattr_serial_num, tvb, pos,
166                                length, ENC_ASCII|ENC_NA);
167           break;
168         case BPKM_MANUFACTURER_ID:
169           if (length == 3)
170             proto_tree_add_item (tree, hf_docsis_bpkmattr_manf_id, tvb, pos,
171                                  length, ENC_NA);
172           else
173             THROW (ReportedBoundsError);
174           break;
175         case BPKM_MAC_ADDR:
176           if (length == 6)
177             proto_tree_add_item (tree, hf_docsis_bpkmattr_mac_addr, tvb, pos,
178                                  length, ENC_NA);
179           else
180             THROW (ReportedBoundsError);
181           break;
182         case BPKM_RSA_PUB_KEY:
183           proto_tree_add_item (tree, hf_docsis_bpkmattr_rsa_pub_key, tvb, pos,
184                                length, ENC_NA);
185           break;
186         case BPKM_CM_ID:
187           cmid_it =
188             proto_tree_add_text (tree, tvb, pos, length,
189                                  "5 CM Identification");
190           cmid_tree =
191             proto_item_add_subtree (cmid_it, ett_docsis_bpkmattr_cmid);
192           cmid_tvb = tvb_new_subset (tvb, pos, length, length);
193           dissect_attrs (cmid_tvb, pinfo, cmid_tree);
194           break;
195         case BPKM_DISPLAY_STR:
196           proto_tree_add_item (tree, hf_docsis_bpkmattr_display_str, tvb, pos,
197                                length, ENC_ASCII|ENC_NA);
198           break;
199         case BPKM_AUTH_KEY:
200           if ((length == 96) || (length == 128))
201             proto_tree_add_item (tree, hf_docsis_bpkmattr_auth_key, tvb, pos,
202                                  length, ENC_NA);
203           else
204             THROW (ReportedBoundsError);
205           break;
206         case BPKM_TEK:
207           if (length == 8)
208             proto_tree_add_item (tree, hf_docsis_bpkmattr_tek, tvb, pos,
209                                  length, ENC_NA);
210           else
211             THROW (ReportedBoundsError);
212           break;
213         case BPKM_KEY_LIFETIME:
214           if (length == 4)
215             proto_tree_add_item (tree, hf_docsis_bpkmattr_key_life, tvb, pos,
216                                  length, ENC_BIG_ENDIAN);
217           else
218             THROW (ReportedBoundsError);
219           break;
220         case BPKM_KEY_SEQ_NUM:
221           if (length == 1)
222             proto_tree_add_item (tree, hf_docsis_bpkmattr_key_seq, tvb, pos,
223                                  length, ENC_BIG_ENDIAN);
224           else
225             THROW (ReportedBoundsError);
226           break;
227         case BPKM_HMAC_DIGEST:
228           if (length == 20)
229             proto_tree_add_item (tree, hf_docsis_bpkmattr_hmac_digest, tvb,
230                                  pos, length, ENC_NA);
231           else
232             THROW (ReportedBoundsError);
233           break;
234         case BPKM_SAID:
235           if (length == 2)
236             proto_tree_add_item (tree, hf_docsis_bpkmattr_said, tvb, pos,
237                                  length, ENC_BIG_ENDIAN);
238           else
239             THROW (ReportedBoundsError);
240           break;
241         case BPKM_TEK_PARAM:
242           tekp_it =
243             proto_tree_add_text (tree, tvb, pos, length, "13 TEK Parameters");
244           tekp_tree =
245             proto_item_add_subtree (tekp_it, ett_docsis_bpkmattr_tekp);
246           tekp_tvb = tvb_new_subset (tvb, pos, length, length);
247           dissect_attrs (tekp_tvb, pinfo, tekp_tree);
248           break;
249         case BPKM_OBSOLETED:
250           break;
251         case BPKM_CBC_IV:
252           if (length == 8)
253             proto_tree_add_item (tree, hf_docsis_bpkmattr_cbc_iv, tvb, pos,
254                                  length, ENC_NA);
255           else
256             THROW (ReportedBoundsError);
257           break;
258         case BPKM_ERROR_CODE:
259           if (length == 1)
260             proto_tree_add_item (tree, hf_docsis_bpkmattr_error_code, tvb,
261                                  pos, length, ENC_BIG_ENDIAN);
262           else
263             THROW (ReportedBoundsError);
264           break;
265         case BPKM_CA_CERT:
266           proto_tree_add_item (tree, hf_docsis_bpkmattr_ca_cert, tvb, pos,
267                                length, ENC_NA);
268           break;
269         case BPKM_CM_CERT:
270           proto_tree_add_item (tree, hf_docsis_bpkmattr_cm_cert, tvb, pos,
271                                length, ENC_NA);
272           break;
273         case BPKM_SEC_CAPABILITIES:
274           scap_it =
275             proto_tree_add_text (tree, tvb, pos, length,
276                                  "19 Security Capabilities");
277           scap_tree =
278             proto_item_add_subtree (scap_it, ett_docsis_bpkmattr_scap);
279           scap_tvb = tvb_new_subset (tvb, pos, length, length);
280           dissect_attrs (scap_tvb, pinfo, scap_tree);
281           break;
282         case BPKM_CRYPTO_SUITE:
283           if (length == 2)
284             proto_tree_add_item (tree, hf_docsis_bpkmattr_crypto_suite, tvb,
285                                  pos, length, ENC_BIG_ENDIAN);
286           else
287             THROW (ReportedBoundsError);
288           break;
289         case BPKM_CRYPTO_SUITE_LIST:
290           proto_tree_add_item (tree, hf_docsis_bpkmattr_crypto_suite_list,
291                                tvb, pos, length, ENC_NA);
292           break;
293         case BPKM_BPI_VERSION:
294           if (length == 1)
295             proto_tree_add_item (tree, hf_docsis_bpkmattr_bpi_version, tvb,
296                                  pos, length, ENC_BIG_ENDIAN);
297           else
298             THROW (ReportedBoundsError);
299           break;
300         case BPKM_SA_DESCRIPTOR:
301           sadsc_it =
302             proto_tree_add_text (tree, tvb, pos, length, "23 SA Descriptor");
303           sadsc_tree =
304             proto_item_add_subtree (sadsc_it, ett_docsis_bpkmattr_sadsc);
305           sadsc_tvb = tvb_new_subset (tvb, pos, length, length);
306           dissect_attrs (sadsc_tvb, pinfo, sadsc_tree);
307           break;
308         case BPKM_SA_TYPE:
309           if (length == 1)
310             proto_tree_add_item (tree, hf_docsis_bpkmattr_sa_type, tvb, pos,
311                                  length, ENC_BIG_ENDIAN);
312           else
313             THROW (ReportedBoundsError);
314           break;
315         case BPKM_SA_QUERY:
316           saqry_it =
317             proto_tree_add_text (tree, tvb, pos, length, "25 SA Query");
318           saqry_tree =
319             proto_item_add_subtree (saqry_it, ett_docsis_bpkmattr_saqry);
320           saqry_tvb = tvb_new_subset (tvb, pos, length, length);
321           dissect_attrs (saqry_tvb, pinfo, saqry_tree);
322           break;
323         case BPKM_SA_QUERY_TYPE:
324           if (length == 1)
325             proto_tree_add_item (tree, hf_docsis_bpkmattr_sa_query_type, tvb,
326                                  pos, length, ENC_BIG_ENDIAN);
327           else
328             THROW (ReportedBoundsError);
329           break;
330         case BPKM_IP_ADDRESS:
331           if (length == 4)
332             proto_tree_add_item (tree, hf_docsis_bpkmattr_ip_address, tvb,
333                                  pos, length, ENC_BIG_ENDIAN);
334           else
335             THROW (ReportedBoundsError);
336           break;
337         case BPKM_VENDOR_DEFINED:
338           proto_tree_add_item (tree, hf_docsis_bpkmattr_vendor_def, tvb, pos,
339                                length, ENC_NA);
340         case BPKM_DNLD_PARAMS:
341           dnld_it =
342             proto_tree_add_text (tree, tvb, pos, length,
343                                  "28 Download Parameters");
344           dnld_tree =
345             proto_item_add_subtree (dnld_it, ett_docsis_bpkmattr_dnld);
346           dnld_tvb = tvb_new_subset (tvb, pos, length, length);
347           dissect_attrs (dnld_tvb, pinfo, dnld_tree);
348           break;
349         default:
350           proto_tree_add_item (tree, hf_docsis_bpkmattr_vendor_def, tvb, pos,
351                                length, ENC_NA);
352           break;
353         }
354       pos += length;            /* switch */
355     }                           /* while */
356 }
357
358 static void
359 dissect_bpkmattr (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
360 {
361
362   proto_item *it;
363   proto_tree *bpkmattr_tree;
364
365   if (tree)
366     {
367       it =
368         proto_tree_add_protocol_format (tree, proto_docsis_bpkmattr, tvb, 0, -1,
369                                         "BPKM Attributes");
370       bpkmattr_tree = proto_item_add_subtree (it, ett_docsis_bpkmattr);
371       dissect_attrs (tvb, pinfo, bpkmattr_tree);
372     }
373
374 }
375
376
377
378 /* Register the protocol with Wireshark */
379
380 /* this format is require because a script is used to build the C function
381    that calls all the protocol registration.
382 */
383
384
385 void
386 proto_register_docsis_bpkmattr (void)
387 {
388
389 /* Setup list of header fields  See Section 1.6.1 for details*/
390   static hf_register_info hf[] = {
391     {&hf_docsis_bpkmattr_serial_num,
392      {"1 Serial Number", "docsis_bpkmattr.serialnum",
393       FT_STRING, BASE_NONE, NULL, 0x0,
394       "Serial Number", HFILL}
395      },
396     {&hf_docsis_bpkmattr_manf_id,
397      {"2 Manufacturer Id", "docsis_bpkmattr.manfid",
398       FT_BYTES, BASE_NONE, NULL, 0x0,
399       "Manufacturer Id", HFILL}
400      },
401     {&hf_docsis_bpkmattr_mac_addr,
402      {"3 Mac Address", "docsis_bpkmattr.macaddr",
403       FT_ETHER, BASE_NONE, NULL, 0x0,
404       "Mac Address", HFILL}
405      },
406     {&hf_docsis_bpkmattr_rsa_pub_key,
407      {"4 RSA Public Key", "docsis_bpkmattr.rsa_pub_key",
408       FT_BYTES, BASE_NONE, NULL, 0x0,
409       "RSA Public Key", HFILL}
410      },
411     {&hf_docsis_bpkmattr_cm_id,
412      {"5 CM Identification", "docsis_bpkmattr.cmid",
413       FT_BYTES, BASE_NONE, NULL, 0x0,
414       "CM Identification", HFILL}
415      },
416     {&hf_docsis_bpkmattr_display_str,
417      {"6 Display String", "docsis_bpkmattr.dispstr",
418       FT_STRING, BASE_NONE, NULL, 0x0,
419       "Display String", HFILL}
420      },
421     {&hf_docsis_bpkmattr_auth_key,
422      {"7 Auth Key", "docsis_bpkmattr.auth_key",
423       FT_BYTES, BASE_NONE, NULL, 0x0,
424       "Auth Key", HFILL}
425      },
426     {&hf_docsis_bpkmattr_tek,
427      {"8 Traffic Encryption Key", "docsis_bpkmattr.tek",
428       FT_BYTES, BASE_NONE, NULL, 0x0,
429       "Traffic Encryption Key", HFILL}
430      },
431     {&hf_docsis_bpkmattr_key_life,
432      {"9 Key Lifetime (s)", "docsis_bpkmattr.keylife",
433       FT_UINT32, BASE_DEC, NULL, 0x0,
434       "Key Lifetime (s)", HFILL}
435      },
436     {&hf_docsis_bpkmattr_key_seq,
437      {"10 Key Sequence Number", "docsis_bpkmattr.keyseq",
438       FT_UINT8, BASE_DEC, NULL, 0x0,
439       "Key Sequence Number", HFILL}
440      },
441     {&hf_docsis_bpkmattr_hmac_digest,
442      {"11 HMAC Digest", "docsis_bpkmattr.hmacdigest",
443       FT_BYTES, BASE_NONE, NULL, 0x0,
444       "HMAC Digest", HFILL}
445      },
446     {&hf_docsis_bpkmattr_said,
447      {"12 SAID", "docsis_bpkmattr.said",
448       FT_UINT16, BASE_DEC, NULL, 0x0,
449       "Security Association ID", HFILL}
450      },
451     {&hf_docsis_bpkmattr_tek_params,
452      {"13 TEK Parameters", "docsis_bpkmattr.tekparams",
453       FT_BYTES, BASE_NONE, NULL, 0x0,
454       "TEK Parameters", HFILL}
455      },
456     {&hf_docsis_bpkmattr_cbc_iv,
457      {"14 CBC IV", "docsis_bpkmattr.cbciv",
458       FT_BYTES, BASE_NONE, NULL, 0x0,
459       "Cypher Block Chaining", HFILL}
460      },
461     {&hf_docsis_bpkmattr_error_code,
462      {"16 Error Code", "docsis_bpkmattr.errcode",
463       FT_UINT8, BASE_DEC, VALS (error_code_vals), 0x0,
464       "Error Code", HFILL}
465      },
466     {&hf_docsis_bpkmattr_vendor_def,
467      {"127 Vendor Defined", "docsis_bpkmattr.vendordef",
468       FT_BYTES, BASE_NONE, NULL, 0x0,
469       "Vendor Defined", HFILL}
470      },
471     {&hf_docsis_bpkmattr_ca_cert,
472      {"17 CA Certificate", "docsis_bpkmattr.cacert",
473       FT_BYTES, BASE_NONE, NULL, 0x0,
474       "CA Certificate", HFILL}
475      },
476     {&hf_docsis_bpkmattr_cm_cert,
477      {"18 CM Certificate", "docsis_bpkmattr.cmcert",
478       FT_BYTES, BASE_NONE, NULL, 0x0,
479       "CM Certificate", HFILL}
480      },
481     {&hf_docsis_bpkmattr_security_cap,
482      {"19 Security Capabilities", "docsis_bpkmattr.seccap",
483       FT_BYTES, BASE_NONE, NULL, 0x0,
484       "Security Capabilities", HFILL}
485      },
486     {&hf_docsis_bpkmattr_crypto_suite,
487      {"20 Cryptographic Suite", "docsis_bpkmattr.cryptosuite",
488       FT_UINT16, BASE_HEX, VALS(crypto_suite_attr_vals), 0x0,
489       "Cryptographic Suite", HFILL}
490      },
491     {&hf_docsis_bpkmattr_crypto_suite_list,
492      {"21 Cryptographic Suite List", "docsis_bpkmattr.crypto_suite_lst",
493       FT_BYTES, BASE_NONE, NULL, 0x0,
494       "Cryptographic Suite", HFILL}
495      },
496     {&hf_docsis_bpkmattr_bpi_version,
497      {"22 BPI Version", "docsis_bpkmattr.bpiver",
498       FT_UINT8, BASE_DEC, VALS (bpi_ver_vals), 0x0,
499       "BPKM Attributes", HFILL}
500      },
501     {&hf_docsis_bpkmattr_sa_descr,
502      {"23 SA Descriptor", "docsis_bpkmattr.sadescr",
503       FT_BYTES, BASE_NONE, NULL, 0x0,
504       "SA Descriptor", HFILL}
505      },
506     {&hf_docsis_bpkmattr_sa_type,
507      {"24 SA Type", "docsis_bpkmattr.satype",
508       FT_UINT8, BASE_DEC, NULL, 0x0,
509       "SA Type", HFILL}
510      },
511     {&hf_docsis_bpkmattr_sa_query,
512      {"25 SA Query", "docsis_bpkmattr.saquery",
513       FT_BYTES, BASE_NONE, NULL, 0x0,
514       "SA Query", HFILL}
515      },
516     {&hf_docsis_bpkmattr_sa_query_type,
517      {"26 SA Query Type", "docsis_bpkmattr.saquery_type",
518       FT_UINT8, BASE_HEX, NULL, 0x0,
519       "SA Query Type", HFILL}
520      },
521     {&hf_docsis_bpkmattr_ip_address,
522      {"27 IP Address", "docsis_bpkmattr.ipaddr",
523       FT_IPv4, BASE_NONE, NULL, 0x0,
524       "IP Address", HFILL}
525      },
526     {&hf_docsis_bpkmattr_download_param,
527      {"28 Download Parameters", "docsis_bpkmattr.dnld_params",
528       FT_BYTES, BASE_NONE, NULL, 0x0,
529       "Download Parameters", HFILL}
530      },
531   };
532
533 /* Setup protocol subtree array */
534   static gint *ett[] = {
535     &ett_docsis_bpkmattr,
536     &ett_docsis_bpkmattr_cmid,
537     &ett_docsis_bpkmattr_scap,
538     &ett_docsis_bpkmattr_tekp,
539     &ett_docsis_bpkmattr_sadsc,
540     &ett_docsis_bpkmattr_saqry,
541     &ett_docsis_bpkmattr_dnld
542   };
543
544 /* Register the protocol name and description */
545   proto_docsis_bpkmattr =
546     proto_register_protocol
547     ("DOCSIS Baseline Privacy Key Management Attributes", "DOCSIS BPKM-ATTR",
548      "docsis_bpkmattr");
549
550 /* Required function calls to register the header fields and subtrees used */
551   proto_register_field_array (proto_docsis_bpkmattr, hf, array_length (hf));
552   proto_register_subtree_array (ett, array_length (ett));
553
554   register_dissector ("docsis_bpkmattr", dissect_bpkmattr,
555                       proto_docsis_bpkmattr);
556 }
557
558
559 /* If this dissector uses sub-dissector registration add a registration routine.
560    This format is required because a script is used to find these routines and
561    create the code that calls these routines.
562 */
563 void
564 proto_reg_handoff_docsis_bpkmattr (void)
565 {
566 #if 0
567   dissector_handle_t docsis_bpkmattr_handle;
568
569   docsis_bpkmattr_handle = find_dissector ("docsis_bpkmattr");
570   dissector_add_uint ("docsis", 0xFE, docsis_bpkmattr_handle);
571 #endif
572
573 }