2 * Routines for the COPS (Common Open Policy Service) protocol dissection
3 * RFC2748 & COPS-PR extension RFC3084
5 * Copyright 2000, Heikki Vatiainen <hessu@cs.tut.fi>
7 * Added PacketCable specifications by Dick Gooris <gooris@lucent.com>
9 * Taken from PacketCable specifications :
10 * PacketCable Dynamic Quality-of-Service Specification
11 * Based on PKT-SP-DQOS-I09-040402 (April 2, 2004)
14 * Implemented in ethereal at April 7-8, 2004
16 * $Id: packet-cops.c,v 1.48 2004/05/04 06:01:52 guy Exp $
18 * Ethereal - Network traffic analyzer
19 * By Gerald Combs <gerald@ethereal.com>
20 * Copyright 1998 Gerald Combs
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License
24 * as published by the Free Software Foundation; either version 2
25 * of the License, or (at your option) any later version.
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
47 #include <epan/packet.h>
48 #include "packet-ipv6.h"
49 #include "packet-tcp.h"
53 # include <net-snmp/net-snmp-config.h>
54 # include <net-snmp/mib_api.h>
55 # include <net-snmp/library/default_store.h>
56 # include <net-snmp/config_api.h>
57 #else /* HAVE_NET_SNMP */
58 # include <ucd-snmp/ucd-snmp-config.h>
59 # include <ucd-snmp/asn1.h>
60 # include <ucd-snmp/snmp_api.h>
61 # include <ucd-snmp/snmp_impl.h>
62 # include <ucd-snmp/mib.h>
63 # include <ucd-snmp/default_store.h>
64 # include <ucd-snmp/read_config.h>
65 # include <ucd-snmp/tools.h>
66 #endif /* HAVE_NET_SNMP */
67 #endif /* HAVE_SOME_SNMP */
70 #include "format-oid.h"
73 /* For PacketCable, port 2126 */
74 #define TCP_PORT_COPS 3288
76 /* Preference: Variable to hold the tcp port preference */
77 static guint global_cops_tcp_port = TCP_PORT_COPS;
79 /* Preference: desegmentation of COPS */
80 static gboolean cops_desegment = TRUE;
82 /* Variable to allow for proper deletion of dissector registration
83 * when the user changes port from the gui
86 static guint cops_tcp_port = 0;
88 /*Some local globals needed to read COPS-PR ASN.1 Types from PIB-MIBs */
89 /*MAX_OID_LEN from NET-SNMP's asn1.h*/
92 static subid_t last_decoded_prid_oid[MAX_OID_LEN]={0};
93 static subid_t last_decoded_prid_oid_length=0;
94 extern struct tree *tree_head;
96 /* Preference: COPS-PR ASN.1 type decoding based on PIB/MIB or data in packet */
97 static gboolean cops_typefrommib = FALSE;
99 #endif /* HAVE_NET_SNMP */
101 #define COPS_OBJECT_HDR_SIZE 4
103 /* Null string of type "guchar[]". */
104 static const guchar nullstring[] = "";
106 #define SAFE_STRING(s) (((s) != NULL) ? (s) : nullstring)
110 #define COPS_IPA 0 /* IP Address */
111 #define COPS_U32 2 /* Unsigned 32*/
112 #define COPS_TIT 3 /* TimeTicks */
113 #define COPS_OPQ 4 /* Opaque */
114 #define COPS_I64 10 /* Integer64 */
115 #define COPS_U64 11 /* Uinteger64 */
120 #define COPS_INTEGER 1 /* l */
121 #define COPS_OCTETSTR 2 /* c */
122 #define COPS_OBJECTID 3 /* ul */
123 #define COPS_IPADDR 4 /* uc */
124 #define COPS_UNSIGNED32 5 /* ul */
125 #define COPS_TIMETICKS 7 /* ul */
126 #define COPS_OPAQUE 8 /* c */
127 #define COPS_INTEGER64 10 /* ll */
128 #define COPS_UNSIGNED64 11 /* ull */
131 typedef struct _COPS_CNV COPS_CNV;
141 static COPS_CNV CopsCnv [] =
143 {ASN1_UNI, ASN1_NUL, COPS_NULL, "NULL"},
144 {ASN1_UNI, ASN1_INT, COPS_INTEGER, "INTEGER"},
145 {ASN1_UNI, ASN1_OTS, COPS_OCTETSTR, "OCTET STRING"},
146 {ASN1_UNI, ASN1_OJI, COPS_OBJECTID, "OBJECTID"},
147 {ASN1_APL, COPS_IPA, COPS_IPADDR, "IPADDR"},
148 {ASN1_APL, COPS_U32, COPS_UNSIGNED32,"UNSIGNED32"},
149 {ASN1_APL, COPS_TIT, COPS_TIMETICKS, "TIMETICKS"},
150 {ASN1_APL, COPS_OPQ, COPS_OPAQUE, "OPAQUE"},
151 {ASN1_APL, COPS_I64, COPS_INTEGER64, "INTEGER64"},
152 {ASN1_APL, COPS_U64, COPS_UNSIGNED64, "UNSIGNED64"},
157 cops_tag_cls2syntax ( guint tag, guint cls, gushort *syntax)
162 while (cnv->syntax != -1)
164 if (cnv->tag == tag && cnv->class == cls)
166 *syntax = cnv->syntax;
174 static const value_string cops_flags_vals[] = {
176 { 0x01, "Solicited Message Flag Bit" },
180 /* The different COPS message types */
182 COPS_NO_MSG, /* Not a COPS Message type */
184 COPS_MSG_REQ, /* Request (REQ) */
185 COPS_MSG_DEC, /* Decision (DEC) */
186 COPS_MSG_RPT, /* Report State (RPT) */
187 COPS_MSG_DRQ, /* Delete Request State (DRQ) */
188 COPS_MSG_SSQ, /* Synchronize State Req (SSQ) */
189 COPS_MSG_OPN, /* Client-Open (OPN) */
190 COPS_MSG_CAT, /* Client-Accept (CAT) */
191 COPS_MSG_CC, /* Client-Close (CC) */
192 COPS_MSG_KA, /* Keep-Alive (KA) */
193 COPS_MSG_SSC, /* Synchronize Complete (SSC) */
195 COPS_LAST_OP_CODE /* For error checking */
198 static const value_string cops_op_code_vals[] = {
199 { COPS_MSG_REQ, "Request (REQ)" },
200 { COPS_MSG_DEC, "Decision (DEC)" },
201 { COPS_MSG_RPT, "Report State (RPT)" },
202 { COPS_MSG_DRQ, "Delete Request State (DRQ)" },
203 { COPS_MSG_SSQ, "Synchronize State Req (SSQ)" },
204 { COPS_MSG_OPN, "Client-Open (OPN)" },
205 { COPS_MSG_CAT, "Client-Accept (CAT)" },
206 { COPS_MSG_CC, "Client-Close (CC)" },
207 { COPS_MSG_KA, "Keep-Alive (KA)" },
208 { COPS_MSG_SSC, "Synchronize Complete (SSC)" },
213 /* The different objects in COPS messages */
215 COPS_NO_OBJECT, /* Not a COPS Object type */
217 COPS_OBJ_HANDLE, /* Handle Object (Handle) */
218 COPS_OBJ_CONTEXT, /* Context Object (Context) */
219 COPS_OBJ_IN_INT, /* In-Interface Object (IN-Int) */
220 COPS_OBJ_OUT_INT, /* Out-Interface Object (OUT-Int) */
221 COPS_OBJ_REASON, /* Reason Object (Reason) */
222 COPS_OBJ_DECISION, /* Decision Object (Decision) */
223 COPS_OBJ_LPDPDECISION, /* LPDP Decision Object (LPDPDecision) */
224 COPS_OBJ_ERROR, /* Error Object (Error) */
225 COPS_OBJ_CLIENTSI, /* Client Specific Information Object (ClientSI) */
226 COPS_OBJ_KATIMER, /* Keep-Alive Timer Object (KATimer) */
227 COPS_OBJ_PEPID, /* PEP Identification Object (PEPID) */
228 COPS_OBJ_REPORT_TYPE, /* Report-Type Object (Report-Type) */
229 COPS_OBJ_PDPREDIRADDR, /* PDP Redirect Address Object (PDPRedirAddr) */
230 COPS_OBJ_LASTPDPADDR, /* Last PDP Address (LastPDPaddr) */
231 COPS_OBJ_ACCTTIMER, /* Accounting Timer Object (AcctTimer) */
232 COPS_OBJ_INTEGRITY, /* Message Integrity Object (Integrity) */
233 COPS_LAST_C_NUM /* For error checking */
236 static const value_string cops_c_num_vals[] = {
237 { COPS_OBJ_HANDLE, "Handle Object (Handle)" },
238 { COPS_OBJ_CONTEXT, "Context Object (Context)" },
239 { COPS_OBJ_IN_INT, "In-Interface Object (IN-Int)" },
240 { COPS_OBJ_OUT_INT, "Out-Interface Object (OUT-Int)" },
241 { COPS_OBJ_REASON, "Reason Object (Reason)" },
242 { COPS_OBJ_DECISION, "Decision Object (Decision)" },
243 { COPS_OBJ_LPDPDECISION, "LPDP Decision Object (LPDPDecision)" },
244 { COPS_OBJ_ERROR, "Error Object (Error)" },
245 { COPS_OBJ_CLIENTSI, "Client Specific Information Object (ClientSI)" },
246 { COPS_OBJ_KATIMER, "Keep-Alive Timer Object (KATimer)" },
247 { COPS_OBJ_PEPID, "PEP Identification Object (PEPID)" },
248 { COPS_OBJ_REPORT_TYPE, "Report-Type Object (Report-Type)" },
249 { COPS_OBJ_PDPREDIRADDR, "PDP Redirect Address Object (PDPRedirAddr)" },
250 { COPS_OBJ_LASTPDPADDR, "Last PDP Address (LastPDPaddr)" },
251 { COPS_OBJ_ACCTTIMER, "Accounting Timer Object (AcctTimer)" },
252 { COPS_OBJ_INTEGRITY, "Message Integrity Object (Integrity)" },
257 /* The different objects in COPS-PR messages */
259 COPS_NO_PR_OBJECT, /* Not a COPS-PR Object type */
260 COPS_OBJ_PRID, /* Provisioning Instance Identifier (PRID) */
261 COPS_OBJ_PPRID, /* Prefix Provisioning Instance Identifier (PPRID) */
262 COPS_OBJ_EPD, /* Encoded Provisioning Instance Data (EPD) */
263 COPS_OBJ_GPERR, /* Global Provisioning Error Object (GPERR) */
264 COPS_OBJ_CPERR, /* PRC Class Provisioning Error Object (CPERR) */
265 COPS_OBJ_ERRPRID, /* Error Provisioning Instance Identifier (ErrorPRID)*/
267 COPS_LAST_S_NUM /* For error checking */
271 static const value_string cops_s_num_vals[] = {
272 { COPS_OBJ_PRID, "Provisioning Instance Identifier (PRID)" },
273 { COPS_OBJ_PPRID, "Prefix Provisioning Instance Identifier (PPRID)" },
274 { COPS_OBJ_EPD, "Encoded Provisioning Instance Data (EPD)" },
275 { COPS_OBJ_GPERR, "Global Provisioning Error Object (GPERR)" },
276 { COPS_OBJ_CPERR, "PRC Class Provisioning Error Object (CPERR)" },
277 { COPS_OBJ_ERRPRID, "Error Provisioning Instance Identifier (ErrorPRID)" },
282 /* R-Type is carried within the Context Object */
283 static const value_string cops_r_type_vals[] = {
284 { 0x01, "Incoming-Message/Admission Control request" },
285 { 0x02, "Resource-Allocation request" },
286 { 0x04, "Outgoing-Message request" },
287 { 0x08, "Configuration request" },
290 /* S-Type is carried within the ClientSI Object for COPS-PR*/
291 static const value_string cops_s_type_vals[] = {
296 /* Reason-Code is carried within the Reason object */
297 static const value_string cops_reason_vals[] = {
298 { 1, "Unspecified" },
300 { 3, "Preempted (Another request state takes precedence)" },
301 { 4, "Tear (Used to communicate a signaled state removal)" },
302 { 5, "Timeout (Local state has timed-out)" },
303 { 6, "Route Change (Change invalidates request state)" },
304 { 7, "Insufficient Resources (No local resource available)" },
305 { 8, "PDP's Directive (PDP decision caused the delete)" },
306 { 9, "Unsupported decision (PDP decision not supported)" },
307 { 10, "Synchronize Handle Unknown" },
308 { 11, "Transient Handle (stateless event)" },
309 { 12, "Malformed Decision (could not recover)" },
310 { 13, "Unknown COPS Object from PDP" },
314 /* Command-Code is carried within the Decision object if C-Type is 1 */
315 static const value_string cops_dec_cmd_code_vals[] = {
316 { 0, "NULL Decision (No configuration data available)" },
317 { 1, "Install (Admit request/Install configuration)" },
318 { 2, "Remove (Remove request/Remove configuration)" },
322 /* Decision flags are also carried with the Decision object if C-Type is 1 */
323 static const value_string cops_dec_cmd_flag_vals[] = {
324 { 0x00, "<None set>" },
325 { 0x01, "Trigger Error (Trigger error message if set)" },
329 /* Error-Code from Error object */
330 static const value_string cops_error_vals[] = {
332 {2, "Invalid handle reference" },
333 {3, "Bad message format (Malformed Message)" },
334 {4, "Unable to process (server gives up on query)" },
335 {5, "Mandatory client-specific info missing" },
336 {6, "Unsupported client" },
337 {7, "Mandatory COPS object missing" },
338 {8, "Client Failure" },
339 {9, "Communication Failure" },
340 {10, "Unspecified" },
341 {11, "Shutting down" },
342 {12, "Redirect to Preferred Server" },
343 {13, "Unknown COPS Object" },
344 {14, "Authentication Failure" },
345 {15, "Authentication Required" },
348 /* Error-Code from GPERR object */
349 static const value_string cops_gperror_vals[] = {
351 {2, "AvailMemExhausted" },
352 {3, "unknownASN.1Tag" },
353 {4, "maxMsgSizeExceeded" },
354 {5, "unknownError" },
355 {6, "maxRequestStatesOpen" },
356 {7, "invalidASN.1Length" },
357 {8, "invalidObjectPad" },
358 {9, "unknownPIBData" },
359 {10, "unknownCOPSPRObject" },
360 {11, "malformedDecision" },
364 /* Error-Code from CPERR object */
365 static const value_string cops_cperror_vals[] = {
366 {1, "priSpaceExhausted" },
367 {2, "priInstanceInvalid" },
368 {3, "attrValueInvalid" },
369 {4, "attrValueSupLimited" },
370 {5, "attrEnumSupLimited" },
371 {6, "attrMaxLengthExceeded" },
372 {7, "attrReferenceUnknown" },
373 {8, "priNotifyOnly" },
375 {10, "tooFewAttrs" },
376 {11, "invalidAttrType" },
377 {12, "deletedInRef" },
378 {13, "priSpecificError" },
383 /* Report-Type from Report-Type object */
384 static const value_string cops_report_type_vals[] = {
385 {1, " Success : Decision was successful at the PEP" },
386 {2, " Failure : Decision could not be completed by PEP" },
387 {3, " Accounting: Accounting update for an installed state" },
391 /* The next tables are for PacketCable */
393 /* Transaction ID table */
394 static const value_string table_cops_transaction_id[] =
396 { 0x1, "Gate Alloc" },
397 { 0x2, "Gate Alloc Ack" },
398 { 0x3, "Gate Alloc Err" },
400 { 0x5, "Gate Set Ack" },
401 { 0x6, "Gate Set Err" },
402 { 0x7, "Gate Info" },
403 { 0x8, "Gate Info Ack" },
404 { 0x9, "Gate Info Err" },
405 { 0xa, "Gate Delete" },
406 { 0xb, "Gate Delete Ack" },
407 { 0xc, "Gate Delete Err" },
408 { 0xd, "Gate Open" },
409 { 0xe, "Gate Close" },
414 static const value_string table_cops_direction[] =
416 { 0x0, "Downstream gate" },
417 { 0x1, "Upstream gate" },
422 static const value_string table_cops_session_class[] =
424 { 0x0, "Unspecified" },
425 { 0x1, "Normal priority VoIP session" },
426 { 0x2, "High priority VoIP session" },
432 static const value_string table_cops_reason_code[] =
434 { 0x0, "Gate Delete Operation" },
435 { 0x1, "Gate Close Operation" },
439 /* Reason Sub Code - Delete */
440 static const value_string table_cops_reason_subcode_delete[] =
442 { 0x0, "Normal Operation" },
443 { 0x1, "Local Gate-coordination not completed" },
444 { 0x2, "Remote Gate-coordination not completed" },
445 { 0x3, "Authorization revoked" },
446 { 0x4, "Unexpected Gate-Open" },
447 { 0x5, "Local Gate-Close failure" },
448 { 0x127,"Unspecified error" },
452 /* Reason Sub Code - Close */
453 static const value_string table_cops_reason_subcode_close[] =
455 { 0x0, "Client initiated release (normal operation)" },
456 { 0x1, "Reservation reassignment" },
457 { 0x2, "Lack of reservation maintenance" },
458 { 0x3, "Lack of Docsis Mac-layer responses" },
459 { 0x4, "Timer T0 expiration; no Gate-Set received from CMS" },
460 { 0x5, "Timer T1 expiration; no Commit received from MTA" },
461 { 0x6, "Timer T7 expiration; Service Flow reservation timeout" },
462 { 0x7, "Timer T8 expiration; Service Flow inactivity in the upstream direction" },
463 { 0x127,"Unspecified error" },
467 /* PacketCable Error */
468 static const value_string table_cops_packetcable_error[] =
470 { 0x1, "No gates urrently available" },
471 { 0x2, "Unknown Gate ID" },
472 { 0x3, "Illegal Session Class value" },
473 { 0x4, "Subscriber exceeded gate limit" },
474 { 0x5, "Gate already set" },
475 { 0x6, "Missing Required Object" },
476 { 0x7, "Invalid Object" },
477 { 0x127,"Unspecified error" },
481 /* End of PacketCable Tables */
484 /* Initialize the protocol and registered fields */
485 static gint proto_cops = -1;
486 static gint hf_cops_ver_flags = -1;
487 static gint hf_cops_version = -1;
488 static gint hf_cops_flags = -1;
490 static gint hf_cops_op_code = -1;
491 static gint hf_cops_client_type = -1;
492 static gint hf_cops_msg_len = -1;
494 static gint hf_cops_obj_len = -1;
495 static gint hf_cops_obj_c_num = -1;
496 static gint hf_cops_obj_c_type = -1;
498 static gint hf_cops_obj_s_num = -1;
499 static gint hf_cops_obj_s_type = -1;
501 static gint hf_cops_r_type_flags = -1;
502 static gint hf_cops_m_type_flags = -1;
504 static gint hf_cops_in_int_ipv4 = -1;
505 static gint hf_cops_in_int_ipv6 = -1;
506 static gint hf_cops_out_int_ipv4 = -1;
507 static gint hf_cops_out_int_ipv6 = -1;
508 static gint hf_cops_int_ifindex = -1;
510 static gint hf_cops_reason = -1;
511 static gint hf_cops_reason_sub = -1;
513 static gint hf_cops_dec_cmd_code = -1;
514 static gint hf_cops_dec_flags = -1;
516 static gint hf_cops_error = -1;
517 static gint hf_cops_error_sub = -1;
519 static gint hf_cops_gperror = -1;
520 static gint hf_cops_gperror_sub = -1;
522 static gint hf_cops_cperror = -1;
523 static gint hf_cops_cperror_sub = -1;
525 static gint hf_cops_katimer = -1;
527 static gint hf_cops_pepid = -1;
529 static gint hf_cops_report_type = -1;
531 static gint hf_cops_pdprediraddr_ipv4 = -1;
532 static gint hf_cops_pdprediraddr_ipv6 = -1;
533 static gint hf_cops_lastpdpaddr_ipv4 = -1;
534 static gint hf_cops_lastpdpaddr_ipv6 = -1;
535 static gint hf_cops_pdp_tcp_port = -1;
537 static gint hf_cops_accttimer = -1;
539 static gint hf_cops_key_id = -1;
540 static gint hf_cops_seq_num = -1;
542 /* For PacketCable */
543 static gint hf_cops_subtree = -1;
544 static gint hf_cops_pc_activity_count = -1;
545 static gint hf_cops_pc_algorithm = -1;
546 static gint hf_cops_pc_close_subcode = -1;
547 static gint hf_cops_pc_cmts_ip = -1;
548 static gint hf_cops_pc_cmts_ip_port = -1;
549 static gint hf_cops_pc_prks_ip = -1;
550 static gint hf_cops_pc_prks_ip_port = -1;
551 static gint hf_cops_pc_srks_ip = -1;
552 static gint hf_cops_pc_srks_ip_port = -1;
553 static gint hf_cops_pc_delete_subcode = -1;
554 static gint hf_cops_pc_dest_ip = -1;
555 static gint hf_cops_pc_dest_port = -1;
556 static gint hf_cops_pc_direction = -1;
557 static gint hf_cops_pc_ds_field = -1;
558 static gint hf_cops_pc_gate_id = -1;
559 static gint hf_cops_pc_gate_spec_flags = -1;
560 static gint hf_cops_pc_gate_command_type = -1;
561 static gint hf_cops_pc_key = -1;
562 static gint hf_cops_pc_max_packet_size = -1;
563 static gint hf_cops_pc_min_policed_unit = -1;
564 static gint hf_cops_pc_packetcable_err_code = -1;
565 static gint hf_cops_pc_packetcable_sub_code = -1;
566 static gint hf_cops_pc_peak_data_rate = -1;
567 static gint hf_cops_pc_protocol_id = -1;
568 static gint hf_cops_pc_reason_code = -1;
569 static gint hf_cops_pc_remote_flags = -1;
570 static gint hf_cops_pc_remote_gate_id = -1;
571 static gint hf_cops_pc_reserved = -1;
572 static gint hf_cops_pc_session_class = -1;
573 static gint hf_cops_pc_slack_term = -1;
574 static gint hf_cops_pc_spec_rate = -1;
575 static gint hf_cops_pc_src_ip = -1;
576 static gint hf_cops_pc_src_port = -1;
577 static gint hf_cops_pc_subscriber_id = -1;
578 static gint hf_cops_pc_t1_value = -1;
579 static gint hf_cops_pc_t7_value = -1;
580 static gint hf_cops_pc_t8_value = -1;
581 static gint hf_cops_pc_token_bucket_rate = -1;
582 static gint hf_cops_pc_token_bucket_size = -1;
583 static gint hf_cops_pc_transaction_id = -1;
584 static gint hf_cops_pc_bcid_ts = -1;
585 static gint hf_cops_pc_bcid = -1;
586 static gint hf_cops_pc_bcid_ev = -1;
587 static gint hf_cops_pc_dfcdc_ip = -1;
588 static gint hf_cops_pc_dfccc_ip = -1;
589 static gint hf_cops_pc_dfcdc_ip_port = -1;
590 static gint hf_cops_pc_dfccc_ip_port = -1;
592 /* Initialize the subtree pointers */
593 static gint ett_cops = -1;
594 static gint ett_cops_ver_flags = -1;
595 static gint ett_cops_obj = -1;
596 static gint ett_cops_pr_obj = -1;
597 static gint ett_cops_obj_data = -1;
598 static gint ett_cops_r_type_flags = -1;
599 static gint ett_cops_itf = -1;
600 static gint ett_cops_reason = -1;
601 static gint ett_cops_decision = -1;
602 static gint ett_cops_error = -1;
603 static gint ett_cops_clientsi = -1;
604 static gint ett_cops_asn1 = -1;
605 static gint ett_cops_gperror = -1;
606 static gint ett_cops_cperror = -1;
607 static gint ett_cops_pdp = -1;
609 /* For PacketCable */
610 static gint ett_cops_subtree = -1;
612 void proto_reg_handoff_cops(void);
614 static guint get_cops_pdu_len(tvbuff_t *tvb, int offset);
615 static void dissect_cops_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
617 static int dissect_cops_object(tvbuff_t *tvb, guint32 offset, proto_tree *tree);
618 static void dissect_cops_object_data(tvbuff_t *tvb, guint32 offset, proto_tree *tree,
619 guint8 c_num, guint8 c_type, guint16 len);
621 static void dissect_cops_pr_objects(tvbuff_t *tvb, guint32 offset, proto_tree *tree, guint16 pr_len);
622 static int dissect_cops_pr_object_data(tvbuff_t *tvb, guint32 offset, proto_tree *tree,
623 guint8 s_num, guint8 s_type, guint16 len);
625 /* Added for PacketCable */
626 proto_tree *info_to_cops_subtree(tvbuff_t *, proto_tree *, int, int, char *);
627 void info_to_display(tvbuff_t *, proto_item *, int, int, char *, const value_string *, int, gint *);
628 void cops_transaction_id(tvbuff_t *, proto_tree *, guint, guint32);
629 void cops_subscriber_id_v4(tvbuff_t *, proto_tree *, guint, guint32);
630 void cops_gate_id(tvbuff_t *, proto_tree *, guint, guint32);
631 void cops_activity_count(tvbuff_t *, proto_tree *, guint, guint32);
632 void cops_gate_specs(tvbuff_t *, proto_tree *, guint, guint32);
633 void cops_remote_gate_info(tvbuff_t *, proto_tree *, guint, guint32);
634 void cops_packetcable_reason(tvbuff_t *, proto_tree *, guint, guint32);
635 void cops_packetcable_error(tvbuff_t *, proto_tree *, guint, guint32);
636 void cops_analyze_packetcable_obj(tvbuff_t *, proto_tree *, guint32);
637 void cops_event_generation_info(tvbuff_t *, proto_tree *, guint, guint32);
638 void cops_surveillance_parameters(tvbuff_t *, proto_tree *, guint, guint32);
640 static packet_info *cpinfo;
641 static guint8 opcode_idx;
642 static gboolean cops_packetcable = TRUE;
643 /* End of addition for PacketCable */
646 /* Code to actually dissect the packets */
648 dissect_cops(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
650 tcp_dissect_pdus(tvb, pinfo, tree, cops_desegment, 8,
651 get_cops_pdu_len, dissect_cops_pdu);
655 get_cops_pdu_len(tvbuff_t *tvb, int offset)
658 * Get the length of the COPS message.
660 return tvb_get_ntohl(tvb, offset + 4);
664 dissect_cops_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
669 if (check_col(pinfo->cinfo, COL_PROTOCOL))
670 col_set_str(pinfo->cinfo, COL_PROTOCOL, "COPS");
671 if (check_col(pinfo->cinfo, COL_INFO))
672 col_clear(pinfo->cinfo, COL_INFO);
674 op_code = tvb_get_guint8(tvb, 1);
675 if (check_col(pinfo->cinfo, COL_INFO))
676 col_add_fstr(pinfo->cinfo, COL_INFO, "COPS %s",
677 val_to_str(op_code, cops_op_code_vals, "Unknown Op Code"));
679 /* PacketCable: Remember the next two values to manipulate the info field in the Gui */
681 opcode_idx = op_code;
685 proto_tree *cops_tree, *ver_flags_tree;
691 ti = proto_tree_add_item(tree, proto_cops, tvb, offset, -1, FALSE);
692 cops_tree = proto_item_add_subtree(ti, ett_cops);
694 /* Version and flags share the same byte, put them in a subtree */
695 ver_flags = tvb_get_guint8(tvb, offset);
696 tv = proto_tree_add_uint_format(cops_tree, hf_cops_ver_flags, tvb, offset, 1,
697 ver_flags, "Version: %u, Flags: %s",
698 hi_nibble(ver_flags),
699 val_to_str(lo_nibble(ver_flags), cops_flags_vals, "Unknown"));
700 ver_flags_tree = proto_item_add_subtree(tv, ett_cops_ver_flags);
701 proto_tree_add_uint(ver_flags_tree, hf_cops_version, tvb, offset, 1, ver_flags);
702 proto_tree_add_uint(ver_flags_tree, hf_cops_flags, tvb, offset, 1, ver_flags);
705 proto_tree_add_item(cops_tree, hf_cops_op_code, tvb, offset, 1, FALSE);
707 proto_tree_add_item(cops_tree, hf_cops_client_type, tvb, offset, 2, FALSE);
710 msg_len = tvb_get_ntohl(tvb, offset);
711 proto_tree_add_uint(cops_tree, hf_cops_msg_len, tvb, offset, 4, msg_len);
714 while (tvb_reported_length_remaining(tvb, offset) >= COPS_OBJECT_HDR_SIZE) {
715 object_len = dissect_cops_object(tvb, offset, cops_tree);
718 offset += object_len;
721 garbage = tvb_length_remaining(tvb, offset);
723 proto_tree_add_text(cops_tree, tvb, offset, garbage,
724 "Trailing garbage: %d byte%s", garbage,
725 plurality(garbage, "", "s"));
729 static char *cops_c_type_to_str(guint8 c_num, guint8 c_type)
732 case COPS_OBJ_HANDLE:
734 return "Client Handle";
736 case COPS_OBJ_IN_INT:
737 case COPS_OBJ_OUT_INT:
739 return "IPv4 Address + Interface";
740 else if (c_type == 2)
741 return "IPv6 Address + Interface";
743 case COPS_OBJ_DECISION:
744 case COPS_OBJ_LPDPDECISION:
746 return "Decision Flags (Mandatory)";
747 else if (c_type == 2)
748 return "Stateless Data";
749 else if (c_type == 3)
750 return "Replacement Data";
751 else if (c_type == 4)
752 return "Client Specific Decision Data";
753 else if (c_type == 5)
754 return "Named Decision Data";
756 case COPS_OBJ_CLIENTSI:
758 return "Signaled ClientSI";
759 else if (c_type == 2)
760 return "Named ClientSI";
762 case COPS_OBJ_KATIMER:
764 return "Keep-alive timer value";
766 case COPS_OBJ_PDPREDIRADDR:
767 case COPS_OBJ_LASTPDPADDR:
769 return "IPv4 Address + TCP Port";
770 else if (c_type == 2)
771 return "IPv6 Address + TCP Port";
773 case COPS_OBJ_ACCTTIMER:
775 return "Accounting timer value";
777 case COPS_OBJ_INTEGRITY:
779 return "HMAC digest";
786 static int dissect_cops_object(tvbuff_t *tvb, guint32 offset, proto_tree *tree)
788 guint16 object_len, contents_len;
789 guint8 c_num, c_type;
791 proto_tree *obj_tree;
794 object_len = tvb_get_ntohs(tvb, offset);
795 if (object_len < COPS_OBJECT_HDR_SIZE) {
797 proto_tree_add_text(tree, tvb, offset, 2,
798 "Bad COPS object length: %u, should be at least %u",
799 object_len, COPS_OBJECT_HDR_SIZE);
802 c_num = tvb_get_guint8(tvb, offset + 2);
803 c_type = tvb_get_guint8(tvb, offset + 3);
805 ti = proto_tree_add_uint_format(tree, hf_cops_obj_c_num, tvb, offset, object_len, c_num,
806 "%s: %s", val_to_str(c_num, cops_c_num_vals, "Unknown"),
807 cops_c_type_to_str(c_num, c_type));
808 obj_tree = proto_item_add_subtree(ti, ett_cops_obj);
810 proto_tree_add_uint(obj_tree, hf_cops_obj_len, tvb, offset, 2, object_len);
813 proto_tree_add_uint(obj_tree, hf_cops_obj_c_num, tvb, offset, 1, c_num);
816 type_str = cops_c_type_to_str(c_num, c_type);
817 proto_tree_add_text(obj_tree, tvb, offset, 1, "C-Type: %s%s%u%s",
819 strlen(type_str) ? " (" : "",
821 strlen(type_str) ? ")" : "");
824 contents_len = object_len - COPS_OBJECT_HDR_SIZE;
825 dissect_cops_object_data(tvb, offset, obj_tree, c_num, c_type, contents_len);
827 /* Pad to 32bit boundary */
828 if (object_len % sizeof (guint32))
829 object_len += (sizeof (guint32) - object_len % sizeof (guint32));
834 static void dissect_cops_pr_objects(tvbuff_t *tvb, guint32 offset, proto_tree *tree, guint16 pr_len)
836 guint16 object_len, contents_len;
837 guint8 s_num, s_type;
840 proto_tree *cops_pr_tree, *obj_tree;
843 cops_pr_tree = proto_item_add_subtree(tree, ett_cops_pr_obj);
845 while (pr_len >= COPS_OBJECT_HDR_SIZE) {
846 object_len = tvb_get_ntohs(tvb, offset);
847 if (object_len < COPS_OBJECT_HDR_SIZE) {
849 proto_tree_add_text(tree, tvb, offset, 2,
850 "Bad COPS PR object length: %u, should be at least %u",
851 object_len, COPS_OBJECT_HDR_SIZE);
854 s_num = tvb_get_guint8(tvb, offset + 2);
856 ti = proto_tree_add_uint_format(cops_pr_tree, hf_cops_obj_s_num, tvb, offset, object_len, s_num,
857 "%s", val_to_str(s_num, cops_s_num_vals, "Unknown"));
858 obj_tree = proto_item_add_subtree(cops_pr_tree, ett_cops_pr_obj);
860 proto_tree_add_uint(obj_tree, hf_cops_obj_len, tvb, offset, 2, object_len);
864 proto_tree_add_uint(obj_tree, hf_cops_obj_s_num, tvb, offset, 1, s_num);
868 s_type = tvb_get_guint8(tvb, offset);
869 type_str = val_to_str(s_type, cops_s_type_vals, "Unknown");
870 proto_tree_add_text(obj_tree, tvb, offset, 1, "S-Type: %s%s%u%s",
872 strlen(type_str) ? " (" : "",
874 strlen(type_str) ? ")" : "");
878 contents_len = object_len - COPS_OBJECT_HDR_SIZE;
879 ret = dissect_cops_pr_object_data(tvb, offset, obj_tree, s_num, s_type, contents_len);
883 /*Pad to 32bit boundary */
884 if (object_len % sizeof (guint32))
885 object_len += (sizeof (guint32) - object_len % sizeof (guint32));
887 pr_len -= object_len - COPS_OBJECT_HDR_SIZE;
888 offset += object_len - COPS_OBJECT_HDR_SIZE;
892 static void dissect_cops_object_data(tvbuff_t *tvb, guint32 offset, proto_tree *tree,
893 guint8 c_num, guint8 c_type, guint16 len)
896 proto_tree *r_type_tree, *itf_tree, *reason_tree, *dec_tree, *error_tree, *clientsi_tree, *pdp_tree;
897 guint16 r_type, m_type, reason, reason_sub, cmd_code, cmd_flags, error, error_sub, tcp_port;
898 guint32 ipv4addr, ifindex;
899 struct e_in6_addr ipv6addr;
902 case COPS_OBJ_CONTEXT:
903 r_type = tvb_get_ntohs(tvb, offset);
904 m_type = tvb_get_ntohs(tvb, offset + 2);
905 ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: R-Type: %s, M-Type: %u",
906 val_to_str(r_type, cops_r_type_vals, "Unknown"),
909 r_type_tree = proto_item_add_subtree(ti, ett_cops_r_type_flags);
910 proto_tree_add_uint(r_type_tree, hf_cops_r_type_flags, tvb, offset, 2, r_type);
912 proto_tree_add_uint(r_type_tree, hf_cops_m_type_flags, tvb, offset, 2, m_type);
915 case COPS_OBJ_IN_INT:
916 case COPS_OBJ_OUT_INT:
917 if (c_type == 1) { /* IPv4 */
918 tvb_memcpy(tvb, (guint8 *)&ipv4addr, offset, 4);
919 ifindex = tvb_get_ntohl(tvb, offset + 4);
920 ti = proto_tree_add_text(tree, tvb, offset, 8, "Contents: IPv4 address %s, ifIndex: %u",
921 ip_to_str((guint8 *)&ipv4addr), ifindex);
922 itf_tree = proto_item_add_subtree(ti, ett_cops_itf);
923 proto_tree_add_ipv4(itf_tree,
924 (c_num == COPS_OBJ_IN_INT) ? hf_cops_in_int_ipv4 : hf_cops_out_int_ipv4,
925 tvb, offset, 4, ipv4addr);
927 } else if (c_type == 2) { /* IPv6 */
928 tvb_memcpy(tvb, (guint8 *)&ipv6addr, offset, sizeof ipv6addr);
929 ifindex = tvb_get_ntohl(tvb, offset + sizeof ipv6addr);
930 ti = proto_tree_add_text(tree, tvb, offset, 20, "Contents: IPv6 address %s, ifIndex: %u",
931 ip6_to_str(&ipv6addr), ifindex);
932 itf_tree = proto_item_add_subtree(ti, ett_cops_itf);
933 proto_tree_add_ipv6(itf_tree,
934 (c_num == COPS_OBJ_IN_INT) ? hf_cops_in_int_ipv6 : hf_cops_out_int_ipv6,
935 tvb, offset, 16, (guint8 *)&ipv6addr);
940 proto_tree_add_uint(itf_tree, hf_cops_int_ifindex, tvb, offset, 4, ifindex);
943 case COPS_OBJ_REASON:
944 reason = tvb_get_ntohs(tvb, offset);
945 reason_sub = tvb_get_ntohs(tvb, offset + 2);
946 ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Reason-Code: %s, Reason Sub-code: 0x%04x",
947 val_to_str(reason, cops_reason_vals, "<Unknown value>"), reason_sub);
948 reason_tree = proto_item_add_subtree(ti, ett_cops_reason);
949 proto_tree_add_uint(reason_tree, hf_cops_reason, tvb, offset, 2, reason);
952 proto_tree_add_text(reason_tree, tvb, offset, 2, "Reason Sub-code: "
953 "Unknown object's C-Num %u, C-Type %u",
954 tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset + 1));
956 proto_tree_add_uint(reason_tree, hf_cops_reason_sub, tvb, offset, 2, reason_sub);
959 case COPS_OBJ_DECISION:
960 case COPS_OBJ_LPDPDECISION:
962 cmd_code = tvb_get_ntohs(tvb, offset);
963 cmd_flags = tvb_get_ntohs(tvb, offset + 2);
964 ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Command-Code: %s, Flags: %s",
965 val_to_str(cmd_code, cops_dec_cmd_code_vals, "<Unknown value>"),
966 val_to_str(cmd_flags, cops_dec_cmd_flag_vals, "<Unknown flag>"));
967 dec_tree = proto_item_add_subtree(ti, ett_cops_decision);
968 proto_tree_add_uint(dec_tree, hf_cops_dec_cmd_code, tvb, offset, 2, cmd_code);
970 proto_tree_add_uint(dec_tree, hf_cops_dec_flags, tvb, offset, 2, cmd_flags);
971 } else if (c_type == 5) { /*COPS-PR Data*/
972 ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: %u bytes", len);
973 dec_tree = proto_item_add_subtree(ti, ett_cops_decision);
974 dissect_cops_pr_objects(tvb, offset, dec_tree, len);
977 /* PacketCable : Analyze the remaining data if available */
978 cops_analyze_packetcable_obj(tvb, tree, offset);
985 error = tvb_get_ntohs(tvb, offset);
986 error_sub = tvb_get_ntohs(tvb, offset + 2);
987 ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Error-Code: %s, Error Sub-code: 0x%04x",
988 val_to_str(error, cops_error_vals, "<Unknown value>"), error_sub);
989 error_tree = proto_item_add_subtree(ti, ett_cops_error);
990 proto_tree_add_uint(error_tree, hf_cops_error, tvb, offset, 2, error);
993 proto_tree_add_text(error_tree, tvb, offset, 2, "Error Sub-code: "
994 "Unknown object's C-Num %u, C-Type %u",
995 tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset + 1));
997 proto_tree_add_uint(error_tree, hf_cops_error_sub, tvb, offset, 2, error_sub);
1000 case COPS_OBJ_CLIENTSI:
1002 /* For PacketCable */
1004 cops_analyze_packetcable_obj(tvb, tree, offset);
1008 if (c_type != 2) /*Not COPS-PR data*/
1011 ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: %u bytes", len);
1012 clientsi_tree = proto_item_add_subtree(ti, ett_cops_clientsi);
1014 dissect_cops_pr_objects(tvb, offset, clientsi_tree, len);
1017 case COPS_OBJ_KATIMER:
1021 proto_tree_add_item(tree, hf_cops_katimer, tvb, offset + 2, 2, FALSE);
1022 if (tvb_get_ntohs(tvb, offset + 2) == 0)
1023 proto_tree_add_text(tree, tvb, offset, 0, "Value of zero implies infinity.");
1026 case COPS_OBJ_PEPID:
1030 if (tvb_strnlen(tvb, offset, len) == -1)
1031 proto_tree_add_text(tree, tvb, offset, len, "<PEP Id is not a NUL terminated ASCII string>");
1033 proto_tree_add_item(tree, hf_cops_pepid, tvb, offset,
1034 tvb_strnlen(tvb, offset, len) + 1, FALSE);
1037 case COPS_OBJ_REPORT_TYPE:
1041 proto_tree_add_item(tree, hf_cops_report_type, tvb, offset, 2, FALSE);
1044 case COPS_OBJ_PDPREDIRADDR:
1045 case COPS_OBJ_LASTPDPADDR:
1046 if (c_type == 1) { /* IPv4 */
1047 tvb_memcpy(tvb, (guint8 *)&ipv4addr, offset, 4);
1048 tcp_port = tvb_get_ntohs(tvb, offset + 4 + 2);
1049 ti = proto_tree_add_text(tree, tvb, offset, 8, "Contents: IPv4 address %s, TCP Port Number: %u",
1050 ip_to_str((guint8 *)&ipv4addr), tcp_port);
1051 pdp_tree = proto_item_add_subtree(ti, ett_cops_pdp);
1052 proto_tree_add_ipv4(pdp_tree,
1053 (c_num == COPS_OBJ_PDPREDIRADDR) ? hf_cops_pdprediraddr_ipv4 : hf_cops_lastpdpaddr_ipv4,
1054 tvb, offset, 4, ipv4addr);
1056 } else if (c_type == 2) { /* IPv6 */
1057 tvb_memcpy(tvb, (guint8 *)&ipv6addr, offset, sizeof ipv6addr);
1058 tcp_port = tvb_get_ntohs(tvb, offset + sizeof ipv6addr + 2);
1059 ti = proto_tree_add_text(tree, tvb, offset, 20, "Contents: IPv6 address %s, TCP Port Number: %u",
1060 ip6_to_str(&ipv6addr), tcp_port);
1061 pdp_tree = proto_item_add_subtree(ti, ett_cops_pdp);
1062 proto_tree_add_ipv6(pdp_tree,
1063 (c_num == COPS_OBJ_PDPREDIRADDR) ? hf_cops_pdprediraddr_ipv6 : hf_cops_lastpdpaddr_ipv6,
1064 tvb, offset, 16, (guint8 *)&ipv6addr);
1070 proto_tree_add_uint(pdp_tree, hf_cops_pdp_tcp_port, tvb, offset, 2, tcp_port);
1073 case COPS_OBJ_ACCTTIMER:
1077 proto_tree_add_item(tree, hf_cops_accttimer, tvb, offset + 2, 2, FALSE);
1078 if (tvb_get_ntohs(tvb, offset + 2) == 0)
1079 proto_tree_add_text(tree, tvb, offset, 0, "Value of zero means "
1080 "there SHOULD be no unsolicited accounting updates.");
1083 case COPS_OBJ_INTEGRITY:
1085 break; /* Not HMAC digest */
1087 proto_tree_add_item(tree, hf_cops_key_id, tvb, offset, 4, FALSE);
1088 proto_tree_add_item(tree, hf_cops_seq_num, tvb, offset + 4, 4, FALSE);
1089 proto_tree_add_text(tree, tvb, offset + 8 , len - 8, "Contents: Keyed Message Digest");
1093 proto_tree_add_text(tree, tvb, offset, len, "Contents: %u bytes", len);
1099 #ifdef HAVE_NET_SNMP
1100 static guchar*format_asn_value (struct variable_list *variable, subid_t *variable_oid,
1101 guint variable_oid_length, u_char type_from_packet)
1103 struct tree *subtree=tree_head;
1109 /*Get the ASN.1 type etc. from the PIB-MIB. If unsuccessful use the type from packet*/
1110 subtree = get_tree(variable_oid,variable_oid_length, subtree);
1112 if (subtree->type == 0)
1113 variable->type= type_from_packet;
1115 buf_len = SPRINT_MAX_LEN; /*defined in NET-SNMP's snmp-impl.h*/
1116 buf = g_malloc(buf_len);
1120 /*If the ASN.1 type was found from PIB-MIB, use it for decoding*/
1121 if (!variable->type)
1122 variable->type=mib_to_asn_type(subtree->type);
1124 if (!sprint_realloc_by_type(&buf, &buf_len, &out_len, TRUE, variable, subtree->enums, subtree->hint, NULL))
1125 sprintf(buf,"%s","sprint_realloc_by_type failed");
1129 #endif /* HAVE_NET_SNMP */
1131 static int decode_cops_pr_asn1_data(tvbuff_t *tvb, guint32 offset,
1132 proto_tree *tree, guint asnlen, guint8 cops_pr_obj
1133 #ifndef HAVE_NET_SNMP
1145 gchar *vb_type_name;
1148 guint cls, con, tag;
1149 subid_t epd_attribute_index=0;
1151 gint32 vb_integer_value;
1152 guint32 vb_uinteger_value;
1154 guint8 *vb_octet_string;
1157 guint vb_oid_length;
1159 gchar *vb_display_string;
1160 gchar *vb_display_string2;
1162 #ifdef HAVE_NET_SNMP
1163 struct variable_list variable;
1165 #endif /* HAVE_NET_SNMP */
1171 while (asnlen > 0) { /*while there is ASN stuff to be decoded*/
1173 epd_attribute_index++;
1174 #ifdef HAVE_NET_SNMP
1175 last_decoded_prid_oid[last_decoded_prid_oid_length-1]=epd_attribute_index;
1176 #endif /* HAVE_NET_SNMP */
1177 asn1_open(&asn1, tvb, offset);
1179 /* parse the type of the object */
1181 start = asn1.offset;
1183 ret = asn1_header_decode (&asn1, &cls, &con, &tag, &def, &vb_length);
1184 if (ret != ASN1_ERR_NOERROR)
1187 return ASN1_ERR_LENGTH_NOT_DEFINITE;
1189 /* Convert the class, constructed flag, and tag to a type. */
1190 vb_type_name = cops_tag_cls2syntax(tag, cls, &vb_type);
1191 if (vb_type_name == NULL) {
1194 * Dissect the value as an opaque string of octets.
1196 vb_type_name = "unsupported type";
1197 vb_type = COPS_OPAQUE;
1200 /* parse the value */
1205 ret = asn1_int32_value_decode(&asn1, vb_length, &vb_integer_value);
1206 if (ret != ASN1_ERR_NOERROR)
1208 length = asn1.offset - start;
1210 #ifdef HAVE_NET_SNMP
1211 if (cops_typefrommib == TRUE)
1214 value = vb_integer_value;
1215 variable.val.integer = &value;
1216 variable.val_len = vb_length ;
1217 vb_display_string=format_asn_value(&variable,
1218 last_decoded_prid_oid,last_decoded_prid_oid_length,ASN_INTEGER);
1220 proto_tree_add_text(tree, asn1.tvb, offset, length,
1221 "Value: %s", vb_display_string);
1222 g_free(vb_display_string);
1225 #endif /* HAVE_NET_SNMP */
1226 proto_tree_add_text(tree, asn1.tvb, offset, length,
1227 "Value: %s: %d (%#x)", vb_type_name,
1228 vb_integer_value, vb_integer_value);
1232 case COPS_UNSIGNED32:
1233 case COPS_TIMETICKS:
1234 ret = asn1_uint32_value_decode(&asn1, vb_length, &vb_uinteger_value);
1235 if (ret != ASN1_ERR_NOERROR)
1237 length = asn1.offset - start;
1239 #ifdef HAVE_NET_SNMP
1240 if (cops_typefrommib == TRUE)
1243 value = vb_uinteger_value;
1244 variable.val.integer = &value;
1245 variable.val_len = vb_length;
1247 vb_display_string=format_asn_value(&variable,
1248 last_decoded_prid_oid,last_decoded_prid_oid_length,ASN_UINTEGER);
1250 proto_tree_add_text(tree, asn1.tvb, offset, length, "Value %s: %s",vb_type_name, vb_display_string);
1252 g_free(vb_display_string);
1255 #endif /* HAVE_NET_SNMP */
1256 proto_tree_add_text(tree, asn1.tvb, offset, length,
1257 "Value: %s: %u (%#x)", vb_type_name,
1258 vb_uinteger_value, vb_uinteger_value);
1265 case COPS_UNSIGNED64:
1266 case COPS_INTEGER64:
1267 ret = asn1_string_value_decode (&asn1, vb_length, &vb_octet_string);
1268 if (ret != ASN1_ERR_NOERROR)
1270 length = asn1.offset - start;
1272 #ifdef HAVE_NET_SNMP
1273 if (cops_typefrommib == TRUE)
1276 variable.val.string = vb_octet_string;
1277 variable.val_len = vb_length;
1278 vb_display_string = format_asn_value(&variable,
1279 last_decoded_prid_oid,last_decoded_prid_oid_length,ASN_OCTET_STR);
1280 proto_tree_add_text(tree, asn1.tvb, offset, length,
1281 "Value: %s (ASN.1 type from packet: %s)", vb_display_string, vb_type_name);
1283 g_free(vb_display_string);
1287 #endif /* HAVE_NET_SNMP */
1288 for (i = 0; i < vb_length; i++) {
1289 if (!(isprint(vb_octet_string[i]) ||isspace(vb_octet_string[i])))
1294 * If some characters are not printable, display the string as bytes.
1296 if (i < vb_length) {
1298 * We stopped, due to a non-printable character, before we got
1299 * to the end of the string.
1301 vb_display_string = g_malloc(4*vb_length);
1302 buf = &vb_display_string[0];
1303 len = sprintf(buf, "%03u", vb_octet_string[0]);
1305 for (i = 1; i < vb_length; i++) {
1306 len = sprintf(buf, ".%03u", vb_octet_string[i]);
1309 proto_tree_add_text(tree, asn1.tvb, offset, length,
1310 "Value: %s: %s", vb_type_name, vb_display_string);
1311 g_free(vb_display_string);
1313 proto_tree_add_text(tree, asn1.tvb, offset, length,
1314 "Value: %s: %.*s", vb_type_name, (int)vb_length,
1315 SAFE_STRING(vb_octet_string));
1317 #ifdef HAVE_NET_SNMP
1319 #endif /* HAVE_NET_SNMP */
1321 g_free(vb_octet_string);
1325 ret = asn1_null_decode (&asn1, vb_length);
1326 if (ret != ASN1_ERR_NOERROR)
1328 length = asn1.offset - start;
1330 proto_tree_add_text(tree, asn1.tvb, offset, length, "Value: %s", vb_type_name);
1334 ret = asn1_oid_value_decode (&asn1, vb_length, &vb_oid, &vb_oid_length);
1335 if (ret != ASN1_ERR_NOERROR)
1337 length = asn1.offset - start;
1340 if (cops_pr_obj == COPS_OBJ_PPRID){
1341 /*we're decoding Prefix PRID, that doesn't have a instance Id,
1342 *Use full length of the OID when decoding it.
1344 new_format_oid(vb_oid,vb_oid_length,&vb_display_string,&vb_display_string2);
1346 if (!vb_display_string2) /*if OID couldn't be decoded, print only numeric format*/
1347 proto_tree_add_text(tree, asn1.tvb, offset, length,
1348 "Value: %s: %s", vb_type_name, vb_display_string);
1350 proto_tree_add_text(tree, asn1.tvb, offset, length,
1351 "Value: %s: %s (%s)", vb_type_name,
1353 vb_display_string2);
1355 else { /*we're decoding PRID, Error PRID or EPD*/
1356 /*strip the instance Id from the OIDs before decoding and paste it back during printing*/
1357 new_format_oid(vb_oid,vb_oid_length-1,&vb_display_string,&vb_display_string2);
1359 if (!vb_display_string2) /*if OID couldn't be decoded, print only numeric format*/
1360 proto_tree_add_text(tree, asn1.tvb, offset, length,
1361 "Value: %s: %s.%lu", vb_type_name,
1363 (unsigned long)vb_oid[vb_oid_length-1]);
1365 proto_tree_add_text(tree, asn1.tvb, offset, length,
1366 "Value: %s: %s.%lu (%s.%lu)", vb_type_name,
1368 (unsigned long)vb_oid[vb_oid_length-1],
1370 (unsigned long)vb_oid[vb_oid_length-1]);
1372 #ifdef HAVE_NET_SNMP
1373 if (cops_pr_obj != COPS_OBJ_EPD) {
1374 /* we're not decoding EPD, so let's store the OID of the PRID so that later
1375 when we're decoding this PRID's EPD we can finetune the output.*/
1376 memcpy(last_decoded_prid_oid,vb_oid,vb_oid_length*sizeof(subid_t));
1377 last_decoded_prid_oid_length=vb_oid_length;
1379 #endif /* HAVE_NET_SNMP */
1381 g_free(vb_display_string);
1382 if(vb_display_string2)
1383 g_free(vb_display_string2);
1389 g_assert_not_reached();
1390 return ASN1_ERR_WRONG_TYPE;
1393 asn1_close(&asn1,&offset);
1397 epd_attribute_index=0;
1401 static int dissect_cops_pr_object_data(tvbuff_t *tvb, guint32 offset, proto_tree *tree,
1402 guint8 s_num, guint8 s_type, guint16 len)
1405 proto_tree *asn1_object_tree, *gperror_tree, *cperror_tree;
1406 guint16 gperror=0, gperror_sub=0, cperror=0, cperror_sub=0;
1410 if (s_type != 1) /* Not Provisioning Instance Identifier (PRID) */
1413 ti=proto_tree_add_text(tree, tvb, offset, len, "Contents:");
1414 asn1_object_tree = proto_item_add_subtree(ti, ett_cops_asn1);
1416 decode_cops_pr_asn1_data(tvb, offset, asn1_object_tree, len, COPS_OBJ_PRID);
1419 case COPS_OBJ_PPRID:
1420 if (s_type != 1) /* Not Prefix Provisioning Instance Identifier (PPRID) */
1423 ti = proto_tree_add_text(tree, tvb, offset, len, "Contents:");
1424 asn1_object_tree = proto_item_add_subtree(ti, ett_cops_asn1);
1426 decode_cops_pr_asn1_data(tvb, offset, asn1_object_tree, len, COPS_OBJ_PPRID);
1430 if (s_type != 1) /* Not Encoded Provisioning Instance Data (EPD) */
1433 ti = proto_tree_add_text(tree, tvb, offset, len, "Contents:");
1434 asn1_object_tree = proto_item_add_subtree(ti, ett_cops_asn1);
1436 decode_cops_pr_asn1_data(tvb, offset, asn1_object_tree, len, COPS_OBJ_EPD);
1439 case COPS_OBJ_GPERR:
1440 if (s_type != 1) /* Not Global Provisioning Error Object (GPERR) */
1443 gperror = tvb_get_ntohs(tvb, offset);
1444 gperror_sub = tvb_get_ntohs(tvb, offset + 2);
1445 ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Error-Code: %s, Error Sub-code: 0x%04x",
1446 val_to_str(gperror, cops_gperror_vals, "<Unknown value>"), gperror_sub);
1447 gperror_tree = proto_item_add_subtree(ti, ett_cops_gperror);
1448 proto_tree_add_uint(gperror_tree, hf_cops_gperror, tvb, offset, 2, gperror);
1450 if (cperror == 13) {
1451 proto_tree_add_text(gperror_tree, tvb, offset, 2, "Error Sub-code: "
1452 "Unknown object's C-Num %u, C-Type %u",
1453 tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset + 1));
1455 proto_tree_add_uint(gperror_tree, hf_cops_gperror_sub, tvb, offset, 2, gperror_sub);
1458 case COPS_OBJ_CPERR:
1459 if (s_type != 1) /*Not PRC Class Provisioning Error Object (CPERR) */
1464 cperror = tvb_get_ntohs(tvb, offset);
1465 cperror_sub = tvb_get_ntohs(tvb, offset + 2);
1466 ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Error-Code: %s, Error Sub-code: 0x%04x",
1467 val_to_str(cperror, cops_cperror_vals, "<Unknown value>"), cperror_sub);
1468 cperror_tree = proto_item_add_subtree(ti, ett_cops_cperror);
1469 proto_tree_add_uint(cperror_tree, hf_cops_cperror, tvb, offset, 2, cperror);
1471 if (cperror == 13) {
1472 proto_tree_add_text(cperror_tree, tvb, offset, 2, "Error Sub-code: "
1473 "Unknown object's S-Num %u, C-Type %u",
1474 tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset + 1));
1476 proto_tree_add_uint(cperror_tree, hf_cops_cperror_sub, tvb, offset, 2, cperror_sub);
1479 case COPS_OBJ_ERRPRID:
1480 if (s_type != 1) /*Not Error Provisioning Instance Identifier (ErrorPRID)*/
1483 ti = proto_tree_add_text(tree, tvb, offset, len, "Contents:");
1484 asn1_object_tree = proto_item_add_subtree(ti, ett_cops_asn1);
1486 decode_cops_pr_asn1_data(tvb, offset, asn1_object_tree, len, COPS_OBJ_ERRPRID);
1490 proto_tree_add_text(tree, tvb, offset, len, "Contents: %u bytes", len);
1498 /* Register the protocol with Ethereal */
1499 void proto_register_cops(void)
1501 /* Setup list of header fields */
1502 static hf_register_info hf[] = {
1503 { &hf_cops_ver_flags,
1504 { "Version and Flags", "cops.ver_flags",
1505 FT_UINT8, BASE_HEX, NULL, 0x0,
1506 "Version and Flags in COPS Common Header", HFILL }
1509 { "Version", "cops.version",
1510 FT_UINT8, BASE_DEC, NULL, 0xF0,
1511 "Version in COPS Common Header", HFILL }
1514 { "Flags", "cops.flags",
1515 FT_UINT8, BASE_HEX, VALS(cops_flags_vals), 0x0F,
1516 "Flags in COPS Common Header", HFILL }
1519 { "Op Code", "cops.op_code",
1520 FT_UINT8, BASE_DEC, VALS(cops_op_code_vals), 0x0,
1521 "Op Code in COPS Common Header", HFILL }
1523 { &hf_cops_client_type,
1524 { "Client Type", "cops.client_type",
1525 FT_UINT16, BASE_DEC, NULL, 0x0,
1526 "Client Type in COPS Common Header", HFILL }
1529 { "Message Length", "cops.msg_len",
1530 FT_UINT32, BASE_DEC, NULL, 0x0,
1531 "Message Length in COPS Common Header", HFILL }
1534 { "Object Length", "cops.obj.len",
1535 FT_UINT32, BASE_DEC, NULL, 0x0,
1536 "Object Length in COPS Object Header", HFILL }
1538 { &hf_cops_obj_c_num,
1539 { "C-Num", "cops.c_num",
1540 FT_UINT8, BASE_DEC, VALS(cops_c_num_vals), 0x0,
1541 "C-Num in COPS Object Header", HFILL }
1543 { &hf_cops_obj_c_type,
1544 { "C-Type", "cops.c_type",
1545 FT_UINT8, BASE_DEC, NULL, 0x0,
1546 "C-Type in COPS Object Header", HFILL }
1549 { &hf_cops_obj_s_num,
1550 { "S-Num", "cops.s_num",
1551 FT_UINT8, BASE_DEC, VALS(cops_s_num_vals), 0x0,
1552 "S-Num in COPS-PR Object Header", HFILL }
1554 { &hf_cops_obj_s_type,
1555 { "S-Type", "cops.s_type",
1556 FT_UINT8, BASE_DEC, NULL, 0x0,
1557 "S-Type in COPS-PR Object Header", HFILL }
1560 { &hf_cops_r_type_flags,
1561 { "R-Type", "cops.context.r_type",
1562 FT_UINT16, BASE_HEX, VALS(cops_r_type_vals), 0xFFFF,
1563 "R-Type in COPS Context Object", HFILL }
1565 { &hf_cops_m_type_flags,
1566 { "M-Type", "cops.context.m_type",
1567 FT_UINT16, BASE_HEX, NULL, 0xFFFF,
1568 "M-Type in COPS Context Object", HFILL }
1570 { &hf_cops_in_int_ipv4,
1571 { "IPv4 address", "cops.in-int.ipv4",
1572 FT_IPv4, 0, NULL, 0xFFFF,
1573 "IPv4 address in COPS IN-Int object", HFILL }
1575 { &hf_cops_in_int_ipv6,
1576 { "IPv6 address", "cops.in-int.ipv6",
1577 FT_IPv6, 0, NULL, 0xFFFF,
1578 "IPv6 address in COPS IN-Int object", HFILL }
1580 { &hf_cops_out_int_ipv4,
1581 { "IPv4 address", "cops.out-int.ipv4",
1582 FT_IPv4, 0, NULL, 0xFFFF,
1583 "IPv4 address in COPS OUT-Int object", HFILL }
1585 { &hf_cops_out_int_ipv6,
1586 { "IPv6 address", "cops.out-int.ipv6",
1587 FT_IPv6, 0, NULL, 0xFFFF,
1588 "IPv6 address in COPS OUT-Int", HFILL }
1590 { &hf_cops_int_ifindex,
1591 { "ifIndex", "cops.in-out-int.ifindex",
1592 FT_UINT32, BASE_DEC, NULL, 0x0,
1593 "If SNMP is supported, corresponds to MIB-II ifIndex", HFILL }
1596 { "Reason", "cops.reason",
1597 FT_UINT16, BASE_DEC, VALS(cops_reason_vals), 0,
1598 "Reason in Reason object", HFILL }
1600 { &hf_cops_reason_sub,
1601 { "Reason Sub-code", "cops.reason_sub",
1602 FT_UINT16, BASE_HEX, NULL, 0,
1603 "Reason Sub-code in Reason object", HFILL }
1605 { &hf_cops_dec_cmd_code,
1606 { "Command-Code", "cops.decision.cmd",
1607 FT_UINT16, BASE_DEC, VALS(cops_dec_cmd_code_vals), 0,
1608 "Command-Code in Decision/LPDP Decision object", HFILL }
1610 { &hf_cops_dec_flags,
1611 { "Flags", "cops.decision.flags",
1612 FT_UINT16, BASE_HEX, VALS(cops_dec_cmd_flag_vals), 0xffff,
1613 "Flags in Decision/LPDP Decision object", HFILL }
1616 { "Error", "cops.error",
1617 FT_UINT16, BASE_DEC, VALS(cops_error_vals), 0,
1618 "Error in Error object", HFILL }
1620 { &hf_cops_error_sub,
1621 { "Error Sub-code", "cops.error_sub",
1622 FT_UINT16, BASE_HEX, NULL, 0,
1623 "Error Sub-code in Error object", HFILL }
1626 { "Contents: KA Timer Value", "cops.katimer.value",
1627 FT_UINT16, BASE_DEC, NULL, 0,
1628 "Keep-Alive Timer Value in KATimer object", HFILL }
1631 { "Contents: PEP Id", "cops.pepid.id",
1632 FT_STRING, BASE_NONE, NULL, 0,
1633 "PEP Id in PEPID object", HFILL }
1635 { &hf_cops_report_type,
1636 { "Contents: Report-Type", "cops.report_type",
1637 FT_UINT16, BASE_DEC, VALS(cops_report_type_vals), 0,
1638 "Report-Type in Report-Type object", HFILL }
1640 { &hf_cops_pdprediraddr_ipv4,
1641 { "IPv4 address", "cops.pdprediraddr.ipv4",
1642 FT_IPv4, 0, NULL, 0xFFFF,
1643 "IPv4 address in COPS PDPRedirAddr object", HFILL }
1645 { &hf_cops_pdprediraddr_ipv6,
1646 { "IPv6 address", "cops.pdprediraddr.ipv6",
1647 FT_IPv6, 0, NULL, 0xFFFF,
1648 "IPv6 address in COPS PDPRedirAddr object", HFILL }
1650 { &hf_cops_lastpdpaddr_ipv4,
1651 { "IPv4 address", "cops.lastpdpaddr.ipv4",
1652 FT_IPv4, 0, NULL, 0xFFFF,
1653 "IPv4 address in COPS LastPDPAddr object", HFILL }
1655 { &hf_cops_lastpdpaddr_ipv6,
1656 { "IPv6 address", "cops.lastpdpaddr.ipv6",
1657 FT_IPv6, 0, NULL, 0xFFFF,
1658 "IPv6 address in COPS LastPDPAddr object", HFILL }
1660 { &hf_cops_pdp_tcp_port,
1661 { "TCP Port Number", "cops.pdp.tcp_port",
1662 FT_UINT32, BASE_DEC, NULL, 0x0,
1663 "TCP Port Number of PDP in PDPRedirAddr/LastPDPAddr object", HFILL }
1665 { &hf_cops_accttimer,
1666 { "Contents: ACCT Timer Value", "cops.accttimer.value",
1667 FT_UINT16, BASE_DEC, NULL, 0,
1668 "Accounting Timer Value in AcctTimer object", HFILL }
1671 { "Contents: Key ID", "cops.integrity.key_id",
1672 FT_UINT32, BASE_DEC, NULL, 0,
1673 "Key ID in Integrity object", HFILL }
1676 { "Contents: Sequence Number", "cops.integrity.seq_num",
1677 FT_UINT32, BASE_DEC, NULL, 0,
1678 "Sequence Number in Integrity object", HFILL }
1681 { "Error", "cops.gperror",
1682 FT_UINT16, BASE_DEC, VALS(cops_gperror_vals), 0,
1683 "Error in Error object", HFILL }
1685 { &hf_cops_gperror_sub,
1686 { "Error Sub-code", "cops.gperror_sub",
1687 FT_UINT16, BASE_HEX, NULL, 0,
1688 "Error Sub-code in Error object", HFILL }
1691 { "Error", "cops.cperror",
1692 FT_UINT16, BASE_DEC, VALS(cops_cperror_vals), 0,
1693 "Error in Error object", HFILL }
1695 { &hf_cops_cperror_sub,
1696 { "Error Sub-code", "cops.cperror_sub",
1697 FT_UINT16, BASE_HEX, NULL, 0,
1698 "Error Sub-code in Error object", HFILL }
1701 /* Added for PacketCable */
1704 { "Object Subtree", "cops.pc_subtree",
1705 FT_UINT16, BASE_HEX, NULL, 0,
1706 "Object Subtree", HFILL }
1708 { &hf_cops_pc_ds_field,
1709 { "DS Field (DSCP or TOS)", "cops.pc_ds_field",
1710 FT_UINT8, BASE_HEX, NULL, 0x00,
1711 "DS Field (DSCP or TOS)", HFILL }
1713 { &hf_cops_pc_direction,
1714 { "Direction", "cops.pc_direction",
1715 FT_UINT8, BASE_HEX, NULL, 0x00,
1716 "Direction", HFILL }
1718 { &hf_cops_pc_gate_spec_flags,
1719 { "Flags", "cops.pc_gate_spec_flags",
1720 FT_UINT8, BASE_HEX, NULL, 0x00,
1723 { &hf_cops_pc_protocol_id,
1724 { "Protocol ID", "cops.pc_protocol_id",
1725 FT_UINT8, BASE_HEX, NULL, 0x00,
1726 "Protocol ID", HFILL }
1728 { &hf_cops_pc_session_class,
1729 { "Session Class", "cops.pc_session_class",
1730 FT_UINT8, BASE_HEX, NULL, 0x00,
1731 "Session Class", HFILL }
1733 { &hf_cops_pc_algorithm,
1734 { "Algorithm", "cops.pc_algorithm",
1735 FT_UINT16, BASE_HEX, NULL, 0x00,
1736 "Algorithm", HFILL }
1738 { &hf_cops_pc_cmts_ip_port,
1739 { "CMTS IP Port", "cops.pc_cmts_ip_port",
1740 FT_UINT16, BASE_HEX, NULL, 0x00,
1741 "CMTS IP Port", HFILL }
1743 { &hf_cops_pc_prks_ip_port,
1744 { "PRKS IP Port", "cops.pc_prks_ip_port",
1745 FT_UINT16, BASE_HEX, NULL, 0x00,
1746 "PRKS IP Port", HFILL }
1748 { &hf_cops_pc_srks_ip_port,
1749 { "SRKS IP Port", "cops.pc_srks_ip_port",
1750 FT_UINT16, BASE_HEX, NULL, 0x00,
1751 "SRKS IP Port", HFILL }
1753 { &hf_cops_pc_dest_port,
1754 { "Destination IP Port", "cops.pc_dest_port",
1755 FT_UINT16, BASE_HEX, NULL, 0x00,
1756 "Destination IP Port", HFILL }
1758 { &hf_cops_pc_packetcable_err_code,
1759 { "Error Code", "cops.pc_packetcable_err_code",
1760 FT_UINT16, BASE_HEX, NULL, 0x00,
1761 "Error Code", HFILL }
1763 { &hf_cops_pc_packetcable_sub_code,
1764 { "Error Sub Code", "cops.pc_packetcable_sub_code",
1765 FT_UINT16, BASE_HEX, NULL, 0x00,
1766 "Error Sub Code", HFILL }
1768 { &hf_cops_pc_remote_flags,
1769 { "Flags", "cops.pc_remote_flags",
1770 FT_UINT16, BASE_HEX, NULL, 0x00,
1773 { &hf_cops_pc_close_subcode,
1774 { "Reason Sub Code", "cops.pc_close_subcode",
1775 FT_UINT16, BASE_HEX, NULL, 0x00,
1776 "Reason Sub Code", HFILL }
1778 { &hf_cops_pc_gate_command_type,
1779 { "Gate Command Type", "cops.pc_gate_command_type",
1780 FT_UINT16, BASE_HEX, NULL, 0x00,
1781 "Gate Command Type", HFILL }
1783 { &hf_cops_pc_reason_code,
1784 { "Reason Code", "cops.pc_reason_code",
1785 FT_UINT16, BASE_HEX, NULL, 0x00,
1786 "Reason Code", HFILL }
1788 { &hf_cops_pc_delete_subcode,
1789 { "Reason Sub Code", "cops.pc_delete_subcode",
1790 FT_UINT16, BASE_HEX, NULL, 0x00,
1791 "Reason Sub Code", HFILL }
1793 { &hf_cops_pc_src_port,
1794 { "Source IP Port", "cops.pc_src_port",
1795 FT_UINT16, BASE_HEX, NULL, 0x00,
1796 "Source IP Port", HFILL }
1798 { &hf_cops_pc_t1_value,
1799 { "Timer T1 Value (sec)", "cops.pc_t1_value",
1800 FT_UINT16, BASE_HEX, NULL, 0x00,
1801 "Timer T1 Value (sec)", HFILL }
1803 { &hf_cops_pc_t7_value,
1804 { "Timer T7 Value (sec)", "cops.pc_t7_value",
1805 FT_UINT16, BASE_HEX, NULL, 0x00,
1806 "Timer T7 Value (sec)", HFILL }
1808 { &hf_cops_pc_t8_value,
1809 { "Timer T8 Value (sec)", "cops.pc_t8_value",
1810 FT_UINT16, BASE_HEX, NULL, 0x00,
1811 "Timer T8 Value (sec)", HFILL }
1813 { &hf_cops_pc_transaction_id,
1814 { "Transaction Identifier", "cops.pc_transaction_id",
1815 FT_UINT16, BASE_HEX, NULL, 0x00,
1816 "Transaction Identifier", HFILL }
1818 { &hf_cops_pc_cmts_ip,
1819 { "CMTS IP Address", "cops.pc_cmts_ip",
1820 FT_UINT32, BASE_HEX, NULL, 0x00,
1821 "CMTS IP Address", HFILL }
1823 { &hf_cops_pc_prks_ip,
1824 { "PRKS IP Address", "cops.pc_prks_ip",
1825 FT_UINT32, BASE_HEX, NULL, 0x00,
1826 "PRKS IP Address", HFILL }
1828 { &hf_cops_pc_srks_ip,
1829 { "SRKS IP Address", "cops.pc_srks_ip",
1830 FT_UINT32, BASE_HEX, NULL, 0x00,
1831 "SRKS IP Address", HFILL }
1833 { &hf_cops_pc_dfcdc_ip,
1834 { "DF IP Address CDC", "cops.pc_dfcdc_ip",
1835 FT_UINT32, BASE_HEX, NULL, 0x00,
1836 "DF IP Address CDC", HFILL }
1838 { &hf_cops_pc_dfccc_ip,
1839 { "DF IP Address CCC", "cops.pc_dfccc_ip",
1840 FT_UINT32, BASE_HEX, NULL, 0x00,
1841 "DF IP Address CCC", HFILL }
1843 { &hf_cops_pc_dfcdc_ip_port,
1844 { "DF IP Port CDC", "cops.pc_dfcdc_ip_port",
1845 FT_UINT16, BASE_HEX, NULL, 0x00,
1846 "DF IP Port CDC", HFILL }
1848 { &hf_cops_pc_dfccc_ip_port,
1849 { "DF IP Port CCC", "cops.pc_dfccc_ip_port",
1850 FT_UINT16, BASE_HEX, NULL, 0x00,
1851 "DF IP Port CCC", HFILL }
1853 { &hf_cops_pc_activity_count,
1854 { "Count", "cops.pc_activity_count",
1855 FT_UINT32, BASE_HEX, NULL, 0x00,
1858 { &hf_cops_pc_dest_ip,
1859 { "Destination IP Address", "cops.pc_dest_ip",
1860 FT_UINT32, BASE_HEX, NULL, 0x00,
1861 "Destination IP Address", HFILL }
1863 { &hf_cops_pc_gate_id,
1864 { "Gate Identifier", "cops.pc_gate_id",
1865 FT_UINT32, BASE_HEX, NULL, 0x00,
1866 "Gate Identifier", HFILL }
1868 { &hf_cops_pc_max_packet_size,
1869 { "Maximum Packet Size", "cops.pc_max_packet_size",
1870 FT_UINT32, BASE_HEX, NULL, 0x00,
1871 "Maximum Packet Size", HFILL }
1873 { &hf_cops_pc_min_policed_unit,
1874 { "Minimum Policed Unit", "cops.pc_min_policed_unit",
1875 FT_UINT32, BASE_HEX, NULL, 0x00,
1876 "Minimum Policed Unit", HFILL }
1878 { &hf_cops_pc_peak_data_rate,
1879 { "Peak Data Rate", "cops.pc_peak_data_rate",
1880 FT_FLOAT, BASE_NONE, NULL, 0x00,
1881 "Peak Data Rate", HFILL }
1883 { &hf_cops_pc_spec_rate,
1884 { "Rate", "cops.pc_spec_rate",
1885 FT_FLOAT, BASE_NONE, NULL, 0x00,
1888 { &hf_cops_pc_remote_gate_id,
1889 { "Remote Gate ID", "cops.pc_remote_gate_id",
1890 FT_UINT32, BASE_HEX, NULL, 0x00,
1891 "Remote Gate ID", HFILL }
1893 { &hf_cops_pc_reserved,
1894 { "Reserved", "cops.pc_reserved",
1895 FT_UINT32, BASE_HEX, NULL, 0x00,
1899 { "Security Key", "cops.pc_key",
1900 FT_UINT32, BASE_HEX, NULL, 0x00,
1901 "Security Key", HFILL }
1903 { &hf_cops_pc_slack_term,
1904 { "Slack Term", "cops.pc_slack_term",
1905 FT_UINT32, BASE_HEX, NULL, 0x00,
1906 "Slack Term", HFILL }
1908 { &hf_cops_pc_src_ip,
1909 { "Source IP Address", "cops.pc_src_ip",
1910 FT_UINT32, BASE_HEX, NULL, 0x00,
1911 "Source IP Address", HFILL }
1913 { &hf_cops_pc_subscriber_id,
1914 { "Subscriber Identifier (IPv4)", "cops.pc_subscriber_id",
1915 FT_UINT32, BASE_HEX, NULL, 0x00,
1916 "Subscriber Identifier (IPv4)", HFILL }
1918 { &hf_cops_pc_token_bucket_rate,
1919 { "Token Bucket Rate", "cops.pc_token_bucket_rate",
1920 FT_FLOAT, BASE_NONE, NULL, 0x00,
1921 "Token Bucket Rate", HFILL }
1923 { &hf_cops_pc_token_bucket_size,
1924 { "Token Bucket Size", "cops.pc_token_bucket_size",
1925 FT_FLOAT, BASE_NONE, NULL, 0x00,
1926 "Token Bucket Size", HFILL }
1929 { "Billing Correlation ID", "cops.pc_bcid",
1930 FT_UINT32, BASE_HEX, NULL, 0x00,
1931 "Billing Correlation ID", HFILL }
1933 { &hf_cops_pc_bcid_ts,
1934 { "BDID Timestamp", "cops.pc_bcid_ts",
1935 FT_UINT32, BASE_HEX, NULL, 0x00,
1936 "BCID Timestamp", HFILL }
1938 { &hf_cops_pc_bcid_ev,
1939 { "BDID Event Counter", "cops.pc_bcid_ev",
1940 FT_UINT32, BASE_HEX, NULL, 0x00,
1941 "BCID Event Counter", HFILL }
1945 /* End of addition for PacketCable */
1949 /* Setup protocol subtree array */
1950 static gint *ett[] = {
1952 &ett_cops_ver_flags,
1956 &ett_cops_r_type_flags,
1969 module_t* cops_module;
1971 /* Register the protocol name and description */
1972 proto_cops = proto_register_protocol("Common Open Policy Service",
1975 /* Required function calls to register the header fields and subtrees used */
1976 proto_register_field_array(proto_cops, hf, array_length(hf));
1977 proto_register_subtree_array(ett, array_length(ett));
1979 /* Register our configuration options for cops */
1980 cops_module = prefs_register_protocol(proto_cops, proto_reg_handoff_cops);
1981 prefs_register_uint_preference(cops_module,"tcp.cops_port",
1983 "Set the TCP port for COPS messages",
1984 10,&global_cops_tcp_port);
1985 prefs_register_bool_preference(cops_module, "desegment",
1986 "Desegment all COPS messages\nspanning multiple TCP segments",
1987 "Whether the COPS dissector should desegment all messages spanning multiple TCP segments",
1990 /* For PacketCable */
1991 prefs_register_bool_preference(cops_module, "packetcable",
1992 "Decode for PacketCable clients",
1993 "Decode the COPS messages using PacketCable clients. (Select port 2126)",
1996 #ifdef HAVE_NET_SNMP /*enable preference only if compiled with NET-SNMP*/
1997 prefs_register_bool_preference(cops_module, "typefrommib",
1998 "Decode COPS-PR ASN.1 types by reading them\nfrom PIBs (converted to MIBs)",
1999 "Whether the COPS dissector should decode COPS-PR ASN.1 types based on data types read from packet or PIBs (converted to MIBs)",
2001 #endif /*HAVE_NET_SNMP*/
2004 void proto_reg_handoff_cops(void)
2006 static int cops_prefs_initialized = FALSE;
2007 static dissector_handle_t cops_handle;
2009 if (!cops_prefs_initialized) {
2010 cops_handle = create_dissector_handle(dissect_cops, proto_cops);
2011 cops_prefs_initialized = TRUE;
2013 dissector_delete("tcp.port",cops_tcp_port,cops_handle);
2015 /* Set our port numbers for future use */
2016 cops_tcp_port = global_cops_tcp_port;
2018 dissector_add("tcp.port", cops_tcp_port, cops_handle);
2022 /* Additions for PacketCable ( Added by Dick Gooris, Lucent Technologies ) */
2024 /* Definitions for print formatting */
2030 /* Print the translated information in the display gui in a formatted way
2032 * octets = The number of octets to obtain from the buffer
2034 * vsp = If not a NULL pointer, it points to an array with text
2036 * mode = 0 -> print decimal value
2037 * 1 -> print hexadecimal vaue
2038 * 2 -> print value as an ip address
2039 * 3 -> print value as an ieee float
2041 * This function in combination with the separate function info_to_cops_subtree() for subtrees.
2045 void info_to_display(tvbuff_t *tvb, proto_item *stt, int offset, int octets, char *str, const value_string *vsp, int mode,gint *hf_proto_parameter)
2054 /* Print information elements in the specified way */
2059 code8 = tvb_get_guint8( tvb, offset );
2061 /* Hexadecimal format */
2063 proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb,
2064 offset, octets, code8,"%-28s : 0x%02x",str,code8);
2066 /* Print an 8 bits integer */
2067 proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb,
2068 offset, octets, code8,"%-28s : %u",str,code8);
2071 /* Hexadecimal format */
2072 proto_tree_add_uint_format(
2073 stt, *hf_proto_parameter,tvb, offset, octets, code8,
2074 "%-28s : %s (0x%02x)",str,val_to_str(code8, vsp, "Unknown"),code8);
2076 /* String table indexed */
2077 proto_tree_add_uint_format(
2078 stt, *hf_proto_parameter,tvb, offset, octets, code8,
2079 "%-28s : %s (%u)",str,val_to_str(code8, vsp, "Unknown"),code8);
2085 /* Get the next two octets */
2086 code16 = tvb_get_ntohs(tvb,offset);
2088 /* Hexadecimal format */
2090 proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb,
2091 offset, octets, code16,"%-28s : 0x%04x",str,code16);
2093 /* Print a 16 bits integer */
2094 proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb,
2095 offset, octets, code16,"%-28s : %u",str,code16);
2098 /* Hexadecimal format */
2099 proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb,
2100 offset, octets, code16,"%-28s : %s (0x%04x)", str,
2101 val_to_str(code16, vsp, "Unknown (0x%04x)"),code16);
2103 /* Print a 16 bits integer */
2104 proto_tree_add_uint_format(
2105 stt, *hf_proto_parameter,tvb, offset, octets, code16,
2106 "%-28s : %s (%u)",str,val_to_str(code16, vsp, "Unknown (0x%04x)"),code16);
2112 /* Get the next four octets */
2114 case FMT_FLT: codefl = tvb_get_ntohieee_float(tvb,offset);
2116 case FMT_IP: tvb_memcpy(tvb, (guint8 *)&code32, offset, 4);
2117 codeip = tvb_get_ntohl(tvb,offset);
2119 default: code32 = tvb_get_ntohl(tvb,offset);
2123 /* Hexadecimal format */
2124 if (mode==FMT_HEX) {
2125 proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb,
2126 offset, octets, code32,"%-28s : 0x%08x",str,code32);
2129 /* Ip address format*/
2131 proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb, offset,octets,
2132 codeip,"%-28s : %s",str,ip_to_str((guint8 *)&code32));
2135 /* Ieee float format */
2136 if (mode==FMT_FLT) {
2137 proto_tree_add_float_format(stt, *hf_proto_parameter,tvb, offset, octets,
2138 codefl,"%-28s : %.10g",str,codefl);
2141 /* Print a 32 bits integer */
2142 proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb, offset, octets,
2143 code32,"%-28s : %u",str,code32);
2145 /* Hexadecimal format */
2147 proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb, offset, octets,
2148 code32,"%-28s : %s (0x%08x)",str,val_to_str(code32, vsp, "Unknown"),code32);
2150 /* String table indexed */
2151 proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb, offset, octets,
2152 code32,"%-28s : %s (%u)",str,val_to_str(code32, vsp, "Unknown"),code32);
2156 /* In case of more than 4 octets.... */
2159 proto_tree_add_bytes(stt, *hf_proto_parameter,
2160 tvb, offset, octets, tvb_get_ptr(tvb, offset,octets));
2162 proto_tree_add_uint_format(stt, *hf_proto_parameter,
2163 tvb, offset, octets, code32,"%s",str);
2170 /* Print the subtree information for cops */
2171 proto_tree *info_to_cops_subtree(tvbuff_t *tvb, proto_tree *st, int n, int offset, char *str) {
2174 tv = proto_tree_add_uint_format( st, hf_cops_subtree, tvb, offset, n, (guint)NULL, str);
2175 return( proto_item_add_subtree( tv, ett_cops_subtree ) );
2178 /* Cops - Section : Transaction ID */
2179 void cops_transaction_id(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
2185 /* Create a subtree */
2186 stt = info_to_cops_subtree(tvb,st,n,offset,"Transaction ID");
2188 /* Transaction Identifier */
2189 info_to_display(tvb,stt,offset,2,"Transaction Identifier", NULL,FMT_DEC,&hf_cops_pc_transaction_id);
2192 /* Gate Command Type */
2193 code16 = tvb_get_ntohs(tvb,offset);
2194 proto_tree_add_uint_format(stt, hf_cops_pc_gate_command_type,tvb, offset, 2,
2195 code16,"%-28s : %s (%u)", "Gate Command Type",
2196 val_to_str(code16,table_cops_transaction_id, "Unknown (0x%04x)"),code16);
2198 /* Write the right data into the 'info field' on the Gui */
2199 sprintf(info,"COPS %-20s - ",val_to_str(opcode_idx,cops_op_code_vals, "Unknown"));
2200 strcat(info,val_to_str(code16,table_cops_transaction_id, "Unknown"));
2202 if (check_col(cpinfo->cinfo, COL_INFO)) {
2203 col_clear(cpinfo->cinfo, COL_INFO);
2204 col_add_str(cpinfo->cinfo, COL_INFO,info);
2209 /* Cops - Section : Subscriber ID */
2210 void cops_subscriber_id_v4(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
2214 /* Create a subtree */
2215 tv = info_to_cops_subtree(tvb,st,n,offset,"Subscriber ID");
2217 /* Subscriber Identifier */
2218 info_to_display(tvb,tv,offset,4,"Subscriber Identifier (IPv4)", NULL,FMT_IP,&hf_cops_pc_subscriber_id);
2221 /* Cops - Section : Gate ID */
2222 void cops_gate_id(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
2226 /* Create a subtree */
2227 stt = info_to_cops_subtree(tvb,st,n,offset,"Gate ID");
2229 /* Gate Identifier */
2230 info_to_display(tvb,stt,offset,4,"Gate Identifier", NULL,FMT_HEX,&hf_cops_pc_gate_id);
2233 /* Cops - Section : Activity Count */
2234 void cops_activity_count(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
2238 /* Create a subtree */
2239 stt = info_to_cops_subtree(tvb,st,n,offset,"Activity Count");
2241 /* Activity Count */
2242 info_to_display(tvb,stt,offset,4,"Count", NULL,FMT_DEC,&hf_cops_pc_activity_count);
2245 /* Cops - Section : Gate Specifications */
2246 void cops_gate_specs(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
2250 /* Create a subtree */
2251 stt = info_to_cops_subtree(tvb,st,n,offset,"Gate Specifications");
2254 info_to_display(tvb,stt,offset,1,"Direction",table_cops_direction,FMT_DEC,&hf_cops_pc_direction);
2258 info_to_display(tvb,stt,offset,1,"Protocol ID",NULL,FMT_DEC,&hf_cops_pc_protocol_id);
2262 info_to_display(tvb,stt,offset,1,"Flags",NULL,FMT_DEC,&hf_cops_pc_gate_spec_flags);
2266 info_to_display(tvb,stt,offset,1,"Session Class",table_cops_session_class,FMT_DEC,&hf_cops_pc_session_class);
2269 /* Source IP Address */
2270 info_to_display(tvb,stt,offset,4,"Source IP Address",NULL,FMT_IP,&hf_cops_pc_src_ip);
2273 /* Destination IP Address */
2274 info_to_display(tvb,stt,offset,4,"Destination IP Address",NULL,FMT_IP,&hf_cops_pc_dest_ip);
2277 /* Source IP Port */
2278 info_to_display(tvb,stt,offset,2,"Source IP Port",NULL,FMT_DEC,&hf_cops_pc_src_port);
2281 /* Destination IP Port */
2282 info_to_display(tvb,stt,offset,2,"Destination IP Port",NULL,FMT_DEC,&hf_cops_pc_dest_port);
2285 /* DiffServ Code Point */
2286 info_to_display(tvb,stt,offset,1,"DS Field (DSCP or TOS)",NULL,FMT_HEX,&hf_cops_pc_ds_field);
2289 /* 3 octets Not specified */
2292 /* Timer T1 Value */
2293 info_to_display(tvb,stt,offset,2,"Timer T1 Value (sec)",NULL,FMT_DEC,&hf_cops_pc_t1_value);
2297 info_to_display(tvb,stt,offset,2,"Reserved",NULL,FMT_DEC,&hf_cops_pc_reserved);
2300 /* Timer T7 Value */
2301 info_to_display(tvb,stt,offset,2,"Timer T7 Value (sec)",NULL,FMT_DEC,&hf_cops_pc_t7_value);
2304 /* Timer T8 Value */
2305 info_to_display(tvb,stt,offset,2,"Timer T8 Value (sec)",NULL,FMT_DEC,&hf_cops_pc_t8_value);
2308 /* Token Bucket Rate */
2309 info_to_display(tvb,stt,offset,4,"Token Bucket Rate",NULL,FMT_FLT,&hf_cops_pc_token_bucket_rate);
2312 /* Token Bucket Size */
2313 info_to_display(tvb,stt,offset,4,"Token Bucket Size",NULL,FMT_FLT,&hf_cops_pc_token_bucket_size);
2316 /* Peak Data Rate */
2317 info_to_display(tvb,stt,offset,4,"Peak Data Rate",NULL,FMT_FLT,&hf_cops_pc_peak_data_rate);
2320 /* Minimum Policed Unit */
2321 info_to_display(tvb,stt,offset,4,"Minimum Policed Unit",NULL,FMT_DEC,&hf_cops_pc_min_policed_unit);
2324 /* Maximum Packet Size */
2325 info_to_display(tvb,stt,offset,4,"Maximum Packet Size",NULL,FMT_DEC,&hf_cops_pc_max_packet_size);
2329 info_to_display(tvb,stt,offset,4,"Rate",NULL,FMT_FLT,&hf_cops_pc_spec_rate);
2333 info_to_display(tvb,stt,offset,4,"Slack Term",NULL,FMT_DEC,&hf_cops_pc_slack_term);
2336 /* Cops - Section : Electronic Surveillance Parameters */
2337 void cops_surveillance_parameters(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
2342 /* Create a subtree */
2343 stt = info_to_cops_subtree(tvb,st,n,offset,"Electronic Surveillance Parameters");
2345 /* DF IP Address for CDC */
2346 info_to_display(tvb,stt,offset,4,"DF IP Address for CDC", NULL,FMT_IP,&hf_cops_pc_dfcdc_ip);
2349 /* DF IP Port for CDC */
2350 info_to_display(tvb,stt,offset,2,"DF IP Port for CDC",NULL,FMT_DEC,&hf_cops_pc_dfcdc_ip_port);
2354 info_to_display(tvb,stt,offset,2,"Flags",NULL,FMT_HEX,&hf_cops_pc_gate_spec_flags);
2357 /* DF IP Address for CCC */
2358 info_to_display(tvb,stt,offset,4,"DF IP Address for CCC", NULL,FMT_IP,&hf_cops_pc_dfccc_ip);
2361 /* DF IP Port for CCC */
2362 info_to_display(tvb,stt,offset,2,"DF IP Port for CCC",NULL,FMT_DEC,&hf_cops_pc_dfccc_ip_port);
2366 info_to_display(tvb,stt,offset,2,"Reserved",NULL,FMT_HEX,&hf_cops_pc_reserved);
2370 info_to_display(tvb,stt,offset,4,"CCCID", NULL,FMT_HEX,&hf_cops_pc_srks_ip);
2373 /* BCID Timestamp */
2374 info_to_display(tvb,stt,offset,4,"BCID - Timestamp",NULL,FMT_HEX,&hf_cops_pc_bcid_ts);
2377 /* BCID Element ID */
2378 bcid_str = tvb_get_string(tvb, offset, 8);
2379 proto_tree_add_text(stt, tvb, offset, 8,"%-28s : '%s'","BCID - Element ID",bcid_str);
2382 /* BCID Time Zone */
2383 bcid_str = tvb_get_string(tvb, offset, 8);
2384 proto_tree_add_text(stt, tvb, offset, 8,"%-28s : '%s'","BCID - Time Zone",bcid_str);
2387 /* BCID Event Counter */
2388 info_to_display(tvb,stt,offset,4,"BCID - Event Counter",NULL,FMT_DEC,&hf_cops_pc_bcid_ev);
2391 /* Cops - Section : Event Gereration-Info */
2392 void cops_event_generation_info(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
2397 /* Create a subtree */
2398 stt = info_to_cops_subtree(tvb,st,n,offset,"Event Generation Info");
2400 /* Primary Record Keeping Server IP Address */
2401 info_to_display(tvb,stt,offset,4,"PRKS IP Address", NULL,FMT_IP,&hf_cops_pc_prks_ip);
2404 /* Primary Record Keeping Server IP Port */
2405 info_to_display(tvb,stt,offset,2,"PRKS IP Port",NULL,FMT_DEC,&hf_cops_pc_prks_ip_port);
2409 info_to_display(tvb,stt,offset,1,"Flags",NULL,FMT_HEX,&hf_cops_pc_gate_spec_flags);
2413 info_to_display(tvb,stt,offset,1,"Reserved",NULL,FMT_HEX,&hf_cops_pc_reserved);
2416 /* Secundary Record Keeping Server IP Address */
2417 info_to_display(tvb,stt,offset,4,"SRKS IP Address", NULL,FMT_IP,&hf_cops_pc_srks_ip);
2420 /* Secundary Record Keeping Server IP Port */
2421 info_to_display(tvb,stt,offset,2,"SRKS IP Port",NULL,FMT_DEC,&hf_cops_pc_srks_ip_port);
2425 info_to_display(tvb,stt,offset,1,"Flags",NULL,FMT_DEC,&hf_cops_pc_gate_spec_flags);
2429 info_to_display(tvb,stt,offset,1,"Reserved",NULL,FMT_HEX,&hf_cops_pc_reserved);
2432 /* BCID Timestamp */
2433 info_to_display(tvb,stt,offset,4,"BCID - Timestamp",NULL,FMT_HEX,&hf_cops_pc_bcid_ts);
2436 /* BCID Element ID */
2437 bcid_str = tvb_get_string(tvb, offset, 8);
2438 proto_tree_add_text(stt, tvb, offset, 8,"%-28s : '%s'","BCID - Element ID",bcid_str);
2441 /* BCID Time Zone */
2442 bcid_str = tvb_get_string(tvb, offset, 8);
2443 proto_tree_add_text(stt, tvb, offset, 8,"%-28s : '%s'","BCID - Time Zone",bcid_str);
2446 /* BCID Event Counter */
2447 info_to_display(tvb,stt,offset,4,"BCID - Event Counter",NULL,FMT_DEC,&hf_cops_pc_bcid_ev);
2450 /* Cops - Section : Remote Gate */
2451 void cops_remote_gate_info(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
2455 /* Create a subtree */
2456 stt = info_to_cops_subtree(tvb,st,n,offset,"Remote Gate Info");
2458 /* CMTS IP Address */
2459 info_to_display(tvb,stt,offset,4,"CMTS IP Address", NULL,FMT_IP,&hf_cops_pc_cmts_ip);
2463 info_to_display(tvb,stt,offset,2,"CMTS IP Port",NULL,FMT_DEC,&hf_cops_pc_cmts_ip_port);
2467 info_to_display(tvb,stt,offset,2,"Flags",NULL,FMT_DEC,&hf_cops_pc_remote_flags);
2470 /* Remote Gate ID */
2471 info_to_display(tvb,stt,offset,4,"Remote Gate ID", NULL,FMT_HEX,&hf_cops_pc_remote_gate_id);
2475 info_to_display(tvb,stt,offset,2,"Algorithm", NULL,FMT_IP,&hf_cops_pc_algorithm);
2479 info_to_display(tvb,stt,offset,4,"Reserved", NULL,FMT_IP,&hf_cops_pc_reserved);
2483 info_to_display(tvb,stt,offset,4,"Security Key", NULL,FMT_HEX,&hf_cops_pc_key);
2487 info_to_display(tvb,stt,offset,4,"Security Key (cont)", NULL,FMT_HEX,&hf_cops_pc_key);
2491 info_to_display(tvb,stt,offset,4,"Security Key (cont)", NULL,FMT_HEX,&hf_cops_pc_key);
2495 info_to_display(tvb,stt,offset,4,"Security Key (cont)", NULL,FMT_HEX,&hf_cops_pc_key);
2498 /* Cops - Section : PacketCable reason */
2499 void cops_packetcable_reason(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
2504 /* Create a subtree */
2505 stt = info_to_cops_subtree(tvb,st,n,offset,"PacketCable Reason");
2508 code16 = tvb_get_ntohs(tvb,offset);
2509 proto_tree_add_uint_format(stt, hf_cops_pc_reason_code,tvb, offset, 2,
2510 code16, "%-28s : %s (%u)","Reason Code",
2511 val_to_str(code16, table_cops_reason_code, "Unknown (0x%04x)"),code16);
2514 if ( code16 == 0 ) {
2515 /* Reason Sub Code with Delete */
2516 info_to_display(tvb,stt,offset,2,"Reason Sub Code",table_cops_reason_subcode_delete,FMT_DEC,&hf_cops_pc_delete_subcode);
2518 /* Reason Sub Code with Close */
2519 info_to_display(tvb,stt,offset,2,"Reason Sub Code",table_cops_reason_subcode_close,FMT_DEC,&hf_cops_pc_close_subcode);
2523 /* Cops - Section : PacketCable error */
2524 void cops_packetcable_error(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
2528 /* Create a subtree */
2529 stt = info_to_cops_subtree(tvb,st,n,offset,"PacketCable Error");
2532 info_to_display(tvb,stt,offset,2,"Error Code",table_cops_packetcable_error,FMT_DEC,&hf_cops_pc_packetcable_err_code);
2535 /* Error Sub Code */
2536 info_to_display(tvb,stt,offset,2,"Error Sub Code",NULL,FMT_HEX,&hf_cops_pc_packetcable_sub_code);
2540 /* Analyze the PacketCable objects */
2541 void cops_analyze_packetcable_obj(tvbuff_t *tvb, proto_tree *tree, guint32 offset) {
2545 guint8 s_num, s_type;
2547 /* Only if this option is enabled by the Gui */
2548 if ( cops_packetcable == FALSE ) {
2552 /* Do the remaining client specific objects */
2553 remdata = tvb_length_remaining(tvb, offset);
2554 while (remdata > 4) {
2556 /* In case we have remaining data, then lets try to get this analyzed */
2557 object_len = tvb_get_ntohs(tvb, offset);
2558 if (object_len < 4) {
2559 proto_tree_add_text(tree, tvb, offset, 2,
2560 "Incorrect PacketCable object length %u < 4", object_len);
2564 s_num = tvb_get_guint8(tvb, offset + 2);
2565 s_type = tvb_get_guint8(tvb, offset + 3);
2570 /* Perform the appropriate functions */
2574 cops_transaction_id(tvb, tree, object_len, offset);
2579 cops_subscriber_id_v4(tvb, tree, object_len, offset);
2584 cops_gate_id(tvb, tree, object_len, offset);
2589 cops_activity_count(tvb, tree, object_len, offset);
2594 cops_gate_specs(tvb, tree, object_len, offset);
2599 cops_remote_gate_info(tvb, tree, object_len, offset);
2604 cops_event_generation_info(tvb, tree, object_len, offset);
2609 cops_packetcable_error(tvb, tree, object_len, offset);
2614 cops_surveillance_parameters(tvb, tree, object_len, offset);
2619 cops_packetcable_reason(tvb, tree, object_len, offset);
2625 offset += object_len-4;
2627 /* See what we can still get from the buffer */
2628 remdata = tvb_length_remaining(tvb, offset);
2632 /* End of PacketCable Addition */