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