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