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