df70b5ddc651b9bdd53b2aca32a613ac00a4cba1
[obnox/wireshark/wip.git] / epan / dissectors / packet-cops.c
1 /* packet-cops.c
2  * Routines for the COPS (Common Open Policy Service) protocol dissection
3  * RFC2748 & COPS-PR extension RFC3084
4  *
5  * Copyright 2000, Heikki Vatiainen <hessu@cs.tut.fi>
6  *
7  * Added PacketCable D-QoS specifications by Dick Gooris <gooris@lucent.com>
8  *
9  * Taken from PacketCable specifications :
10  *    PacketCable Dynamic Quality-of-Service Specification
11  *    Based on PKT-SP-DQOS-I09-040402 (April 2, 2004)
12  *
13  *    PacketCable Multimedia Specification
14  *    Based on PKT-SP-MM-I02-040930
15  *
16  *    www.packetcable.com
17  *
18  * Implemented in ethereal at April 7-8, 2004
19  *
20  * $Id$
21  *
22  * Ethereal - Network traffic analyzer
23  * By Gerald Combs <gerald@ethereal.com>
24  * Copyright 1998 Gerald Combs
25  *
26  * This program is free software; you can redistribute it and/or
27  * modify it under the terms of the GNU General Public License
28  * as published by the Free Software Foundation; either version 2
29  * of the License, or (at your option) any later version.
30  *
31  * This program is distributed in the hope that it will be useful,
32  * but WITHOUT ANY WARRANTY; without even the implied warranty of
33  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
34  * GNU General Public License for more details.
35  *
36  * You should have received a copy of the GNU General Public License
37  * along with this program; if not, write to the Free Software
38  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
39  */
40
41 /*
42  * Some of the development of the COPS protocol decoder was sponsored by
43  * Cable Television Laboratories, Inc. ("CableLabs") based upon proprietary
44  * CableLabs' specifications. Your license and use of this protocol decoder
45  * does not mean that you are licensed to use the CableLabs'
46  * specifications.  If you have questions about this protocol, contact
47  * jf.mule [AT] cablelabs.com or c.stuart [AT] cablelabs.com for additional
48  * information.
49  */
50
51
52 #ifdef HAVE_CONFIG_H
53 # include "config.h"
54 #endif
55
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <string.h>
59 #include <ctype.h>
60
61 #include <glib.h>
62
63 #include "isprint.h"
64
65 #include <epan/packet.h>
66 #include "packet-ipv6.h"
67 #include "packet-tcp.h"
68
69 #ifdef HAVE_SOME_SNMP
70 #ifdef HAVE_NET_SNMP
71 # include <net-snmp/net-snmp-config.h>
72 # include <net-snmp/mib_api.h>
73 # include <net-snmp/library/default_store.h>
74 # include <net-snmp/config_api.h>
75 #else /* HAVE_NET_SNMP */
76 # include <ucd-snmp/ucd-snmp-config.h>
77 # include <ucd-snmp/asn1.h>
78 # include <ucd-snmp/snmp_api.h>
79 # include <ucd-snmp/snmp_impl.h>
80 # include <ucd-snmp/mib.h>
81 # include <ucd-snmp/default_store.h>
82 # include <ucd-snmp/read_config.h>
83 # include <ucd-snmp/tools.h>
84 #endif /* HAVE_NET_SNMP */
85 #endif /* HAVE_SOME_SNMP */
86
87 #include <epan/asn1.h>
88 #include <epan/dissectors/format-oid.h>
89 #include <epan/prefs.h>
90 #include <epan/emem.h>
91 #include "packet-ber.h"
92
93 /* XXX - The "plain" COPS port (3288) can be overridden in the prefs.
94    The PacketCable port cannot - should this be the case? */
95 #define TCP_PORT_COPS 3288
96 #define TCP_PORT_PKTCABLE_COPS 2126
97 #define TCP_PORT_PKTCABLE_MM_COPS 3918
98
99 /* Preference: Variable to hold the tcp port preference */
100 static guint global_cops_tcp_port = TCP_PORT_COPS;
101
102 /* Preference: desegmentation of COPS */
103 static gboolean cops_desegment = TRUE;
104
105 /* Variable to allow for proper deletion of dissector registration
106  * when the user changes port from the gui
107  */
108
109 static guint cops_tcp_port = 0;
110
111 /*Some local globals needed to read COPS-PR ASN.1 Types from PIB-MIBs */
112 /*MAX_OID_LEN from NET-SNMP's asn1.h*/
113
114 #ifdef HAVE_NET_SNMP
115 static  subid_t last_decoded_prid_oid[MAX_OID_LEN]={0};
116 static  subid_t last_decoded_prid_oid_length=0;
117 extern struct tree *tree_head;
118
119 /* Preference: COPS-PR ASN.1 type decoding based on PIB/MIB or data in packet */
120 static gboolean cops_typefrommib = FALSE;
121
122 #endif /* HAVE_NET_SNMP */
123
124 #define COPS_OBJECT_HDR_SIZE 4
125
126 /* Null string of type "guchar[]". */
127 static const guchar nullstring[] = "";
128
129 #define SAFE_STRING(s)  (((s) != NULL) ? (s) : nullstring)
130
131 /* COPS PR Tags */
132
133 #define COPS_IPA    0           /* IP Address */
134 #define COPS_U32    2           /* Unsigned 32*/
135 #define COPS_TIT    3           /* TimeTicks */
136 #define COPS_OPQ    4           /* Opaque */
137 #define COPS_I64    10          /* Integer64 */
138 #define COPS_U64    11          /* Uinteger64 */
139
140 /* COPS PR Types */
141
142 #define COPS_NULL                0
143 #define COPS_INTEGER             1    /* l  */
144 #define COPS_OCTETSTR            2    /* c  */
145 #define COPS_OBJECTID            3    /* ul */
146 #define COPS_IPADDR              4    /* uc */
147 #define COPS_UNSIGNED32          5    /* ul */
148 #define COPS_TIMETICKS           7    /* ul */
149 #define COPS_OPAQUE              8    /* c  */
150 #define COPS_INTEGER64           10   /* ll */
151 #define COPS_UNSIGNED64          11   /* ull  */
152
153
154 typedef struct _COPS_CNV COPS_CNV;
155
156 struct _COPS_CNV
157 {
158   guint class;
159   guint tag;
160   gint  syntax;
161   const gchar *name;
162 };
163
164 static COPS_CNV CopsCnv [] =
165 {
166   {BER_CLASS_UNI, BER_UNI_TAG_NULL,                     COPS_NULL,      "NULL"},
167   {BER_CLASS_UNI, BER_UNI_TAG_INTEGER,          COPS_INTEGER,   "INTEGER"},
168   {BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING,      COPS_OCTETSTR,  "OCTET STRING"},
169   {BER_CLASS_UNI, BER_UNI_TAG_OID,                      COPS_OBJECTID,  "OBJECTID"},
170   {BER_CLASS_APP, COPS_IPA,                                     COPS_IPADDR,    "IPADDR"},
171   {BER_CLASS_APP, COPS_U32,                                     COPS_UNSIGNED32,"UNSIGNED32"},
172   {BER_CLASS_APP, COPS_TIT,                                     COPS_TIMETICKS, "TIMETICKS"},
173   {BER_CLASS_APP, COPS_OPQ,                                     COPS_OPAQUE,    "OPAQUE"},
174   {BER_CLASS_APP, COPS_I64,                                     COPS_INTEGER64, "INTEGER64"},
175   {BER_CLASS_APP, COPS_U64,                                     COPS_UNSIGNED64, "UNSIGNED64"},
176   {0,       0,         -1,                  NULL}
177 };
178
179 static const gchar *
180 cops_tag_cls2syntax ( guint tag, guint cls, gushort *syntax)
181 {
182   COPS_CNV *cnv;
183
184   cnv = CopsCnv;
185   while (cnv->syntax != -1)
186   {
187     if (cnv->tag == tag && cnv->class == cls)
188     {
189       *syntax = cnv->syntax;
190       return cnv->name;
191     }
192     cnv++;
193   }
194   return NULL;
195 }
196
197 static const value_string cops_flags_vals[] = {
198   { 0x00,          "None" },
199   { 0x01,          "Solicited Message Flag Bit" },
200   { 0, NULL },
201 };
202
203 /* The different COPS message types */
204 enum cops_op_code {
205   COPS_NO_MSG,          /* Not a COPS Message type     */
206
207   COPS_MSG_REQ,         /* Request (REQ)               */
208   COPS_MSG_DEC,         /* Decision (DEC)              */
209   COPS_MSG_RPT,         /* Report State (RPT)          */
210   COPS_MSG_DRQ,         /* Delete Request State (DRQ)  */
211   COPS_MSG_SSQ,         /* Synchronize State Req (SSQ) */
212   COPS_MSG_OPN,         /* Client-Open (OPN)           */
213   COPS_MSG_CAT,         /* Client-Accept (CAT)         */
214   COPS_MSG_CC,          /* Client-Close (CC)           */
215   COPS_MSG_KA,          /* Keep-Alive (KA)             */
216   COPS_MSG_SSC,         /* Synchronize Complete (SSC)  */
217
218   COPS_LAST_OP_CODE     /* For error checking          */
219 };
220
221 static const value_string cops_op_code_vals[] = {
222   { COPS_MSG_REQ,          "Request (REQ)" },
223   { COPS_MSG_DEC,          "Decision (DEC)" },
224   { COPS_MSG_RPT,          "Report State (RPT)" },
225   { COPS_MSG_DRQ,          "Delete Request State (DRQ)" },
226   { COPS_MSG_SSQ,          "Synchronize State Req (SSQ)" },
227   { COPS_MSG_OPN,          "Client-Open (OPN)" },
228   { COPS_MSG_CAT,          "Client-Accept (CAT)" },
229   { COPS_MSG_CC,           "Client-Close (CC)" },
230   { COPS_MSG_KA,           "Keep-Alive (KA)" },
231   { COPS_MSG_SSC,          "Synchronize Complete (SSC)" },
232   { 0, NULL },
233 };
234
235
236 /* The different objects in COPS messages */
237 enum cops_c_num {
238   COPS_NO_OBJECT,        /* Not a COPS Object type               */
239
240   COPS_OBJ_HANDLE,       /* Handle Object (Handle)               */
241   COPS_OBJ_CONTEXT,      /* Context Object (Context)             */
242   COPS_OBJ_IN_INT,       /* In-Interface Object (IN-Int)         */
243   COPS_OBJ_OUT_INT,      /* Out-Interface Object (OUT-Int)       */
244   COPS_OBJ_REASON,       /* Reason Object (Reason)               */
245   COPS_OBJ_DECISION,     /* Decision Object (Decision)           */
246   COPS_OBJ_LPDPDECISION, /* LPDP Decision Object (LPDPDecision)  */
247   COPS_OBJ_ERROR,        /* Error Object (Error)                 */
248   COPS_OBJ_CLIENTSI,     /* Client Specific Information Object (ClientSI) */
249   COPS_OBJ_KATIMER,      /* Keep-Alive Timer Object (KATimer)    */
250   COPS_OBJ_PEPID,        /* PEP Identification Object (PEPID)    */
251   COPS_OBJ_REPORT_TYPE,  /* Report-Type Object (Report-Type)     */
252   COPS_OBJ_PDPREDIRADDR, /* PDP Redirect Address Object (PDPRedirAddr) */
253   COPS_OBJ_LASTPDPADDR,  /* Last PDP Address (LastPDPaddr)       */
254   COPS_OBJ_ACCTTIMER,    /* Accounting Timer Object (AcctTimer)  */
255   COPS_OBJ_INTEGRITY,    /* Message Integrity Object (Integrity) */
256   COPS_LAST_C_NUM        /* For error checking                   */
257 };
258
259 static const value_string cops_c_num_vals[] = {
260   { COPS_OBJ_HANDLE,       "Handle Object (Handle)" },
261   { COPS_OBJ_CONTEXT,      "Context Object (Context)" },
262   { COPS_OBJ_IN_INT,       "In-Interface Object (IN-Int)" },
263   { COPS_OBJ_OUT_INT,      "Out-Interface Object (OUT-Int)" },
264   { COPS_OBJ_REASON,       "Reason Object (Reason)" },
265   { COPS_OBJ_DECISION,     "Decision Object (Decision)" },
266   { COPS_OBJ_LPDPDECISION, "LPDP Decision Object (LPDPDecision)" },
267   { COPS_OBJ_ERROR,        "Error Object (Error)" },
268   { COPS_OBJ_CLIENTSI,     "Client Specific Information Object (ClientSI)" },
269   { COPS_OBJ_KATIMER,      "Keep-Alive Timer Object (KATimer)" },
270   { COPS_OBJ_PEPID,        "PEP Identification Object (PEPID)" },
271   { COPS_OBJ_REPORT_TYPE,  "Report-Type Object (Report-Type)" },
272   { COPS_OBJ_PDPREDIRADDR, "PDP Redirect Address Object (PDPRedirAddr)" },
273   { COPS_OBJ_LASTPDPADDR,  "Last PDP Address (LastPDPaddr)" },
274   { COPS_OBJ_ACCTTIMER,    "Accounting Timer Object (AcctTimer)" },
275   { COPS_OBJ_INTEGRITY,    "Message Integrity Object (Integrity)" },
276   { 0, NULL },
277 };
278
279
280 /* The different objects in COPS-PR messages */
281 enum cops_s_num {
282   COPS_NO_PR_OBJECT,     /* Not a COPS-PR Object type               */
283   COPS_OBJ_PRID,         /* Provisioning Instance Identifier (PRID) */
284   COPS_OBJ_PPRID,        /* Prefix Provisioning Instance Identifier (PPRID) */
285   COPS_OBJ_EPD,          /* Encoded Provisioning Instance Data (EPD) */
286   COPS_OBJ_GPERR,        /* Global Provisioning Error Object (GPERR) */
287   COPS_OBJ_CPERR,        /* PRC Class Provisioning Error Object (CPERR) */
288   COPS_OBJ_ERRPRID,      /* Error Provisioning Instance Identifier (ErrorPRID)*/
289
290   COPS_LAST_S_NUM        /* For error checking                   */
291 };
292
293
294 static const value_string cops_s_num_vals[] = {
295   { COPS_OBJ_PRID,         "Provisioning Instance Identifier (PRID)" },
296   { COPS_OBJ_PPRID,        "Prefix Provisioning Instance Identifier (PPRID)" },
297   { COPS_OBJ_EPD,          "Encoded Provisioning Instance Data (EPD)" },
298   { COPS_OBJ_GPERR,        "Global Provisioning Error Object (GPERR)" },
299   { COPS_OBJ_CPERR,        "PRC Class Provisioning Error Object (CPERR)" },
300   { COPS_OBJ_ERRPRID,      "Error Provisioning Instance Identifier (ErrorPRID)" },
301   { 0, NULL },
302
303 };
304
305 /* R-Type is carried within the Context Object */
306 static const value_string cops_r_type_vals[] = {
307   { 0x01, "Incoming-Message/Admission Control request" },
308   { 0x02, "Resource-Allocation request" },
309   { 0x04, "Outgoing-Message request" },
310   { 0x08, "Configuration request" },
311   { 0, NULL },
312 };
313 /* S-Type is carried within the ClientSI Object for COPS-PR*/
314 static const value_string cops_s_type_vals[] = {
315   { 0x01, "BER" },
316   { 0, NULL },
317 };
318
319 /* Reason-Code is carried within the Reason object */
320 static const value_string cops_reason_vals[] = {
321   { 1,  "Unspecified" },
322   { 2,  "Management" },
323   { 3,  "Preempted (Another request state takes precedence)" },
324   { 4,  "Tear (Used to communicate a signaled state removal)" },
325   { 5,  "Timeout (Local state has timed-out)" },
326   { 6,  "Route Change (Change invalidates request state)" },
327   { 7,  "Insufficient Resources (No local resource available)" },
328   { 8,  "PDP's Directive (PDP decision caused the delete)" },
329   { 9,  "Unsupported decision (PDP decision not supported)" },
330   { 10, "Synchronize Handle Unknown" },
331   { 11, "Transient Handle (stateless event)" },
332   { 12, "Malformed Decision (could not recover)" },
333   { 13, "Unknown COPS Object from PDP" },
334   { 0, NULL },
335 };
336
337 /* Command-Code is carried within the Decision object if C-Type is 1 */
338 static const value_string cops_dec_cmd_code_vals[] = {
339   { 0, "NULL Decision (No configuration data available)" },
340   { 1, "Install (Admit request/Install configuration)" },
341   { 2, "Remove (Remove request/Remove configuration)" },
342   { 0, NULL },
343 };
344
345 /* Decision flags are also carried with the Decision object if C-Type is 1 */
346 static const value_string cops_dec_cmd_flag_vals[] = {
347   { 0x00, "<None set>" },
348   { 0x01, "Trigger Error (Trigger error message if set)" },
349   { 0, NULL },
350 };
351
352 /* Error-Code from Error object */
353 static const value_string cops_error_vals[] = {
354   {1,  "Bad handle" },
355   {2,  "Invalid handle reference" },
356   {3,  "Bad message format (Malformed Message)" },
357   {4,  "Unable to process (server gives up on query)" },
358   {5,  "Mandatory client-specific info missing" },
359   {6,  "Unsupported client" },
360   {7,  "Mandatory COPS object missing" },
361   {8,  "Client Failure" },
362   {9,  "Communication Failure" },
363   {10, "Unspecified" },
364   {11, "Shutting down" },
365   {12, "Redirect to Preferred Server" },
366   {13, "Unknown COPS Object" },
367   {14, "Authentication Failure" },
368   {15, "Authentication Required" },
369   {0,  NULL },
370 };
371 /* Error-Code from GPERR object */
372 static const value_string cops_gperror_vals[] = {
373   {1,  "AvailMemLow" },
374   {2,  "AvailMemExhausted" },
375   {3,  "unknownASN.1Tag" },
376   {4,  "maxMsgSizeExceeded" },
377   {5,  "unknownError" },
378   {6,  "maxRequestStatesOpen" },
379   {7,  "invalidASN.1Length" },
380   {8,  "invalidObjectPad" },
381   {9,  "unknownPIBData" },
382   {10, "unknownCOPSPRObject" },
383   {11, "malformedDecision" },
384   {0,  NULL },
385 };
386
387 /* Error-Code from CPERR object */
388 static const value_string cops_cperror_vals[] = {
389   {1,  "priSpaceExhausted" },
390   {2,  "priInstanceInvalid" },
391   {3,  "attrValueInvalid" },
392   {4,  "attrValueSupLimited" },
393   {5,  "attrEnumSupLimited" },
394   {6,  "attrMaxLengthExceeded" },
395   {7,  "attrReferenceUnknown" },
396   {8,  "priNotifyOnly" },
397   {9,  "unknownPrc" },
398   {10, "tooFewAttrs" },
399   {11, "invalidAttrType" },
400   {12, "deletedInRef" },
401   {13, "priSpecificError" },
402         {0,  NULL },
403 };
404
405
406 /* Report-Type from Report-Type object */
407 static const value_string cops_report_type_vals[] = {
408   {1, " Success   : Decision was successful at the PEP" },
409   {2, " Failure   : Decision could not be completed by PEP" },
410   {3, " Accounting: Accounting update for an installed state" },
411   {0, NULL },
412 };
413
414
415 /* Client-type descriptions */
416 /* http://www.iana.org/assignments/cops-parameters */
417
418 /* PacketCable Types */
419
420 /* static dissector_handle_t sdp_handle; */
421
422 #define COPS_CLIENT_PC_DQOS     0x8008
423 #define COPS_CLIENT_PC_MM       0x800a
424
425 static const value_string cops_client_type_vals[] = {
426         {0,                   "None"},
427         {1,                   "RSVP"},
428         {2,                   "DiffServ QoS"},
429         {0x8001,              "IP Highway"},
430         {0x8002,              "IP Highway"},
431         {0x8003,              "IP Highway"},
432         {0x8004,              "IP Highway"},
433         {0x8005,              "Fujitsu"},
434         {0x8006,              "HP OpenView PolicyXpert"},
435         {0x8007,              "HP OpenView PolicyXpert"},
436         {COPS_CLIENT_PC_DQOS, "PacketCable Dynamic Quality-of-Service"},
437         {0x8009,              "3GPP"},
438         {COPS_CLIENT_PC_MM,   "PacketCable Multimedia"},
439         {0, NULL},
440 };
441
442 /* The next tables are for PacketCable */
443
444 /* Transaction ID table */
445 static const value_string table_cops_dqos_transaction_id[] =
446 {
447   { 0x1,  "Gate Alloc" },
448   { 0x2,  "Gate Alloc Ack" },
449   { 0x3,  "Gate Alloc Err" },
450   { 0x4,  "Gate Set" },
451   { 0x5,  "Gate Set Ack" },
452   { 0x6,  "Gate Set Err" },
453   { 0x7,  "Gate Info" },
454   { 0x8,  "Gate Info Ack" },
455   { 0x9,  "Gate Info Err" },
456   { 0xa,  "Gate Delete" },
457   { 0xb,  "Gate Delete Ack" },
458   { 0xc,  "Gate Delete Err" },
459   { 0xd,  "Gate Open" },
460   { 0xe,  "Gate Close" },
461   { 0, NULL },
462 };
463
464 /* Direction */
465 static const value_string table_cops_direction[] =
466 {
467   { 0x0,  "Downstream gate" },
468   { 0x1,  "Upstream gate" },
469   { 0, NULL },
470 };
471
472 /* Session Class */
473 static const value_string table_cops_session_class[] =
474 {
475   { 0x0,  "Unspecified" },
476   { 0x1,  "Normal priority VoIP session" },
477   { 0x2,  "High priority VoIP session" },
478   { 0x3,  "Reserved" },
479   { 0, NULL },
480 };
481
482 /* Reason Code */
483 static const value_string table_cops_reason_code[] =
484 {
485   { 0x0,  "Gate Delete Operation" },
486   { 0x1,  "Gate Close Operation" },
487   { 0, NULL },
488 };
489
490 /* Reason Sub Code - Delete */
491 static const value_string table_cops_reason_subcode_delete[] =
492 {
493   { 0x0,  "Normal Operation" },
494   { 0x1,  "Local Gate-coordination not completed" },
495   { 0x2,  "Remote Gate-coordination not completed" },
496   { 0x3,  "Authorization revoked" },
497   { 0x4,  "Unexpected Gate-Open" },
498   { 0x5,  "Local Gate-Close failure" },
499   { 0x127,"Unspecified error" },
500   { 0, NULL },
501 };
502
503 /* Reason Sub Code - Close */
504 static const value_string table_cops_reason_subcode_close[] =
505 {
506   { 0x0,  "Client initiated release (normal operation)" },
507   { 0x1,  "Reservation reassignment (e.g., for priority session)" },
508   { 0x2,  "Lack of reservation maintenance (e.g., RSVP refreshes)" },
509   { 0x3,  "Lack of Docsis Mac-layer responses (e.g., station maintenance)" },
510   { 0x4,  "Timer T0 expiration; no Gate-Set received from CMS" },
511   { 0x5,  "Timer T1 expiration; no Commit received from MTA" },
512   { 0x6,  "Timer T7 expiration; Service Flow reservation timeout" },
513   { 0x7,  "Timer T8 expiration; Service Flow inactivity in the upstream direction" },
514   { 0x127,"Unspecified error" },
515   { 0, NULL },
516 };
517
518 /* PacketCable Error */
519 static const value_string table_cops_packetcable_error[] =
520 {
521   { 0x1,  "No gates urrently available" },
522   { 0x2,  "Unknown Gate ID" },
523   { 0x3,  "Illegal Session Class value" },
524   { 0x4,  "Subscriber exceeded gate limit" },
525   { 0x5,  "Gate already set" },
526   { 0x6,  "Missing Required Object" },
527   { 0x7,  "Invalid Object" },
528   { 0x127,"Unspecified error" },
529   { 0, NULL },
530 };
531
532
533 /* PacketCable Multimedia */
534
535 static const value_string table_cops_mm_transaction_id[] = {
536         {1,  "Reserved"},
537         {2,  "Reserved"},
538         {3,  "Reserved"},
539         {4,  "Gate Set"},
540         {5,  "Gate Set Ack"},
541         {6,  "Gate Set Err"},
542         {7,  "Gate Info"},
543         {8,  "Gate Info Ack"},
544         {9,  "Gate Info Err"},
545         {10, "Gate Delete"},
546         {11, "Gate Delete Ack"},
547         {12, "Gate Delete Err"},
548         {13, "Gate Open"},
549         {14, "Gate Close"},
550         {15, "Gate Report State"},
551         {0, NULL },
552 };
553
554 static const value_string pcmm_flow_spec_service_vals[] = {
555         {2, "Guaranteed Rate"},
556         {5, "Controlled Load"},
557         {0, NULL },
558 };
559
560 static const value_string pcmm_packetcable_error_code[] = {
561         {1,  "Insufficient Resources"},
562         {2,  "Unknown GateID"},
563         {6,  "Missing Required Object"},
564         {7,  "Invalid Object"},
565         {8,  "Volume-Based Usage Limit Exceeded"},
566         {9,  "Time-Based Usage Limit Exceeded"},
567         {10, "Session Class Limit Exceeded"},
568         {11, "Undefined Service Class Name"},
569         {12, "Incompatible Envelope"},
570         {13, "Invalid SubscriberID"},
571         {14, "Unauthorized AMID"},
572         {15, "Number of Classifiers Not Supported"},
573         {127, "Other, Unspecified Error"},
574         {0, NULL},
575 };
576
577 static const value_string pcmm_gate_state[] = {
578         {1, "Idle/Closed"},
579         {2, "Authorized"},
580         {3, "Reserved"},
581         {4, "Committed"},
582         {5, "Committed-Recovery"},
583         {0, NULL},
584 };
585
586 static const value_string pcmm_gate_state_reason[] = {
587         {1, "Close initiated by CMTS due to reservation reassignment"},
588         {2, "Close initiated by CMTS due to lack of DOCSIS MAC-layer responses"},
589         {3, "Close initiated by CMTS due to timer T1 expiration"},
590         {4, "Close initiated by CMTS due to timer T2 expiration"},
591         {5, "Inactivity timer expired due to Service Flow inactivity (timer T3 expiration)"},
592         {6, "Close initiated by CMTS due to lack of Reservation Maintenance"},
593         {7, "Gate state unchanged, but volume limit reached"},
594         {8, "Close initiated by CMTS due to timer T4 expiration"},
595         {9, "Gate state unchanged, but timer T2 expiration caused reservation reduction"},
596         {65535, "Other"},
597         {0, NULL},
598 };
599
600
601 /* End of PacketCable Tables */
602
603
604 /* Initialize the protocol and registered fields */
605 static gint proto_cops = -1;
606 static gint hf_cops_ver_flags = -1;
607 static gint hf_cops_version = -1;
608 static gint hf_cops_flags = -1;
609
610 static gint hf_cops_op_code = -1;
611 static gint hf_cops_client_type = -1;
612 static gint hf_cops_msg_len = -1;
613
614 static gint hf_cops_obj_len = -1;
615 static gint hf_cops_obj_c_num = -1;
616 static gint hf_cops_obj_c_type = -1;
617
618 static gint hf_cops_obj_s_num = -1;
619 static gint hf_cops_obj_s_type = -1;
620
621 static gint hf_cops_r_type_flags = -1;
622 static gint hf_cops_m_type_flags = -1;
623
624 static gint hf_cops_in_int_ipv4 = -1;
625 static gint hf_cops_in_int_ipv6 = -1;
626 static gint hf_cops_out_int_ipv4 = -1;
627 static gint hf_cops_out_int_ipv6 = -1;
628 static gint hf_cops_int_ifindex = -1;
629
630 static gint hf_cops_reason = -1;
631 static gint hf_cops_reason_sub = -1;
632
633 static gint hf_cops_dec_cmd_code = -1;
634 static gint hf_cops_dec_flags = -1;
635
636 static gint hf_cops_error = -1;
637 static gint hf_cops_error_sub = -1;
638
639 static gint hf_cops_gperror = -1;
640 static gint hf_cops_gperror_sub = -1;
641
642 static gint hf_cops_cperror = -1;
643 static gint hf_cops_cperror_sub = -1;
644
645 static gint hf_cops_katimer = -1;
646
647 static gint hf_cops_pepid = -1;
648
649 static gint hf_cops_report_type = -1;
650
651 static gint hf_cops_pdprediraddr_ipv4 = -1;
652 static gint hf_cops_pdprediraddr_ipv6 = -1;
653 static gint hf_cops_lastpdpaddr_ipv4 = -1;
654 static gint hf_cops_lastpdpaddr_ipv6 = -1;
655 static gint hf_cops_pdp_tcp_port = -1;
656
657 static gint hf_cops_accttimer = -1;
658
659 static gint hf_cops_key_id = -1;
660 static gint hf_cops_seq_num = -1;
661
662 /* For PacketCable D-QoS */
663 static gint hf_cops_subtree = -1;
664 static gint hf_cops_pc_activity_count = -1;
665 static gint hf_cops_pc_algorithm = -1;
666 static gint hf_cops_pc_close_subcode = -1;
667 static gint hf_cops_pc_cmts_ip = -1;
668 static gint hf_cops_pc_cmts_ip_port = -1;
669 static gint hf_cops_pc_prks_ip = -1;
670 static gint hf_cops_pc_prks_ip_port = -1;
671 static gint hf_cops_pc_srks_ip = -1;
672 static gint hf_cops_pc_srks_ip_port = -1;
673 static gint hf_cops_pc_delete_subcode = -1;
674 static gint hf_cops_pc_dest_ip = -1;
675 static gint hf_cops_pc_dest_port = -1;
676 static gint hf_cops_pc_direction = -1;
677 static gint hf_cops_pc_ds_field = -1;
678 static gint hf_cops_pc_gate_id = -1;
679 static gint hf_cops_pc_gate_spec_flags = -1;
680 static gint hf_cops_pc_gate_command_type = -1;
681 static gint hf_cops_pc_key = -1;
682 static gint hf_cops_pc_max_packet_size = -1;
683 static gint hf_cops_pc_min_policed_unit = -1;
684 static gint hf_cops_pc_packetcable_err_code = -1;
685 static gint hf_cops_pc_packetcable_sub_code = -1;
686 static gint hf_cops_pc_peak_data_rate = -1;
687 static gint hf_cops_pc_protocol_id = -1;
688 static gint hf_cops_pc_reason_code = -1;
689 static gint hf_cops_pc_remote_flags = -1;
690 static gint hf_cops_pc_remote_gate_id = -1;
691 static gint hf_cops_pc_reserved = -1;
692 static gint hf_cops_pc_session_class = -1;
693 static gint hf_cops_pc_slack_term = -1;
694 static gint hf_cops_pc_spec_rate = -1;
695 static gint hf_cops_pc_src_ip = -1;
696 static gint hf_cops_pc_src_port = -1;
697 static gint hf_cops_pc_subscriber_id_ipv4 = -1;
698 static gint hf_cops_pc_subscriber_id_ipv6 = -1;
699 static gint hf_cops_pc_t1_value = -1;
700 static gint hf_cops_pc_t7_value = -1;
701 static gint hf_cops_pc_t8_value = -1;
702 static gint hf_cops_pc_token_bucket_rate = -1;
703 static gint hf_cops_pc_token_bucket_size = -1;
704 static gint hf_cops_pc_transaction_id = -1;
705 static gint hf_cops_pc_bcid_ts = -1;
706 static gint hf_cops_pc_bcid = -1;
707 static gint hf_cops_pc_bcid_ev = -1;
708 static gint hf_cops_pc_dfcdc_ip = -1;
709 static gint hf_cops_pc_dfccc_ip = -1;
710 static gint hf_cops_pc_dfcdc_ip_port = -1;
711 static gint hf_cops_pc_dfccc_ip_port = -1;
712 static gint hf_cops_pc_dfccc_id = -1;
713
714 /* PacketCable Multimedia */
715 static gint hf_cops_pcmm_amid = -1;
716 static gint hf_cops_pcmm_gate_spec_flags = -1;
717 static gint hf_cops_pcmm_gate_spec_dscp_tos_field = -1;
718 static gint hf_cops_pcmm_gate_spec_dscp_tos_mask = -1;
719 static gint hf_cops_pcmm_gate_spec_session_class_id = -1;
720 static gint hf_cops_pcmm_gate_spec_session_class_id_priority = -1;
721 static gint hf_cops_pcmm_gate_spec_session_class_id_preemption = -1;
722 static gint hf_cops_pcmm_gate_spec_session_class_id_configurable = -1;
723 static gint hf_cops_pcmm_gate_spec_timer_t1 = -1;
724 static gint hf_cops_pcmm_gate_spec_timer_t2 = -1;
725 static gint hf_cops_pcmm_gate_spec_timer_t3 = -1;
726 static gint hf_cops_pcmm_gate_spec_timer_t4 = -1;
727 static gint hf_cops_pcmm_classifier_protocol_id = -1;
728 static gint hf_cops_pcmm_classifier_dscp_tos_field = -1;
729 static gint hf_cops_pcmm_classifier_dscp_tos_mask = -1;
730 static gint hf_cops_pcmm_classifier_src_addr = -1;
731 static gint hf_cops_pcmm_classifier_dst_addr = -1;
732 static gint hf_cops_pcmm_classifier_src_port = -1;
733 static gint hf_cops_pcmm_classifier_dst_port = -1;
734 static gint hf_cops_pcmm_classifier_priority = -1;
735 static gint hf_cops_pcmm_flow_spec_envelope = -1;
736 static gint hf_cops_pcmm_flow_spec_service_number = -1;
737 static gint hf_cops_pcmm_docsis_scn = -1;
738 static gint hf_cops_pcmm_envelope = -1;
739 static gint hf_cops_pcmm_traffic_priority = -1;
740 static gint hf_cops_pcmm_request_transmission_policy = -1;
741 static gint hf_cops_pcmm_max_sustained_traffic_rate = -1;
742 static gint hf_cops_pcmm_max_traffic_burst = -1;
743 static gint hf_cops_pcmm_min_reserved_traffic_rate = -1;
744 static gint hf_cops_pcmm_ass_min_rtr_packet_size = -1;
745 static gint hf_cops_pcmm_nominal_polling_interval = -1;
746 static gint hf_cops_pcmm_tolerated_poll_jitter = -1;
747 static gint hf_cops_pcmm_unsolicited_grant_size = -1;
748 static gint hf_cops_pcmm_grants_per_interval = -1;
749 static gint hf_cops_pcmm_nominal_grant_interval = -1;
750 static gint hf_cops_pcmm_tolerated_grant_jitter = -1;
751 static gint hf_cops_pcmm_max_downstream_latency = -1;
752 static gint hf_cops_pcmm_volume_based_usage_limit = -1;
753 static gint hf_cops_pcmm_time_based_usage_limit = -1;
754 static gint hf_cops_pcmm_gate_time_info = -1;
755 static gint hf_cops_pcmm_gate_usage_info = -1;
756 static gint hf_cops_pcmm_packetcable_error_code = -1;
757 static gint hf_cops_pcmm_packetcable_error_subcode = -1;
758 static gint hf_cops_pcmm_packetcable_gate_state = -1;
759 static gint hf_cops_pcmm_packetcable_gate_state_reason = -1;
760 static gint hf_cops_pcmm_packetcable_version_info_major = -1;
761 static gint hf_cops_pcmm_packetcable_version_info_minor = -1;
762
763
764 /* Initialize the subtree pointers */
765 static gint ett_cops = -1;
766 static gint ett_cops_ver_flags = -1;
767 static gint ett_cops_obj = -1;
768 static gint ett_cops_pr_obj = -1;
769 static gint ett_cops_obj_data = -1;
770 static gint ett_cops_r_type_flags = -1;
771 static gint ett_cops_itf = -1;
772 static gint ett_cops_reason = -1;
773 static gint ett_cops_decision = -1;
774 static gint ett_cops_error = -1;
775 static gint ett_cops_clientsi = -1;
776 static gint ett_cops_asn1 = -1;
777 static gint ett_cops_gperror = -1;
778 static gint ett_cops_cperror = -1;
779 static gint ett_cops_pdp = -1;
780
781 /* For PacketCable */
782 static gint ett_cops_subtree = -1;
783
784 static gint ett_docsis_request_transmission_policy = -1;
785
786
787 void proto_reg_handoff_cops(void);
788
789 static guint get_cops_pdu_len(tvbuff_t *tvb, int offset);
790 static void dissect_cops_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
791
792 static int dissect_cops_object(tvbuff_t *tvb, packet_info *pinfo, guint8 op_code, guint32 offset, proto_tree *tree, guint16 client_type);
793 static void dissect_cops_object_data(tvbuff_t *tvb, packet_info *pinfo, guint32 offset, proto_tree *tree,
794                                      guint8 op_code, guint16 client_type, guint8 c_num, guint8 c_type, int len);
795
796 static void dissect_cops_pr_objects(tvbuff_t *tvb,packet_info *pinfo, guint32 offset, proto_tree *tree, int pr_len);
797 static int dissect_cops_pr_object_data(tvbuff_t *tvb, packet_info *pinfo, guint32 offset, proto_tree *tree,
798                                        guint8 s_num, guint8 s_type, int len);
799
800 /* Added for PacketCable */
801 static proto_tree *info_to_cops_subtree(tvbuff_t *, proto_tree *, int, int, const char *);
802 static proto_item *info_to_display(tvbuff_t *, proto_item *, int, int, const char *, const value_string *, int, gint *);
803
804 static void cops_transaction_id(tvbuff_t *, packet_info *, proto_tree *, guint8, guint, guint32);
805 static void cops_subscriber_id_v4(tvbuff_t *, proto_tree *, guint, guint32);
806 static void cops_subscriber_id_v6(tvbuff_t *, proto_tree *, guint, guint32);
807 static void cops_gate_id(tvbuff_t *, proto_tree *, guint, guint32);
808 static void cops_activity_count(tvbuff_t *, proto_tree *, guint, guint32);
809 static void cops_gate_specs(tvbuff_t *, proto_tree *, guint, guint32);
810 static void cops_remote_gate_info(tvbuff_t *, proto_tree *, guint, guint32);
811 static void cops_packetcable_reason(tvbuff_t *, proto_tree *, guint, guint32);
812 static void cops_packetcable_error(tvbuff_t *, proto_tree *, guint, guint32);
813 static void cops_event_generation_info(tvbuff_t *, proto_tree *, guint, guint32);
814 static void cops_surveillance_parameters(tvbuff_t *, proto_tree *, guint, guint32);
815
816 static void cops_amid(tvbuff_t *, proto_tree *, guint, guint32);
817
818 static void decode_docsis_request_transmission_policy(tvbuff_t *tvb, guint32 offset, proto_tree *tree, gint hf);
819
820 static void cops_analyze_packetcable_dqos_obj(tvbuff_t *, packet_info *, proto_tree *, guint8, guint32);
821 static void cops_analyze_packetcable_mm_obj(tvbuff_t *, packet_info *, proto_tree *, guint8, guint32);
822
823 static gboolean cops_packetcable = TRUE;
824
825 /* End of addition for PacketCable */
826
827
828 /* Code to actually dissect the packets */
829 static void
830 dissect_cops(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
831 {
832   tcp_dissect_pdus(tvb, pinfo, tree, cops_desegment, 8,
833                    get_cops_pdu_len, dissect_cops_pdu);
834 }
835
836 static guint
837 get_cops_pdu_len(tvbuff_t *tvb, int offset)
838 {
839   /*
840    * Get the length of the COPS message.
841    */
842   return tvb_get_ntohl(tvb, offset + 4);
843 }
844
845 static void
846 dissect_cops_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
847 {
848   guint8 op_code;
849   guint16 client_type;
850   int object_len;
851
852   if (check_col(pinfo->cinfo, COL_PROTOCOL))
853     col_set_str(pinfo->cinfo, COL_PROTOCOL, "COPS");
854   if (check_col(pinfo->cinfo, COL_INFO))
855     col_clear(pinfo->cinfo, COL_INFO);
856
857   op_code = tvb_get_guint8(tvb, 1);
858   if (check_col(pinfo->cinfo, COL_INFO))
859     col_add_fstr(pinfo->cinfo, COL_INFO, "COPS %s",
860                  val_to_str(op_code, cops_op_code_vals, "Unknown Op Code"));
861
862   /* Currently used by PacketCable */
863   client_type = tvb_get_ntohs(tvb, 2);
864
865   if (tree) {
866     proto_item *ti, *tv;
867     proto_tree *cops_tree, *ver_flags_tree;
868     guint32 msg_len;
869     guint32 offset = 0;
870     guint8 ver_flags;
871     gint garbage;
872
873     ti = proto_tree_add_item(tree, proto_cops, tvb, offset, -1, FALSE);
874     cops_tree = proto_item_add_subtree(ti, ett_cops);
875
876     /* Version and flags share the same byte, put them in a subtree */
877     ver_flags = tvb_get_guint8(tvb, offset);
878     tv = proto_tree_add_uint_format(cops_tree, hf_cops_ver_flags, tvb, offset, 1,
879                                       ver_flags, "Version: %u, Flags: %s",
880                                       hi_nibble(ver_flags),
881                                       val_to_str(lo_nibble(ver_flags), cops_flags_vals, "Unknown"));
882     ver_flags_tree = proto_item_add_subtree(tv, ett_cops_ver_flags);
883     proto_tree_add_uint(ver_flags_tree, hf_cops_version, tvb, offset, 1, ver_flags);
884     proto_tree_add_uint(ver_flags_tree, hf_cops_flags, tvb, offset, 1, ver_flags);
885     offset++;
886
887     proto_tree_add_item(cops_tree, hf_cops_op_code, tvb, offset, 1, FALSE);
888     offset ++;
889     proto_tree_add_item(cops_tree, hf_cops_client_type, tvb, offset, 2, FALSE);
890     offset += 2;
891
892     msg_len = tvb_get_ntohl(tvb, offset);
893     proto_tree_add_uint(cops_tree, hf_cops_msg_len, tvb, offset, 4, msg_len);
894     offset += 4;
895
896     while (tvb_reported_length_remaining(tvb, offset) >= COPS_OBJECT_HDR_SIZE) {
897       object_len = dissect_cops_object(tvb, pinfo, op_code, offset, cops_tree, client_type);
898       if (object_len < 0)
899         return;
900       offset += object_len;
901     }
902
903     garbage = tvb_length_remaining(tvb, offset);
904     if (garbage > 0)
905       proto_tree_add_text(cops_tree, tvb, offset, garbage,
906                           "Trailing garbage: %d byte%s", garbage,
907                           plurality(garbage, "", "s"));
908   }
909 }
910
911 static const char *cops_c_type_to_str(guint8 c_num, guint8 c_type)
912 {
913   switch (c_num) {
914   case COPS_OBJ_HANDLE:
915     if (c_type == 1)
916       return "Client Handle";
917     break;
918   case COPS_OBJ_IN_INT:
919   case COPS_OBJ_OUT_INT:
920     if (c_type == 1)
921       return "IPv4 Address + Interface";
922     else if (c_type == 2)
923       return "IPv6 Address + Interface";
924     break;
925   case COPS_OBJ_DECISION:
926   case COPS_OBJ_LPDPDECISION:
927     if (c_type == 1)
928       return "Decision Flags (Mandatory)";
929     else if (c_type == 2)
930       return "Stateless Data";
931     else if (c_type == 3)
932       return "Replacement Data";
933     else if (c_type == 4)
934       return "Client Specific Decision Data";
935     else if (c_type == 5)
936       return "Named Decision Data";
937     break;
938   case COPS_OBJ_CLIENTSI:
939     if (c_type == 1)
940       return "Signaled ClientSI";
941     else if (c_type == 2)
942       return "Named ClientSI";
943     break;
944   case COPS_OBJ_KATIMER:
945     if (c_type == 1)
946       return "Keep-alive timer value";
947     break;
948   case COPS_OBJ_PDPREDIRADDR:
949   case COPS_OBJ_LASTPDPADDR:
950     if (c_type == 1)
951       return "IPv4 Address + TCP Port";
952     else if (c_type == 2)
953       return "IPv6 Address + TCP Port";
954     break;
955   case COPS_OBJ_ACCTTIMER:
956     if (c_type == 1)
957       return "Accounting timer value";
958     break;
959   case COPS_OBJ_INTEGRITY:
960     if (c_type == 1)
961       return "HMAC digest";
962     break;
963   }
964
965   return "";
966 }
967
968 static int dissect_cops_object(tvbuff_t *tvb, packet_info *pinfo, guint8 op_code, guint32 offset, proto_tree *tree, guint16 client_type)
969 {
970   int object_len, contents_len;
971   guint8 c_num, c_type;
972   proto_item *ti;
973   proto_tree *obj_tree;
974   const char *type_str;
975
976   object_len = tvb_get_ntohs(tvb, offset);
977   if (object_len < COPS_OBJECT_HDR_SIZE) {
978     /* Bogus! */
979     proto_tree_add_text(tree, tvb, offset, 2,
980                         "Bad COPS object length: %u, should be at least %u",
981                         object_len, COPS_OBJECT_HDR_SIZE);
982     return -1;
983   }
984   c_num = tvb_get_guint8(tvb, offset + 2);
985   c_type = tvb_get_guint8(tvb, offset + 3);
986
987   ti = proto_tree_add_uint_format(tree, hf_cops_obj_c_num, tvb, offset, object_len, c_num,
988                                   "%s: %s", val_to_str(c_num, cops_c_num_vals, "Unknown"),
989                                   cops_c_type_to_str(c_num, c_type));
990   obj_tree = proto_item_add_subtree(ti, ett_cops_obj);
991
992   proto_tree_add_uint(obj_tree, hf_cops_obj_len, tvb, offset, 2, object_len);
993   offset += 2;
994
995   proto_tree_add_uint(obj_tree, hf_cops_obj_c_num, tvb, offset, 1, c_num);
996   offset++;
997
998   type_str = cops_c_type_to_str(c_num, c_type);
999   proto_tree_add_text(obj_tree, tvb, offset, 1, "C-Type: %s%s%u%s",
1000                       type_str,
1001                       strlen(type_str) ? " (" : "",
1002                       c_type,
1003                       strlen(type_str) ? ")" : "");
1004   offset++;
1005
1006   contents_len = object_len - COPS_OBJECT_HDR_SIZE;
1007   dissect_cops_object_data(tvb, pinfo, offset, obj_tree, op_code, client_type, c_num, c_type, contents_len);
1008
1009   /* Pad to 32bit boundary */
1010   if (object_len % sizeof (guint32))
1011     object_len += (sizeof (guint32) - object_len % sizeof (guint32));
1012
1013   return object_len;
1014 }
1015
1016 static void dissect_cops_pr_objects(tvbuff_t *tvb, packet_info *pinfo, guint32 offset, proto_tree *tree, int pr_len)
1017 {
1018   int object_len, contents_len;
1019   guint8 s_num, s_type;
1020   const char *type_str;
1021   int ret;
1022   proto_tree *cops_pr_tree, *obj_tree;
1023   proto_item *ti;
1024
1025   cops_pr_tree = proto_item_add_subtree(tree, ett_cops_pr_obj);
1026
1027   while (pr_len >= COPS_OBJECT_HDR_SIZE) {
1028     object_len = tvb_get_ntohs(tvb, offset);
1029     if (object_len < COPS_OBJECT_HDR_SIZE) {
1030       /* Bogus! */
1031       proto_tree_add_text(tree, tvb, offset, 2,
1032                           "Bad COPS PR object length: %u, should be at least %u",
1033                           object_len, COPS_OBJECT_HDR_SIZE);
1034       return;
1035     }
1036     s_num = tvb_get_guint8(tvb, offset + 2);
1037
1038     ti = proto_tree_add_uint_format(cops_pr_tree, hf_cops_obj_s_num, tvb, offset, object_len, s_num,
1039                                     "%s", val_to_str(s_num, cops_s_num_vals, "Unknown"));
1040     obj_tree = proto_item_add_subtree(cops_pr_tree, ett_cops_pr_obj);
1041
1042     proto_tree_add_uint(obj_tree, hf_cops_obj_len, tvb, offset, 2, object_len);
1043     offset += 2;
1044     pr_len -= 2;
1045
1046     proto_tree_add_uint(obj_tree, hf_cops_obj_s_num, tvb, offset, 1, s_num);
1047     offset++;
1048     pr_len--;
1049
1050     s_type = tvb_get_guint8(tvb, offset);
1051     type_str = val_to_str(s_type, cops_s_type_vals, "Unknown");
1052     proto_tree_add_text(obj_tree, tvb, offset, 1, "S-Type: %s%s%u%s",
1053                         type_str,
1054                         strlen(type_str) ? " (" : "",
1055                         s_type,
1056                         strlen(type_str) ? ")" : "");
1057     offset++;
1058     pr_len--;
1059
1060     contents_len = object_len - COPS_OBJECT_HDR_SIZE;
1061     ret = dissect_cops_pr_object_data(tvb, pinfo, offset, obj_tree, s_num, s_type, contents_len);
1062     if (ret < 0)
1063       break;
1064
1065     /*Pad to 32bit boundary */
1066     if (object_len % sizeof (guint32))
1067       object_len += (sizeof (guint32) - object_len % sizeof (guint32));
1068
1069     pr_len -= object_len - COPS_OBJECT_HDR_SIZE;
1070     offset += object_len - COPS_OBJECT_HDR_SIZE;
1071   }
1072 }
1073
1074 static void dissect_cops_object_data(tvbuff_t *tvb, packet_info *pinfo, guint32 offset, proto_tree *tree,
1075                                      guint8 op_code, guint16 client_type, guint8 c_num, guint8 c_type, int len)
1076 {
1077   proto_item *ti;
1078   proto_tree *r_type_tree, *itf_tree, *reason_tree, *dec_tree, *error_tree, *clientsi_tree, *pdp_tree;
1079   guint16 r_type, m_type, reason, reason_sub, cmd_code, cmd_flags, error, error_sub, tcp_port;
1080   guint32 ipv4addr, ifindex;
1081   struct e_in6_addr ipv6addr;
1082
1083   switch (c_num) {
1084   case COPS_OBJ_CONTEXT:
1085     r_type = tvb_get_ntohs(tvb, offset);
1086     m_type = tvb_get_ntohs(tvb, offset + 2);
1087     ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: R-Type: %s, M-Type: %u",
1088                              val_to_str(r_type, cops_r_type_vals, "Unknown"),
1089                              m_type);
1090
1091     r_type_tree = proto_item_add_subtree(ti, ett_cops_r_type_flags);
1092     proto_tree_add_uint(r_type_tree, hf_cops_r_type_flags, tvb, offset, 2, r_type);
1093     offset += 2;
1094     proto_tree_add_uint(r_type_tree, hf_cops_m_type_flags, tvb, offset, 2, m_type);
1095
1096     break;
1097   case COPS_OBJ_IN_INT:
1098   case COPS_OBJ_OUT_INT:
1099     if (c_type == 1) {          /* IPv4 */
1100       ipv4addr = tvb_get_ipv4(tvb, offset);
1101       ifindex = tvb_get_ntohl(tvb, offset + 4);
1102       ti = proto_tree_add_text(tree, tvb, offset, 8, "Contents: IPv4 address %s, ifIndex: %u",
1103                                ip_to_str((guint8 *)&ipv4addr), ifindex);
1104       itf_tree = proto_item_add_subtree(ti, ett_cops_itf);
1105       proto_tree_add_ipv4(itf_tree,
1106                           (c_num == COPS_OBJ_IN_INT) ? hf_cops_in_int_ipv4 : hf_cops_out_int_ipv4,
1107                           tvb, offset, 4, ipv4addr);
1108       offset += 4;
1109     } else if (c_type == 2) {   /* IPv6 */
1110       tvb_get_ipv6(tvb, offset, &ipv6addr);
1111       ifindex = tvb_get_ntohl(tvb, offset + sizeof ipv6addr);
1112       ti = proto_tree_add_text(tree, tvb, offset, 20, "Contents: IPv6 address %s, ifIndex: %u",
1113                                ip6_to_str(&ipv6addr), ifindex);
1114       itf_tree = proto_item_add_subtree(ti, ett_cops_itf);
1115       proto_tree_add_ipv6(itf_tree,
1116                           (c_num == COPS_OBJ_IN_INT) ? hf_cops_in_int_ipv6 : hf_cops_out_int_ipv6,
1117                           tvb, offset, 16, (guint8 *)&ipv6addr);
1118       offset += 16;
1119     } else {
1120       break;
1121     }
1122     proto_tree_add_uint(itf_tree, hf_cops_int_ifindex, tvb, offset, 4, ifindex);
1123
1124     break;
1125   case COPS_OBJ_REASON:
1126     reason = tvb_get_ntohs(tvb, offset);
1127     reason_sub = tvb_get_ntohs(tvb, offset + 2);
1128     ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Reason-Code: %s, Reason Sub-code: 0x%04x",
1129                              val_to_str(reason, cops_reason_vals, "<Unknown value>"), reason_sub);
1130     reason_tree = proto_item_add_subtree(ti, ett_cops_reason);
1131     proto_tree_add_uint(reason_tree, hf_cops_reason, tvb, offset, 2, reason);
1132     offset += 2;
1133     if (reason == 13) {
1134       proto_tree_add_text(reason_tree, tvb, offset, 2, "Reason Sub-code: "
1135                           "Unknown object's C-Num %u, C-Type %u",
1136                           tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset + 1));
1137     } else
1138       proto_tree_add_uint(reason_tree, hf_cops_reason_sub, tvb, offset, 2, reason_sub);
1139
1140     break;
1141   case COPS_OBJ_DECISION:
1142   case COPS_OBJ_LPDPDECISION:
1143     if (c_type == 1) {
1144       cmd_code = tvb_get_ntohs(tvb, offset);
1145       cmd_flags = tvb_get_ntohs(tvb, offset + 2);
1146       ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Command-Code: %s, Flags: %s",
1147                                val_to_str(cmd_code, cops_dec_cmd_code_vals, "<Unknown value>"),
1148                                val_to_str(cmd_flags, cops_dec_cmd_flag_vals, "<Unknown flag>"));
1149       dec_tree = proto_item_add_subtree(ti, ett_cops_decision);
1150       proto_tree_add_uint(dec_tree, hf_cops_dec_cmd_code, tvb, offset, 2, cmd_code);
1151       offset += 2;
1152       proto_tree_add_uint(dec_tree, hf_cops_dec_flags, tvb, offset, 2, cmd_flags);
1153     } else if (c_type == 5) { /*COPS-PR Data*/
1154       ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: %d bytes", len);
1155       dec_tree = proto_item_add_subtree(ti, ett_cops_decision);
1156       dissect_cops_pr_objects(tvb, pinfo, offset, dec_tree, len);
1157     }
1158
1159     /* PacketCable : Analyze the remaining data if available */
1160     if (client_type == COPS_CLIENT_PC_DQOS && c_type == 4) {
1161         cops_analyze_packetcable_dqos_obj(tvb, pinfo, tree, op_code, offset);
1162     } else if (client_type == COPS_CLIENT_PC_MM && c_type == 4) {
1163         cops_analyze_packetcable_mm_obj(tvb, pinfo, tree, op_code, offset);
1164     }
1165
1166     break;
1167   case COPS_OBJ_ERROR:
1168     if (c_type != 1)
1169       break;
1170
1171     error = tvb_get_ntohs(tvb, offset);
1172     error_sub = tvb_get_ntohs(tvb, offset + 2);
1173     ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Error-Code: %s, Error Sub-code: 0x%04x",
1174                              val_to_str(error, cops_error_vals, "<Unknown value>"), error_sub);
1175     error_tree = proto_item_add_subtree(ti, ett_cops_error);
1176     proto_tree_add_uint(error_tree, hf_cops_error, tvb, offset, 2, error);
1177     offset += 2;
1178     if (error == 13) {
1179       proto_tree_add_text(error_tree, tvb, offset, 2, "Error Sub-code: "
1180                           "Unknown object's C-Num %u, C-Type %u",
1181                           tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset + 1));
1182     } else
1183       proto_tree_add_uint(error_tree, hf_cops_error_sub, tvb, offset, 2, error_sub);
1184
1185     break;
1186   case COPS_OBJ_CLIENTSI:
1187
1188     /* For PacketCable */
1189     if (client_type == COPS_CLIENT_PC_DQOS && c_type == 1) {
1190        cops_analyze_packetcable_dqos_obj(tvb, pinfo, tree, op_code, offset);
1191        break;
1192     } else if (client_type == COPS_CLIENT_PC_MM && c_type == 1) {
1193        cops_analyze_packetcable_mm_obj(tvb, pinfo, tree, op_code, offset);
1194        break;
1195     }
1196
1197     if (c_type != 2) /*Not COPS-PR data*/
1198       break;
1199
1200     ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: %d bytes", len);
1201     clientsi_tree = proto_item_add_subtree(ti, ett_cops_clientsi);
1202
1203     dissect_cops_pr_objects(tvb, pinfo, offset, clientsi_tree, len);
1204
1205     break;
1206   case COPS_OBJ_KATIMER:
1207     if (c_type != 1)
1208       break;
1209
1210     proto_tree_add_item(tree, hf_cops_katimer, tvb, offset + 2, 2, FALSE);
1211     if (tvb_get_ntohs(tvb, offset + 2) == 0)
1212       proto_tree_add_text(tree, tvb, offset, 0, "Value of zero implies infinity.");
1213
1214     break;
1215   case COPS_OBJ_PEPID:
1216     if (c_type != 1)
1217       break;
1218
1219     if (tvb_strnlen(tvb, offset, len) == -1)
1220       proto_tree_add_text(tree, tvb, offset, len, "<PEP Id is not a NUL terminated ASCII string>");
1221     else
1222       proto_tree_add_item(tree, hf_cops_pepid, tvb, offset,
1223                           tvb_strnlen(tvb, offset, len) + 1, FALSE);
1224
1225     break;
1226   case COPS_OBJ_REPORT_TYPE:
1227     if (c_type != 1)
1228       break;
1229
1230     proto_tree_add_item(tree, hf_cops_report_type, tvb, offset, 2, FALSE);
1231
1232     break;
1233   case COPS_OBJ_PDPREDIRADDR:
1234   case COPS_OBJ_LASTPDPADDR:
1235     if (c_type == 1) {          /* IPv4 */
1236       ipv4addr = tvb_get_ipv4(tvb, offset);
1237       tcp_port = tvb_get_ntohs(tvb, offset + 4 + 2);
1238       ti = proto_tree_add_text(tree, tvb, offset, 8, "Contents: IPv4 address %s, TCP Port Number: %u",
1239                                ip_to_str((guint8 *)&ipv4addr), tcp_port);
1240       pdp_tree = proto_item_add_subtree(ti, ett_cops_pdp);
1241       proto_tree_add_ipv4(pdp_tree,
1242                           (c_num == COPS_OBJ_PDPREDIRADDR) ? hf_cops_pdprediraddr_ipv4 : hf_cops_lastpdpaddr_ipv4,
1243                           tvb, offset, 4, ipv4addr);
1244       offset += 4;
1245     } else if (c_type == 2) {   /* IPv6 */
1246       tvb_get_ipv6(tvb, offset, &ipv6addr);
1247       tcp_port = tvb_get_ntohs(tvb, offset + sizeof ipv6addr + 2);
1248       ti = proto_tree_add_text(tree, tvb, offset, 20, "Contents: IPv6 address %s, TCP Port Number: %u",
1249                                ip6_to_str(&ipv6addr), tcp_port);
1250       pdp_tree = proto_item_add_subtree(ti, ett_cops_pdp);
1251       proto_tree_add_ipv6(pdp_tree,
1252                           (c_num == COPS_OBJ_PDPREDIRADDR) ? hf_cops_pdprediraddr_ipv6 : hf_cops_lastpdpaddr_ipv6,
1253                           tvb, offset, 16, (guint8 *)&ipv6addr);
1254       offset += 16;
1255     } else {
1256       break;
1257     }
1258     offset += 2;
1259     proto_tree_add_uint(pdp_tree, hf_cops_pdp_tcp_port, tvb, offset, 2, tcp_port);
1260
1261     break;
1262   case COPS_OBJ_ACCTTIMER:
1263     if (c_type != 1)
1264       break;
1265
1266     proto_tree_add_item(tree, hf_cops_accttimer, tvb, offset + 2, 2, FALSE);
1267     if (tvb_get_ntohs(tvb, offset + 2) == 0)
1268       proto_tree_add_text(tree, tvb, offset, 0, "Value of zero means "
1269                           "there SHOULD be no unsolicited accounting updates.");
1270
1271     break;
1272   case COPS_OBJ_INTEGRITY:
1273     if (c_type != 1)
1274       break;      /* Not HMAC digest */
1275
1276     proto_tree_add_item(tree, hf_cops_key_id, tvb, offset, 4, FALSE);
1277     proto_tree_add_item(tree, hf_cops_seq_num, tvb, offset + 4, 4, FALSE);
1278     proto_tree_add_text(tree, tvb, offset + 8 , len - 8, "Contents: Keyed Message Digest");
1279
1280     break;
1281   default:
1282     proto_tree_add_text(tree, tvb, offset, len, "Contents: %d bytes", len);
1283
1284     break;
1285   }
1286 }
1287
1288 #ifdef HAVE_NET_SNMP
1289 static guchar*format_asn_value (struct variable_list *variable, subid_t *variable_oid,
1290                                 guint variable_oid_length, u_char type_from_packet)
1291 {
1292   struct tree *subtree=tree_head;
1293
1294   guchar *buf=NULL;
1295   size_t buf_len=0;
1296   size_t out_len=0;
1297
1298   /*Get the ASN.1 type etc. from the PIB-MIB. If unsuccessful use the type from packet*/
1299   subtree = get_tree(variable_oid,variable_oid_length, subtree);
1300
1301   if (subtree->type == 0)
1302     variable->type= type_from_packet;
1303
1304   buf_len = SPRINT_MAX_LEN; /*defined in NET-SNMP's snmp-impl.h*/
1305   buf = ep_alloc(buf_len);
1306   *buf = '\0';
1307   out_len = 0;
1308
1309   /*If the ASN.1 type was found from PIB-MIB, use it for decoding*/
1310   if (!variable->type)
1311     variable->type=mib_to_asn_type(subtree->type);
1312
1313   if (!sprint_realloc_by_type(&buf, &buf_len, &out_len, TRUE, variable, subtree->enums, subtree->hint, NULL))
1314     g_snprintf(buf,SPRINT_MAX_LEN,"%s","sprint_realloc_by_type failed");
1315
1316   return buf;
1317 }
1318 #endif  /* HAVE_NET_SNMP */
1319
1320 static int decode_cops_pr_asn1_data(tvbuff_t *tvb,packet_info *pinfo, guint32 offset,
1321     proto_tree *tree, guint asnlen, guint8 cops_pr_obj
1322 #ifndef HAVE_NET_SNMP
1323                                                   _U_
1324 #endif
1325     )
1326 {
1327   int start, vb_value_start;
1328   guint length;
1329
1330   guint vb_length;
1331   gushort vb_type;
1332   const gchar *vb_type_name;
1333
1334   subid_t epd_attribute_index=0;
1335
1336   gint32 vb_integer_value;
1337   guint32 vb_uinteger_value;
1338
1339   const guint8 *oid_buf;
1340   guint8 *vb_octet_string;
1341
1342   subid_t *vb_oid;
1343   guint vb_oid_length;
1344
1345   gchar *vb_display_string;
1346   gchar *vb_display_string2;
1347
1348 #ifdef HAVE_NET_SNMP
1349   struct variable_list variable;
1350   long value;
1351 #endif  /* HAVE_NET_SNMP */
1352
1353   unsigned int i;
1354   gchar *buf;
1355   gint8 class;
1356   gboolean pc, ind = 0;
1357   gint32 ber_tag;
1358
1359   while (asnlen > 0) { /*while there is ASN stuff to be decoded*/
1360
1361     epd_attribute_index++;
1362 #ifdef HAVE_NET_SNMP
1363     last_decoded_prid_oid[last_decoded_prid_oid_length-1]=epd_attribute_index;
1364 #endif  /* HAVE_NET_SNMP */
1365
1366     /* parse the type of the object */
1367
1368     start = offset;
1369
1370         offset = dissect_ber_identifier(pinfo , NULL, tvb, start, &class, &pc, &ber_tag);
1371         offset = dissect_ber_length(pinfo, NULL, tvb, offset, &vb_length, &ind);
1372
1373         vb_value_start = offset;
1374
1375     /* Convert the class, constructed flag, and tag to a type. */
1376     vb_type_name = cops_tag_cls2syntax(ber_tag, class, &vb_type);
1377     if (vb_type_name == NULL) {
1378       /*
1379        * Unsupported type.
1380        * Dissect the value as an opaque string of octets.
1381        */
1382       vb_type_name = "unsupported type";
1383       vb_type = COPS_OPAQUE;
1384     }
1385
1386     /* parse the value */
1387
1388     switch (vb_type) {
1389
1390     case COPS_INTEGER:
1391                 offset = dissect_ber_integer(FALSE, pinfo, tree, tvb, start, -1, &vb_integer_value);
1392                 length = offset - vb_value_start;
1393       if (tree) {
1394 #ifdef HAVE_NET_SNMP
1395         if (cops_typefrommib == TRUE)
1396         {
1397           variable.type = 0;
1398           value = vb_integer_value;
1399           variable.val.integer = &value;
1400           variable.val_len = vb_length ;
1401           vb_display_string=format_asn_value(&variable,
1402                                              last_decoded_prid_oid,last_decoded_prid_oid_length,ASN_INTEGER);
1403
1404           proto_tree_add_text(tree, tvb, vb_value_start, length,
1405                               "Value: %s", vb_display_string);
1406         }
1407         else
1408 #endif /* HAVE_NET_SNMP */
1409           proto_tree_add_text(tree, tvb, vb_value_start, length,
1410                               "Value: %s: %d (%#x)", vb_type_name,
1411                               vb_integer_value, vb_integer_value);
1412       }
1413       break;
1414
1415     case COPS_UNSIGNED32:
1416     case COPS_TIMETICKS:
1417                 offset = dissect_ber_integer(FALSE, pinfo, tree, tvb, start, -1, &vb_uinteger_value);
1418                 length = offset - vb_value_start;
1419       if (tree) {
1420 #ifdef HAVE_NET_SNMP
1421         if (cops_typefrommib == TRUE)
1422         {
1423           variable.type = 0;
1424           value = vb_uinteger_value;
1425           variable.val.integer = &value;
1426           variable.val_len = vb_length;
1427
1428           vb_display_string=format_asn_value(&variable,
1429                                              last_decoded_prid_oid,last_decoded_prid_oid_length,ASN_UINTEGER);
1430
1431           proto_tree_add_text(tree,tvb, vb_value_start, length, "Value %s: %s",vb_type_name, vb_display_string);
1432
1433         }
1434         else
1435 #endif /* HAVE_NET_SNMP */
1436           proto_tree_add_text(tree,tvb, vb_value_start, length,
1437                               "Value: %s: %u (%#x)", vb_type_name,
1438                               vb_uinteger_value, vb_uinteger_value);
1439       }
1440       break;
1441
1442     case COPS_OCTETSTR:
1443     case COPS_IPADDR:
1444     case COPS_OPAQUE:
1445     case COPS_UNSIGNED64:
1446     case COPS_INTEGER64:
1447                 offset = dissect_ber_octet_string(FALSE, pinfo, tree, tvb, start, -1, NULL);
1448                 vb_octet_string = ep_tvb_memdup(tvb, vb_value_start, vb_length);
1449                 length = offset - vb_value_start;
1450       if (tree) {
1451 #ifdef HAVE_NET_SNMP
1452         if (cops_typefrommib == TRUE)
1453         {
1454           variable.type = 0;
1455           variable.val.string = vb_octet_string;
1456           variable.val_len = vb_length;
1457           vb_display_string = format_asn_value(&variable,
1458                                                last_decoded_prid_oid,last_decoded_prid_oid_length,ASN_OCTET_STR);
1459           proto_tree_add_text(tree, tvb, vb_value_start, length,
1460                               "Value: %s (ASN.1 type from packet: %s)", vb_display_string, vb_type_name);
1461
1462         }
1463         else
1464         {
1465 #endif /* HAVE_NET_SNMP */
1466           for (i = 0; i < vb_length; i++) {
1467             if (!(isprint(vb_octet_string[i]) ||isspace(vb_octet_string[i])))
1468               break;
1469           }
1470
1471           /*
1472            * If some characters are not printable, display the string as bytes.
1473            */
1474           if (i < vb_length) {
1475             /*
1476              * We stopped, due to a non-printable character, before we got
1477              * to the end of the string.
1478              */
1479             vb_display_string = ep_alloc(4*vb_length);
1480             buf = vb_display_string;
1481             buf += g_snprintf(buf, 4*vb_length, "%03u", vb_octet_string[0]);
1482             for (i = 1; i < vb_length; i++) {
1483               buf += g_snprintf(buf, 4*vb_length-(buf-vb_display_string), ".%03u", vb_octet_string[i]);
1484             }
1485             proto_tree_add_text(tree, tvb, vb_value_start, length,
1486                                 "Value: %s: %s", vb_type_name, vb_display_string);
1487           } else {
1488             proto_tree_add_text(tree, tvb, vb_value_start, length,
1489                                 "Value: %s: %.*s", vb_type_name, (int)vb_length,
1490                                 SAFE_STRING(vb_octet_string));
1491           }
1492 #ifdef HAVE_NET_SNMP
1493         }
1494 #endif /* HAVE_NET_SNMP */
1495       }
1496       break;
1497
1498     case COPS_NULL:
1499                 dissect_ber_null(FALSE, pinfo, tree,tvb, start, -1);
1500                 length = offset - vb_value_start;
1501       if (tree)
1502         proto_tree_add_text(tree, tvb, vb_value_start, length, "Value: %s", vb_type_name);
1503       break;
1504
1505     case COPS_OBJECTID:
1506                 /* XXX Redo this using dissect_ber_object... when it returns tvb */ 
1507                 oid_buf = tvb_get_ptr(tvb, vb_value_start, vb_length);
1508                 vb_oid = g_malloc((vb_length+1) * sizeof(gulong));
1509                 vb_oid_length = oid_to_subid_buf(oid_buf, vb_length, vb_oid, ((vb_length+1) * sizeof(gulong)));
1510
1511                 offset = offset + vb_length;
1512                 length = offset - vb_value_start;
1513
1514 /*      ret = asn1_oid_value_decode (&asn1, vb_length, &vb_oid, &vb_oid_length); 
1515       if (ret != ASN1_ERR_NOERROR)
1516         return ret; 
1517       length = asn1.offset - start;
1518 */
1519       if (tree) {
1520         if (cops_pr_obj == COPS_OBJ_PPRID){
1521           /*we're decoding Prefix PRID, that doesn't have a instance Id,
1522            *Use full length of the OID when decoding it.
1523            */
1524           new_format_oid(vb_oid,vb_oid_length,&vb_display_string,&vb_display_string2);
1525
1526           if (!vb_display_string2)   /*if OID couldn't be decoded, print only numeric format*/
1527             proto_tree_add_text(tree, tvb, vb_value_start, length,
1528                                 "Value: %s: %s", vb_type_name, vb_display_string);
1529           else
1530             proto_tree_add_text(tree, tvb, vb_value_start, length,
1531                                 "Value: %s: %s (%s)", vb_type_name,
1532                                 vb_display_string,
1533                                 vb_display_string2);
1534         }
1535         else { /*we're decoding PRID, Error PRID or EPD*/
1536           /*strip the instance Id from the OIDs before decoding and paste it back during printing*/
1537           new_format_oid(vb_oid,vb_oid_length-1,&vb_display_string,&vb_display_string2);
1538
1539           if (!vb_display_string2)  /*if OID couldn't be decoded, print only numeric format*/
1540             proto_tree_add_text(tree, tvb, vb_value_start, length,
1541                                 "Value: %s: %s.%lu", vb_type_name,
1542                                 vb_display_string,
1543                                 (unsigned long)vb_oid[vb_oid_length-1]);
1544           else
1545             proto_tree_add_text(tree, tvb, vb_value_start, length,
1546                                 "Value: %s: %s.%lu (%s.%lu)", vb_type_name,
1547                                 vb_display_string,
1548                                 (unsigned long)vb_oid[vb_oid_length-1],
1549                                 vb_display_string2,
1550                                 (unsigned long)vb_oid[vb_oid_length-1]);
1551         }
1552 #ifdef HAVE_NET_SNMP
1553         if (cops_pr_obj != COPS_OBJ_EPD) {
1554           /* we're not decoding EPD, so let's store the OID of the PRID so that later
1555              when we're decoding this PRID's EPD we can finetune the output.*/
1556           memcpy(last_decoded_prid_oid,vb_oid,vb_oid_length*sizeof(subid_t));
1557           last_decoded_prid_oid_length=vb_oid_length;
1558         }
1559 #endif /* HAVE_NET_SNMP */
1560       }
1561       g_free(vb_oid);
1562       break;
1563
1564     default:
1565       DISSECTOR_ASSERT_NOT_REACHED();
1566       return 2; /* type not right */
1567     }
1568
1569
1570     asnlen -= offset - start;
1571   }
1572   epd_attribute_index=0;
1573   return 0;
1574 }
1575
1576 static int dissect_cops_pr_object_data(tvbuff_t *tvb, packet_info *pinfo, guint32 offset, proto_tree *tree,
1577                                        guint8 s_num, guint8 s_type, int len)
1578 {
1579   proto_item *ti;
1580   proto_tree *asn1_object_tree, *gperror_tree, *cperror_tree;
1581   guint16 gperror=0, gperror_sub=0, cperror=0, cperror_sub=0;
1582
1583   switch (s_num){
1584   case COPS_OBJ_PRID:
1585    if (s_type != 1) /* Not Provisioning Instance Identifier (PRID) */
1586       break;
1587
1588     ti=proto_tree_add_text(tree, tvb, offset, len, "Contents:");
1589     asn1_object_tree = proto_item_add_subtree(ti, ett_cops_asn1);
1590
1591     decode_cops_pr_asn1_data(tvb, pinfo, offset, asn1_object_tree, len, COPS_OBJ_PRID);
1592
1593     break;
1594   case COPS_OBJ_PPRID:
1595     if (s_type != 1) /* Not Prefix Provisioning Instance Identifier (PPRID) */
1596       break;
1597
1598     ti = proto_tree_add_text(tree, tvb, offset, len, "Contents:");
1599     asn1_object_tree = proto_item_add_subtree(ti, ett_cops_asn1);
1600
1601     decode_cops_pr_asn1_data(tvb, pinfo, offset, asn1_object_tree, len, COPS_OBJ_PPRID);
1602
1603     break;
1604   case COPS_OBJ_EPD:
1605     if (s_type != 1) /* Not  Encoded Provisioning Instance Data (EPD) */
1606       break;
1607
1608     ti = proto_tree_add_text(tree, tvb, offset, len, "Contents:");
1609     asn1_object_tree = proto_item_add_subtree(ti, ett_cops_asn1);
1610
1611     decode_cops_pr_asn1_data(tvb, pinfo, offset, asn1_object_tree, len, COPS_OBJ_EPD);
1612
1613     break;
1614   case COPS_OBJ_GPERR:
1615     if (s_type != 1) /* Not Global Provisioning Error Object (GPERR) */
1616       break;
1617
1618     gperror = tvb_get_ntohs(tvb, offset);
1619     gperror_sub = tvb_get_ntohs(tvb, offset + 2);
1620     ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Error-Code: %s, Error Sub-code: 0x%04x",
1621                        val_to_str(gperror, cops_gperror_vals, "<Unknown value>"), gperror_sub);
1622     gperror_tree = proto_item_add_subtree(ti, ett_cops_gperror);
1623     proto_tree_add_uint(gperror_tree, hf_cops_gperror, tvb, offset, 2, gperror);
1624     offset += 2;
1625     if (cperror == 13) {
1626       proto_tree_add_text(gperror_tree, tvb, offset, 2, "Error Sub-code: "
1627                           "Unknown object's C-Num %u, C-Type %u",
1628                           tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset + 1));
1629     } else
1630       proto_tree_add_uint(gperror_tree, hf_cops_gperror_sub, tvb, offset, 2, gperror_sub);
1631
1632     break;
1633   case COPS_OBJ_CPERR:
1634     if (s_type != 1) /*Not PRC Class Provisioning Error Object (CPERR) */
1635       break;
1636
1637     break;
1638
1639     cperror = tvb_get_ntohs(tvb, offset);
1640     cperror_sub = tvb_get_ntohs(tvb, offset + 2);
1641     ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Error-Code: %s, Error Sub-code: 0x%04x",
1642                        val_to_str(cperror, cops_cperror_vals, "<Unknown value>"), cperror_sub);
1643     cperror_tree = proto_item_add_subtree(ti, ett_cops_cperror);
1644     proto_tree_add_uint(cperror_tree, hf_cops_cperror, tvb, offset, 2, cperror);
1645     offset += 2;
1646     if (cperror == 13) {
1647       proto_tree_add_text(cperror_tree, tvb, offset, 2, "Error Sub-code: "
1648                           "Unknown object's S-Num %u, C-Type %u",
1649                           tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset + 1));
1650     } else
1651       proto_tree_add_uint(cperror_tree, hf_cops_cperror_sub, tvb, offset, 2, cperror_sub);
1652
1653     break;
1654   case COPS_OBJ_ERRPRID:
1655     if (s_type != 1) /*Not  Error Provisioning Instance Identifier (ErrorPRID)*/
1656       break;
1657
1658     ti = proto_tree_add_text(tree, tvb, offset, len, "Contents:");
1659     asn1_object_tree = proto_item_add_subtree(ti, ett_cops_asn1);
1660
1661     decode_cops_pr_asn1_data(tvb, pinfo, offset, asn1_object_tree, len, COPS_OBJ_ERRPRID);
1662
1663     break;
1664   default:
1665     proto_tree_add_text(tree, tvb, offset, len, "Contents: %d bytes", len);
1666     break;
1667   }
1668
1669   return 0;
1670 }
1671
1672
1673 /* Register the protocol with Ethereal */
1674 void proto_register_cops(void)
1675 {
1676   /* Setup list of header fields */
1677   static hf_register_info hf[] = {
1678     { &hf_cops_ver_flags,
1679       { "Version and Flags",           "cops.ver_flags",
1680       FT_UINT8, BASE_HEX, NULL, 0x0,
1681       "Version and Flags in COPS Common Header", HFILL }
1682     },
1683     { &hf_cops_version,
1684       { "Version",           "cops.version",
1685       FT_UINT8, BASE_DEC, NULL, 0xF0,
1686       "Version in COPS Common Header", HFILL }
1687     },
1688     { &hf_cops_flags,
1689       { "Flags",           "cops.flags",
1690       FT_UINT8, BASE_HEX, VALS(cops_flags_vals), 0x0F,
1691       "Flags in COPS Common Header", HFILL }
1692     },
1693     { &hf_cops_op_code,
1694       { "Op Code",           "cops.op_code",
1695       FT_UINT8, BASE_DEC, VALS(cops_op_code_vals), 0x0,
1696       "Op Code in COPS Common Header", HFILL }
1697     },
1698     { &hf_cops_client_type,
1699       { "Client Type",           "cops.client_type",
1700       FT_UINT16, BASE_DEC, VALS(cops_client_type_vals), 0x0,
1701       "Client Type in COPS Common Header", HFILL }
1702     },
1703     { &hf_cops_msg_len,
1704       { "Message Length",           "cops.msg_len",
1705       FT_UINT32, BASE_DEC, NULL, 0x0,
1706       "Message Length in COPS Common Header", HFILL }
1707     },
1708     { &hf_cops_obj_len,
1709       { "Object Length",           "cops.obj.len",
1710       FT_UINT32, BASE_DEC, NULL, 0x0,
1711       "Object Length in COPS Object Header", HFILL }
1712     },
1713     { &hf_cops_obj_c_num,
1714       { "C-Num",           "cops.c_num",
1715       FT_UINT8, BASE_DEC, VALS(cops_c_num_vals), 0x0,
1716       "C-Num in COPS Object Header", HFILL }
1717     },
1718     { &hf_cops_obj_c_type,
1719       { "C-Type",           "cops.c_type",
1720       FT_UINT8, BASE_DEC, NULL, 0x0,
1721       "C-Type in COPS Object Header", HFILL }
1722     },
1723
1724     { &hf_cops_obj_s_num,
1725       { "S-Num",           "cops.s_num",
1726       FT_UINT8, BASE_DEC, VALS(cops_s_num_vals), 0x0,
1727       "S-Num in COPS-PR Object Header", HFILL }
1728     },
1729     { &hf_cops_obj_s_type,
1730       { "S-Type",           "cops.s_type",
1731       FT_UINT8, BASE_DEC, NULL, 0x0,
1732       "S-Type in COPS-PR Object Header", HFILL }
1733     },
1734
1735     { &hf_cops_r_type_flags,
1736       { "R-Type",           "cops.context.r_type",
1737       FT_UINT16, BASE_HEX, VALS(cops_r_type_vals), 0xFFFF,
1738       "R-Type in COPS Context Object", HFILL }
1739     },
1740     { &hf_cops_m_type_flags,
1741       { "M-Type",           "cops.context.m_type",
1742       FT_UINT16, BASE_HEX, NULL, 0xFFFF,
1743       "M-Type in COPS Context Object", HFILL }
1744     },
1745     { &hf_cops_in_int_ipv4,
1746       { "IPv4 address",           "cops.in-int.ipv4",
1747       FT_IPv4, 0, NULL, 0,
1748       "IPv4 address in COPS IN-Int object", HFILL }
1749     },
1750     { &hf_cops_in_int_ipv6,
1751       { "IPv6 address",           "cops.in-int.ipv6",
1752       FT_IPv6, 0, NULL, 0,
1753       "IPv6 address in COPS IN-Int object", HFILL }
1754     },
1755     { &hf_cops_out_int_ipv4,
1756       { "IPv4 address",           "cops.out-int.ipv4",
1757       FT_IPv4, 0, NULL, 0,
1758       "IPv4 address in COPS OUT-Int object", HFILL }
1759     },
1760     { &hf_cops_out_int_ipv6,
1761       { "IPv6 address",           "cops.out-int.ipv6",
1762       FT_IPv6, 0, NULL, 0,
1763       "IPv6 address in COPS OUT-Int", HFILL }
1764     },
1765     { &hf_cops_int_ifindex,
1766       { "ifIndex",           "cops.in-out-int.ifindex",
1767       FT_UINT32, BASE_DEC, NULL, 0x0,
1768       "If SNMP is supported, corresponds to MIB-II ifIndex", HFILL }
1769     },
1770     { &hf_cops_reason,
1771       { "Reason",           "cops.reason",
1772       FT_UINT16, BASE_DEC, VALS(cops_reason_vals), 0,
1773       "Reason in Reason object", HFILL }
1774     },
1775     { &hf_cops_reason_sub,
1776       { "Reason Sub-code",           "cops.reason_sub",
1777       FT_UINT16, BASE_HEX, NULL, 0,
1778       "Reason Sub-code in Reason object", HFILL }
1779     },
1780     { &hf_cops_dec_cmd_code,
1781       { "Command-Code",           "cops.decision.cmd",
1782       FT_UINT16, BASE_DEC, VALS(cops_dec_cmd_code_vals), 0,
1783       "Command-Code in Decision/LPDP Decision object", HFILL }
1784     },
1785     { &hf_cops_dec_flags,
1786       { "Flags",           "cops.decision.flags",
1787       FT_UINT16, BASE_HEX, VALS(cops_dec_cmd_flag_vals), 0xffff,
1788       "Flags in Decision/LPDP Decision object", HFILL }
1789     },
1790     { &hf_cops_error,
1791       { "Error",           "cops.error",
1792       FT_UINT16, BASE_DEC, VALS(cops_error_vals), 0,
1793       "Error in Error object", HFILL }
1794     },
1795     { &hf_cops_error_sub,
1796       { "Error Sub-code",           "cops.error_sub",
1797       FT_UINT16, BASE_HEX, NULL, 0,
1798       "Error Sub-code in Error object", HFILL }
1799     },
1800     { &hf_cops_katimer,
1801       { "Contents: KA Timer Value",           "cops.katimer.value",
1802       FT_UINT16, BASE_DEC, NULL, 0,
1803       "Keep-Alive Timer Value in KATimer object", HFILL }
1804     },
1805     { &hf_cops_pepid,
1806       { "Contents: PEP Id",           "cops.pepid.id",
1807       FT_STRING, BASE_NONE, NULL, 0,
1808       "PEP Id in PEPID object", HFILL }
1809     },
1810     { &hf_cops_report_type,
1811       { "Contents: Report-Type",           "cops.report_type",
1812       FT_UINT16, BASE_DEC, VALS(cops_report_type_vals), 0,
1813       "Report-Type in Report-Type object", HFILL }
1814     },
1815     { &hf_cops_pdprediraddr_ipv4,
1816       { "IPv4 address",           "cops.pdprediraddr.ipv4",
1817       FT_IPv4, 0, NULL, 0,
1818       "IPv4 address in COPS PDPRedirAddr object", HFILL }
1819     },
1820     { &hf_cops_pdprediraddr_ipv6,
1821       { "IPv6 address",           "cops.pdprediraddr.ipv6",
1822       FT_IPv6, 0, NULL, 0,
1823       "IPv6 address in COPS PDPRedirAddr object", HFILL }
1824     },
1825     { &hf_cops_lastpdpaddr_ipv4,
1826       { "IPv4 address",           "cops.lastpdpaddr.ipv4",
1827       FT_IPv4, 0, NULL, 0,
1828       "IPv4 address in COPS LastPDPAddr object", HFILL }
1829     },
1830     { &hf_cops_lastpdpaddr_ipv6,
1831       { "IPv6 address",           "cops.lastpdpaddr.ipv6",
1832       FT_IPv6, 0, NULL, 0,
1833       "IPv6 address in COPS LastPDPAddr object", HFILL }
1834     },
1835     { &hf_cops_pdp_tcp_port,
1836       { "TCP Port Number",           "cops.pdp.tcp_port",
1837       FT_UINT32, BASE_DEC, NULL, 0x0,
1838        "TCP Port Number of PDP in PDPRedirAddr/LastPDPAddr object", HFILL }
1839     },
1840     { &hf_cops_accttimer,
1841       { "Contents: ACCT Timer Value",           "cops.accttimer.value",
1842       FT_UINT16, BASE_DEC, NULL, 0,
1843       "Accounting Timer Value in AcctTimer object", HFILL }
1844     },
1845     { &hf_cops_key_id,
1846       { "Contents: Key ID",           "cops.integrity.key_id",
1847       FT_UINT32, BASE_DEC, NULL, 0,
1848       "Key ID in Integrity object", HFILL }
1849     },
1850     { &hf_cops_seq_num,
1851       { "Contents: Sequence Number",           "cops.integrity.seq_num",
1852       FT_UINT32, BASE_DEC, NULL, 0,
1853       "Sequence Number in Integrity object", HFILL }
1854     },
1855     { &hf_cops_gperror,
1856       { "Error",           "cops.gperror",
1857       FT_UINT16, BASE_DEC, VALS(cops_gperror_vals), 0,
1858       "Error in Error object", HFILL }
1859     },
1860     { &hf_cops_gperror_sub,
1861       { "Error Sub-code",           "cops.gperror_sub",
1862       FT_UINT16, BASE_HEX, NULL, 0,
1863       "Error Sub-code in Error object", HFILL }
1864     },
1865     { &hf_cops_cperror,
1866       { "Error",           "cops.cperror",
1867       FT_UINT16, BASE_DEC, VALS(cops_cperror_vals), 0,
1868       "Error in Error object", HFILL }
1869     },
1870     { &hf_cops_cperror_sub,
1871       { "Error Sub-code",           "cops.cperror_sub",
1872       FT_UINT16, BASE_HEX, NULL, 0,
1873       "Error Sub-code in Error object", HFILL }
1874     },
1875
1876     /* Added for PacketCable */
1877
1878     { &hf_cops_subtree,
1879       { "Object Subtree", "cops.pc_subtree",
1880         FT_UINT16, BASE_HEX, NULL, 0,
1881         "Object Subtree", HFILL }
1882     },
1883     { &hf_cops_pc_ds_field,
1884       { "DS Field (DSCP or TOS)", "cops.pc_ds_field",
1885         FT_UINT8, BASE_HEX, NULL, 0x00,
1886         "DS Field (DSCP or TOS)", HFILL }
1887     },
1888     { &hf_cops_pc_direction,
1889       { "Direction", "cops.pc_direction",
1890         FT_UINT8, BASE_HEX, NULL, 0x00,
1891         "Direction", HFILL }
1892     },
1893     { &hf_cops_pc_gate_spec_flags,
1894       { "Flags", "cops.pc_gate_spec_flags",
1895         FT_UINT8, BASE_HEX, NULL, 0x00,
1896         "Flags", HFILL }
1897     },
1898     { &hf_cops_pc_protocol_id,
1899       { "Protocol ID", "cops.pc_protocol_id",
1900         FT_UINT8, BASE_HEX, NULL, 0x00,
1901         "Protocol ID", HFILL }
1902     },
1903     { &hf_cops_pc_session_class,
1904       { "Session Class", "cops.pc_session_class",
1905         FT_UINT8, BASE_HEX, NULL, 0x00,
1906         "Session Class", HFILL }
1907     },
1908     { &hf_cops_pc_algorithm,
1909       { "Algorithm", "cops.pc_algorithm",
1910         FT_UINT16, BASE_HEX, NULL, 0x00,
1911         "Algorithm", HFILL }
1912     },
1913     { &hf_cops_pc_cmts_ip_port,
1914       { "CMTS IP Port", "cops.pc_cmts_ip_port",
1915         FT_UINT16, BASE_HEX, NULL, 0x00,
1916         "CMTS IP Port", HFILL }
1917     },
1918     { &hf_cops_pc_prks_ip_port,
1919       { "PRKS IP Port", "cops.pc_prks_ip_port",
1920         FT_UINT16, BASE_HEX, NULL, 0x00,
1921         "PRKS IP Port", HFILL }
1922     },
1923     { &hf_cops_pc_srks_ip_port,
1924       { "SRKS IP Port", "cops.pc_srks_ip_port",
1925         FT_UINT16, BASE_HEX, NULL, 0x00,
1926         "SRKS IP Port", HFILL }
1927     },
1928     { &hf_cops_pc_dest_port,
1929       { "Destination IP Port", "cops.pc_dest_port",
1930         FT_UINT16, BASE_HEX, NULL, 0x00,
1931         "Destination IP Port", HFILL }
1932     },
1933     { &hf_cops_pc_packetcable_err_code,
1934       { "Error Code", "cops.pc_packetcable_err_code",
1935         FT_UINT16, BASE_HEX, NULL, 0x00,
1936         "Error Code", HFILL }
1937     },
1938     { &hf_cops_pc_packetcable_sub_code,
1939       { "Error Sub Code", "cops.pc_packetcable_sub_code",
1940         FT_UINT16, BASE_HEX, NULL, 0x00,
1941         "Error Sub Code", HFILL }
1942     },
1943     { &hf_cops_pc_remote_flags,
1944       { "Flags", "cops.pc_remote_flags",
1945         FT_UINT16, BASE_HEX, NULL, 0x00,
1946         "Flags", HFILL }
1947     },
1948     { &hf_cops_pc_close_subcode,
1949       { "Reason Sub Code", "cops.pc_close_subcode",
1950         FT_UINT16, BASE_HEX, NULL, 0x00,
1951         "Reason Sub Code", HFILL }
1952     },
1953     { &hf_cops_pc_gate_command_type,
1954       { "Gate Command Type", "cops.pc_gate_command_type",
1955         FT_UINT16, BASE_HEX, NULL, 0x00,
1956         "Gate Command Type", HFILL }
1957     },
1958     { &hf_cops_pc_reason_code,
1959       { "Reason Code", "cops.pc_reason_code",
1960         FT_UINT16, BASE_HEX, NULL, 0x00,
1961         "Reason Code", HFILL }
1962     },
1963     { &hf_cops_pc_delete_subcode,
1964       { "Reason Sub Code", "cops.pc_delete_subcode",
1965         FT_UINT16, BASE_HEX, NULL, 0x00,
1966         "Reason Sub Code", HFILL }
1967     },
1968     { &hf_cops_pc_src_port,
1969       { "Source IP Port", "cops.pc_src_port",
1970         FT_UINT16, BASE_HEX, NULL, 0x00,
1971         "Source IP Port", HFILL }
1972     },
1973     { &hf_cops_pc_t1_value,
1974       { "Timer T1 Value (sec)", "cops.pc_t1_value",
1975         FT_UINT16, BASE_HEX, NULL, 0x00,
1976         "Timer T1 Value (sec)", HFILL }
1977     },
1978     { &hf_cops_pc_t7_value,
1979       { "Timer T7 Value (sec)", "cops.pc_t7_value",
1980         FT_UINT16, BASE_HEX, NULL, 0x00,
1981         "Timer T7 Value (sec)", HFILL }
1982     },
1983     { &hf_cops_pc_t8_value,
1984       { "Timer T8 Value (sec)", "cops.pc_t8_value",
1985         FT_UINT16, BASE_HEX, NULL, 0x00,
1986         "Timer T8 Value (sec)", HFILL }
1987     },
1988     { &hf_cops_pc_transaction_id,
1989       { "Transaction Identifier", "cops.pc_transaction_id",
1990         FT_UINT16, BASE_HEX, NULL, 0x00,
1991         "Transaction Identifier", HFILL }
1992     },
1993     { &hf_cops_pc_cmts_ip,
1994       { "CMTS IP Address", "cops.pc_cmts_ip",
1995         FT_IPv4, BASE_HEX, NULL, 0x00,
1996         "CMTS IP Address", HFILL }
1997     },
1998     { &hf_cops_pc_prks_ip,
1999       { "PRKS IP Address", "cops.pc_prks_ip",
2000         FT_IPv4, BASE_HEX, NULL, 0x00,
2001         "PRKS IP Address", HFILL }
2002     },
2003     { &hf_cops_pc_srks_ip,
2004       { "SRKS IP Address", "cops.pc_srks_ip",
2005         FT_IPv4, BASE_HEX, NULL, 0x00,
2006         "SRKS IP Address", HFILL }
2007     },
2008     { &hf_cops_pc_dfcdc_ip,
2009       { "DF IP Address CDC", "cops.pc_dfcdc_ip",
2010         FT_IPv4, BASE_HEX, NULL, 0x00,
2011         "DF IP Address CDC", HFILL }
2012     },
2013     { &hf_cops_pc_dfccc_ip,
2014       { "DF IP Address CCC", "cops.pc_dfccc_ip",
2015         FT_IPv4, BASE_HEX, NULL, 0x00,
2016         "DF IP Address CCC", HFILL }
2017     },
2018     { &hf_cops_pc_dfcdc_ip_port,
2019       { "DF IP Port CDC", "cops.pc_dfcdc_ip_port",
2020         FT_UINT16, BASE_HEX, NULL, 0x00,
2021         "DF IP Port CDC", HFILL }
2022     },
2023     { &hf_cops_pc_dfccc_ip_port,
2024       { "DF IP Port CCC", "cops.pc_dfccc_ip_port",
2025         FT_UINT16, BASE_HEX, NULL, 0x00,
2026         "DF IP Port CCC", HFILL }
2027     },
2028     { &hf_cops_pc_dfccc_id,
2029       { "CCC ID", "cops.pc_dfccc_id",
2030         FT_UINT32, BASE_DEC, NULL, 0x00,
2031         "CCC ID", HFILL }
2032     },
2033     { &hf_cops_pc_activity_count,
2034       { "Count", "cops.pc_activity_count",
2035         FT_UINT32, BASE_HEX, NULL, 0x00,
2036         "Count", HFILL }
2037     },
2038     { &hf_cops_pc_dest_ip,
2039       { "Destination IP Address", "cops.pc_dest_ip",
2040         FT_IPv4, BASE_HEX, NULL, 0x00,
2041         "Destination IP Address", HFILL }
2042     },
2043     { &hf_cops_pc_gate_id,
2044       { "Gate Identifier", "cops.pc_gate_id",
2045         FT_UINT32, BASE_HEX, NULL, 0x00,
2046         "Gate Identifier", HFILL }
2047     },
2048     { &hf_cops_pc_max_packet_size,
2049       { "Maximum Packet Size", "cops.pc_max_packet_size",
2050         FT_UINT32, BASE_HEX, NULL, 0x00,
2051         "Maximum Packet Size", HFILL }
2052     },
2053     { &hf_cops_pc_min_policed_unit,
2054       { "Minimum Policed Unit", "cops.pc_min_policed_unit",
2055         FT_UINT32, BASE_HEX, NULL, 0x00,
2056         "Minimum Policed Unit", HFILL }
2057     },
2058     { &hf_cops_pc_peak_data_rate,
2059       { "Peak Data Rate", "cops.pc_peak_data_rate",
2060         FT_FLOAT, BASE_NONE, NULL, 0x00,
2061         "Peak Data Rate", HFILL }
2062     },
2063     { &hf_cops_pc_spec_rate,
2064       { "Rate", "cops.pc_spec_rate",
2065         FT_FLOAT, BASE_NONE, NULL, 0x00,
2066         "Rate", HFILL }
2067     },
2068     { &hf_cops_pc_remote_gate_id,
2069       { "Remote Gate ID", "cops.pc_remote_gate_id",
2070         FT_UINT32, BASE_HEX, NULL, 0x00,
2071         "Remote Gate ID", HFILL }
2072     },
2073     { &hf_cops_pc_reserved,
2074       { "Reserved", "cops.pc_reserved",
2075         FT_UINT32, BASE_HEX, NULL, 0x00,
2076         "Reserved", HFILL }
2077     },
2078     { &hf_cops_pc_key,
2079       { "Security Key", "cops.pc_key",
2080         FT_UINT32, BASE_HEX, NULL, 0x00,
2081         "Security Key", HFILL }
2082     },
2083     { &hf_cops_pc_slack_term,
2084       { "Slack Term", "cops.pc_slack_term",
2085         FT_UINT32, BASE_HEX, NULL, 0x00,
2086         "Slack Term", HFILL }
2087     },
2088     { &hf_cops_pc_src_ip,
2089       { "Source IP Address", "cops.pc_src_ip",
2090         FT_IPv4, BASE_HEX, NULL, 0x00,
2091         "Source IP Address", HFILL }
2092     },
2093     { &hf_cops_pc_subscriber_id_ipv4,
2094       { "Subscriber Identifier (IPv4)", "cops.pc_subscriber_id4",
2095         FT_IPv4, BASE_HEX, NULL, 0x00,
2096         "Subscriber Identifier (IPv4)", HFILL }
2097     },
2098     { &hf_cops_pc_subscriber_id_ipv6,
2099       { "Subscriber Identifier (IPv6)", "cops.pc_subscriber_id6",
2100         FT_IPv6, BASE_HEX, NULL, 0x00,
2101         "Subscriber Identifier (IPv6)", HFILL }
2102     },
2103     { &hf_cops_pc_token_bucket_rate,
2104       { "Token Bucket Rate", "cops.pc_token_bucket_rate",
2105         FT_FLOAT, BASE_NONE, NULL, 0x00,
2106         "Token Bucket Rate", HFILL }
2107     },
2108     { &hf_cops_pc_token_bucket_size,
2109       { "Token Bucket Size", "cops.pc_token_bucket_size",
2110         FT_FLOAT, BASE_NONE, NULL, 0x00,
2111         "Token Bucket Size", HFILL }
2112     },
2113     { &hf_cops_pc_bcid,
2114       { "Billing Correlation ID", "cops.pc_bcid",
2115         FT_UINT32, BASE_HEX, NULL, 0x00,
2116         "Billing Correlation ID", HFILL }
2117     },
2118     { &hf_cops_pc_bcid_ts,
2119       { "BDID Timestamp", "cops.pc_bcid_ts",
2120         FT_UINT32, BASE_HEX, NULL, 0x00,
2121         "BCID Timestamp", HFILL }
2122     },
2123     { &hf_cops_pc_bcid_ev,
2124       { "BDID Event Counter", "cops.pc_bcid_ev",
2125         FT_UINT32, BASE_HEX, NULL, 0x00,
2126         "BCID Event Counter", HFILL }
2127     },
2128
2129     { &hf_cops_pcmm_amid,
2130             { "AMID", "cops.pc_mm_amid",
2131             FT_UINT32, BASE_DEC, NULL, 0,
2132             "PacketCable Multimedia AMID", HFILL }
2133     },
2134
2135     { &hf_cops_pcmm_gate_spec_flags,
2136             { "Flags", "cops.pc_mm_gs_flags",
2137             FT_UINT8, BASE_HEX, NULL, 0,
2138             "PacketCable Multimedia GateSpec Flags", HFILL }
2139     },
2140     { &hf_cops_pcmm_gate_spec_dscp_tos_field,
2141             { "DSCP/TOS Field",           "cops.pc_mm_gs_dscp",
2142             FT_UINT8, BASE_HEX, NULL, 0,
2143             "PacketCable Multimedia GateSpec DSCP/TOS Field", HFILL }
2144     },
2145     { &hf_cops_pcmm_gate_spec_dscp_tos_mask,
2146             { "DSCP/TOS Mask",           "cops.pc_mm_gs_dscp_mask",
2147             FT_UINT8, BASE_HEX, NULL, 0,
2148             "PacketCable Multimedia GateSpec DSCP/TOS Mask", HFILL }
2149     },
2150     { &hf_cops_pcmm_gate_spec_session_class_id,
2151             { "SessionClassID", "cops.pc_mm_gs_scid",
2152             FT_UINT8, BASE_DEC, NULL, 0,
2153             "PacketCable Multimedia GateSpec SessionClassID", HFILL }
2154     },
2155     { &hf_cops_pcmm_gate_spec_session_class_id_priority,
2156             { "SessionClassID Priority", "cops.pc_mm_gs_scid_prio",
2157             FT_UINT8, BASE_DEC, NULL, 0x07,
2158             "PacketCable Multimedia GateSpec SessionClassID Priority", HFILL }
2159     },
2160     { &hf_cops_pcmm_gate_spec_session_class_id_preemption,
2161             { "SessionClassID Preemption", "cops.pc_mm_gs_scid_preempt",
2162             FT_UINT8, BASE_DEC, NULL, 0x08,
2163             "PacketCable Multimedia GateSpec SessionClassID Preemption", HFILL }
2164     },
2165     { &hf_cops_pcmm_gate_spec_session_class_id_configurable,
2166             { "SessionClassID Configurable", "cops.pc_mm_gs_scid_conf",
2167             FT_UINT8, BASE_DEC, NULL, 0xf0,
2168             "PacketCable Multimedia GateSpec SessionClassID Configurable", HFILL }
2169     },
2170     { &hf_cops_pcmm_gate_spec_timer_t1,
2171             { "Timer T1", "cops.pc_mm_gs_timer_t1",
2172             FT_UINT16, BASE_DEC, NULL, 0,
2173             "PacketCable Multimedia GateSpec Timer T1", HFILL }
2174     },
2175     { &hf_cops_pcmm_gate_spec_timer_t2,
2176             { "Timer T2", "cops.pc_mm_gs_timer_t2",
2177             FT_UINT16, BASE_DEC, NULL, 0,
2178             "PacketCable Multimedia GateSpec Timer T2", HFILL }
2179     },
2180     { &hf_cops_pcmm_gate_spec_timer_t3,
2181             { "Timer T3", "cops.pc_mm_gs_timer_t3",
2182             FT_UINT16, BASE_DEC, NULL, 0,
2183             "PacketCable Multimedia GateSpec Timer T3", HFILL }
2184     },
2185     { &hf_cops_pcmm_gate_spec_timer_t4,
2186             { "Timer T4", "cops.pc_mm_gs_timer_t4",
2187             FT_UINT16, BASE_DEC, NULL, 0,
2188             "PacketCable Multimedia GateSpec Timer T4", HFILL }
2189     },
2190
2191     { &hf_cops_pcmm_classifier_protocol_id,
2192             { "Protocol ID", "cops.pc_mm_classifier_proto_id",
2193             FT_UINT16, BASE_HEX, NULL, 0,
2194             "PacketCable Multimedia Classifier Protocol ID", HFILL }
2195     },
2196     { &hf_cops_pcmm_classifier_dscp_tos_field,
2197             { "DSCP/TOS Field", "cops.pc_mm_classifier_dscp",
2198             FT_UINT8, BASE_HEX, NULL, 0,
2199             "PacketCable Multimedia Classifier DSCP/TOS Field", HFILL }
2200     },
2201     { &hf_cops_pcmm_classifier_dscp_tos_mask,
2202             { "DSCP/TOS Mask", "cops.pc_mm_classifier_dscp_mask",
2203             FT_UINT8, BASE_HEX, NULL, 0,
2204             "PacketCable Multimedia Classifer DSCP/TOS Mask", HFILL }
2205     },
2206     { &hf_cops_pcmm_classifier_src_addr,
2207             { "Source address", "cops.pc_mm_classifier_src_addr",
2208             FT_IPv4, 0, NULL, 0,
2209             "PacketCable Multimedia Classifier Source IP Address", HFILL }
2210     },
2211     { &hf_cops_pcmm_classifier_dst_addr,
2212             { "Destination address", "cops.pc_mm_classifier_dst_addr",
2213             FT_IPv4, 0, NULL, 0,
2214             "PacketCable Multimedia Classifier Destination IP Address", HFILL }
2215     },
2216     { &hf_cops_pcmm_classifier_src_port,
2217             { "Source Port", "cops.pc_mm_classifier_src_port",
2218             FT_UINT16, BASE_DEC, NULL, 0,
2219             "PacketCable Multimedia Classifier Source Port", HFILL }
2220     },
2221     { &hf_cops_pcmm_classifier_dst_port,
2222             { "Destination Port", "cops.pc_mm_classifier_dst_port",
2223             FT_UINT16, BASE_DEC, NULL, 0,
2224             "PacketCable Multimedia Classifier Source Port", HFILL }
2225     },
2226     { &hf_cops_pcmm_classifier_priority,
2227             { "Priority", "cops.pc_mm_classifier_priority",
2228             FT_UINT8, BASE_HEX, NULL, 0,
2229             "PacketCable Multimedia Classifier Priority", HFILL }
2230     },
2231
2232     { &hf_cops_pcmm_flow_spec_envelope,
2233             { "Envelope", "cops.pc_mm_fs_envelope",
2234             FT_UINT8, BASE_DEC, NULL, 0,
2235             "PacketCable Multimedia Flow Spec Envelope", HFILL }
2236     },
2237     { &hf_cops_pcmm_flow_spec_service_number,
2238             { "Service Number", "cops.pc_mm_fs_svc_num",
2239             FT_UINT8, BASE_DEC, pcmm_flow_spec_service_vals, 0,
2240             "PacketCable Multimedia Flow Spec Service Number", HFILL }
2241     },
2242
2243     { &hf_cops_pcmm_docsis_scn,
2244             { "Service Class Name", "cops.pc_mm_docsis_scn",
2245             FT_STRINGZ, BASE_DEC, NULL, 0,
2246             "PacketCable Multimedia DOCSIS Service Class Name", HFILL }
2247     },
2248
2249     { &hf_cops_pcmm_envelope,
2250             { "Envelope", "cops.pc_mm_envelope",
2251             FT_UINT8, BASE_DEC, NULL, 0,
2252             "PacketCable Multimedia Envelope", HFILL }
2253     },
2254
2255     { &hf_cops_pcmm_traffic_priority,
2256             { "Traffic Priority", "cops.pc_mm_tp",
2257             FT_UINT8, BASE_DEC, NULL, 0,
2258             "PacketCable Multimedia Committed Envelope Traffic Priority", HFILL }
2259     },
2260     { &hf_cops_pcmm_request_transmission_policy,
2261             { "Request Transmission Policy", "cops.pc_mm_rtp",
2262             FT_UINT32, BASE_HEX, NULL, 0,
2263             "PacketCable Multimedia Committed Envelope Traffic Priority", HFILL }
2264     },
2265     { &hf_cops_pcmm_max_sustained_traffic_rate,
2266             { "Maximum Sustained Traffic Rate", "cops.pc_mm_mstr",
2267             FT_UINT32, BASE_DEC, NULL, 0,
2268             "PacketCable Multimedia Committed Envelope Maximum Sustained Traffic Rate", HFILL }
2269     },
2270     { &hf_cops_pcmm_max_traffic_burst,
2271             { "Maximum Traffic Burst", "cops.pc_mm_mtb",
2272             FT_UINT32, BASE_DEC, NULL, 0,
2273             "PacketCable Multimedia Committed Envelope Maximum Traffic Burst", HFILL }
2274     },
2275     { &hf_cops_pcmm_min_reserved_traffic_rate,
2276             { "Minimum Reserved Traffic Rate", "cops.pc_mm_mrtr",
2277             FT_UINT32, BASE_DEC, NULL, 0,
2278             "PacketCable Multimedia Committed Envelope Minimum Reserved Traffic Rate", HFILL }
2279     },
2280     { &hf_cops_pcmm_ass_min_rtr_packet_size,
2281             { "Assumed Minimum Reserved Traffic Rate Packet Size", "cops.pc_mm_amrtrps",
2282             FT_UINT16, BASE_DEC, NULL, 0,
2283             "PacketCable Multimedia Committed Envelope Assumed Minimum Reserved Traffic Rate Packet Size", HFILL }
2284     },
2285
2286     { &hf_cops_pcmm_nominal_polling_interval,
2287             { "Nominal Polling Interval", "cops.pc_mm_npi",
2288             FT_UINT32, BASE_DEC, NULL, 0,
2289             "PacketCable Multimedia Nominal Polling Interval", HFILL }
2290     },
2291
2292     { &hf_cops_pcmm_tolerated_poll_jitter,
2293             { "Tolerated Poll Jitter", "cops.pc_mm_tpj",
2294             FT_UINT32, BASE_DEC, NULL, 0,
2295             "PacketCable Multimedia Tolerated Poll Jitter", HFILL }
2296     },
2297
2298     { &hf_cops_pcmm_unsolicited_grant_size,
2299             { "Unsolicited Grant Size", "cops.pc_mm_ugs",
2300             FT_UINT16, BASE_DEC, NULL, 0,
2301             "PacketCable Multimedia Unsolicited Grant Size", HFILL }
2302     },
2303     { &hf_cops_pcmm_grants_per_interval,
2304             { "Grants Per Interval", "cops.pc_mm_gpi",
2305             FT_UINT8, BASE_DEC, NULL, 0,
2306             "PacketCable Multimedia Grants Per Interval", HFILL }
2307     },
2308     { &hf_cops_pcmm_nominal_grant_interval,
2309             { "Nominal Grant Interval", "cops.pc_mm_ngi",
2310             FT_UINT32, BASE_DEC, NULL, 0,
2311             "PacketCable Multimedia Nominal Grant Interval", HFILL }
2312     },
2313     { &hf_cops_pcmm_tolerated_grant_jitter,
2314             { "Tolerated Grant Jitter", "cops.pc_mm_tgj",
2315             FT_UINT32, BASE_DEC, NULL, 0,
2316             "PacketCable Multimedia Tolerated Grant Jitter", HFILL }
2317     },
2318
2319     { &hf_cops_pcmm_max_downstream_latency,
2320             { "Maximum Downstream Latency", "cops.pc_mm_mdl",
2321             FT_UINT32, BASE_DEC, NULL, 0,
2322             "PacketCable Multimedia Maximum Downstream Latency", HFILL }
2323     },
2324
2325     { &hf_cops_pcmm_volume_based_usage_limit,
2326             { "Usage Limit", "cops.pc_mm_vbul_ul",
2327             FT_UINT64, BASE_DEC, NULL, 0,
2328             "PacketCable Multimedia Volume-Based Usage Limit", HFILL }
2329     },
2330
2331     { &hf_cops_pcmm_time_based_usage_limit,
2332             { "Usage Limit", "cops.pc_mm_tbul_ul",
2333             FT_UINT32, BASE_DEC, NULL, 0,
2334             "PacketCable Multimedia Time-Based Usage Limit", HFILL }
2335     },
2336
2337     { &hf_cops_pcmm_gate_time_info,
2338             { "Gate Time Info", "cops.pc_mm_gti",
2339             FT_UINT32, BASE_DEC, NULL, 0,
2340             "PacketCable Multimedia Gate Time Info", HFILL }
2341     },
2342
2343     { &hf_cops_pcmm_gate_usage_info,
2344             { "Gate Usage Info", "cops.pc_mm_gui",
2345             FT_UINT32, BASE_DEC, NULL, 0,
2346             "PacketCable Multimedia Gate Usage Info", HFILL }
2347     },
2348
2349     { &hf_cops_pcmm_packetcable_error_code,
2350             { "Error-Code", "cops.pc_mm_error_ec",
2351             FT_UINT16, BASE_DEC, NULL, 0,
2352             "PacketCable Multimedia PacketCable-Error Error-Code", HFILL }
2353     },
2354     { &hf_cops_pcmm_packetcable_error_subcode,
2355             { "Error-code", "cops.pc_mm_error_esc",
2356             FT_UINT16, BASE_HEX, NULL, 0,
2357             "PacketCable Multimedia PacketCable-Error Error Sub-code", HFILL }
2358     },
2359
2360     { &hf_cops_pcmm_packetcable_gate_state,
2361             { "State", "cops.pc_mm_gs_state",
2362             FT_UINT16, BASE_DEC, NULL, 0,
2363             "PacketCable Multimedia Gate State", HFILL }
2364     },
2365     { &hf_cops_pcmm_packetcable_gate_state_reason,
2366             { "Reason", "cops.pc_mm_gs_reason",
2367             FT_UINT16, BASE_HEX, NULL, 0,
2368             "PacketCable Multimedia Gate State Reason", HFILL }
2369     },
2370     { &hf_cops_pcmm_packetcable_version_info_major,
2371             { "Major Version Number", "cops.pc_mm_vi_major",
2372             FT_UINT16, BASE_DEC, NULL, 0,
2373             "PacketCable Multimedia Major Version Number", HFILL }
2374     },
2375     { &hf_cops_pcmm_packetcable_version_info_minor,
2376             { "Minor Version Number", "cops.pc_mm_vi_minor",
2377             FT_UINT16, BASE_DEC, NULL, 0,
2378             "PacketCable Multimedia Minor Version Number", HFILL }
2379     },
2380
2381     /* End of addition for PacketCable */
2382
2383   };
2384
2385   /* Setup protocol subtree array */
2386   static gint *ett[] = {
2387     &ett_cops,
2388     &ett_cops_ver_flags,
2389     &ett_cops_obj,
2390     &ett_cops_pr_obj,
2391     &ett_cops_obj_data,
2392     &ett_cops_r_type_flags,
2393     &ett_cops_itf,
2394     &ett_cops_reason,
2395     &ett_cops_decision,
2396     &ett_cops_error,
2397     &ett_cops_clientsi,
2398     &ett_cops_asn1,
2399     &ett_cops_gperror,
2400     &ett_cops_cperror,
2401     &ett_cops_pdp,
2402     &ett_cops_subtree,
2403     &ett_docsis_request_transmission_policy,
2404   };
2405
2406   module_t* cops_module;
2407
2408   /* Register the protocol name and description */
2409   proto_cops = proto_register_protocol("Common Open Policy Service",
2410       "COPS", "cops");
2411
2412   /* Required function calls to register the header fields and subtrees used */
2413   proto_register_field_array(proto_cops, hf, array_length(hf));
2414   proto_register_subtree_array(ett, array_length(ett));
2415
2416   /* Register our configuration options for cops */
2417   cops_module = prefs_register_protocol(proto_cops, proto_reg_handoff_cops);
2418   prefs_register_uint_preference(cops_module,"tcp.cops_port",
2419                                  "COPS TCP Port",
2420                                  "Set the TCP port for COPS messages",
2421                                  10,&global_cops_tcp_port);
2422   prefs_register_bool_preference(cops_module, "desegment",
2423                                  "Reassemble COPS messages spanning multiple TCP segments",
2424                                  "Whether the COPS dissector should reassemble messages spanning multiple TCP segments."
2425                                  " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2426                                  &cops_desegment);
2427
2428   /* For PacketCable */
2429   prefs_register_bool_preference(cops_module, "packetcable",
2430                                  "Decode for PacketCable clients",
2431                                  "Decode the COPS messages using PacketCable clients. (Select port 2126)",
2432                                  &cops_packetcable);
2433
2434 #ifdef HAVE_NET_SNMP /*enable preference only if compiled with NET-SNMP*/
2435   prefs_register_bool_preference(cops_module, "typefrommib",
2436                                  "Decode COPS-PR ASN.1 types by reading them\nfrom PIBs (converted to MIBs)",
2437                                  "Whether the COPS dissector should decode COPS-PR ASN.1 types based on data types read from packet or PIBs (converted to MIBs)",
2438                                  &cops_typefrommib);
2439 #endif /*HAVE_NET_SNMP*/
2440 }
2441
2442 void proto_reg_handoff_cops(void)
2443 {
2444   static int cops_prefs_initialized = FALSE;
2445   static dissector_handle_t cops_handle;
2446
2447   if (!cops_prefs_initialized) {
2448     cops_handle = create_dissector_handle(dissect_cops, proto_cops);
2449     cops_prefs_initialized = TRUE;
2450   } else
2451     dissector_delete("tcp.port",cops_tcp_port,cops_handle);
2452
2453   /* Set our port numbers for future use */
2454   cops_tcp_port = global_cops_tcp_port;
2455
2456   dissector_add("tcp.port", cops_tcp_port, cops_handle);
2457   dissector_add("tcp.port", TCP_PORT_PKTCABLE_COPS, cops_handle);
2458   dissector_add("tcp.port", TCP_PORT_PKTCABLE_MM_COPS, cops_handle);
2459 }
2460
2461
2462 /* Additions for PacketCable ( Added by Dick Gooris, Lucent Technologies ) */
2463
2464 /* Definitions for print formatting */
2465 /* XXX - Why don't we just use ftenum types here? */
2466 #define   FMT_DEC   0
2467 #define   FMT_HEX   1
2468 #define   FMT_IPv4  2
2469 #define   FMT_IPv6  3
2470 #define   FMT_FLT   4
2471
2472 /* Print the translated information in the display gui in a formatted way
2473  *
2474  * octets = The number of octets to obtain from the buffer
2475  *
2476  * vsp    = If not a NULL pointer, it points to an array with text
2477  *
2478  * mode   = 0 -> print decimal value
2479  *          1 -> print hexadecimal vaue
2480  *          2 -> print value as an IPv4 address
2481  *          3 -> print value as an IPv6 address
2482  *          4 -> print value as an IEEE float
2483  *
2484  * This function in combination with the separate function info_to_cops_subtree() for subtrees.
2485  *
2486  */
2487
2488 static proto_item *
2489 info_to_display(tvbuff_t *tvb, proto_item *stt, int offset, int octets, const char *str, const value_string *vsp, int mode,gint *hf_proto_parameter)
2490 {
2491      proto_item *pi = NULL;
2492      guint8   code8  = 0;
2493      guint16  code16 = 0;
2494      guint32  codeipv4 = 0;
2495      guint32  code32 = 0;
2496      float    codefl = 0.0;
2497
2498      /* Print information elements in the specified way */
2499      switch (octets) {
2500
2501      case 1:
2502              /* Get the octet */
2503              code8 = tvb_get_guint8( tvb, offset );
2504              if (vsp == NULL) {
2505                 /* Hexadecimal format */
2506                 if (mode==FMT_HEX)
2507                    pi = proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb,
2508                        offset, octets, code8,"%-28s : 0x%02x",str,code8);
2509                 else
2510                    /* Print an 8 bits integer */
2511                    pi = proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb,
2512                        offset, octets, code8,"%-28s : %u",str,code8);
2513              } else {
2514                if (mode==FMT_HEX)
2515                   /* Hexadecimal format */
2516                   pi = proto_tree_add_uint_format(
2517                       stt, *hf_proto_parameter,tvb, offset, octets, code8,
2518                       "%-28s : %s (0x%02x)",str,val_to_str(code8, vsp, "Unknown"),code8);
2519                else
2520                   /* String table indexed */
2521                   pi = proto_tree_add_uint_format(
2522                       stt, *hf_proto_parameter,tvb, offset, octets, code8,
2523                       "%-28s : %s (%u)",str,val_to_str(code8, vsp, "Unknown"),code8);
2524              }
2525              break;
2526
2527        case 2:
2528
2529              /* Get the next two octets */
2530              code16 = tvb_get_ntohs(tvb,offset);
2531              if (vsp == NULL) {
2532                 /* Hexadecimal format */
2533                 if (mode==FMT_HEX)
2534                    pi = proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb,
2535                        offset, octets, code16,"%-28s : 0x%04x",str,code16);
2536                 else
2537                    /* Print a 16 bits integer */
2538                    pi = proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb,
2539                        offset, octets, code16,"%-28s : %u",str,code16);
2540              }  else {
2541                 if (mode==FMT_HEX)
2542                    /* Hexadecimal format */
2543                    pi = proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb,
2544                        offset, octets, code16,"%-28s : %s (0x%04x)", str,
2545                        val_to_str(code16, vsp, "Unknown (0x%04x)"),code16);
2546                 else
2547                    /* Print a 16 bits integer */
2548                    pi = proto_tree_add_uint_format(
2549                        stt, *hf_proto_parameter,tvb, offset, octets, code16,
2550                        "%-28s : %s (%u)",str,val_to_str(code16, vsp, "Unknown (0x%04x)"),code16);
2551              }
2552              break;
2553
2554         case 4:
2555
2556              /* Get the next four octets */
2557              switch (mode) {
2558                case FMT_FLT:  codefl  = tvb_get_ntohieee_float(tvb,offset);
2559                               break;
2560                case FMT_IPv4: codeipv4 = tvb_get_ipv4(tvb, offset);
2561                               break;
2562                default:       code32  = tvb_get_ntohl(tvb,offset);
2563              }
2564
2565              if (vsp == NULL) {
2566                 /* Hexadecimal format */
2567                 if (mode==FMT_HEX) {
2568                    pi = proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb,
2569                        offset, octets, code32,"%-28s : 0x%08x",str,code32);
2570                    break;
2571                 }
2572                 /* Ip address format*/
2573                 if (mode==FMT_IPv4) {
2574                    pi = proto_tree_add_ipv4(stt, *hf_proto_parameter,tvb, offset, octets, codeipv4);
2575                    break;
2576                 }
2577                 /* Ieee float format */
2578                 if (mode==FMT_FLT) {
2579                    pi = proto_tree_add_float_format(stt, *hf_proto_parameter,tvb, offset, octets,
2580                        codefl,"%-28s : %.10g",str,codefl);
2581                    break;
2582                 }
2583                 /* Print a 32 bits integer */
2584                 pi = proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb, offset, octets,
2585                     code32,"%-28s : %u",str,code32);
2586              } else {
2587                 /* Hexadecimal format */
2588                 if (mode==FMT_HEX)
2589                    pi = proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb, offset, octets,
2590                            code32,"%-28s : %s (0x%08x)",str,val_to_str(code32, vsp, "Unknown"),code32);
2591                 else
2592                    /* String table indexed */
2593                    pi = proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb, offset, octets,
2594                        code32,"%-28s : %s (%u)",str,val_to_str(code32, vsp, "Unknown"),code32);
2595              }
2596              break;
2597
2598         /* In case of more than 4 octets.... */
2599         default: {
2600              if (mode==FMT_HEX) {
2601                 pi = proto_tree_add_bytes(stt, *hf_proto_parameter,
2602                    tvb, offset, octets, tvb_get_ptr(tvb, offset,octets));
2603              } else if (mode==FMT_IPv6 && octets==16) {
2604                 pi = proto_tree_add_ipv6(stt, *hf_proto_parameter, tvb, offset, octets,
2605                    tvb_get_ptr(tvb, offset, octets));
2606              } else {
2607                 pi = proto_tree_add_uint_format(stt, *hf_proto_parameter,
2608                    tvb, offset, octets, code32,"%s",str);
2609              }
2610              break;
2611         }
2612
2613      }
2614      return pi;
2615 }
2616
2617 /* Print the subtree information for cops */
2618 static proto_tree *
2619 info_to_cops_subtree(tvbuff_t *tvb, proto_tree *st, int n, int offset, const char *str) {
2620      proto_item *tv;
2621
2622      tv  = proto_tree_add_uint_format( st, hf_cops_subtree, tvb, offset, n, (guint)NULL, str);
2623      return( proto_item_add_subtree( tv, ett_cops_subtree ) );
2624 }
2625
2626 /* Cops - Section : D-QoS Transaction ID */
2627 static void
2628 cops_transaction_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *st, guint8 op_code, guint n, guint32 offset) {
2629
2630      proto_tree *stt;
2631      guint16  code16;
2632      char info[50];
2633
2634      /* Create a subtree */
2635      stt = info_to_cops_subtree(tvb,st,n,offset,"D-QoS Transaction ID");
2636      offset += 4;
2637
2638      /* Transaction Identifier */
2639      info_to_display(tvb,stt,offset,2,"D-QoS Transaction Identifier", NULL,FMT_DEC,&hf_cops_pc_transaction_id);
2640      offset +=2;
2641
2642      /* Gate Command Type */
2643      code16 = tvb_get_ntohs(tvb,offset);
2644      proto_tree_add_uint_format(stt, hf_cops_pc_gate_command_type,tvb, offset, 2,
2645             code16,"%-28s : %s (%u)", "Gate Command Type",
2646             val_to_str(code16,table_cops_dqos_transaction_id, "Unknown (0x%04x)"),code16);
2647
2648      /* Write the right data into the 'info field' on the Gui */
2649      g_snprintf(info,sizeof(info),"COPS %-20s - ",val_to_str(op_code,cops_op_code_vals, "Unknown"));
2650      strcat(info,val_to_str(code16,table_cops_dqos_transaction_id, "Unknown"));
2651
2652      if (check_col(pinfo->cinfo, COL_INFO)) {
2653           col_clear(pinfo->cinfo, COL_INFO);
2654           col_add_str(pinfo->cinfo, COL_INFO,info);
2655      }
2656
2657 }
2658
2659 /* Cops - Section : Subscriber IDv4 */
2660 static void
2661 cops_subscriber_id_v4(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
2662
2663      proto_item *tv;
2664
2665      /* Create a subtree */
2666      tv = info_to_cops_subtree(tvb,st,n,offset,"Subscriber ID (IPv4)");
2667      offset += 4;
2668
2669      /* Subscriber Identifier */
2670      info_to_display(tvb,tv,offset,4,"Subscriber Identifier (IPv4)", NULL,FMT_IPv4,&hf_cops_pc_subscriber_id_ipv4);
2671 }
2672
2673 /* Cops - Section : Subscriber IDv6 */
2674 static void
2675 cops_subscriber_id_v6(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
2676
2677      proto_item *tv;
2678
2679      /* Create a subtree */
2680      tv = info_to_cops_subtree(tvb,st,n,offset,"Subscriber ID (IPv6)");
2681      offset += 4;
2682
2683      /* Subscriber Identifier */
2684      info_to_display(tvb,tv,offset,16,"Subscriber Identifier (IPv6)", NULL,FMT_IPv6,&hf_cops_pc_subscriber_id_ipv6);
2685 }
2686
2687 /* Cops - Section : Gate ID */
2688 static void
2689 cops_gate_id(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
2690
2691      proto_tree *stt;
2692
2693      /* Create a subtree */
2694      stt = info_to_cops_subtree(tvb,st,n,offset,"Gate ID");
2695      offset += 4;
2696
2697      /* Gate Identifier */
2698      info_to_display(tvb,stt,offset,4,"Gate Identifier", NULL,FMT_HEX,&hf_cops_pc_gate_id);
2699 }
2700
2701 /* Cops - Section : Activity Count */
2702 static void
2703 cops_activity_count(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
2704
2705      proto_tree *stt;
2706
2707      /* Create a subtree */
2708      stt = info_to_cops_subtree(tvb,st,n,offset,"Activity Count");
2709      offset += 4;
2710
2711      /* Activity Count */
2712      info_to_display(tvb,stt,offset,4,"Count", NULL,FMT_DEC,&hf_cops_pc_activity_count);
2713 }
2714
2715 /* Cops - Section : Gate Specifications */
2716 static void
2717 cops_gate_specs(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
2718
2719      proto_tree *stt;
2720
2721      /* Create a subtree */
2722      stt = info_to_cops_subtree(tvb,st,n,offset,"Gate Specifications");
2723      offset += 4;
2724
2725      /* Direction */
2726      info_to_display(tvb,stt,offset,1,"Direction",table_cops_direction,FMT_DEC,&hf_cops_pc_direction);
2727      offset += 1;
2728
2729      /* Protocol ID */
2730      info_to_display(tvb,stt,offset,1,"Protocol ID",NULL,FMT_DEC,&hf_cops_pc_protocol_id);
2731      offset += 1;
2732
2733      /* Flags */
2734      info_to_display(tvb,stt,offset,1,"Flags",NULL,FMT_DEC,&hf_cops_pc_gate_spec_flags);
2735      offset += 1;
2736
2737      /* Session Class */
2738      info_to_display(tvb,stt,offset,1,"Session Class",table_cops_session_class,FMT_DEC,&hf_cops_pc_session_class);
2739      offset += 1;
2740
2741      /* Source IP Address */
2742      info_to_display(tvb,stt,offset,4,"Source IP Address",NULL,FMT_IPv4,&hf_cops_pc_src_ip);
2743      offset += 4;
2744
2745      /* Destination IP Address */
2746      info_to_display(tvb,stt,offset,4,"Destination IP Address",NULL,FMT_IPv4,&hf_cops_pc_dest_ip);
2747      offset += 4;
2748
2749      /* Source IP Port */
2750      info_to_display(tvb,stt,offset,2,"Source IP Port",NULL,FMT_DEC,&hf_cops_pc_src_port);
2751      offset += 2;
2752
2753      /* Destination IP Port */
2754      info_to_display(tvb,stt,offset,2,"Destination IP Port",NULL,FMT_DEC,&hf_cops_pc_dest_port);
2755      offset += 2;
2756
2757      /* DiffServ Code Point */
2758      info_to_display(tvb,stt,offset,1,"DS Field (DSCP or TOS)",NULL,FMT_HEX,&hf_cops_pc_ds_field);
2759      offset += 1;
2760
2761      /* 3 octets Not specified */
2762      offset += 3;
2763
2764      /* Timer T1 Value */
2765      info_to_display(tvb,stt,offset,2,"Timer T1 Value (sec)",NULL,FMT_DEC,&hf_cops_pc_t1_value);
2766      offset += 2;
2767
2768      /* Reserved */
2769      info_to_display(tvb,stt,offset,2,"Reserved",NULL,FMT_DEC,&hf_cops_pc_reserved);
2770      offset += 2;
2771
2772      /* Timer T7 Value */
2773      info_to_display(tvb,stt,offset,2,"Timer T7 Value (sec)",NULL,FMT_DEC,&hf_cops_pc_t7_value);
2774      offset += 2;
2775
2776      /* Timer T8 Value */
2777      info_to_display(tvb,stt,offset,2,"Timer T8 Value (sec)",NULL,FMT_DEC,&hf_cops_pc_t8_value);
2778      offset += 2;
2779
2780      /* Token Bucket Rate */
2781      info_to_display(tvb,stt,offset,4,"Token Bucket Rate",NULL,FMT_FLT,&hf_cops_pc_token_bucket_rate);
2782      offset += 4;
2783
2784      /* Token Bucket Size */
2785      info_to_display(tvb,stt,offset,4,"Token Bucket Size",NULL,FMT_FLT,&hf_cops_pc_token_bucket_size);
2786      offset += 4;
2787
2788      /* Peak Data Rate */
2789      info_to_display(tvb,stt,offset,4,"Peak Data Rate",NULL,FMT_FLT,&hf_cops_pc_peak_data_rate);
2790      offset += 4;
2791
2792      /* Minimum Policed Unit */
2793      info_to_display(tvb,stt,offset,4,"Minimum Policed Unit",NULL,FMT_DEC,&hf_cops_pc_min_policed_unit);
2794      offset += 4;
2795
2796      /* Maximum Packet Size */
2797      info_to_display(tvb,stt,offset,4,"Maximum Packet Size",NULL,FMT_DEC,&hf_cops_pc_max_packet_size);
2798      offset += 4;
2799
2800      /* Rate */
2801      info_to_display(tvb,stt,offset,4,"Rate",NULL,FMT_FLT,&hf_cops_pc_spec_rate);
2802      offset += 4;
2803
2804      /* Slack Term */
2805      info_to_display(tvb,stt,offset,4,"Slack Term",NULL,FMT_DEC,&hf_cops_pc_slack_term);
2806 }
2807
2808 /* Cops - Section : Electronic Surveillance Parameters  */
2809 static void
2810 cops_surveillance_parameters(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
2811
2812      proto_tree *stt;
2813      guint8 *bcid_str;
2814
2815      /* Create a subtree */
2816      stt = info_to_cops_subtree(tvb,st,n,offset,"Electronic Surveillance Parameters");
2817      offset += 4;
2818
2819      /* DF IP Address for CDC */
2820      info_to_display(tvb,stt,offset,4,"DF IP Address for CDC", NULL,FMT_IPv4,&hf_cops_pc_dfcdc_ip);
2821      offset += 4;
2822
2823      /* DF IP Port for CDC */
2824      info_to_display(tvb,stt,offset,2,"DF IP Port for CDC",NULL,FMT_DEC,&hf_cops_pc_dfcdc_ip_port);
2825      offset += 2;
2826
2827      /* Flags */
2828      info_to_display(tvb,stt,offset,2,"Flags",NULL,FMT_HEX,&hf_cops_pc_gate_spec_flags);
2829      offset += 2;
2830
2831      /* DF IP Address for CCC */
2832      info_to_display(tvb,stt,offset,4,"DF IP Address for CCC", NULL,FMT_IPv4,&hf_cops_pc_dfccc_ip);
2833      offset += 4;
2834
2835      /* DF IP Port for CCC */
2836      info_to_display(tvb,stt,offset,2,"DF IP Port for CCC",NULL,FMT_DEC,&hf_cops_pc_dfccc_ip_port);
2837      offset += 2;
2838
2839      /* Reserved */
2840      info_to_display(tvb,stt,offset,2,"Reserved",NULL,FMT_HEX,&hf_cops_pc_reserved);
2841      offset += 2;
2842
2843      /* CCCID */
2844      info_to_display(tvb,stt,offset,4,"CCCID", NULL,FMT_DEC,&hf_cops_pc_dfccc_id);
2845      offset += 4;
2846
2847      /* BCID Timestamp */
2848      info_to_display(tvb,stt,offset,4,"BCID - Timestamp",NULL,FMT_HEX,&hf_cops_pc_bcid_ts);
2849      offset += 4;
2850
2851      /* BCID Element ID */
2852      bcid_str = tvb_format_text(tvb, offset, 8);
2853      proto_tree_add_text(stt, tvb, offset, 8,"%-28s : '%s'","BCID - Element ID",bcid_str);
2854      offset += 8;
2855
2856      /* BCID Time Zone */
2857      bcid_str = tvb_format_text(tvb, offset, 8);
2858      proto_tree_add_text(stt, tvb, offset, 8,"%-28s : '%s'","BCID - Time Zone",bcid_str);
2859      offset += 8;
2860
2861      /* BCID Event Counter */
2862      info_to_display(tvb,stt,offset,4,"BCID - Event Counter",NULL,FMT_DEC,&hf_cops_pc_bcid_ev);
2863 }
2864
2865 /* Cops - Section : Event Gereration-Info */
2866 static void
2867 cops_event_generation_info(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
2868
2869      proto_tree *stt;
2870      guint8 *bcid_str;
2871
2872      /* Create a subtree */
2873      stt = info_to_cops_subtree(tvb,st,n,offset,"Event Generation Info");
2874      offset += 4;
2875
2876      /* Primary Record Keeping Server IP Address */
2877      info_to_display(tvb,stt,offset,4,"PRKS IP Address", NULL,FMT_IPv4,&hf_cops_pc_prks_ip);
2878      offset += 4;
2879
2880      /* Primary Record Keeping Server IP Port */
2881      info_to_display(tvb,stt,offset,2,"PRKS IP Port",NULL,FMT_DEC,&hf_cops_pc_prks_ip_port);
2882      offset += 2;
2883
2884      /* Flags */
2885      info_to_display(tvb,stt,offset,1,"Flags",NULL,FMT_HEX,&hf_cops_pc_gate_spec_flags);
2886      offset += 1;
2887
2888      /* Reserved */
2889      info_to_display(tvb,stt,offset,1,"Reserved",NULL,FMT_HEX,&hf_cops_pc_reserved);
2890      offset += 1;
2891
2892      /* Secondary Record Keeping Server IP Address */
2893      info_to_display(tvb,stt,offset,4,"SRKS IP Address", NULL,FMT_IPv4,&hf_cops_pc_srks_ip);
2894      offset += 4;
2895
2896      /* Secondary Record Keeping Server IP Port */
2897      info_to_display(tvb,stt,offset,2,"SRKS IP Port",NULL,FMT_DEC,&hf_cops_pc_srks_ip_port);
2898      offset += 2;
2899
2900      /* Flags */
2901      info_to_display(tvb,stt,offset,1,"Flags",NULL,FMT_DEC,&hf_cops_pc_gate_spec_flags);
2902      offset += 1;
2903
2904      /* Reserved */
2905      info_to_display(tvb,stt,offset,1,"Reserved",NULL,FMT_HEX,&hf_cops_pc_reserved);
2906      offset += 1;
2907
2908      /* BCID Timestamp */
2909      info_to_display(tvb,stt,offset,4,"BCID - Timestamp",NULL,FMT_HEX,&hf_cops_pc_bcid_ts);
2910      offset += 4;
2911
2912      /* BCID Element ID */
2913      bcid_str = tvb_format_text(tvb, offset, 8);
2914      proto_tree_add_text(stt, tvb, offset, 8,"%-28s : '%s'","BCID - Element ID",bcid_str);
2915      offset += 8;
2916
2917      /* BCID Time Zone */
2918      bcid_str = tvb_format_text(tvb, offset, 8);
2919      proto_tree_add_text(stt, tvb, offset, 8,"%-28s : '%s'","BCID - Time Zone",bcid_str);
2920      offset += 8;
2921
2922      /* BCID Event Counter */
2923      info_to_display(tvb,stt,offset,4,"BCID - Event Counter",NULL,FMT_DEC,&hf_cops_pc_bcid_ev);
2924 }
2925
2926 /* Cops - Section : Remote Gate */
2927 static void
2928 cops_remote_gate_info(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
2929
2930      proto_tree *stt;
2931
2932      /* Create a subtree */
2933      stt = info_to_cops_subtree(tvb,st,n,offset,"Remote Gate Info");
2934      offset += 4;
2935
2936      /* CMTS IP Address */
2937      info_to_display(tvb,stt,offset,4,"CMTS IP Address", NULL,FMT_IPv4,&hf_cops_pc_cmts_ip);
2938      offset += 4;
2939
2940      /* CMTS IP Port */
2941      info_to_display(tvb,stt,offset,2,"CMTS IP Port",NULL,FMT_DEC,&hf_cops_pc_cmts_ip_port);
2942      offset += 2;
2943
2944      /* Flags */
2945      info_to_display(tvb,stt,offset,2,"Flags",NULL,FMT_DEC,&hf_cops_pc_remote_flags);
2946      offset += 2;
2947
2948      /* Remote Gate ID */
2949      info_to_display(tvb,stt,offset,4,"Remote Gate ID", NULL,FMT_HEX,&hf_cops_pc_remote_gate_id);
2950      offset += 4;
2951
2952      /* Algorithm */
2953      info_to_display(tvb,stt,offset,2,"Algorithm", NULL,FMT_DEC,&hf_cops_pc_algorithm);
2954      offset += 2;
2955
2956      /* Reserved */
2957      info_to_display(tvb,stt,offset,4,"Reserved", NULL,FMT_HEX,&hf_cops_pc_reserved);
2958      offset += 4;
2959
2960      /* Security Key */
2961      info_to_display(tvb,stt,offset,4,"Security Key", NULL,FMT_HEX,&hf_cops_pc_key);
2962      offset += 4;
2963
2964      /* Security Key */
2965      info_to_display(tvb,stt,offset,4,"Security Key (cont)", NULL,FMT_HEX,&hf_cops_pc_key);
2966      offset += 4;
2967
2968      /* Security Key */
2969      info_to_display(tvb,stt,offset,4,"Security Key (cont)", NULL,FMT_HEX,&hf_cops_pc_key);
2970      offset += 4;
2971
2972      /* Security Key */
2973      info_to_display(tvb,stt,offset,4,"Security Key (cont)", NULL,FMT_HEX,&hf_cops_pc_key);
2974 }
2975
2976 /* Cops - Section : PacketCable reason */
2977 static void
2978 cops_packetcable_reason(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
2979
2980      proto_tree *stt;
2981      guint16  code16;
2982
2983      /* Create a subtree */
2984      stt = info_to_cops_subtree(tvb,st,n,offset,"PacketCable Reason");
2985      offset += 4;
2986
2987      /* Reason Code */
2988      code16 = tvb_get_ntohs(tvb,offset);
2989      proto_tree_add_uint_format(stt, hf_cops_pc_reason_code,tvb, offset, 2,
2990        code16, "%-28s : %s (%u)","Reason Code",
2991        val_to_str(code16, table_cops_reason_code, "Unknown (0x%04x)"),code16);
2992      offset += 2;
2993
2994      if ( code16 == 0 ) {
2995         /* Reason Sub Code with Delete */
2996         info_to_display(tvb,stt,offset,2,"Reason Sub Code",table_cops_reason_subcode_delete,FMT_DEC,&hf_cops_pc_delete_subcode);
2997      } else {
2998         /* Reason Sub Code with Close */
2999         info_to_display(tvb,stt,offset,2,"Reason Sub Code",table_cops_reason_subcode_close,FMT_DEC,&hf_cops_pc_close_subcode);
3000      }
3001 }
3002
3003 /* Cops - Section : PacketCable error */
3004 static void
3005 cops_packetcable_error(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
3006
3007      proto_tree *stt;
3008
3009      /* Create a subtree */
3010      stt = info_to_cops_subtree(tvb,st,n,offset,"PacketCable Error");
3011      offset += 4;
3012
3013      /* Error Code */
3014      info_to_display(tvb,stt,offset,2,"Error Code",table_cops_packetcable_error,FMT_DEC,&hf_cops_pc_packetcable_err_code);
3015      offset += 2;
3016
3017      /* Error Sub Code */
3018      info_to_display(tvb,stt,offset,2,"Error Sub Code",NULL,FMT_HEX,&hf_cops_pc_packetcable_sub_code);
3019
3020 }
3021
3022 /* Cops - Section : Multimedia Transaction ID */
3023 static void
3024 cops_mm_transaction_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *st, guint8 op_code, guint n, guint32 offset) {
3025
3026      proto_tree *stt;
3027      guint16  code16;
3028      char info[50];
3029
3030      /* Create a subtree */
3031      stt = info_to_cops_subtree(tvb,st,n,offset,"MM Transaction ID");
3032      offset += 4;
3033
3034      /* Transaction Identifier */
3035      info_to_display(tvb,stt,offset,2,"Multimedia Transaction Identifier", NULL,FMT_DEC,&hf_cops_pc_transaction_id);
3036      offset +=2;
3037
3038      /* Gate Command Type */
3039      code16 = tvb_get_ntohs(tvb,offset);
3040      proto_tree_add_uint_format(stt, hf_cops_pc_gate_command_type,tvb, offset, 2,
3041             code16,"%-28s : %s (%u)", "Gate Command Type",
3042             val_to_str(code16,table_cops_mm_transaction_id, "Unknown (0x%04x)"),code16);
3043
3044      /* Write the right data into the 'info field' on the Gui */
3045      g_snprintf(info,sizeof(info),"COPS %-20s - ",val_to_str(op_code,cops_op_code_vals, "Unknown"));
3046      strcat(info,val_to_str(code16,table_cops_mm_transaction_id, "Unknown"));
3047
3048      if (check_col(pinfo->cinfo, COL_INFO)) {
3049           col_clear(pinfo->cinfo, COL_INFO);
3050           col_add_str(pinfo->cinfo, COL_INFO,info);
3051      }
3052
3053 }
3054
3055 /* Cops - Section : AMID */
3056 static void
3057 cops_amid(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
3058
3059      proto_tree *stt;
3060
3061      /* Create a subtree */
3062      stt = info_to_cops_subtree(tvb,st,n,offset,"AMID");
3063      offset += 4;
3064
3065      /* Gate Identifier */
3066      info_to_display(tvb,stt,offset,4,"Application Manager ID", NULL,FMT_DEC,&hf_cops_pcmm_amid);
3067 }
3068
3069
3070 /* Cops - Section : Multimedia Gate Specifications */
3071 static void
3072 cops_mm_gate_spec(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
3073      proto_item *ti;
3074      proto_tree *stt, *object_tree;
3075      guint8 gs_flags;
3076
3077      /* Create a subtree */
3078      stt = info_to_cops_subtree(tvb,st,n,offset,"Gate Spec");
3079      offset += 4;
3080
3081      /* Flags */
3082      gs_flags = tvb_get_guint8(tvb, offset);
3083      ti = info_to_display(tvb,stt,offset,1,"Flags",NULL,FMT_HEX,&hf_cops_pcmm_gate_spec_flags);
3084      object_tree = proto_item_add_subtree(ti, ett_cops_subtree );
3085      proto_tree_add_text(object_tree, tvb, offset, 1, "%s gate",
3086             decode_boolean_bitfield(gs_flags, 1 << 0, 8,
3087                     "Upstream", "Downstream"));
3088      proto_tree_add_text(object_tree, tvb, offset, 1, "%s DSCP/TOS overwrite",
3089             decode_boolean_bitfield(gs_flags, 1 << 1, 8,
3090                     "Enable", "Disable"));
3091      offset += 1;
3092
3093      /* DiffServ Code Point */
3094      info_to_display(tvb,stt,offset,1,"DS Field (DSCP or TOS)",NULL,FMT_HEX,&hf_cops_pcmm_gate_spec_dscp_tos_field);
3095      offset += 1;
3096
3097      /* DiffServ Code Point Mask */
3098      info_to_display(tvb,stt,offset,1,"DS Field (DSCP or TOS) Mask",NULL,FMT_HEX,&hf_cops_pcmm_gate_spec_dscp_tos_mask);
3099      offset += 1;
3100
3101      /* Session Class */
3102      ti = info_to_display(tvb,stt,offset,1,"Session Class",table_cops_session_class,FMT_DEC,&hf_cops_pcmm_gate_spec_session_class_id);
3103      object_tree = proto_item_add_subtree(ti, ett_cops_subtree);
3104      proto_tree_add_item(object_tree, hf_cops_pcmm_gate_spec_session_class_id_priority, tvb, offset, 1, FALSE);
3105      proto_tree_add_item(object_tree, hf_cops_pcmm_gate_spec_session_class_id_preemption, tvb, offset, 1, FALSE);
3106      proto_tree_add_item(object_tree, hf_cops_pcmm_gate_spec_session_class_id_configurable, tvb, offset, 1, FALSE);
3107      offset += 1;
3108
3109      /* Timer T1 Value */
3110      info_to_display(tvb,stt,offset,2,"Timer T1 Value (sec)",NULL,FMT_DEC,&hf_cops_pcmm_gate_spec_timer_t1);
3111      offset += 2;
3112
3113      /* Timer T2 Value */
3114      info_to_display(tvb,stt,offset,2,"Timer T2 Value (sec)",NULL,FMT_DEC,&hf_cops_pcmm_gate_spec_timer_t2);
3115      offset += 2;
3116
3117      /* Timer T3 Value */
3118      info_to_display(tvb,stt,offset,2,"Timer T3 Value (sec)",NULL,FMT_DEC,&hf_cops_pcmm_gate_spec_timer_t3);
3119      offset += 2;
3120
3121      /* Timer T4 Value */
3122      info_to_display(tvb,stt,offset,2,"Timer T4 Value (sec)",NULL,FMT_DEC,&hf_cops_pcmm_gate_spec_timer_t4);
3123      offset += 2;
3124 }
3125
3126 /* Cops - Section : Classifier */
3127 static void
3128 cops_classifier(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
3129
3130      proto_tree *stt;
3131
3132      /* Create a subtree */
3133      stt = info_to_cops_subtree(tvb,st,n,offset,"Classifier");
3134      offset += 4;
3135
3136      /* Protocol ID */
3137      info_to_display(tvb,stt,offset,2,"Protocol ID",NULL,FMT_DEC,&hf_cops_pcmm_classifier_protocol_id);
3138      offset += 2;
3139
3140      /* DiffServ Code Point */
3141      info_to_display(tvb,stt,offset,1,"DS Field (DSCP or TOS)",NULL,FMT_HEX,&hf_cops_pcmm_classifier_dscp_tos_field);
3142      offset += 1;
3143
3144      /* DiffServ Code Point Mask */
3145      info_to_display(tvb,stt,offset,1,"DS Field (DSCP or TOS) Mask",NULL,FMT_HEX,&hf_cops_pcmm_classifier_dscp_tos_mask);
3146      offset += 1;
3147
3148      /* Source IP Address */
3149      info_to_display(tvb,stt,offset,4,"Source IP Address",NULL,FMT_IPv4,&hf_cops_pcmm_classifier_src_addr);
3150      offset += 4;
3151
3152      /* Destination IP Address */
3153      info_to_display(tvb,stt,offset,4,"Destination IP Address",NULL,FMT_IPv4,&hf_cops_pcmm_classifier_dst_addr);
3154      offset += 4;
3155
3156      /* Source IP Port */
3157      info_to_display(tvb,stt,offset,2,"Source IP Port",NULL,FMT_DEC,&hf_cops_pcmm_classifier_src_port);
3158      offset += 2;
3159
3160      /* Destination IP Port */
3161      info_to_display(tvb,stt,offset,2,"Destination IP Port",NULL,FMT_DEC,&hf_cops_pcmm_classifier_dst_port);
3162      offset += 2;
3163
3164      /* Priority */
3165      info_to_display(tvb,stt,offset,1,"Priority",NULL,FMT_HEX,&hf_cops_pcmm_classifier_priority);
3166      offset += 1;
3167
3168      /* 3 octets Not specified */
3169      offset += 3;
3170 }
3171
3172 /* Cops - Section : Gate Specifications */
3173 static void
3174 cops_flow_spec(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
3175      proto_item *ti;
3176      proto_tree *stt, *object_tree;
3177
3178      /* Create a subtree */
3179      stt = info_to_cops_subtree(tvb,st,n,offset,"Flow Spec");
3180      offset += 4;
3181
3182      /* Envelope */
3183      info_to_display(tvb,stt,offset,1,"Envelope",NULL,FMT_DEC,&hf_cops_pcmm_flow_spec_envelope);
3184      offset += 1;
3185
3186      /* Service Number */
3187      info_to_display(tvb,stt,offset,1,"Service Number",NULL,FMT_DEC,&hf_cops_pcmm_flow_spec_service_number);
3188      offset += 1;
3189
3190      /* Reserved */
3191      info_to_display(tvb,stt,offset,2,"Reserved",NULL,FMT_HEX,&hf_cops_pc_reserved);
3192      offset += 2;
3193
3194      /* Authorized Envelope */
3195      ti = proto_tree_add_text(stt, tvb, offset, 28, "Authorized Envelope");
3196      object_tree = proto_item_add_subtree(ti, ett_cops_subtree);
3197
3198      /* Token Bucket Rate */
3199      info_to_display(tvb,object_tree,offset,4,"Token Bucket Rate",NULL,FMT_FLT,&hf_cops_pc_token_bucket_rate);
3200      offset += 4;
3201
3202      /* Token Bucket Size */
3203      info_to_display(tvb,object_tree,offset,4,"Token Bucket Size",NULL,FMT_FLT,&hf_cops_pc_token_bucket_size);
3204      offset += 4;
3205
3206      /* Peak Data Rate */
3207      info_to_display(tvb,object_tree,offset,4,"Peak Data Rate",NULL,FMT_FLT,&hf_cops_pc_peak_data_rate);
3208      offset += 4;
3209
3210      /* Minimum Policed Unit */
3211      info_to_display(tvb,object_tree,offset,4,"Minimum Policed Unit",NULL,FMT_DEC,&hf_cops_pc_min_policed_unit);
3212      offset += 4;
3213
3214      /* Maximum Packet Size */
3215      info_to_display(tvb,object_tree,offset,4,"Maximum Packet Size",NULL,FMT_DEC,&hf_cops_pc_max_packet_size);
3216      offset += 4;
3217
3218      /* Rate */
3219      info_to_display(tvb,object_tree,offset,4,"Rate",NULL,FMT_FLT,&hf_cops_pc_spec_rate);
3220      offset += 4;
3221
3222      /* Slack Term */
3223      info_to_display(tvb,object_tree,offset,4,"Slack Term",NULL,FMT_DEC,&hf_cops_pc_slack_term);
3224      offset += 4;
3225
3226      if (n < 64) return;
3227
3228      /* Reserved Envelope */
3229      ti = proto_tree_add_text(stt, tvb, offset, 28, "Reserved Envelope");
3230      object_tree = proto_item_add_subtree(ti, ett_cops_subtree);
3231
3232      /* Token Bucket Rate */
3233      info_to_display(tvb,object_tree,offset,4,"Token Bucket Rate",NULL,FMT_FLT,&hf_cops_pc_token_bucket_rate);
3234      offset += 4;
3235
3236      /* Token Bucket Size */
3237      info_to_display(tvb,object_tree,offset,4,"Token Bucket Size",NULL,FMT_FLT,&hf_cops_pc_token_bucket_size);
3238      offset += 4;
3239
3240      /* Peak Data Rate */
3241      info_to_display(tvb,object_tree,offset,4,"Peak Data Rate",NULL,FMT_FLT,&hf_cops_pc_peak_data_rate);
3242      offset += 4;
3243
3244      /* Minimum Policed Unit */
3245      info_to_display(tvb,object_tree,offset,4,"Minimum Policed Unit",NULL,FMT_DEC,&hf_cops_pc_min_policed_unit);
3246      offset += 4;
3247
3248      /* Maximum Packet Size */
3249      info_to_display(tvb,object_tree,offset,4,"Maximum Packet Size",NULL,FMT_DEC,&hf_cops_pc_max_packet_size);
3250      offset += 4;
3251
3252      /* Rate */
3253      info_to_display(tvb,object_tree,offset,4,"Rate",NULL,FMT_FLT,&hf_cops_pc_spec_rate);
3254      offset += 4;
3255
3256      /* Slack Term */
3257      info_to_display(tvb,object_tree,offset,4,"Slack Term",NULL,FMT_DEC,&hf_cops_pc_slack_term);
3258      offset += 4;
3259
3260      if (n < 92) return;
3261
3262      /* Committed Envelope */
3263      ti = proto_tree_add_text(stt, tvb, offset, 28, "Committed Envelope");
3264      object_tree = proto_item_add_subtree(ti, ett_cops_subtree);
3265
3266      /* Token Bucket Rate */
3267      info_to_display(tvb,object_tree,offset,4,"Token Bucket Rate",NULL,FMT_FLT,&hf_cops_pc_token_bucket_rate);
3268      offset += 4;
3269
3270      /* Token Bucket Size */
3271      info_to_display(tvb,object_tree,offset,4,"Token Bucket Size",NULL,FMT_FLT,&hf_cops_pc_token_bucket_size);
3272      offset += 4;
3273
3274      /* Peak Data Rate */
3275      info_to_display(tvb,object_tree,offset,4,"Peak Data Rate",NULL,FMT_FLT,&hf_cops_pc_peak_data_rate);
3276      offset += 4;
3277
3278      /* Minimum Policed Unit */
3279      info_to_display(tvb,object_tree,offset,4,"Minimum Policed Unit",NULL,FMT_DEC,&hf_cops_pc_min_policed_unit);
3280      offset += 4;
3281
3282      /* Maximum Packet Size */
3283      info_to_display(tvb,object_tree,offset,4,"Maximum Packet Size",NULL,FMT_DEC,&hf_cops_pc_max_packet_size);
3284      offset += 4;
3285
3286      /* Rate */
3287      info_to_display(tvb,object_tree,offset,4,"Rate",NULL,FMT_FLT,&hf_cops_pc_spec_rate);
3288      offset += 4;
3289
3290      /* Slack Term */
3291      info_to_display(tvb,object_tree,offset,4,"Slack Term",NULL,FMT_DEC,&hf_cops_pc_slack_term);
3292 }
3293
3294 /* Cops - Section : DOCSIS Service Class Name */
3295 static void
3296 cops_docsis_service_class_name(tvbuff_t *tvb, proto_tree *st, guint object_len, guint32 offset) {
3297
3298      proto_tree *stt;
3299
3300      /* Create a subtree */
3301      stt = info_to_cops_subtree(tvb,st,object_len,offset,"DOCSIS Service Class Name");
3302      offset += 4;
3303
3304      /* Envelope */
3305      info_to_display(tvb,stt,offset,1,"Envelope",NULL,FMT_DEC,&hf_cops_pcmm_envelope);
3306      offset += 1;
3307
3308      proto_tree_add_text(stt, tvb, offset, 3, "Reserved");
3309      offset += 3;
3310
3311      if (object_len >= 12) {
3312             proto_tree_add_item(stt, hf_cops_pcmm_docsis_scn, tvb, offset, object_len - 8, FALSE);
3313             offset += object_len - 8;
3314      } else {
3315             proto_tree_add_text(stt, tvb, offset - 8, 2, "Invalid object length: %u", object_len);
3316      }
3317 }
3318
3319 /* Cops - Section : Best Effort Service */
3320 static void
3321 cops_best_effort_service(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
3322      proto_item *ti;
3323      proto_tree *stt, *object_tree;
3324
3325      /* Create a subtree */
3326      stt = info_to_cops_subtree(tvb,st,n,offset,"Best Effort Service");
3327      offset += 4;
3328
3329      /* Envelope */
3330      info_to_display(tvb,stt,offset,1,"Envelope",NULL,FMT_DEC,&hf_cops_pcmm_envelope);
3331      offset += 1;
3332
3333      proto_tree_add_text(stt, tvb, offset, 3, "Reserved");
3334      offset += 3;
3335
3336      /* Authorized Envelope */
3337      ti = proto_tree_add_text(stt, tvb, offset, 24, "Authorized Envelope");
3338      object_tree = proto_item_add_subtree(ti, ett_cops_subtree);
3339
3340      /* Traffic Priority */
3341      info_to_display(tvb,object_tree,offset,1,"Traffic Priority",NULL,FMT_HEX,&hf_cops_pcmm_traffic_priority);
3342      offset += 1;
3343
3344      proto_tree_add_text(object_tree, tvb, offset, 3, "Reserved");
3345      offset += 3;
3346
3347      /* Request Transmission Policy */
3348      decode_docsis_request_transmission_policy(tvb, offset, object_tree, hf_cops_pcmm_request_transmission_policy);
3349      offset += 4;
3350
3351      /* Maximum Sustained Traffic Rate */
3352      info_to_display(tvb,object_tree,offset,4,"Maximum Sustained Traffic Rate",NULL,FMT_DEC,&hf_cops_pcmm_max_sustained_traffic_rate);
3353      offset += 4;
3354
3355      /* Maximum Traffic Burst */
3356      info_to_display(tvb,object_tree,offset,4,"Maximum Traffic Burst",NULL,FMT_DEC,&hf_cops_pcmm_max_traffic_burst);
3357      offset += 4;
3358
3359      /* Minimum Reserved Traffic Rate */
3360      info_to_display(tvb,object_tree,offset,4,"Minimum Reserved Traffic Rate",NULL,FMT_DEC,&hf_cops_pcmm_min_reserved_traffic_rate);
3361      offset += 4;
3362
3363      /* Assumed Minimum Reserved Traffic Rate Packet Size */
3364      info_to_display(tvb,object_tree,offset,2,"Assumed Minimum Reserved Traffic Rate Packet Size",NULL,FMT_DEC,&hf_cops_pcmm_ass_min_rtr_packet_size);
3365      offset += 2;
3366
3367      /* Reserved */
3368      info_to_display(tvb,object_tree,offset,2,"Reserved",NULL,FMT_HEX,&hf_cops_pc_reserved);
3369      offset += 2;
3370
3371      if (n < 56) return;
3372
3373      /* Reserved Envelope */
3374      ti = proto_tree_add_text(stt, tvb, offset, 24, "Reserved Envelope");
3375      object_tree = proto_item_add_subtree(ti, ett_cops_subtree);
3376
3377      /* Traffic Priority */
3378      info_to_display(tvb,object_tree,offset,1,"Traffic Priority",NULL,FMT_HEX,&hf_cops_pcmm_traffic_priority);
3379      offset += 1;
3380
3381      proto_tree_add_text(object_tree, tvb, offset, 3, "Reserved");
3382      offset += 3;
3383
3384      /* Request Transmission Policy */
3385      decode_docsis_request_transmission_policy(tvb, offset, object_tree, hf_cops_pcmm_request_transmission_policy);
3386      offset += 4;
3387
3388      /* Maximum Sustained Traffic Rate */
3389      info_to_display(tvb,object_tree,offset,4,"Maximum Sustained Traffic Rate",NULL,FMT_DEC,&hf_cops_pcmm_max_sustained_traffic_rate);
3390      offset += 4;
3391
3392      /* Maximum Traffic Burst */
3393      info_to_display(tvb,object_tree,offset,4,"Maximum Traffic Burst",NULL,FMT_DEC,&hf_cops_pcmm_max_traffic_burst);
3394      offset += 4;
3395
3396      /* Minimum Reserved Traffic Rate */
3397      info_to_display(tvb,object_tree,offset,4,"Minimum Reserved Traffic Rate",NULL,FMT_DEC,&hf_cops_pcmm_min_reserved_traffic_rate);
3398      offset += 4;
3399
3400      /* Assumed Minimum Reserved Traffic Rate Packet Size */
3401      info_to_display(tvb,object_tree,offset,2,"Assumed Minimum Reserved Traffic Rate Packet Size",NULL,FMT_DEC,&hf_cops_pcmm_ass_min_rtr_packet_size);
3402      offset += 2;
3403
3404      /* Reserved */
3405      info_to_display(tvb,object_tree,offset,2,"Reserved",NULL,FMT_HEX,&hf_cops_pc_reserved);
3406      offset += 2;
3407
3408      if (n < 80) return;
3409
3410      /* Committed Envelope */
3411      ti = proto_tree_add_text(stt, tvb, offset, 24, "Committed Envelope");
3412      object_tree = proto_item_add_subtree(ti, ett_cops_subtree);
3413
3414      /* Traffic Priority */
3415      info_to_display(tvb,object_tree,offset,1,"Traffic Priority",NULL,FMT_HEX,&hf_cops_pcmm_traffic_priority);
3416      offset += 1;
3417
3418      proto_tree_add_text(object_tree, tvb, offset, 3, "Reserved");
3419      offset += 3;
3420
3421      /* Request Transmission Policy */
3422      decode_docsis_request_transmission_policy(tvb, offset, object_tree, hf_cops_pcmm_request_transmission_policy);
3423      offset += 4;
3424
3425      /* Maximum Sustained Traffic Rate */
3426      info_to_display(tvb,object_tree,offset,4,"Maximum Sustained Traffic Rate",NULL,FMT_DEC,&hf_cops_pcmm_max_sustained_traffic_rate);
3427      offset += 4;
3428
3429      /* Maximum Traffic Burst */
3430      info_to_display(tvb,object_tree,offset,4,"Maximum Traffic Burst",NULL,FMT_DEC,&hf_cops_pcmm_max_traffic_burst);
3431      offset += 4;
3432
3433      /* Minimum Reserved Traffic Rate */
3434      info_to_display(tvb,object_tree,offset,4,"Minimum Reserved Traffic Rate",NULL,FMT_DEC,&hf_cops_pcmm_min_reserved_traffic_rate);
3435      offset += 4;
3436
3437      /* Assumed Minimum Reserved Traffic Rate Packet Size */
3438      info_to_display(tvb,object_tree,offset,2,"Assumed Minimum Reserved Traffic Rate Packet Size",NULL,FMT_DEC,&hf_cops_pcmm_ass_min_rtr_packet_size);
3439      offset += 2;
3440
3441      /* Reserved */
3442      info_to_display(tvb,object_tree,offset,2,"Reserved",NULL,FMT_HEX,&hf_cops_pc_reserved);
3443      offset += 2;
3444 }
3445
3446 /* Cops - Section : Non-Real-Time Polling Service */
3447 static void
3448 cops_non_real_time_polling_service(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
3449      proto_item *ti;
3450      proto_tree *stt, *object_tree;
3451
3452      /* Create a subtree */
3453      stt = info_to_cops_subtree(tvb,st,n,offset,"Non-Real-Time Polling Service");
3454      offset += 4;
3455
3456      /* Envelope */
3457      info_to_display(tvb,stt,offset,1,"Envelope",NULL,FMT_DEC,&hf_cops_pcmm_envelope);
3458      offset += 1;
3459
3460      proto_tree_add_text(stt, tvb, offset, 3, "Reserved");
3461      offset += 3;
3462
3463      /* Authorized Envelope */
3464      ti = proto_tree_add_text(stt, tvb, offset, 28, "Authorized Envelope");
3465      object_tree = proto_item_add_subtree(ti, ett_cops_subtree);
3466
3467      /* Traffic Priority */
3468      info_to_display(tvb,object_tree,offset,1,"Traffic Priority",NULL,FMT_HEX,&hf_cops_pcmm_traffic_priority);
3469      offset += 1;
3470
3471      proto_tree_add_text(object_tree, tvb, offset, 3, "Reserved");
3472      offset += 3;
3473
3474      /* Request Transmission Policy */
3475      decode_docsis_request_transmission_policy(tvb, offset, object_tree, hf_cops_pcmm_request_transmission_policy);
3476      offset += 4;
3477
3478      /* Maximum Sustained Traffic Rate */
3479      info_to_display(tvb,object_tree,offset,4,"Maximum Sustained Traffic Rate",NULL,FMT_DEC,&hf_cops_pcmm_max_sustained_traffic_rate);
3480      offset += 4;
3481
3482      /* Maximum Traffic Burst */
3483      info_to_display(tvb,object_tree,offset,4,"Maximum Traffic Burst",NULL,FMT_DEC,&hf_cops_pcmm_max_traffic_burst);
3484      offset += 4;
3485
3486      /* Minimum Reserved Traffic Rate */
3487      info_to_display(tvb,object_tree,offset,4,"Minimum Reserved Traffic Rate",NULL,FMT_DEC,&hf_cops_pcmm_min_reserved_traffic_rate);
3488      offset += 4;
3489
3490      /* Assumed Minimum Reserved Traffic Rate Packet Size */
3491      info_to_display(tvb,object_tree,offset,2,"Assumed Minimum Reserved Traffic Rate Packet Size",NULL,FMT_DEC,&hf_cops_pcmm_ass_min_rtr_packet_size);
3492      offset += 2;
3493
3494      /* Reserved */
3495      info_to_display(tvb,object_tree,offset,2,"Reserved",NULL,FMT_HEX,&hf_cops_pc_reserved);
3496      offset += 2;
3497
3498      /* Nominal Polling Interval */
3499      info_to_display(tvb,object_tree,offset,4,"Nominal Polling Interval",NULL,FMT_DEC,&hf_cops_pcmm_nominal_polling_interval);
3500      offset += 4;
3501
3502      if (n < 64) return;
3503
3504      /* Reserved Envelope */
3505      ti = proto_tree_add_text(stt, tvb, offset, 24, "Reserved Envelope");
3506      object_tree = proto_item_add_subtree(ti, ett_cops_subtree);
3507
3508      /* Traffic Priority */
3509      info_to_display(tvb,object_tree,offset,1,"Traffic Priority",NULL,FMT_HEX,&hf_cops_pcmm_traffic_priority);
3510      offset += 1;
3511
3512      proto_tree_add_text(object_tree, tvb, offset, 3, "Reserved");
3513      offset += 3;
3514
3515      /* Request Transmission Policy */
3516      decode_docsis_request_transmission_policy(tvb, offset, object_tree, hf_cops_pcmm_request_transmission_policy);
3517      offset += 4;
3518
3519      /* Maximum Sustained Traffic Rate */
3520      info_to_display(tvb,object_tree,offset,4,"Maximum Sustained Traffic Rate",NULL,FMT_DEC,&hf_cops_pcmm_max_sustained_traffic_rate);
3521      offset += 4;
3522
3523      /* Maximum Traffic Burst */
3524      info_to_display(tvb,object_tree,offset,4,"Maximum Traffic Burst",NULL,FMT_DEC,&hf_cops_pcmm_max_traffic_burst);
3525      offset += 4;
3526
3527      /* Minimum Reserved Traffic Rate */
3528      info_to_display(tvb,object_tree,offset,4,"Minimum Reserved Traffic Rate",NULL,FMT_DEC,&hf_cops_pcmm_min_reserved_traffic_rate);
3529      offset += 4;
3530
3531      /* Assumed Minimum Reserved Traffic Rate Packet Size */
3532      info_to_display(tvb,object_tree,offset,2,"Assumed Minimum Reserved Traffic Rate Packet Size",NULL,FMT_DEC,&hf_cops_pcmm_ass_min_rtr_packet_size);
3533      offset += 2;
3534
3535      /* Reserved */
3536      info_to_display(tvb,object_tree,offset,2,"Reserved",NULL,FMT_HEX,&hf_cops_pc_reserved);
3537      offset += 2;
3538
3539      /* Nominal Polling Interval */
3540      info_to_display(tvb,object_tree,offset,4,"Nominal Polling Interval",NULL,FMT_DEC,&hf_cops_pcmm_nominal_polling_interval);
3541      offset += 4;
3542
3543      if (n < 92) return;
3544
3545      /* Committed Envelope */
3546      ti = proto_tree_add_text(stt, tvb, offset, 24, "Committed Envelope");
3547      object_tree = proto_item_add_subtree(ti, ett_cops_subtree);
3548
3549      /* Traffic Priority */
3550      info_to_display(tvb,object_tree,offset,1,"Traffic Priority",NULL,FMT_HEX,&hf_cops_pcmm_traffic_priority);
3551      offset += 1;
3552
3553      proto_tree_add_text(object_tree, tvb, offset, 3, "Reserved");
3554      offset += 3;
3555
3556      /* Request Transmission Policy */
3557      decode_docsis_request_transmission_policy(tvb, offset, object_tree, hf_cops_pcmm_request_transmission_policy);
3558      offset += 4;
3559
3560      /* Maximum Sustained Traffic Rate */
3561      info_to_display(tvb,object_tree,offset,4,"Maximum Sustained Traffic Rate",NULL,FMT_DEC,&hf_cops_pcmm_max_sustained_traffic_rate);
3562      offset += 4;
3563
3564      /* Maximum Traffic Burst */
3565      info_to_display(tvb,object_tree,offset,4,"Maximum Traffic Burst",NULL,FMT_DEC,&hf_cops_pcmm_max_traffic_burst);
3566      offset += 4;
3567
3568      /* Minimum Reserved Traffic Rate */
3569      info_to_display(tvb,object_tree,offset,4,"Minimum Reserved Traffic Rate",NULL,FMT_DEC,&hf_cops_pcmm_min_reserved_traffic_rate);
3570      offset += 4;
3571
3572      /* Assumed Minimum Reserved Traffic Rate Packet Size */
3573      info_to_display(tvb,object_tree,offset,2,"Assumed Minimum Reserved Traffic Rate Packet Size",NULL,FMT_DEC,&hf_cops_pcmm_ass_min_rtr_packet_size);
3574      offset += 2;
3575
3576      /* Reserved */
3577      info_to_display(tvb,object_tree,offset,2,"Reserved",NULL,FMT_HEX,&hf_cops_pc_reserved);
3578      offset += 2;
3579
3580      /* Nominal Polling Interval */
3581      info_to_display(tvb,object_tree,offset,4,"Nominal Polling Interval",NULL,FMT_DEC,&hf_cops_pcmm_nominal_polling_interval);
3582      offset += 4;
3583 }
3584
3585 /* Cops - Section : Real-Time Polling Service */
3586 static void
3587 cops_real_time_polling_service(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
3588      proto_item *ti;
3589      proto_tree *stt, *object_tree;
3590
3591      /* Create a subtree */
3592      stt = info_to_cops_subtree(tvb,st,n,offset,"Real-Time Polling Service");
3593      offset += 4;
3594
3595      /* Envelope */
3596      info_to_display(tvb,stt,offset,1,"Envelope",NULL,FMT_DEC,&hf_cops_pcmm_envelope);
3597      offset += 1;
3598
3599      proto_tree_add_text(stt, tvb, offset, 3, "Reserved");
3600      offset += 3;
3601
3602      /* Authorized Envelope */
3603      ti = proto_tree_add_text(stt, tvb, offset, 28, "Authorized Envelope");
3604      object_tree = proto_item_add_subtree(ti, ett_cops_subtree);
3605
3606      /* Request Transmission Policy */
3607      decode_docsis_request_transmission_policy(tvb, offset, object_tree, hf_cops_pcmm_request_transmission_policy);
3608      offset += 4;
3609
3610      /* Maximum Sustained Traffic Rate */
3611      info_to_display(tvb,object_tree,offset,4,"Maximum Sustained Traffic Rate",NULL,FMT_DEC,&hf_cops_pcmm_max_sustained_traffic_rate);
3612      offset += 4;
3613
3614      /* Maximum Traffic Burst */
3615      info_to_display(tvb,object_tree,offset,4,"Maximum Traffic Burst",NULL,FMT_DEC,&hf_cops_pcmm_max_traffic_burst);
3616      offset += 4;
3617
3618      /* Minimum Reserved Traffic Rate */
3619      info_to_display(tvb,object_tree,offset,4,"Minimum Reserved Traffic Rate",NULL,FMT_DEC,&hf_cops_pcmm_min_reserved_traffic_rate);
3620      offset += 4;
3621
3622      /* Assumed Minimum Reserved Traffic Rate Packet Size */
3623      info_to_display(tvb,object_tree,offset,2,"Assumed Minimum Reserved Traffic Rate Packet Size",NULL,FMT_DEC,&hf_cops_pcmm_ass_min_rtr_packet_size);
3624      offset += 2;
3625
3626      /* Reserved */
3627      info_to_display(tvb,object_tree,offset,2,"Reserved",NULL,FMT_HEX,&hf_cops_pc_reserved);
3628      offset += 2;
3629
3630      /* Nominal Polling Interval */
3631      info_to_display(tvb,object_tree,offset,4,"Nominal Polling Interval",NULL,FMT_DEC,&hf_cops_pcmm_nominal_polling_interval);
3632      offset += 4;
3633
3634      /* Tolerated Poll Jitter */
3635      info_to_display(tvb,object_tree,offset,4,"Tolerated Poll Jitter",NULL,FMT_DEC,&hf_cops_pcmm_tolerated_poll_jitter);
3636      offset += 4;
3637
3638      if (n < 64) return;
3639
3640      /* Reserved Envelope */
3641      ti = proto_tree_add_text(stt, tvb, offset, 24, "Reserved Envelope");
3642      object_tree = proto_item_add_subtree(ti, ett_cops_subtree);
3643
3644      /* Request Transmission Policy */
3645      decode_docsis_request_transmission_policy(tvb, offset, object_tree, hf_cops_pcmm_request_transmission_policy);
3646      offset += 4;
3647
3648      /* Maximum Sustained Traffic Rate */
3649      info_to_display(tvb,object_tree,offset,4,"Maximum Sustained Traffic Rate",NULL,FMT_DEC,&hf_cops_pcmm_max_sustained_traffic_rate);
3650      offset += 4;
3651
3652      /* Maximum Traffic Burst */
3653      info_to_display(tvb,object_tree,offset,4,"Maximum Traffic Burst",NULL,FMT_DEC,&hf_cops_pcmm_max_traffic_burst);
3654      offset += 4;
3655
3656      /* Minimum Reserved Traffic Rate */
3657      info_to_display(tvb,object_tree,offset,4,"Minimum Reserved Traffic Rate",NULL,FMT_DEC,&hf_cops_pcmm_min_reserved_traffic_rate);
3658      offset += 4;
3659
3660      /* Assumed Minimum Reserved Traffic Rate Packet Size */
3661      info_to_display(tvb,object_tree,offset,2,"Assumed Minimum Reserved Traffic Rate Packet Size",NULL,FMT_DEC,&hf_cops_pcmm_ass_min_rtr_packet_size);
3662      offset += 2;
3663
3664      /* Reserved */
3665      info_to_display(tvb,object_tree,offset,2,"Reserved",NULL,FMT_HEX,&hf_cops_pc_reserved);
3666      offset += 2;
3667
3668      /* Nominal Polling Interval */
3669      info_to_display(tvb,object_tree,offset,4,"Nominal Polling Interval",NULL,FMT_DEC,&hf_cops_pcmm_nominal_polling_interval);
3670      offset += 4;
3671
3672      /* Tolerated Poll Jitter */
3673      info_to_display(tvb,object_tree,offset,4,"Tolerated Poll Jitter",NULL,FMT_DEC,&hf_cops_pcmm_tolerated_poll_jitter);
3674      offset += 4;
3675
3676      if (n < 92) return;
3677
3678      /* Committed Envelope */
3679      ti = proto_tree_add_text(stt, tvb, offset, 24, "Committed Envelope");
3680      object_tree = proto_item_add_subtree(ti, ett_cops_subtree);
3681
3682      /* Request Transmission Policy */
3683      decode_docsis_request_transmission_policy(tvb, offset, object_tree, hf_cops_pcmm_request_transmission_policy);
3684      offset += 4;
3685
3686      /* Maximum Sustained Traffic Rate */
3687      info_to_display(tvb,object_tree,offset,4,"Maximum Sustained Traffic Rate",NULL,FMT_DEC,&hf_cops_pcmm_max_sustained_traffic_rate);
3688      offset += 4;
3689
3690      /* Maximum Traffic Burst */
3691      info_to_display(tvb,object_tree,offset,4,"Maximum Traffic Burst",NULL,FMT_DEC,&hf_cops_pcmm_max_traffic_burst);
3692      offset += 4;
3693
3694      /* Minimum Reserved Traffic Rate */
3695      info_to_display(tvb,object_tree,offset,4,"Minimum Reserved Traffic Rate",NULL,FMT_DEC,&hf_cops_pcmm_min_reserved_traffic_rate);
3696      offset += 4;
3697
3698      /* Assumed Minimum Reserved Traffic Rate Packet Size */
3699      info_to_display(tvb,object_tree,offset,2,"Assumed Minimum Reserved Traffic Rate Packet Size",NULL,FMT_DEC,&hf_cops_pcmm_ass_min_rtr_packet_size);
3700      offset += 2;
3701
3702      /* Reserved */
3703      info_to_display(tvb,object_tree,offset,2,"Reserved",NULL,FMT_HEX,&hf_cops_pc_reserved);
3704      offset += 2;
3705
3706      /* Nominal Polling Interval */
3707      info_to_display(tvb,object_tree,offset,4,"Nominal Polling Interval",NULL,FMT_DEC,&hf_cops_pcmm_nominal_polling_interval);
3708      offset += 4;
3709
3710      /* Tolerated Poll Jitter */
3711      info_to_display(tvb,object_tree,offset,4,"Tolerated Poll Jitter",NULL,FMT_DEC,&hf_cops_pcmm_tolerated_poll_jitter);
3712      offset += 4;
3713 }
3714
3715 /* Cops - Section : Unsolicited Grant Service */
3716 static void
3717 cops_unsolicited_grant_service(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
3718      proto_item *ti;
3719      proto_tree *stt, *object_tree;
3720
3721      /* Create a subtree */
3722      stt = info_to_cops_subtree(tvb,st,n,offset,"Unsolicited Grant Service");
3723      offset += 4;
3724
3725      /* Envelope */
3726      info_to_display(tvb,stt,offset,1,"Envelope",NULL,FMT_DEC,&hf_cops_pcmm_envelope);
3727      offset += 1;
3728
3729      proto_tree_add_text(stt, tvb, offset, 3, "Reserved");
3730      offset += 3;
3731
3732      /* Authorized Envelope */
3733      ti = proto_tree_add_text(stt, tvb, offset, 16, "Authorized Envelope");
3734      object_tree = proto_item_add_subtree(ti, ett_cops_subtree);
3735
3736      /* Request Transmission Policy */
3737      decode_docsis_request_transmission_policy(tvb, offset, object_tree, hf_cops_pcmm_request_transmission_policy);
3738      offset += 4;
3739
3740      /* Unsolicited Grant Size */
3741      info_to_display(tvb,object_tree,offset,2,"Unsolicited Grant Size",NULL,FMT_DEC,&hf_cops_pcmm_unsolicited_grant_size);
3742      offset += 2;
3743
3744      /* Grants Per Interval */
3745      info_to_display(tvb,object_tree,offset,1,"Grants Per Interval",NULL,FMT_DEC,&hf_cops_pcmm_grants_per_interval);
3746      offset += 1;
3747
3748      proto_tree_add_text(object_tree, tvb, offset, 1, "Reserved");
3749      offset += 1;
3750
3751      /* Nominal Grant Interval */
3752      info_to_display(tvb,object_tree,offset,4,"Nominal Grant Interval",NULL,FMT_DEC,&hf_cops_pcmm_nominal_grant_interval);
3753      offset += 4;
3754
3755      /* Tolerated Grant Jitter */
3756      info_to_display(tvb,object_tree,offset,4,"Tolerated Grant Jitter",NULL,FMT_DEC,&hf_cops_pcmm_tolerated_grant_jitter);
3757      offset += 4;
3758
3759      if (n < 40) return;
3760
3761      /* Reserved Envelope */
3762      ti = proto_tree_add_text(stt, tvb, offset, 16, "Reserved Envelope");
3763      object_tree = proto_item_add_subtree(ti, ett_cops_subtree);
3764
3765      /* Request Transmission Policy */
3766      decode_docsis_request_transmission_policy(tvb, offset, object_tree, hf_cops_pcmm_request_transmission_policy);
3767      offset += 4;
3768
3769      /* Unsolicited Grant Size */
3770      info_to_display(tvb,object_tree,offset,2,"Unsolicited Grant Size",NULL,FMT_DEC,&hf_cops_pcmm_unsolicited_grant_size);
3771      offset += 2;
3772
3773      /* Grants Per Interval */
3774      info_to_display(tvb,object_tree,offset,1,"Grants Per Interval",NULL,FMT_DEC,&hf_cops_pcmm_grants_per_interval);
3775      offset += 1;
3776
3777      proto_tree_add_text(object_tree, tvb, offset, 1, "Reserved");
3778      offset += 1;
3779
3780      /* Nominal Grant Interval */
3781      info_to_display(tvb,object_tree,offset,4,"Nominal Grant Interval",NULL,FMT_DEC,&hf_cops_pcmm_nominal_grant_interval);
3782      offset += 4;
3783
3784      /* Tolerated Grant Jitter */
3785      info_to_display(tvb,object_tree,offset,4,"Tolerated Grant Jitter",NULL,FMT_DEC,&hf_cops_pcmm_tolerated_grant_jitter);
3786      offset += 4;
3787
3788      if (n < 56) return;
3789
3790      /* Committed Envelope */
3791      ti = proto_tree_add_text(stt, tvb, offset, 16, "Committed Envelope");
3792      object_tree = proto_item_add_subtree(ti, ett_cops_subtree);
3793
3794      /* Request Transmission Policy */
3795      decode_docsis_request_transmission_policy(tvb, offset, object_tree, hf_cops_pcmm_request_transmission_policy);
3796      offset += 4;
3797
3798      /* Unsolicited Grant Size */
3799      info_to_display(tvb,object_tree,offset,2,"Unsolicited Grant Size",NULL,FMT_DEC,&hf_cops_pcmm_unsolicited_grant_size);
3800      offset += 2;
3801
3802      /* Grants Per Interval */
3803      info_to_display(tvb,object_tree,offset,1,"Grants Per Interval",NULL,FMT_DEC,&hf_cops_pcmm_grants_per_interval);
3804      offset += 1;
3805
3806      proto_tree_add_text(object_tree, tvb, offset, 1, "Reserved");
3807      offset += 1;
3808
3809      /* Nominal Grant Interval */
3810      info_to_display(tvb,object_tree,offset,4,"Nominal Grant Interval",NULL,FMT_DEC,&hf_cops_pcmm_nominal_grant_interval);
3811      offset += 4;
3812
3813      /* Tolerated Grant Jitter */
3814      info_to_display(tvb,object_tree,offset,4,"Tolerated Grant Jitter",NULL,FMT_DEC,&hf_cops_pcmm_tolerated_grant_jitter);
3815      offset += 4;
3816 }
3817
3818 /* Cops - Section : Unsolicited Grant Service with Activity Detection */
3819 static void
3820 cops_ugs_with_activity_detection(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
3821      proto_item *ti;
3822      proto_tree *stt, *object_tree;
3823
3824      /* Create a subtree */
3825      stt = info_to_cops_subtree(tvb,st,n,offset,"Unsolicited Grant Service with Activity Detection");
3826      offset += 4;
3827
3828      /* Envelope */
3829      info_to_display(tvb,stt,offset,1,"Envelope",NULL,FMT_DEC,&hf_cops_pcmm_envelope);
3830      offset += 1;
3831
3832      proto_tree_add_text(stt, tvb, offset, 3, "Reserved");
3833      offset += 3;
3834
3835      /* Authorized Envelope */
3836      ti = proto_tree_add_text(stt, tvb, offset, 24, "Authorized Envelope");
3837      object_tree = proto_item_add_subtree(ti, ett_cops_subtree);
3838
3839      /* Request Transmission Policy */
3840      decode_docsis_request_transmission_policy(tvb, offset, object_tree, hf_cops_pcmm_request_transmission_policy);
3841      offset += 4;
3842
3843      /* Unsolicited Grant Size */
3844      info_to_display(tvb,object_tree,offset,2,"Unsolicited Grant Size",NULL,FMT_DEC,&hf_cops_pcmm_unsolicited_grant_size);
3845      offset += 2;
3846
3847      /* Grants Per Interval */
3848      info_to_display(tvb,object_tree,offset,1,"Grants Per Interval",NULL,FMT_DEC,&hf_cops_pcmm_grants_per_interval);
3849      offset += 1;
3850
3851      proto_tree_add_text(object_tree, tvb, offset, 1, "Reserved");
3852      offset += 1;
3853
3854      /* Nominal Grant Interval */
3855      info_to_display(tvb,object_tree,offset,4,"Nominal Grant Interval",NULL,FMT_DEC,&hf_cops_pcmm_nominal_grant_interval);
3856      offset += 4;
3857
3858      /* Tolerated Grant Jitter */
3859      info_to_display(tvb,object_tree,offset,4,"Tolerated Grant Jitter",NULL,FMT_DEC,&hf_cops_pcmm_tolerated_grant_jitter);
3860      offset += 4;
3861
3862      /* Nominal Polling Interval */
3863      info_to_display(tvb,object_tree,offset,4,"Nominal Polling Interval",NULL,FMT_DEC,&hf_cops_pcmm_nominal_polling_interval);
3864      offset += 4;
3865
3866      /* Tolerated Poll Jitter */
3867      info_to_display(tvb,object_tree,offset,4,"Tolerated Poll Jitter",NULL,FMT_DEC,&hf_cops_pcmm_tolerated_poll_jitter);
3868      offset += 4;
3869
3870      if (n < 56) return;
3871
3872      /* Reserved Envelope */
3873      ti = proto_tree_add_text(stt, tvb, offset, 24, "Reserved Envelope");
3874      object_tree = proto_item_add_subtree(ti, ett_cops_subtree);
3875
3876      /* Request Transmission Policy */
3877      decode_docsis_request_transmission_policy(tvb, offset, object_tree, hf_cops_pcmm_request_transmission_policy);
3878      offset += 4;
3879
3880      /* Unsolicited Grant Size */
3881      info_to_display(tvb,object_tree,offset,2,"Unsolicited Grant Size",NULL,FMT_DEC,&hf_cops_pcmm_unsolicited_grant_size);
3882      offset += 2;
3883
3884      /* Grants Per Interval */
3885      info_to_display(tvb,object_tree,offset,1,"Grants Per Interval",NULL,FMT_DEC,&hf_cops_pcmm_grants_per_interval);
3886      offset += 1;
3887
3888      proto_tree_add_text(object_tree, tvb, offset, 1, "Reserved");
3889      offset += 1;
3890
3891      /* Nominal Grant Interval */
3892      info_to_display(tvb,object_tree,offset,4,"Nominal Grant Interval",NULL,FMT_DEC,&hf_cops_pcmm_nominal_grant_interval);
3893      offset += 4;
3894
3895      /* Tolerated Grant Jitter */
3896      info_to_display(tvb,object_tree,offset,4,"Tolerated Grant Jitter",NULL,FMT_DEC,&hf_cops_pcmm_tolerated_grant_jitter);
3897      offset += 4;
3898
3899      /* Nominal Polling Interval */
3900      info_to_display(tvb,object_tree,offset,4,"Nominal Polling Interval",NULL,FMT_DEC,&hf_cops_pcmm_nominal_polling_interval);
3901      offset += 4;
3902
3903      /* Tolerated Poll Jitter */
3904      info_to_display(tvb,object_tree,offset,4,"Tolerated Poll Jitter",NULL,FMT_DEC,&hf_cops_pcmm_tolerated_poll_jitter);
3905      offset += 4;
3906
3907      if (n < 80) return;
3908
3909      /* Committed Envelope */
3910      ti = proto_tree_add_text(stt, tvb, offset, 24, "Committed Envelope");
3911      object_tree = proto_item_add_subtree(ti, ett_cops_subtree);
3912
3913      /* Request Transmission Policy */
3914      decode_docsis_request_transmission_policy(tvb, offset, object_tree, hf_cops_pcmm_request_transmission_policy);
3915      offset += 4;
3916
3917      /* Unsolicited Grant Size */
3918      info_to_display(tvb,object_tree,offset,2,"Unsolicited Grant Size",NULL,FMT_DEC,&hf_cops_pcmm_unsolicited_grant_size);
3919      offset += 2;
3920
3921      /* Grants Per Interval */
3922      info_to_display(tvb,object_tree,offset,1,"Grants Per Interval",NULL,FMT_DEC,&hf_cops_pcmm_grants_per_interval);
3923      offset += 1;
3924
3925      proto_tree_add_text(object_tree, tvb, offset, 1, "Reserved");
3926      offset += 1;
3927
3928      /* Nominal Grant Interval */
3929      info_to_display(tvb,object_tree,offset,4,"Nominal Grant Interval",NULL,FMT_DEC,&hf_cops_pcmm_nominal_grant_interval);
3930      offset += 4;
3931
3932      /* Tolerated Grant Jitter */
3933      info_to_display(tvb,object_tree,offset,4,"Tolerated Grant Jitter",NULL,FMT_DEC,&hf_cops_pcmm_tolerated_grant_jitter);
3934      offset += 4;
3935
3936      /* Nominal Polling Interval */
3937      info_to_display(tvb,object_tree,offset,4,"Nominal Polling Interval",NULL,FMT_DEC,&hf_cops_pcmm_nominal_polling_interval);
3938      offset += 4;
3939
3940      /* Tolerated Poll Jitter */
3941      info_to_display(tvb,object_tree,offset,4,"Tolerated Poll Jitter",NULL,FMT_DEC,&hf_cops_pcmm_tolerated_poll_jitter);
3942      offset += 4;
3943 }
3944
3945 /* Cops - Section : Downstream Service */
3946 static void
3947 cops_downstream_service(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
3948      proto_item *ti;
3949      proto_tree *stt, *object_tree;
3950
3951      /* Create a subtree */
3952      stt = info_to_cops_subtree(tvb,st,n,offset,"Downstream Service");
3953      offset += 4;
3954
3955      /* Envelope */
3956      info_to_display(tvb,stt,offset,1,"Envelope",NULL,FMT_DEC,&hf_cops_pcmm_envelope);
3957      offset += 1;
3958
3959      proto_tree_add_text(stt, tvb, offset, 3, "Reserved");
3960      offset += 3;
3961
3962      /* Authorized Envelope */
3963      ti = proto_tree_add_text(stt, tvb, offset, 24, "Authorized Envelope");
3964      object_tree = proto_item_add_subtree(ti, ett_cops_subtree);
3965
3966      /* Traffic Priority */
3967      info_to_display(tvb,object_tree,offset,1,"Traffic Priority",NULL,FMT_HEX,&hf_cops_pcmm_traffic_priority);
3968      offset += 1;
3969
3970      proto_tree_add_text(object_tree, tvb, offset, 3, "Reserved");
3971      offset += 3;
3972
3973      /* Maximum Sustained Traffic Rate */
3974      info_to_display(tvb,object_tree,offset,4,"Maximum Sustained Traffic Rate",NULL,FMT_DEC,&hf_cops_pcmm_max_sustained_traffic_rate);
3975      offset += 4;
3976
3977      /* Maximum Traffic Burst */
3978      info_to_display(tvb,object_tree,offset,4,"Maximum Traffic Burst",NULL,FMT_DEC,&hf_cops_pcmm_max_traffic_burst);
3979      offset += 4;
3980
3981      /* Minimum Reserved Traffic Rate */
3982      info_to_display(tvb,object_tree,offset,4,"Minimum Reserved Traffic Rate",NULL,FMT_DEC,&hf_cops_pcmm_min_reserved_traffic_rate);
3983      offset += 4;
3984
3985      /* Assumed Minimum Reserved Traffic Rate Packet Size */
3986      info_to_display(tvb,object_tree,offset,2,"Assumed Minimum Reserved Traffic Rate Packet Size",NULL,FMT_DEC,&hf_cops_pcmm_ass_min_rtr_packet_size);
3987      offset += 2;
3988
3989      /* Reserved */
3990      info_to_display(tvb,object_tree,offset,2,"Reserved",NULL,FMT_HEX,&hf_cops_pc_reserved);
3991      offset += 2;
3992
3993      /* Maximum Downstream Latency */
3994      info_to_display(tvb,object_tree,offset,4,"Maximum Downstream Latency",NULL,FMT_DEC,&hf_cops_pcmm_max_downstream_latency);
3995      offset += 4;
3996
3997      if (n < 56) return;
3998
3999      /* Reserved Envelope */
4000      ti = proto_tree_add_text(stt, tvb, offset, 24, "Reserved Envelope");
4001      object_tree = proto_item_add_subtree(ti, ett_cops_subtree);
4002
4003      /* Traffic Priority */
4004      info_to_display(tvb,object_tree,offset,1,"Traffic Priority",NULL,FMT_HEX,&hf_cops_pcmm_traffic_priority);
4005      offset += 1;
4006
4007      proto_tree_add_text(object_tree, tvb, offset, 3, "Reserved");
4008      offset += 3;
4009
4010      /* Maximum Sustained Traffic Rate */
4011      info_to_display(tvb,object_tree,offset,4,"Maximum Sustained Traffic Rate",NULL,FMT_DEC,&hf_cops_pcmm_max_sustained_traffic_rate);
4012      offset += 4;
4013
4014      /* Maximum Traffic Burst */
4015      info_to_display(tvb,object_tree,offset,4,"Maximum Traffic Burst",NULL,FMT_DEC,&hf_cops_pcmm_max_traffic_burst);
4016      offset += 4;
4017
4018      /* Minimum Reserved Traffic Rate */
4019      info_to_display(tvb,object_tree,offset,4,"Minimum Reserved Traffic Rate",NULL,FMT_DEC,&hf_cops_pcmm_min_reserved_traffic_rate);
4020      offset += 4;
4021
4022      /* Assumed Minimum Reserved Traffic Rate Packet Size */
4023      info_to_display(tvb,object_tree,offset,2,"Assumed Minimum Reserved Traffic Rate Packet Size",NULL,FMT_DEC,&hf_cops_pcmm_ass_min_rtr_packet_size);
4024      offset += 2;
4025
4026      /* Reserved */
4027      info_to_display(tvb,object_tree,offset,2,"Reserved",NULL,FMT_HEX,&hf_cops_pc_reserved);
4028      offset += 2;
4029
4030      /* Maximum Downstream Latency */
4031      info_to_display(tvb,object_tree,offset,4,"Maximum Downstream Latency",NULL,FMT_DEC,&hf_cops_pcmm_max_downstream_latency);
4032      offset += 4;
4033
4034      if (n < 80) return;
4035
4036      /* Committed Envelope */
4037      ti = proto_tree_add_text(stt, tvb, offset, 24, "Committed Envelope");
4038      object_tree = proto_item_add_subtree(ti, ett_cops_subtree);
4039
4040      /* Traffic Priority */
4041      info_to_display(tvb,object_tree,offset,1,"Traffic Priority",NULL,FMT_HEX,&hf_cops_pcmm_traffic_priority);
4042      offset += 1;
4043
4044      proto_tree_add_text(object_tree, tvb, offset, 3, "Reserved");
4045      offset += 3;
4046
4047      /* Maximum Sustained Traffic Rate */
4048      info_to_display(tvb,object_tree,offset,4,"Maximum Sustained Traffic Rate",NULL,FMT_DEC,&hf_cops_pcmm_max_sustained_traffic_rate);
4049      offset += 4;
4050
4051      /* Maximum Traffic Burst */
4052      info_to_display(tvb,object_tree,offset,4,"Maximum Traffic Burst",NULL,FMT_DEC,&hf_cops_pcmm_max_traffic_burst);
4053      offset += 4;
4054
4055      /* Minimum Reserved Traffic Rate */
4056      info_to_display(tvb,object_tree,offset,4,"Minimum Reserved Traffic Rate",NULL,FMT_DEC,&hf_cops_pcmm_min_reserved_traffic_rate);
4057      offset += 4;
4058
4059      /* Assumed Minimum Reserved Traffic Rate Packet Size */
4060      info_to_display(tvb,object_tree,offset,2,"Assumed Minimum Reserved Traffic Rate Packet Size",NULL,FMT_DEC,&hf_cops_pcmm_ass_min_rtr_packet_size);
4061      offset += 2;
4062
4063      /* Reserved */
4064      info_to_display(tvb,object_tree,offset,2,"Reserved",NULL,FMT_HEX,&hf_cops_pc_reserved);
4065      offset += 2;
4066
4067      /* Maximum Downstream Latency */
4068      info_to_display(tvb,object_tree,offset,4,"Maximum Downstream Latency",NULL,FMT_DEC,&hf_cops_pcmm_max_downstream_latency);
4069      offset += 4;
4070 }
4071
4072 /* Cops - Section : PacketCable Multimedia Event Gereration-Info */
4073 static void
4074 cops_mm_event_generation_info(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
4075
4076      proto_tree *stt;
4077      guint8 *bcid_str;
4078
4079      /* Create a subtree */
4080      stt = info_to_cops_subtree(tvb,st,n,offset,"Event Generation Info");
4081      offset += 4;
4082
4083      /* Primary Record Keeping Server IP Address */
4084      info_to_display(tvb,stt,offset,4,"PRKS IP Address", NULL,FMT_IPv4,&hf_cops_pc_prks_ip);
4085      offset += 4;
4086
4087      /* Primary Record Keeping Server IP Port */
4088      info_to_display(tvb,stt,offset,2,"PRKS IP Port",NULL,FMT_DEC,&hf_cops_pc_prks_ip_port);
4089      offset += 2;
4090
4091      /* Reserved */
4092      info_to_display(tvb,stt,offset,2,"Reserved",NULL,FMT_HEX,&hf_cops_pc_reserved);
4093      offset += 2;
4094
4095      /* Secondary Record Keeping Server IP Address */
4096      info_to_display(tvb,stt,offset,4,"SRKS IP Address", NULL,FMT_IPv4,&hf_cops_pc_srks_ip);
4097      offset += 4;
4098
4099      /* Secondary Record Keeping Server IP Port */
4100      info_to_display(tvb,stt,offset,2,"SRKS IP Port",NULL,FMT_DEC,&hf_cops_pc_srks_ip_port);
4101      offset += 2;
4102
4103      /* Reserved */
4104      info_to_display(tvb,stt,offset,2,"Reserved",NULL,FMT_HEX,&hf_cops_pc_reserved);
4105      offset += 2;
4106
4107      /* BCID Timestamp */
4108      info_to_display(tvb,stt,offset,4,"BCID - Timestamp",NULL,FMT_HEX,&hf_cops_pc_bcid_ts);
4109      offset += 4;
4110
4111      /* BCID Element ID */
4112      bcid_str = tvb_format_text(tvb, offset, 8);
4113      proto_tree_add_text(stt, tvb, offset, 8,"%-28s : '%s'","BCID - Element ID",bcid_str);
4114      offset += 8;
4115
4116      /* BCID Time Zone */
4117      bcid_str = tvb_format_text(tvb, offset, 8);
4118      proto_tree_add_text(stt, tvb, offset, 8,"%-28s : '%s'","BCID - Time Zone",bcid_str);
4119      offset += 8;
4120
4121      /* BCID Event Counter */
4122      info_to_display(tvb,stt,offset,4,"BCID - Event Counter",NULL,FMT_DEC,&hf_cops_pc_bcid_ev);
4123 }
4124
4125 /* Cops - Section : Volume-Based Usage Limit */
4126 static void
4127 cops_volume_based_usage_limit(tvbuff_t *tvb, proto_tree *st, guint object_len, guint32 offset) {
4128
4129      proto_tree *stt;
4130
4131      /* Create a subtree */
4132      stt = info_to_cops_subtree(tvb,st,object_len,offset,"Volume-Based Usage Limit");
4133      offset += 4;
4134
4135      /* Usage Limit */
4136      proto_tree_add_item(stt, hf_cops_pcmm_volume_based_usage_limit, tvb, offset, 8,
4137             FALSE);
4138 }
4139
4140 /* Cops - Section : Time-Based Usage Limit */
4141 static void
4142 cops_time_based_usage_limit(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
4143
4144      proto_tree *stt;
4145
4146      /* Create a subtree */
4147      stt = info_to_cops_subtree(tvb,st,n,offset,"Time-Based Usage Limit");
4148      offset += 4;
4149
4150      /* Time Limit */
4151      info_to_display(tvb,stt,offset,4,"Time Limit", NULL,FMT_DEC,&hf_cops_pcmm_time_based_usage_limit);
4152      offset += 4;
4153 }
4154
4155 /* Cops - Section : Opaque Data */
4156 static void
4157 cops_opaque_data(tvbuff_t *tvb, proto_tree *st, guint object_len, guint32 offset) {
4158
4159      proto_tree *stt;
4160
4161      /* Create a subtree */
4162      stt = info_to_cops_subtree(tvb,st,object_len,offset,"Opaque Data");
4163      offset += 4;
4164
4165      /* Opaque Data */
4166      proto_tree_add_text(stt, tvb, offset, 8,"Opaque Data");
4167 }
4168
4169 /* Cops - Section : Gate Time Info */
4170 static void
4171 cops_gate_time_info(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
4172
4173      proto_tree *stt;
4174
4175      /* Create a subtree */
4176      stt = info_to_cops_subtree(tvb,st,n,offset,"Gate Time Info");
4177      offset += 4;
4178
4179      /* Gate Time Info */
4180      info_to_display(tvb,stt,offset,4,"Time Committed", NULL,FMT_DEC,&hf_cops_pcmm_gate_time_info);
4181      offset += 4;
4182 }
4183
4184 /* Cops - Section : Gate Usage Info */
4185 static void
4186 cops_gate_usage_info(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
4187
4188      proto_tree *stt;
4189
4190      /* Create a subtree */
4191      stt = info_to_cops_subtree(tvb,st,n,offset,"Gate Usage Info");
4192      offset += 4;
4193
4194      /* Gate Time Info */
4195      info_to_display(tvb,stt,offset,4,"Octet Count", NULL,FMT_DEC,&hf_cops_pcmm_gate_usage_info);
4196      offset += 4;
4197 }
4198
4199 /* Cops - Section : PacketCable error */
4200 static void
4201 cops_packetcable_mm_error(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
4202
4203      proto_tree *stt;
4204      guint16 code, subcode;
4205
4206      /* Create a subtree */
4207      stt = info_to_cops_subtree(tvb,st,n,offset,"PacketCable Error");
4208      offset += 4;
4209
4210      code = tvb_get_ntohs(tvb, offset);
4211      proto_tree_add_uint_format(stt, hf_cops_pcmm_packetcable_error_code, tvb, offset, 2, code,
4212             "Error Code: %s (%u)", val_to_str(code, pcmm_packetcable_error_code, "Unknown"),
4213             code);
4214      offset += 2;
4215
4216      subcode = tvb_get_ntohs(tvb, offset);
4217      if (code == 6 || code == 7)
4218             proto_tree_add_uint_format(stt, hf_cops_pcmm_packetcable_error_subcode,
4219                     tvb, offset, 2, code, "Error-Subcode: 0x%02x, S-Num: 0x%02x, S-Type: 0x%02x",
4220                     subcode, subcode >> 8, subcode & 0xf);
4221      else
4222             proto_tree_add_uint_format(stt, hf_cops_pcmm_packetcable_error_subcode,
4223                     tvb, offset, 2, code, "Error-Subcode: 0x%04x", subcode);
4224      offset += 2;
4225 }
4226
4227 /* Cops - Section : Gate State */
4228 static void
4229 cops_gate_state(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
4230
4231      proto_tree *stt;
4232
4233      /* Create a subtree */
4234      stt = info_to_cops_subtree(tvb,st,n,offset,"Gate State");
4235      offset += 4;
4236
4237      /* State */
4238      info_to_display(tvb,stt,offset,2,"State",pcmm_gate_state,FMT_DEC,&hf_cops_pcmm_packetcable_gate_state);
4239      offset += 2;
4240
4241      /* Reason */
4242      info_to_display(tvb,stt,offset,2,"Reason",pcmm_gate_state_reason,FMT_DEC,&hf_cops_pcmm_packetcable_gate_state_reason);
4243      offset += 2;
4244 }
4245
4246 /* Cops - Section : Version Info */
4247 static void
4248 cops_version_info(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
4249
4250      proto_tree *stt;
4251
4252      /* Create a subtree */
4253      stt = info_to_cops_subtree(tvb,st,n,offset,"Version Info");
4254      offset += 4;
4255
4256      /* State */
4257      info_to_display(tvb,stt,offset,2,"Major Version Number",NULL,FMT_DEC,&hf_cops_pcmm_packetcable_version_info_major);
4258      offset += 2;
4259
4260      /* Reason */
4261      info_to_display(tvb,stt,offset,2,"Minor Version Number",NULL,FMT_DEC,&hf_cops_pcmm_packetcable_version_info_minor);
4262      offset += 2;
4263 }
4264
4265
4266
4267 /* PacketCable D-QoS S-Num/S-Type globs */
4268 #define PCDQ_TRANSACTION_ID              0x0101
4269 #define PCDQ_SUBSCRIBER_IDv4             0x0201
4270 #define PCDQ_SUBSCRIBER_IDv6             0x0202
4271 #define PCDQ_GATE_ID                     0x0301
4272 #define PCDQ_ACTIVITY_COUNT              0x0401
4273 #define PCDQ_GATE_SPEC                   0x0501
4274 #define PCDQ_REMOTE_GATE_INFO            0x0601
4275 #define PCDQ_EVENT_GENERATION_INFO       0x0701
4276 #define PCDQ_MEDIA_CONNECTION_EVENT_INFO 0x0801
4277 #define PCDQ_PACKETCABLE_ERROR           0x0901
4278 #define PCDQ_PACKETCABLE_REASON          0x0d01
4279 #define PCDQ_ELECTRONIC_SURVEILLANCE     0x0a01
4280 #define PCDQ_SESSION_DESCRIPTION         0x0b01
4281
4282 /* Analyze the PacketCable objects */
4283 static void
4284 cops_analyze_packetcable_dqos_obj(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint8 op_code, guint32 offset) {
4285
4286     gint remdata;
4287     guint16 object_len;
4288     guint8 s_num, s_type;
4289     guint16 num_type_glob;
4290
4291     /* Only if this option is enabled by the Gui */
4292     if ( cops_packetcable == FALSE ) {
4293        return;
4294     }
4295
4296     /* Do the remaining client specific objects */
4297     remdata = tvb_length_remaining(tvb, offset);
4298     while (remdata > 4) {
4299
4300        /* In case we have remaining data, then lets try to get this analyzed */
4301        object_len   = tvb_get_ntohs(tvb, offset);
4302        if (object_len < 4) {
4303         proto_tree_add_text(tree, tvb, offset, 2,
4304             "Incorrect PacketCable object length %u < 4", object_len);
4305         return;
4306        }
4307
4308        s_num        = tvb_get_guint8(tvb, offset + 2);
4309        s_type       = tvb_get_guint8(tvb, offset + 3);
4310
4311        /* Glom the s_num and s_type together to make switching easier */
4312        num_type_glob = s_num << 8 | s_type;
4313
4314        /* Perform the appropriate functions */
4315        switch (num_type_glob){
4316         case PCDQ_TRANSACTION_ID:
4317                cops_transaction_id(tvb, pinfo, tree, op_code, object_len, offset);
4318                break;
4319         case PCDQ_SUBSCRIBER_IDv4:
4320                cops_subscriber_id_v4(tvb, tree, object_len, offset);
4321                break;
4322         case PCDQ_SUBSCRIBER_IDv6:
4323                cops_subscriber_id_v6(tvb, tree, object_len, offset);
4324                break;
4325         case PCDQ_GATE_ID:
4326                cops_gate_id(tvb, tree, object_len, offset);
4327                break;
4328         case PCDQ_ACTIVITY_COUNT:
4329                cops_activity_count(tvb, tree, object_len, offset);
4330                break;
4331         case PCDQ_GATE_SPEC:
4332                cops_gate_specs(tvb, tree, object_len, offset);
4333                break;
4334         case PCDQ_REMOTE_GATE_INFO:
4335                cops_remote_gate_info(tvb, tree, object_len, offset);
4336                break;
4337         case PCDQ_EVENT_GENERATION_INFO:
4338                cops_event_generation_info(tvb, tree, object_len, offset);
4339                break;
4340         case PCDQ_PACKETCABLE_ERROR:
4341                cops_packetcable_error(tvb, tree, object_len, offset);
4342                break;
4343         case PCDQ_ELECTRONIC_SURVEILLANCE:
4344                cops_surveillance_parameters(tvb, tree, object_len, offset);
4345                break;
4346         case PCDQ_PACKETCABLE_REASON:
4347                cops_packetcable_reason(tvb, tree, object_len, offset);
4348                break;
4349        }
4350
4351        /* Tune offset */
4352        offset += object_len;
4353
4354        /* See what we can still get from the buffer */
4355        remdata = tvb_length_remaining(tvb, offset);
4356     }
4357 }
4358
4359 /* XXX - This duplicates code in the DOCSIS dissector. */
4360 static void
4361 decode_docsis_request_transmission_policy(tvbuff_t *tvb, guint32 offset, proto_tree *tree, gint hf) {
4362         proto_tree *drtp_tree;
4363         proto_item *item;
4364         guint32 policy = tvb_get_ntohl(tvb, offset);
4365         int i;
4366         char bit_fld[48];
4367         static const value_string drtp_vals[] = {
4368                 { 1 << 0, "The Service Flow MUST NOT use \"all CMs\" broadcast request opportunities" },
4369                 { 1 << 1, "The Service Flow MUST NOT use Priority Request multicast request opportunities" },
4370                 { 1 << 2, "The Service Flow MUST NOT use Request/Data opportunities for Requests" },
4371                 { 1 << 3, "The Service Flow MUST NOT use Request/Data opportunities for Data" },
4372                 { 1 << 4, "The Service Flow MUST NOT piggyback requests with data" },
4373                 { 1 << 5, "The Service Flow MUST NOT concatenate data" },
4374                 { 1 << 6, "The Service Flow MUST NOT fragment data" },
4375                 { 1 << 7, "The Service Flow MUST NOT suppress payload headers" },
4376                 { 1 << 8, "The Service Flow MUST drop packets that do not fit in the Unsolicited Grant Size" },
4377                 { 0, NULL }
4378         };
4379
4380         item = proto_tree_add_item (tree, hf, tvb, offset, 4, FALSE);
4381         drtp_tree = proto_item_add_subtree(item, ett_docsis_request_transmission_policy);
4382         for (i = 0 ; i <= 8; i++) {
4383                 if (policy & drtp_vals[i].value) {
4384                         decode_bitfield_value(bit_fld, policy, drtp_vals[i].value, 32);
4385                         proto_tree_add_text(drtp_tree, tvb, offset, 4, "%s%s",
4386                                 bit_fld, drtp_vals[i].strptr);
4387                 }
4388         }
4389 }
4390
4391
4392 #define PCMM_TRANSACTION_ID                0x0101
4393 #define PCMM_AMID                          0x0201
4394 #define PCMM_SUBSCRIBER_ID                 0x0301
4395 #define PCMM_GATE_ID                       0x0401
4396 #define PCMM_GATE_SPEC                     0x0501
4397 #define PCMM_CLASSIFIER                    0x0601
4398 #define PCMM_FLOW_SPEC                     0x0701
4399 #define PCMM_DOCSIS_SERVICE_CLASS_NAME     0x0702
4400 #define PCMM_BEST_EFFORT_SERVICE           0x0703
4401 #define PCMM_NON_REAL_TIME_POLLING_SERVICE 0x0704
4402 #define PCMM_REAL_TIME_POLLING_SERVICE     0x0705
4403 #define PCMM_UNSOLICITED_GRANT_SERVICE     0x0706
4404 #define PCMM_UGS_WITH_ACTIVITY_DETECTION   0x0707
4405 #define PCMM_DOWNSTREAM_SERVICE            0x0708
4406 #define PCMM_EVENT_GENERATION_INFO         0x0801
4407 #define PCMM_VOLUME_BASED_USAGE_LIMIT      0x0901
4408 #define PCMM_TIME_BASED_USAGE_LIMIT        0x0a01
4409 #define PCMM_OPAQUE_DATA                   0x0b01
4410 #define PCMM_GATE_TIME_INFO                0x0c01
4411 #define PCMM_GATE_USAGE_INFO               0x0d01
4412 #define PCMM_PACKETCABLE_ERROR             0x0e01
4413 #define PCMM_GATE_STATE                    0x0f01
4414 #define PCMM_VERSION_INFO                  0x1001
4415
4416
4417 static void
4418 cops_analyze_packetcable_mm_obj(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint8 op_code, guint32 offset) {
4419
4420     guint16 object_len;
4421     guint8 s_num, s_type;
4422     guint16 num_type_glob;
4423
4424     /* Only if this option is enabled by the Gui */
4425     if ( cops_packetcable == FALSE ) {
4426        return;
4427     }
4428
4429     /* Do the remaining client specific objects */
4430     while (tvb_reported_length_remaining(tvb, offset) > 4) {
4431
4432        /* In case we have remaining data, then lets try to get this analyzed */
4433        object_len   = tvb_get_ntohs(tvb, offset);
4434        if (object_len < 4) {
4435         proto_tree_add_text(tree, tvb, offset, 2,
4436             "Incorrect PacketCable object length %u < 4", object_len);
4437         return;
4438        }
4439
4440        s_num        = tvb_get_guint8(tvb, offset + 2);
4441        s_type       = tvb_get_guint8(tvb, offset + 3);
4442
4443        /* Glom the s_num and s_type together to make switching easier */
4444        num_type_glob = s_num << 8 | s_type;
4445
4446        /* Perform the appropriate functions */
4447        switch (num_type_glob){
4448         case PCMM_TRANSACTION_ID:
4449                cops_mm_transaction_id(tvb, pinfo, tree, op_code, object_len, offset);
4450                break;
4451         case PCMM_AMID:
4452                cops_amid(tvb, tree, object_len, offset);
4453                break;
4454         case PCMM_SUBSCRIBER_ID:
4455                cops_subscriber_id_v4(tvb, tree, object_len, offset);
4456                break;
4457         case PCMM_GATE_ID:
4458                cops_gate_id(tvb, tree, object_len, offset);
4459                break;
4460         case PCMM_GATE_SPEC:
4461                cops_mm_gate_spec(tvb, tree, object_len, offset);
4462                break;
4463         case PCMM_CLASSIFIER:
4464                cops_classifier(tvb, tree, object_len, offset);
4465                break;
4466         case PCMM_FLOW_SPEC:
4467                cops_flow_spec(tvb, tree, object_len, offset);
4468                break;
4469         case PCMM_DOCSIS_SERVICE_CLASS_NAME:
4470                cops_docsis_service_class_name(tvb, tree, object_len, offset);
4471                break;
4472         case PCMM_BEST_EFFORT_SERVICE:
4473                cops_best_effort_service(tvb, tree, object_len, offset);
4474                break;
4475         case PCMM_NON_REAL_TIME_POLLING_SERVICE:
4476                cops_non_real_time_polling_service(tvb, tree, object_len, offset);
4477                break;
4478         case PCMM_REAL_TIME_POLLING_SERVICE:
4479                cops_real_time_polling_service(tvb, tree, object_len, offset);
4480                break;
4481         case PCMM_UNSOLICITED_GRANT_SERVICE:
4482                cops_unsolicited_grant_service(tvb, tree, object_len, offset);
4483                break;
4484         case PCMM_UGS_WITH_ACTIVITY_DETECTION:
4485                cops_ugs_with_activity_detection(tvb, tree, object_len, offset);
4486                break;
4487         case PCMM_DOWNSTREAM_SERVICE:
4488                cops_downstream_service(tvb, tree, object_len, offset);
4489                break;
4490         case PCMM_EVENT_GENERATION_INFO:
4491                cops_mm_event_generation_info(tvb, tree, object_len, offset);
4492                break;
4493         case PCMM_VOLUME_BASED_USAGE_LIMIT:
4494                cops_volume_based_usage_limit(tvb, tree, object_len, offset);
4495                break;
4496         case PCMM_TIME_BASED_USAGE_LIMIT:
4497                cops_time_based_usage_limit(tvb, tree, object_len, offset);
4498                break;
4499         case PCMM_OPAQUE_DATA:
4500                cops_opaque_data(tvb, tree, object_len, offset);
4501                break;
4502         case PCMM_GATE_TIME_INFO:
4503                cops_gate_time_info(tvb, tree, object_len, offset);
4504                break;
4505         case PCMM_GATE_USAGE_INFO:
4506                cops_gate_usage_info(tvb, tree, object_len, offset);
4507                break;
4508         case PCMM_PACKETCABLE_ERROR:
4509                cops_packetcable_mm_error(tvb, tree, object_len, offset);
4510                break;
4511         case PCMM_GATE_STATE:
4512                cops_gate_state(tvb, tree, object_len, offset);
4513                break;
4514         case PCMM_VERSION_INFO:
4515                cops_version_info(tvb, tree, object_len, offset);
4516                break;
4517        }
4518
4519        /* Tune offset */
4520        offset += object_len;
4521     }
4522 }
4523
4524
4525 /* End of PacketCable Addition */