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