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 * PKT-SP-DQOS-I09-040402 (April 2, 2004)
14 * Implemented in ethereal at April 7-8, 2004
16 * $Id: packet-cops.c,v 1.44 2004/04/15 09:24:07 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_delete_subcode = -1;
550 static gint hf_cops_pc_dest_ip = -1;
551 static gint hf_cops_pc_dest_port = -1;
552 static gint hf_cops_pc_direction = -1;
553 static gint hf_cops_pc_ds_field = -1;
554 static gint hf_cops_pc_gate_id = -1;
555 static gint hf_cops_pc_gate_spec_flags = -1;
556 static gint hf_cops_pc_gate_command_type = -1;
557 static gint hf_cops_pc_key = -1;
558 static gint hf_cops_pc_max_packet_size = -1;
559 static gint hf_cops_pc_min_policed_unit = -1;
560 static gint hf_cops_pc_packetcable_err_code = -1;
561 static gint hf_cops_pc_packetcable_sub_code = -1;
562 static gint hf_cops_pc_peak_data_rate = -1;
563 static gint hf_cops_pc_protocol_id = -1;
564 static gint hf_cops_pc_reason_code = -1;
565 static gint hf_cops_pc_remote_flags = -1;
566 static gint hf_cops_pc_remote_gate_id = -1;
567 static gint hf_cops_pc_reserved = -1;
568 static gint hf_cops_pc_session_class = -1;
569 static gint hf_cops_pc_slack_term = -1;
570 static gint hf_cops_pc_spec_rate = -1;
571 static gint hf_cops_pc_src_ip = -1;
572 static gint hf_cops_pc_src_port = -1;
573 static gint hf_cops_pc_subscriber_id = -1;
574 static gint hf_cops_pc_t1_value = -1;
575 static gint hf_cops_pc_t7_value = -1;
576 static gint hf_cops_pc_t8_value = -1;
577 static gint hf_cops_pc_token_bucket_rate = -1;
578 static gint hf_cops_pc_token_bucket_size = -1;
579 static gint hf_cops_pc_transaction_id = -1;
581 /* Initialize the subtree pointers */
582 static gint ett_cops = -1;
583 static gint ett_cops_ver_flags = -1;
584 static gint ett_cops_obj = -1;
585 static gint ett_cops_pr_obj = -1;
586 static gint ett_cops_obj_data = -1;
587 static gint ett_cops_r_type_flags = -1;
588 static gint ett_cops_itf = -1;
589 static gint ett_cops_reason = -1;
590 static gint ett_cops_decision = -1;
591 static gint ett_cops_error = -1;
592 static gint ett_cops_clientsi = -1;
593 static gint ett_cops_asn1 = -1;
594 static gint ett_cops_gperror = -1;
595 static gint ett_cops_cperror = -1;
596 static gint ett_cops_pdp = -1;
598 /* For PacketCable */
599 static gint ett_cops_subtree = -1;
601 void proto_reg_handoff_cops(void);
603 static guint get_cops_pdu_len(tvbuff_t *tvb, int offset);
604 static void dissect_cops_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
606 static int dissect_cops_object(tvbuff_t *tvb, guint32 offset, proto_tree *tree);
607 static void dissect_cops_object_data(tvbuff_t *tvb, guint32 offset, proto_tree *tree,
608 guint8 c_num, guint8 c_type, guint16 len);
610 static void dissect_cops_pr_objects(tvbuff_t *tvb, guint32 offset, proto_tree *tree, guint16 pr_len);
611 static int dissect_cops_pr_object_data(tvbuff_t *tvb, guint32 offset, proto_tree *tree,
612 guint8 s_num, guint8 s_type, guint16 len);
614 /* Added for PacketCable */
615 proto_tree *cops_to_subtree(tvbuff_t *, proto_tree *, int, int, char *);
616 void cops_to_disp_fmt(tvbuff_t *, proto_item *, int, int, char *, const value_string *, int, gint *);
617 void cops_transaction_id(tvbuff_t *, proto_tree *, guint, guint32);
618 void cops_subscriber_id_v4(tvbuff_t *, proto_tree *, guint, guint32);
619 void cops_gate_id(tvbuff_t *, proto_tree *, guint, guint32);
620 void cops_activity_count(tvbuff_t *, proto_tree *, guint, guint32);
621 void cops_gate_specs(tvbuff_t *, proto_tree *, guint, guint32);
622 void cops_remote_gate_info(tvbuff_t *, proto_tree *, guint, guint32);
623 void cops_packetcable_reason(tvbuff_t *, proto_tree *, guint, guint32);
624 void cops_packetcable_error(tvbuff_t *, proto_tree *, guint, guint32);
625 void cops_analyze_packetcable_obj(tvbuff_t *, proto_tree *, guint32);
627 static packet_info *cpinfo;
628 static guint8 opcode_idx;
629 static gboolean cops_packetcable = FALSE;
630 /* End of addition for PacketCable */
633 /* Code to actually dissect the packets */
635 dissect_cops(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
637 tcp_dissect_pdus(tvb, pinfo, tree, cops_desegment, 8,
638 get_cops_pdu_len, dissect_cops_pdu);
642 get_cops_pdu_len(tvbuff_t *tvb, int offset)
645 * Get the length of the COPS message.
647 return tvb_get_ntohl(tvb, offset + 4);
651 dissect_cops_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
656 if (check_col(pinfo->cinfo, COL_PROTOCOL))
657 col_set_str(pinfo->cinfo, COL_PROTOCOL, "COPS");
658 if (check_col(pinfo->cinfo, COL_INFO))
659 col_clear(pinfo->cinfo, COL_INFO);
661 op_code = tvb_get_guint8(tvb, 1);
662 if (check_col(pinfo->cinfo, COL_INFO))
663 col_add_fstr(pinfo->cinfo, COL_INFO, "COPS %s",
664 val_to_str(op_code, cops_op_code_vals, "Unknown Op Code"));
666 /* PacketCable: Remember the next two values to manipulate the info field in the Gui */
668 opcode_idx = op_code;
672 proto_tree *cops_tree, *ver_flags_tree;
678 ti = proto_tree_add_item(tree, proto_cops, tvb, offset, -1, FALSE);
679 cops_tree = proto_item_add_subtree(ti, ett_cops);
681 /* Version and flags share the same byte, put them in a subtree */
682 ver_flags = tvb_get_guint8(tvb, offset);
683 tv = proto_tree_add_uint_format(cops_tree, hf_cops_ver_flags, tvb, offset, 1,
684 ver_flags, "Version: %u, Flags: %s",
685 hi_nibble(ver_flags),
686 val_to_str(lo_nibble(ver_flags), cops_flags_vals, "Unknown"));
687 ver_flags_tree = proto_item_add_subtree(tv, ett_cops_ver_flags);
688 proto_tree_add_uint(ver_flags_tree, hf_cops_version, tvb, offset, 1, ver_flags);
689 proto_tree_add_uint(ver_flags_tree, hf_cops_flags, tvb, offset, 1, ver_flags);
692 proto_tree_add_item(cops_tree, hf_cops_op_code, tvb, offset, 1, FALSE);
694 proto_tree_add_item(cops_tree, hf_cops_client_type, tvb, offset, 2, FALSE);
697 msg_len = tvb_get_ntohl(tvb, offset);
698 proto_tree_add_uint(cops_tree, hf_cops_msg_len, tvb, offset, 4, msg_len);
701 while (tvb_reported_length_remaining(tvb, offset) >= COPS_OBJECT_HDR_SIZE) {
702 object_len = dissect_cops_object(tvb, offset, cops_tree);
705 offset += object_len;
708 garbage = tvb_length_remaining(tvb, offset);
710 proto_tree_add_text(cops_tree, tvb, offset, garbage,
711 "Trailing garbage: %d byte%s", garbage,
712 plurality(garbage, "", "s"));
716 static char *cops_c_type_to_str(guint8 c_num, guint8 c_type)
719 case COPS_OBJ_HANDLE:
721 return "Client Handle";
723 case COPS_OBJ_IN_INT:
724 case COPS_OBJ_OUT_INT:
726 return "IPv4 Address + Interface";
727 else if (c_type == 2)
728 return "IPv6 Address + Interface";
730 case COPS_OBJ_DECISION:
731 case COPS_OBJ_LPDPDECISION:
733 return "Decision Flags (Mandatory)";
734 else if (c_type == 2)
735 return "Stateless Data";
736 else if (c_type == 3)
737 return "Replacement Data";
738 else if (c_type == 4)
739 return "Client Specific Decision Data";
740 else if (c_type == 5)
741 return "Named Decision Data";
743 case COPS_OBJ_CLIENTSI:
745 return "Signaled ClientSI";
746 else if (c_type == 2)
747 return "Named ClientSI";
749 case COPS_OBJ_KATIMER:
751 return "Keep-alive timer value";
753 case COPS_OBJ_PDPREDIRADDR:
754 case COPS_OBJ_LASTPDPADDR:
756 return "IPv4 Address + TCP Port";
757 else if (c_type == 2)
758 return "IPv6 Address + TCP Port";
760 case COPS_OBJ_ACCTTIMER:
762 return "Accounting timer value";
764 case COPS_OBJ_INTEGRITY:
766 return "HMAC digest";
773 static int dissect_cops_object(tvbuff_t *tvb, guint32 offset, proto_tree *tree)
775 guint16 object_len, contents_len;
776 guint8 c_num, c_type;
778 proto_tree *obj_tree;
781 object_len = tvb_get_ntohs(tvb, offset);
782 if (object_len < COPS_OBJECT_HDR_SIZE) {
784 proto_tree_add_text(tree, tvb, offset, 2,
785 "Bad COPS object length: %u, should be at least %u",
786 object_len, COPS_OBJECT_HDR_SIZE);
789 c_num = tvb_get_guint8(tvb, offset + 2);
790 c_type = tvb_get_guint8(tvb, offset + 3);
792 ti = proto_tree_add_uint_format(tree, hf_cops_obj_c_num, tvb, offset, object_len, c_num,
793 "%s: %s", val_to_str(c_num, cops_c_num_vals, "Unknown"),
794 cops_c_type_to_str(c_num, c_type));
795 obj_tree = proto_item_add_subtree(ti, ett_cops_obj);
797 proto_tree_add_uint(obj_tree, hf_cops_obj_len, tvb, offset, 2, object_len);
800 proto_tree_add_uint(obj_tree, hf_cops_obj_c_num, tvb, offset, 1, c_num);
803 type_str = cops_c_type_to_str(c_num, c_type);
804 proto_tree_add_text(obj_tree, tvb, offset, 1, "C-Type: %s%s%u%s",
806 strlen(type_str) ? " (" : "",
808 strlen(type_str) ? ")" : "");
811 contents_len = object_len - COPS_OBJECT_HDR_SIZE;
812 dissect_cops_object_data(tvb, offset, obj_tree, c_num, c_type, contents_len);
814 /* Pad to 32bit boundary */
815 if (object_len % sizeof (guint32))
816 object_len += (sizeof (guint32) - object_len % sizeof (guint32));
821 static void dissect_cops_pr_objects(tvbuff_t *tvb, guint32 offset, proto_tree *tree, guint16 pr_len)
823 guint16 object_len, contents_len;
824 guint8 s_num, s_type;
827 proto_tree *cops_pr_tree, *obj_tree;
830 cops_pr_tree = proto_item_add_subtree(tree, ett_cops_pr_obj);
832 while (pr_len >= COPS_OBJECT_HDR_SIZE) {
833 object_len = tvb_get_ntohs(tvb, offset);
834 if (object_len < COPS_OBJECT_HDR_SIZE) {
836 proto_tree_add_text(tree, tvb, offset, 2,
837 "Bad COPS PR object length: %u, should be at least %u",
838 object_len, COPS_OBJECT_HDR_SIZE);
841 s_num = tvb_get_guint8(tvb, offset + 2);
843 ti = proto_tree_add_uint_format(cops_pr_tree, hf_cops_obj_s_num, tvb, offset, object_len, s_num,
844 "%s", val_to_str(s_num, cops_s_num_vals, "Unknown"));
845 obj_tree = proto_item_add_subtree(cops_pr_tree, ett_cops_pr_obj);
847 proto_tree_add_uint(obj_tree, hf_cops_obj_len, tvb, offset, 2, object_len);
851 proto_tree_add_uint(obj_tree, hf_cops_obj_s_num, tvb, offset, 1, s_num);
855 s_type = tvb_get_guint8(tvb, offset);
856 type_str = val_to_str(s_type, cops_s_type_vals, "Unknown");
857 proto_tree_add_text(obj_tree, tvb, offset, 1, "S-Type: %s%s%u%s",
859 strlen(type_str) ? " (" : "",
861 strlen(type_str) ? ")" : "");
865 contents_len = object_len - COPS_OBJECT_HDR_SIZE;
866 ret = dissect_cops_pr_object_data(tvb, offset, obj_tree, s_num, s_type, contents_len);
870 /*Pad to 32bit boundary */
871 if (object_len % sizeof (guint32))
872 object_len += (sizeof (guint32) - object_len % sizeof (guint32));
874 pr_len -= object_len - COPS_OBJECT_HDR_SIZE;
875 offset += object_len - COPS_OBJECT_HDR_SIZE;
879 static void dissect_cops_object_data(tvbuff_t *tvb, guint32 offset, proto_tree *tree,
880 guint8 c_num, guint8 c_type, guint16 len)
883 proto_tree *r_type_tree, *itf_tree, *reason_tree, *dec_tree, *error_tree, *clientsi_tree, *pdp_tree;
884 guint16 r_type, m_type, reason, reason_sub, cmd_code, cmd_flags, error, error_sub, tcp_port;
885 guint32 ipv4addr, ifindex;
886 struct e_in6_addr ipv6addr;
889 case COPS_OBJ_CONTEXT:
890 r_type = tvb_get_ntohs(tvb, offset);
891 m_type = tvb_get_ntohs(tvb, offset + 2);
892 ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: R-Type: %s, M-Type: %u",
893 val_to_str(r_type, cops_r_type_vals, "Unknown"),
896 r_type_tree = proto_item_add_subtree(ti, ett_cops_r_type_flags);
897 proto_tree_add_uint(r_type_tree, hf_cops_r_type_flags, tvb, offset, 2, r_type);
899 proto_tree_add_uint(r_type_tree, hf_cops_m_type_flags, tvb, offset, 2, m_type);
902 case COPS_OBJ_IN_INT:
903 case COPS_OBJ_OUT_INT:
904 if (c_type == 1) { /* IPv4 */
905 tvb_memcpy(tvb, (guint8 *)&ipv4addr, offset, 4);
906 ifindex = tvb_get_ntohl(tvb, offset + 4);
907 ti = proto_tree_add_text(tree, tvb, offset, 8, "Contents: IPv4 address %s, ifIndex: %u",
908 ip_to_str((guint8 *)&ipv4addr), ifindex);
909 itf_tree = proto_item_add_subtree(ti, ett_cops_itf);
910 proto_tree_add_ipv4(itf_tree,
911 (c_num == COPS_OBJ_IN_INT) ? hf_cops_in_int_ipv4 : hf_cops_out_int_ipv4,
912 tvb, offset, 4, ipv4addr);
914 } else if (c_type == 2) { /* IPv6 */
915 tvb_memcpy(tvb, (guint8 *)&ipv6addr, offset, sizeof ipv6addr);
916 ifindex = tvb_get_ntohl(tvb, offset + sizeof ipv6addr);
917 ti = proto_tree_add_text(tree, tvb, offset, 20, "Contents: IPv6 address %s, ifIndex: %u",
918 ip6_to_str(&ipv6addr), ifindex);
919 itf_tree = proto_item_add_subtree(ti, ett_cops_itf);
920 proto_tree_add_ipv6(itf_tree,
921 (c_num == COPS_OBJ_IN_INT) ? hf_cops_in_int_ipv6 : hf_cops_out_int_ipv6,
922 tvb, offset, 16, (guint8 *)&ipv6addr);
927 proto_tree_add_uint(itf_tree, hf_cops_int_ifindex, tvb, offset, 4, ifindex);
930 case COPS_OBJ_REASON:
931 reason = tvb_get_ntohs(tvb, offset);
932 reason_sub = tvb_get_ntohs(tvb, offset + 2);
933 ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Reason-Code: %s, Reason Sub-code: 0x%04x",
934 val_to_str(reason, cops_reason_vals, "<Unknown value>"), reason_sub);
935 reason_tree = proto_item_add_subtree(ti, ett_cops_reason);
936 proto_tree_add_uint(reason_tree, hf_cops_reason, tvb, offset, 2, reason);
939 proto_tree_add_text(reason_tree, tvb, offset, 2, "Reason Sub-code: "
940 "Unknown object's C-Num %u, C-Type %u",
941 tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset + 1));
943 proto_tree_add_uint(reason_tree, hf_cops_reason_sub, tvb, offset, 2, reason_sub);
946 case COPS_OBJ_DECISION:
947 case COPS_OBJ_LPDPDECISION:
949 cmd_code = tvb_get_ntohs(tvb, offset);
950 cmd_flags = tvb_get_ntohs(tvb, offset + 2);
951 ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Command-Code: %s, Flags: %s",
952 val_to_str(cmd_code, cops_dec_cmd_code_vals, "<Unknown value>"),
953 val_to_str(cmd_flags, cops_dec_cmd_flag_vals, "<Unknown flag>"));
954 dec_tree = proto_item_add_subtree(ti, ett_cops_decision);
955 proto_tree_add_uint(dec_tree, hf_cops_dec_cmd_code, tvb, offset, 2, cmd_code);
957 proto_tree_add_uint(dec_tree, hf_cops_dec_flags, tvb, offset, 2, cmd_flags);
958 } else if (c_type == 5) { /*COPS-PR Data*/
959 ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: %u bytes", len);
960 dec_tree = proto_item_add_subtree(ti, ett_cops_decision);
961 dissect_cops_pr_objects(tvb, offset, dec_tree, len);
964 /* PacketCable : Analyze the remaining data if available */
965 cops_analyze_packetcable_obj(tvb, tree, offset);
972 error = tvb_get_ntohs(tvb, offset);
973 error_sub = tvb_get_ntohs(tvb, offset + 2);
974 ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Error-Code: %s, Error Sub-code: 0x%04x",
975 val_to_str(error, cops_error_vals, "<Unknown value>"), error_sub);
976 error_tree = proto_item_add_subtree(ti, ett_cops_error);
977 proto_tree_add_uint(error_tree, hf_cops_error, tvb, offset, 2, error);
980 proto_tree_add_text(error_tree, tvb, offset, 2, "Error Sub-code: "
981 "Unknown object's C-Num %u, C-Type %u",
982 tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset + 1));
984 proto_tree_add_uint(error_tree, hf_cops_error_sub, tvb, offset, 2, error_sub);
987 case COPS_OBJ_CLIENTSI:
989 /* For PacketCable */
991 cops_analyze_packetcable_obj(tvb, tree, offset);
995 if (c_type != 2) /*Not COPS-PR data*/
998 ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: %u bytes", len);
999 clientsi_tree = proto_item_add_subtree(ti, ett_cops_clientsi);
1001 dissect_cops_pr_objects(tvb, offset, clientsi_tree, len);
1004 case COPS_OBJ_KATIMER:
1008 proto_tree_add_item(tree, hf_cops_katimer, tvb, offset + 2, 2, FALSE);
1009 if (tvb_get_ntohs(tvb, offset + 2) == 0)
1010 proto_tree_add_text(tree, tvb, offset, 0, "Value of zero implies infinity.");
1013 case COPS_OBJ_PEPID:
1017 if (tvb_strnlen(tvb, offset, len) == -1)
1018 proto_tree_add_text(tree, tvb, offset, len, "<PEP Id is not a NUL terminated ASCII string>");
1020 proto_tree_add_item(tree, hf_cops_pepid, tvb, offset,
1021 tvb_strnlen(tvb, offset, len) + 1, FALSE);
1024 case COPS_OBJ_REPORT_TYPE:
1028 proto_tree_add_item(tree, hf_cops_report_type, tvb, offset, 2, FALSE);
1031 case COPS_OBJ_PDPREDIRADDR:
1032 case COPS_OBJ_LASTPDPADDR:
1033 if (c_type == 1) { /* IPv4 */
1034 tvb_memcpy(tvb, (guint8 *)&ipv4addr, offset, 4);
1035 tcp_port = tvb_get_ntohs(tvb, offset + 4 + 2);
1036 ti = proto_tree_add_text(tree, tvb, offset, 8, "Contents: IPv4 address %s, TCP Port Number: %u",
1037 ip_to_str((guint8 *)&ipv4addr), tcp_port);
1038 pdp_tree = proto_item_add_subtree(ti, ett_cops_pdp);
1039 proto_tree_add_ipv4(pdp_tree,
1040 (c_num == COPS_OBJ_PDPREDIRADDR) ? hf_cops_pdprediraddr_ipv4 : hf_cops_lastpdpaddr_ipv4,
1041 tvb, offset, 4, ipv4addr);
1043 } else if (c_type == 2) { /* IPv6 */
1044 tvb_memcpy(tvb, (guint8 *)&ipv6addr, offset, sizeof ipv6addr);
1045 tcp_port = tvb_get_ntohs(tvb, offset + sizeof ipv6addr + 2);
1046 ti = proto_tree_add_text(tree, tvb, offset, 20, "Contents: IPv6 address %s, TCP Port Number: %u",
1047 ip6_to_str(&ipv6addr), tcp_port);
1048 pdp_tree = proto_item_add_subtree(ti, ett_cops_pdp);
1049 proto_tree_add_ipv6(pdp_tree,
1050 (c_num == COPS_OBJ_PDPREDIRADDR) ? hf_cops_pdprediraddr_ipv6 : hf_cops_lastpdpaddr_ipv6,
1051 tvb, offset, 16, (guint8 *)&ipv6addr);
1057 proto_tree_add_uint(pdp_tree, hf_cops_pdp_tcp_port, tvb, offset, 2, tcp_port);
1060 case COPS_OBJ_ACCTTIMER:
1064 proto_tree_add_item(tree, hf_cops_accttimer, tvb, offset + 2, 2, FALSE);
1065 if (tvb_get_ntohs(tvb, offset + 2) == 0)
1066 proto_tree_add_text(tree, tvb, offset, 0, "Value of zero means "
1067 "there SHOULD be no unsolicited accounting updates.");
1070 case COPS_OBJ_INTEGRITY:
1072 break; /* Not HMAC digest */
1074 proto_tree_add_item(tree, hf_cops_key_id, tvb, offset, 4, FALSE);
1075 proto_tree_add_item(tree, hf_cops_seq_num, tvb, offset + 4, 4, FALSE);
1076 proto_tree_add_text(tree, tvb, offset + 8 , len - 8, "Contents: Keyed Message Digest");
1080 proto_tree_add_text(tree, tvb, offset, len, "Contents: %u bytes", len);
1086 #ifdef HAVE_NET_SNMP
1087 static guchar*format_asn_value (struct variable_list *variable, subid_t *variable_oid,
1088 guint variable_oid_length, u_char type_from_packet)
1090 struct tree *subtree=tree_head;
1096 /*Get the ASN.1 type etc. from the PIB-MIB. If unsuccessful use the type from packet*/
1097 subtree = get_tree(variable_oid,variable_oid_length, subtree);
1099 if (subtree->type == 0)
1100 variable->type= type_from_packet;
1102 buf_len = SPRINT_MAX_LEN; /*defined in NET-SNMP's snmp-impl.h*/
1103 buf = g_malloc(buf_len);
1107 /*If the ASN.1 type was found from PIB-MIB, use it for decoding*/
1108 if (!variable->type)
1109 variable->type=mib_to_asn_type(subtree->type);
1111 if (!sprint_realloc_by_type(&buf, &buf_len, &out_len, TRUE, variable, subtree->enums, subtree->hint, NULL))
1112 sprintf(buf,"%s","sprint_realloc_by_type failed");
1116 #endif /* HAVE_NET_SNMP */
1118 static int decode_cops_pr_asn1_data(tvbuff_t *tvb, guint32 offset,
1119 proto_tree *tree, guint asnlen, guint8 cops_pr_obj
1120 #ifndef HAVE_NET_SNMP
1132 gchar *vb_type_name;
1135 guint cls, con, tag;
1136 subid_t epd_attribute_index=0;
1138 gint32 vb_integer_value;
1139 guint32 vb_uinteger_value;
1141 guint8 *vb_octet_string;
1144 guint vb_oid_length;
1146 gchar *vb_display_string;
1147 gchar *vb_display_string2;
1149 #ifdef HAVE_NET_SNMP
1150 struct variable_list variable;
1152 #endif /* HAVE_NET_SNMP */
1158 while (asnlen > 0) { /*while there is ASN stuff to be decoded*/
1160 epd_attribute_index++;
1161 #ifdef HAVE_NET_SNMP
1162 last_decoded_prid_oid[last_decoded_prid_oid_length-1]=epd_attribute_index;
1163 #endif /* HAVE_NET_SNMP */
1164 asn1_open(&asn1, tvb, offset);
1166 /* parse the type of the object */
1168 start = asn1.offset;
1170 ret = asn1_header_decode (&asn1, &cls, &con, &tag, &def, &vb_length);
1171 if (ret != ASN1_ERR_NOERROR)
1174 return ASN1_ERR_LENGTH_NOT_DEFINITE;
1176 /* Convert the class, constructed flag, and tag to a type. */
1177 vb_type_name = cops_tag_cls2syntax(tag, cls, &vb_type);
1178 if (vb_type_name == NULL) {
1181 * Dissect the value as an opaque string of octets.
1183 vb_type_name = "unsupported type";
1184 vb_type = COPS_OPAQUE;
1187 /* parse the value */
1192 ret = asn1_int32_value_decode(&asn1, vb_length, &vb_integer_value);
1193 if (ret != ASN1_ERR_NOERROR)
1195 length = asn1.offset - start;
1197 #ifdef HAVE_NET_SNMP
1198 if (cops_typefrommib == TRUE)
1201 value = vb_integer_value;
1202 variable.val.integer = &value;
1203 variable.val_len = vb_length ;
1204 vb_display_string=format_asn_value(&variable,
1205 last_decoded_prid_oid,last_decoded_prid_oid_length,ASN_INTEGER);
1207 proto_tree_add_text(tree, asn1.tvb, offset, length,
1208 "Value: %s", vb_display_string);
1209 g_free(vb_display_string);
1212 #endif /* HAVE_NET_SNMP */
1213 proto_tree_add_text(tree, asn1.tvb, offset, length,
1214 "Value: %s: %d (%#x)", vb_type_name,
1215 vb_integer_value, vb_integer_value);
1219 case COPS_UNSIGNED32:
1220 case COPS_TIMETICKS:
1221 ret = asn1_uint32_value_decode(&asn1, vb_length, &vb_uinteger_value);
1222 if (ret != ASN1_ERR_NOERROR)
1224 length = asn1.offset - start;
1226 #ifdef HAVE_NET_SNMP
1227 if (cops_typefrommib == TRUE)
1230 value = vb_uinteger_value;
1231 variable.val.integer = &value;
1232 variable.val_len = vb_length;
1234 vb_display_string=format_asn_value(&variable,
1235 last_decoded_prid_oid,last_decoded_prid_oid_length,ASN_UINTEGER);
1237 proto_tree_add_text(tree, asn1.tvb, offset, length, "Value %s: %s",vb_type_name, vb_display_string);
1239 g_free(vb_display_string);
1242 #endif /* HAVE_NET_SNMP */
1243 proto_tree_add_text(tree, asn1.tvb, offset, length,
1244 "Value: %s: %u (%#x)", vb_type_name,
1245 vb_uinteger_value, vb_uinteger_value);
1252 case COPS_UNSIGNED64:
1253 case COPS_INTEGER64:
1254 ret = asn1_string_value_decode (&asn1, vb_length, &vb_octet_string);
1255 if (ret != ASN1_ERR_NOERROR)
1257 length = asn1.offset - start;
1259 #ifdef HAVE_NET_SNMP
1260 if (cops_typefrommib == TRUE)
1263 variable.val.string = vb_octet_string;
1264 variable.val_len = vb_length;
1265 vb_display_string = format_asn_value(&variable,
1266 last_decoded_prid_oid,last_decoded_prid_oid_length,ASN_OCTET_STR);
1267 proto_tree_add_text(tree, asn1.tvb, offset, length,
1268 "Value: %s (ASN.1 type from packet: %s)", vb_display_string, vb_type_name);
1270 g_free(vb_display_string);
1274 #endif /* HAVE_NET_SNMP */
1275 for (i = 0; i < vb_length; i++) {
1276 if (!(isprint(vb_octet_string[i]) ||isspace(vb_octet_string[i])))
1281 * If some characters are not printable, display the string as bytes.
1283 if (i < vb_length) {
1285 * We stopped, due to a non-printable character, before we got
1286 * to the end of the string.
1288 vb_display_string = g_malloc(4*vb_length);
1289 buf = &vb_display_string[0];
1290 len = sprintf(buf, "%03u", vb_octet_string[0]);
1292 for (i = 1; i < vb_length; i++) {
1293 len = sprintf(buf, ".%03u", vb_octet_string[i]);
1296 proto_tree_add_text(tree, asn1.tvb, offset, length,
1297 "Value: %s: %s", vb_type_name, vb_display_string);
1298 g_free(vb_display_string);
1300 proto_tree_add_text(tree, asn1.tvb, offset, length,
1301 "Value: %s: %.*s", vb_type_name, (int)vb_length,
1302 SAFE_STRING(vb_octet_string));
1304 #ifdef HAVE_NET_SNMP
1306 #endif /* HAVE_NET_SNMP */
1308 g_free(vb_octet_string);
1312 ret = asn1_null_decode (&asn1, vb_length);
1313 if (ret != ASN1_ERR_NOERROR)
1315 length = asn1.offset - start;
1317 proto_tree_add_text(tree, asn1.tvb, offset, length, "Value: %s", vb_type_name);
1321 ret = asn1_oid_value_decode (&asn1, vb_length, &vb_oid, &vb_oid_length);
1322 if (ret != ASN1_ERR_NOERROR)
1324 length = asn1.offset - start;
1327 if (cops_pr_obj == COPS_OBJ_PPRID){
1328 /*we're decoding Prefix PRID, that doesn't have a instance Id,
1329 *Use full length of the OID when decoding it.
1331 new_format_oid(vb_oid,vb_oid_length,&vb_display_string,&vb_display_string2);
1333 if (!vb_display_string2) /*if OID couldn't be decoded, print only numeric format*/
1334 proto_tree_add_text(tree, asn1.tvb, offset, length,
1335 "Value: %s: %s", vb_type_name, vb_display_string);
1337 proto_tree_add_text(tree, asn1.tvb, offset, length,
1338 "Value: %s: %s (%s)", vb_type_name,
1340 vb_display_string2);
1342 else { /*we're decoding PRID, Error PRID or EPD*/
1343 /*strip the instance Id from the OIDs before decoding and paste it back during printing*/
1344 new_format_oid(vb_oid,vb_oid_length-1,&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.%lu", vb_type_name,
1350 (unsigned long)vb_oid[vb_oid_length-1]);
1352 proto_tree_add_text(tree, asn1.tvb, offset, length,
1353 "Value: %s: %s.%lu (%s.%lu)", vb_type_name,
1355 (unsigned long)vb_oid[vb_oid_length-1],
1357 (unsigned long)vb_oid[vb_oid_length-1]);
1359 #ifdef HAVE_NET_SNMP
1360 if (cops_pr_obj != COPS_OBJ_EPD) {
1361 /* we're not decoding EPD, so let's store the OID of the PRID so that later
1362 when we're decoding this PRID's EPD we can finetune the output.*/
1363 memcpy(last_decoded_prid_oid,vb_oid,vb_oid_length*sizeof(subid_t));
1364 last_decoded_prid_oid_length=vb_oid_length;
1366 #endif /* HAVE_NET_SNMP */
1368 g_free(vb_display_string);
1369 if(vb_display_string2)
1370 g_free(vb_display_string2);
1376 g_assert_not_reached();
1377 return ASN1_ERR_WRONG_TYPE;
1380 asn1_close(&asn1,&offset);
1384 epd_attribute_index=0;
1388 static int dissect_cops_pr_object_data(tvbuff_t *tvb, guint32 offset, proto_tree *tree,
1389 guint8 s_num, guint8 s_type, guint16 len)
1392 proto_tree *asn1_object_tree, *gperror_tree, *cperror_tree;
1393 guint16 gperror=0, gperror_sub=0, cperror=0, cperror_sub=0;
1397 if (s_type != 1) /* Not Provisioning Instance Identifier (PRID) */
1400 ti=proto_tree_add_text(tree, tvb, offset, len, "Contents:");
1401 asn1_object_tree = proto_item_add_subtree(ti, ett_cops_asn1);
1403 decode_cops_pr_asn1_data(tvb, offset, asn1_object_tree, len, COPS_OBJ_PRID);
1406 case COPS_OBJ_PPRID:
1407 if (s_type != 1) /* Not Prefix Provisioning Instance Identifier (PPRID) */
1410 ti = proto_tree_add_text(tree, tvb, offset, len, "Contents:");
1411 asn1_object_tree = proto_item_add_subtree(ti, ett_cops_asn1);
1413 decode_cops_pr_asn1_data(tvb, offset, asn1_object_tree, len, COPS_OBJ_PPRID);
1417 if (s_type != 1) /* Not Encoded Provisioning Instance Data (EPD) */
1420 ti = proto_tree_add_text(tree, tvb, offset, len, "Contents:");
1421 asn1_object_tree = proto_item_add_subtree(ti, ett_cops_asn1);
1423 decode_cops_pr_asn1_data(tvb, offset, asn1_object_tree, len, COPS_OBJ_EPD);
1426 case COPS_OBJ_GPERR:
1427 if (s_type != 1) /* Not Global Provisioning Error Object (GPERR) */
1430 gperror = tvb_get_ntohs(tvb, offset);
1431 gperror_sub = tvb_get_ntohs(tvb, offset + 2);
1432 ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Error-Code: %s, Error Sub-code: 0x%04x",
1433 val_to_str(gperror, cops_gperror_vals, "<Unknown value>"), gperror_sub);
1434 gperror_tree = proto_item_add_subtree(ti, ett_cops_gperror);
1435 proto_tree_add_uint(gperror_tree, hf_cops_gperror, tvb, offset, 2, gperror);
1437 if (cperror == 13) {
1438 proto_tree_add_text(gperror_tree, tvb, offset, 2, "Error Sub-code: "
1439 "Unknown object's C-Num %u, C-Type %u",
1440 tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset + 1));
1442 proto_tree_add_uint(gperror_tree, hf_cops_gperror_sub, tvb, offset, 2, gperror_sub);
1445 case COPS_OBJ_CPERR:
1446 if (s_type != 1) /*Not PRC Class Provisioning Error Object (CPERR) */
1451 cperror = tvb_get_ntohs(tvb, offset);
1452 cperror_sub = tvb_get_ntohs(tvb, offset + 2);
1453 ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Error-Code: %s, Error Sub-code: 0x%04x",
1454 val_to_str(cperror, cops_cperror_vals, "<Unknown value>"), cperror_sub);
1455 cperror_tree = proto_item_add_subtree(ti, ett_cops_cperror);
1456 proto_tree_add_uint(cperror_tree, hf_cops_cperror, tvb, offset, 2, cperror);
1458 if (cperror == 13) {
1459 proto_tree_add_text(cperror_tree, tvb, offset, 2, "Error Sub-code: "
1460 "Unknown object's S-Num %u, C-Type %u",
1461 tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset + 1));
1463 proto_tree_add_uint(cperror_tree, hf_cops_cperror_sub, tvb, offset, 2, cperror_sub);
1466 case COPS_OBJ_ERRPRID:
1467 if (s_type != 1) /*Not Error Provisioning Instance Identifier (ErrorPRID)*/
1470 ti = proto_tree_add_text(tree, tvb, offset, len, "Contents:");
1471 asn1_object_tree = proto_item_add_subtree(ti, ett_cops_asn1);
1473 decode_cops_pr_asn1_data(tvb, offset, asn1_object_tree, len, COPS_OBJ_ERRPRID);
1477 proto_tree_add_text(tree, tvb, offset, len, "Contents: %u bytes", len);
1485 /* Register the protocol with Ethereal */
1486 void proto_register_cops(void)
1488 /* Setup list of header fields */
1489 static hf_register_info hf[] = {
1490 { &hf_cops_ver_flags,
1491 { "Version and Flags", "cops.ver_flags",
1492 FT_UINT8, BASE_HEX, NULL, 0x0,
1493 "Version and Flags in COPS Common Header", HFILL }
1496 { "Version", "cops.version",
1497 FT_UINT8, BASE_DEC, NULL, 0xF0,
1498 "Version in COPS Common Header", HFILL }
1501 { "Flags", "cops.flags",
1502 FT_UINT8, BASE_HEX, VALS(cops_flags_vals), 0x0F,
1503 "Flags in COPS Common Header", HFILL }
1506 { "Op Code", "cops.op_code",
1507 FT_UINT8, BASE_DEC, VALS(cops_op_code_vals), 0x0,
1508 "Op Code in COPS Common Header", HFILL }
1510 { &hf_cops_client_type,
1511 { "Client Type", "cops.client_type",
1512 FT_UINT16, BASE_DEC, NULL, 0x0,
1513 "Client Type in COPS Common Header", HFILL }
1516 { "Message Length", "cops.msg_len",
1517 FT_UINT32, BASE_DEC, NULL, 0x0,
1518 "Message Length in COPS Common Header", HFILL }
1521 { "Object Length", "cops.obj.len",
1522 FT_UINT32, BASE_DEC, NULL, 0x0,
1523 "Object Length in COPS Object Header", HFILL }
1525 { &hf_cops_obj_c_num,
1526 { "C-Num", "cops.c_num",
1527 FT_UINT8, BASE_DEC, VALS(cops_c_num_vals), 0x0,
1528 "C-Num in COPS Object Header", HFILL }
1530 { &hf_cops_obj_c_type,
1531 { "C-Type", "cops.c_type",
1532 FT_UINT8, BASE_DEC, NULL, 0x0,
1533 "C-Type in COPS Object Header", HFILL }
1536 { &hf_cops_obj_s_num,
1537 { "S-Num", "cops.s_num",
1538 FT_UINT8, BASE_DEC, VALS(cops_s_num_vals), 0x0,
1539 "S-Num in COPS-PR Object Header", HFILL }
1541 { &hf_cops_obj_s_type,
1542 { "S-Type", "cops.s_type",
1543 FT_UINT8, BASE_DEC, NULL, 0x0,
1544 "S-Type in COPS-PR Object Header", HFILL }
1547 { &hf_cops_r_type_flags,
1548 { "R-Type", "cops.context.r_type",
1549 FT_UINT16, BASE_HEX, VALS(cops_r_type_vals), 0xFFFF,
1550 "R-Type in COPS Context Object", HFILL }
1552 { &hf_cops_m_type_flags,
1553 { "M-Type", "cops.context.m_type",
1554 FT_UINT16, BASE_HEX, NULL, 0xFFFF,
1555 "M-Type in COPS Context Object", HFILL }
1557 { &hf_cops_in_int_ipv4,
1558 { "IPv4 address", "cops.in-int.ipv4",
1559 FT_IPv4, 0, NULL, 0xFFFF,
1560 "IPv4 address in COPS IN-Int object", HFILL }
1562 { &hf_cops_in_int_ipv6,
1563 { "IPv6 address", "cops.in-int.ipv6",
1564 FT_IPv6, 0, NULL, 0xFFFF,
1565 "IPv6 address in COPS IN-Int object", HFILL }
1567 { &hf_cops_out_int_ipv4,
1568 { "IPv4 address", "cops.out-int.ipv4",
1569 FT_IPv4, 0, NULL, 0xFFFF,
1570 "IPv4 address in COPS OUT-Int object", HFILL }
1572 { &hf_cops_out_int_ipv6,
1573 { "IPv6 address", "cops.out-int.ipv6",
1574 FT_IPv6, 0, NULL, 0xFFFF,
1575 "IPv6 address in COPS OUT-Int", HFILL }
1577 { &hf_cops_int_ifindex,
1578 { "ifIndex", "cops.in-out-int.ifindex",
1579 FT_UINT32, BASE_DEC, NULL, 0x0,
1580 "If SNMP is supported, corresponds to MIB-II ifIndex", HFILL }
1583 { "Reason", "cops.reason",
1584 FT_UINT16, BASE_DEC, VALS(cops_reason_vals), 0,
1585 "Reason in Reason object", HFILL }
1587 { &hf_cops_reason_sub,
1588 { "Reason Sub-code", "cops.reason_sub",
1589 FT_UINT16, BASE_HEX, NULL, 0,
1590 "Reason Sub-code in Reason object", HFILL }
1592 { &hf_cops_dec_cmd_code,
1593 { "Command-Code", "cops.decision.cmd",
1594 FT_UINT16, BASE_DEC, VALS(cops_dec_cmd_code_vals), 0,
1595 "Command-Code in Decision/LPDP Decision object", HFILL }
1597 { &hf_cops_dec_flags,
1598 { "Flags", "cops.decision.flags",
1599 FT_UINT16, BASE_HEX, VALS(cops_dec_cmd_flag_vals), 0xffff,
1600 "Flags in Decision/LPDP Decision object", HFILL }
1603 { "Error", "cops.error",
1604 FT_UINT16, BASE_DEC, VALS(cops_error_vals), 0,
1605 "Error in Error object", HFILL }
1607 { &hf_cops_error_sub,
1608 { "Error Sub-code", "cops.error_sub",
1609 FT_UINT16, BASE_HEX, NULL, 0,
1610 "Error Sub-code in Error object", HFILL }
1613 { "Contents: KA Timer Value", "cops.katimer.value",
1614 FT_UINT16, BASE_DEC, NULL, 0,
1615 "Keep-Alive Timer Value in KATimer object", HFILL }
1618 { "Contents: PEP Id", "cops.pepid.id",
1619 FT_STRING, BASE_NONE, NULL, 0,
1620 "PEP Id in PEPID object", HFILL }
1622 { &hf_cops_report_type,
1623 { "Contents: Report-Type", "cops.report_type",
1624 FT_UINT16, BASE_DEC, VALS(cops_report_type_vals), 0,
1625 "Report-Type in Report-Type object", HFILL }
1627 { &hf_cops_pdprediraddr_ipv4,
1628 { "IPv4 address", "cops.pdprediraddr.ipv4",
1629 FT_IPv4, 0, NULL, 0xFFFF,
1630 "IPv4 address in COPS PDPRedirAddr object", HFILL }
1632 { &hf_cops_pdprediraddr_ipv6,
1633 { "IPv6 address", "cops.pdprediraddr.ipv6",
1634 FT_IPv6, 0, NULL, 0xFFFF,
1635 "IPv6 address in COPS PDPRedirAddr object", HFILL }
1637 { &hf_cops_lastpdpaddr_ipv4,
1638 { "IPv4 address", "cops.lastpdpaddr.ipv4",
1639 FT_IPv4, 0, NULL, 0xFFFF,
1640 "IPv4 address in COPS LastPDPAddr object", HFILL }
1642 { &hf_cops_lastpdpaddr_ipv6,
1643 { "IPv6 address", "cops.lastpdpaddr.ipv6",
1644 FT_IPv6, 0, NULL, 0xFFFF,
1645 "IPv6 address in COPS LastPDPAddr object", HFILL }
1647 { &hf_cops_pdp_tcp_port,
1648 { "TCP Port Number", "cops.pdp.tcp_port",
1649 FT_UINT32, BASE_DEC, NULL, 0x0,
1650 "TCP Port Number of PDP in PDPRedirAddr/LastPDPAddr object", HFILL }
1652 { &hf_cops_accttimer,
1653 { "Contents: ACCT Timer Value", "cops.accttimer.value",
1654 FT_UINT16, BASE_DEC, NULL, 0,
1655 "Accounting Timer Value in AcctTimer object", HFILL }
1658 { "Contents: Key ID", "cops.integrity.key_id",
1659 FT_UINT32, BASE_DEC, NULL, 0,
1660 "Key ID in Integrity object", HFILL }
1663 { "Contents: Sequence Number", "cops.integrity.seq_num",
1664 FT_UINT32, BASE_DEC, NULL, 0,
1665 "Sequence Number in Integrity object", HFILL }
1668 { "Error", "cops.gperror",
1669 FT_UINT16, BASE_DEC, VALS(cops_gperror_vals), 0,
1670 "Error in Error object", HFILL }
1672 { &hf_cops_gperror_sub,
1673 { "Error Sub-code", "cops.gperror_sub",
1674 FT_UINT16, BASE_HEX, NULL, 0,
1675 "Error Sub-code in Error object", HFILL }
1678 { "Error", "cops.cperror",
1679 FT_UINT16, BASE_DEC, VALS(cops_cperror_vals), 0,
1680 "Error in Error object", HFILL }
1682 { &hf_cops_cperror_sub,
1683 { "Error Sub-code", "cops.cperror_sub",
1684 FT_UINT16, BASE_HEX, NULL, 0,
1685 "Error Sub-code in Error object", HFILL }
1688 /* Added for PacketCable */
1691 { "Object Subtree", "cops.pc_subtree",
1692 FT_UINT16, BASE_HEX, NULL, 0,
1693 "Object Subtree", HFILL }
1695 { &hf_cops_pc_ds_field,
1696 { "DS Field (DSCP or TOS)", "cops.pc_ds_field",
1697 FT_UINT8, BASE_HEX, NULL, 0x00,
1698 "DS Field (DSCP or TOS)", HFILL }
1700 { &hf_cops_pc_direction,
1701 { "Direction", "cops.pc_direction",
1702 FT_UINT8, BASE_HEX, NULL, 0x00,
1703 "Direction", HFILL }
1705 { &hf_cops_pc_gate_spec_flags,
1706 { "Flags", "cops.pc_gate_spec_flags",
1707 FT_UINT8, BASE_HEX, NULL, 0x00,
1710 { &hf_cops_pc_protocol_id,
1711 { "Protocol ID", "cops.pc_protocol_id",
1712 FT_UINT8, BASE_HEX, NULL, 0x00,
1713 "Protocol ID", HFILL }
1715 { &hf_cops_pc_session_class,
1716 { "Session Class", "cops.pc_session_class",
1717 FT_UINT8, BASE_HEX, NULL, 0x00,
1718 "Session Class", HFILL }
1720 { &hf_cops_pc_algorithm,
1721 { "Algorithm", "cops.pc_algorithm",
1722 FT_UINT16, BASE_HEX, NULL, 0x00,
1723 "Algorithm", HFILL }
1725 { &hf_cops_pc_cmts_ip_port,
1726 { "CMTS IP Port", "cops.pc_cmts_ip_port",
1727 FT_UINT16, BASE_HEX, NULL, 0x00,
1728 "CMTS IP Port", HFILL }
1730 { &hf_cops_pc_dest_port,
1731 { "Destination IP Port", "cops.pc_dest_port",
1732 FT_UINT16, BASE_HEX, NULL, 0x00,
1733 "Destination IP Port", HFILL }
1735 { &hf_cops_pc_packetcable_err_code,
1736 { "Error Code", "cops.pc_packetcable_err_code",
1737 FT_UINT16, BASE_HEX, NULL, 0x00,
1738 "Error Code", HFILL }
1740 { &hf_cops_pc_packetcable_sub_code,
1741 { "Error Sub Code", "cops.pc_packetcable_sub_code",
1742 FT_UINT16, BASE_HEX, NULL, 0x00,
1743 "Error Sub Code", HFILL }
1745 { &hf_cops_pc_remote_flags,
1746 { "Flags", "cops.pc_remote_flags",
1747 FT_UINT16, BASE_HEX, NULL, 0x00,
1750 { &hf_cops_pc_close_subcode,
1751 { "Reason Sub Code", "cops.pc_close_subcode",
1752 FT_UINT16, BASE_HEX, NULL, 0x00,
1753 "Reason Sub Code", HFILL }
1755 { &hf_cops_pc_gate_command_type,
1756 { "Gate Command Type", "cops.pc_gate_command_type",
1757 FT_UINT16, BASE_HEX, NULL, 0x00,
1758 "Gate Command Type", HFILL }
1760 { &hf_cops_pc_reason_code,
1761 { "Reason Code", "cops.pc_reason_code",
1762 FT_UINT16, BASE_HEX, NULL, 0x00,
1763 "Reason Code", HFILL }
1765 { &hf_cops_pc_delete_subcode,
1766 { "Reason Sub Code", "cops.pc_delete_subcode",
1767 FT_UINT16, BASE_HEX, NULL, 0x00,
1768 "Reason Sub Code", HFILL }
1770 { &hf_cops_pc_src_port,
1771 { "Source IP Port", "cops.pc_src_port",
1772 FT_UINT16, BASE_HEX, NULL, 0x00,
1773 "Source IP Port", HFILL }
1775 { &hf_cops_pc_t1_value,
1776 { "Timer T1 Value (sec)", "cops.pc_t1_value",
1777 FT_UINT16, BASE_HEX, NULL, 0x00,
1778 "Timer T1 Value (sec)", HFILL }
1780 { &hf_cops_pc_t7_value,
1781 { "Timer T7 Value (sec)", "cops.pc_t7_value",
1782 FT_UINT16, BASE_HEX, NULL, 0x00,
1783 "Timer T7 Value (sec)", HFILL }
1785 { &hf_cops_pc_t8_value,
1786 { "Timer T8 Value (sec)", "cops.pc_t8_value",
1787 FT_UINT16, BASE_HEX, NULL, 0x00,
1788 "Timer T8 Value (sec)", HFILL }
1790 { &hf_cops_pc_transaction_id,
1791 { "Transaction Identifier", "cops.pc_transaction_id",
1792 FT_UINT16, BASE_HEX, NULL, 0x00,
1793 "Transaction Identifier", HFILL }
1795 { &hf_cops_pc_cmts_ip,
1796 { "CMTS IP Address", "cops.pc_cmts_ip",
1797 FT_UINT32, BASE_HEX, NULL, 0x00,
1798 "CMTS IP Address", HFILL }
1800 { &hf_cops_pc_activity_count,
1801 { "Count", "cops.pc_activity_count",
1802 FT_UINT32, BASE_HEX, NULL, 0x00,
1805 { &hf_cops_pc_dest_ip,
1806 { "Destination IP Address", "cops.pc_dest_ip",
1807 FT_UINT32, BASE_HEX, NULL, 0x00,
1808 "Destination IP Address", HFILL }
1810 { &hf_cops_pc_gate_id,
1811 { "Gate Identifier", "cops.pc_gate_id",
1812 FT_UINT32, BASE_HEX, NULL, 0x00,
1813 "Gate Identifier", HFILL }
1815 { &hf_cops_pc_max_packet_size,
1816 { "Maximum Packet Size", "cops.pc_max_packet_size",
1817 FT_UINT32, BASE_HEX, NULL, 0x00,
1818 "Maximum Packet Size", HFILL }
1820 { &hf_cops_pc_min_policed_unit,
1821 { "Minimum Policed Unit", "cops.pc_min_policed_unit",
1822 FT_UINT32, BASE_HEX, NULL, 0x00,
1823 "Minimum Policed Unit", HFILL }
1825 { &hf_cops_pc_peak_data_rate,
1826 { "Peak Data Rate", "cops.pc_peak_data_rate",
1827 FT_UINT32, BASE_HEX, NULL, 0x00,
1828 "Peak Data Rate", HFILL }
1830 { &hf_cops_pc_spec_rate,
1831 { "Rate", "cops.pc_spec_rate",
1832 FT_UINT32, BASE_HEX, NULL, 0x00,
1835 { &hf_cops_pc_remote_gate_id,
1836 { "Remote Gate ID", "cops.pc_remote_gate_id",
1837 FT_UINT32, BASE_HEX, NULL, 0x00,
1838 "Remote Gate ID", HFILL }
1840 { &hf_cops_pc_reserved,
1841 { "Reserved", "cops.pc_reserved",
1842 FT_UINT32, BASE_HEX, NULL, 0x00,
1846 { "Security Key", "cops.pc_key",
1847 FT_UINT32, BASE_HEX, NULL, 0x00,
1848 "Security Key", HFILL }
1850 { &hf_cops_pc_slack_term,
1851 { "Slack Term", "cops.pc_slack_term",
1852 FT_UINT32, BASE_HEX, NULL, 0x00,
1853 "Slack Term", HFILL }
1855 { &hf_cops_pc_src_ip,
1856 { "Source IP Address", "cops.pc_src_ip",
1857 FT_UINT32, BASE_HEX, NULL, 0x00,
1858 "Source IP Address", HFILL }
1860 { &hf_cops_pc_subscriber_id,
1861 { "Subscriber Identifier (IPv4)", "cops.pc_subscriber_id",
1862 FT_UINT32, BASE_HEX, NULL, 0x00,
1863 "Subscriber Identifier (IPv4)", HFILL }
1865 { &hf_cops_pc_token_bucket_rate,
1866 { "Token Bucket Rate", "cops.pc_token_bucket_rate",
1867 FT_UINT32, BASE_HEX, NULL, 0x00,
1868 "Token Bucket Rate", HFILL }
1870 { &hf_cops_pc_token_bucket_size,
1871 { "Token Bucket Size", "cops.pc_token_bucket_size",
1872 FT_UINT32, BASE_HEX, NULL, 0x00,
1873 "Token Bucket Size", HFILL }
1875 /* End of addition for PacketCable */
1879 /* Setup protocol subtree array */
1880 static gint *ett[] = {
1882 &ett_cops_ver_flags,
1886 &ett_cops_r_type_flags,
1899 module_t* cops_module;
1901 /* Register the protocol name and description */
1902 proto_cops = proto_register_protocol("Common Open Policy Service",
1905 /* Required function calls to register the header fields and subtrees used */
1906 proto_register_field_array(proto_cops, hf, array_length(hf));
1907 proto_register_subtree_array(ett, array_length(ett));
1909 /* Register our configuration options for cops */
1910 cops_module = prefs_register_protocol(proto_cops, proto_reg_handoff_cops);
1911 prefs_register_uint_preference(cops_module,"tcp.cops_port",
1913 "Set the TCP port for COPS messages",
1914 10,&global_cops_tcp_port);
1915 prefs_register_bool_preference(cops_module, "desegment",
1916 "Desegment all COPS messages\nspanning multiple TCP segments",
1917 "Whether the COPS dissector should desegment all messages spanning multiple TCP segments",
1920 /* For PacketCable */
1921 prefs_register_bool_preference(cops_module, "packetcable",
1922 "Decode for PacketCable clients",
1923 "Decode the COPS messages using PacketCable clients",
1926 #ifdef HAVE_NET_SNMP /*enable preference only if compiled with NET-SNMP*/
1927 prefs_register_bool_preference(cops_module, "typefrommib",
1928 "Decode COPS-PR ASN.1 types by reading them\nfrom PIBs (converted to MIBs)",
1929 "Whether the COPS dissector should decode COPS-PR ASN.1 types based on data types read from packet or PIBs (converted to MIBs)",
1931 #endif /*HAVE_NET_SNMP*/
1934 void proto_reg_handoff_cops(void)
1936 static int cops_prefs_initialized = FALSE;
1937 static dissector_handle_t cops_handle;
1939 if (!cops_prefs_initialized) {
1940 cops_handle = create_dissector_handle(dissect_cops, proto_cops);
1941 cops_prefs_initialized = TRUE;
1943 dissector_delete("tcp.port",cops_tcp_port,cops_handle);
1945 /* Set our port numbers for future use */
1946 cops_tcp_port = global_cops_tcp_port;
1948 dissector_add("tcp.port", cops_tcp_port, cops_handle);
1952 /* Additions for PacketCable ( Added by Dick Gooris, Lucent Technologies ) */
1954 /* Definitions for print formatting */
1960 /* Print the translated information in the display gui in a formatted way...
1962 * octets = The number of octets to obtain from the buffer
1964 * vsp = If not a NULL pointer, it points to an array with text, indexed by the obtained value
1966 * mode = 0 -> print decimal value
1967 * 1 -> print hexadecial vaue
1968 * 2 -> print value as an ip address
1969 * 3 -> print value as an ieee float
1971 * This function could well be generalized. Using this function in combination with the
1972 * separate function cops_to_subtree() for subtrees, will give great structure to table formatted messages
1973 * like PacketCable cops, and many other protocols.
1977 void cops_to_disp_fmt(tvbuff_t *tvb, proto_item *stt, int offset, int octets, char *str, const value_string *vsp, int mode,gint *hf_cops_parameter)
1982 guint32 code32 = 0L;
1983 guint32 codeip = 0L;
1986 /* Print information elements in the specified way */
1991 code8 = tvb_get_guint8( tvb, offset );
1993 /* Hexadecimal format */
1995 proto_tree_add_uint_format(stt, *hf_cops_parameter,tvb,
1996 offset, octets, code8,"%-28s : 0x%02x",str,code8);
1998 /* Print an 8 bits integer */
1999 proto_tree_add_uint_format(stt, *hf_cops_parameter,tvb,
2000 offset, octets, code8,"%-28s : %u",str,code8);
2003 /* Hexadecimal format */
2004 proto_tree_add_uint_format(
2005 stt, *hf_cops_parameter,tvb, offset, octets, code8,
2006 "%-28s : %s (0x%02x)",str,val_to_str(code8, vsp, "Unknown"),code8);
2008 /* String table indexed */
2009 proto_tree_add_uint_format(
2010 stt, *hf_cops_parameter,tvb, offset, octets, code8,
2011 "%-28s : %s (%u)",str,val_to_str(code8, vsp, "Unknown"),code8);
2017 /* Get the next two octets */
2018 code16 = tvb_get_ntohs(tvb,offset);
2020 /* Hexadecimal format */
2022 proto_tree_add_uint_format(stt, *hf_cops_parameter,tvb,
2023 offset, octets, code16,"%-28s : 0x%04x",str,code16);
2025 /* Print a 16 bits integer */
2026 proto_tree_add_uint_format(stt, *hf_cops_parameter,tvb,
2027 offset, octets, code16,"%-28s : %u",str,code16);
2030 /* Hexadecimal format */
2031 proto_tree_add_uint_format(stt, *hf_cops_parameter,tvb,
2032 offset, octets, code16,"%-28s : %s (0x%04x)", str,
2033 val_to_str(code16, vsp, "Unknown (0x%04x)"),code16);
2035 /* Print a 16 bits integer */
2036 proto_tree_add_uint_format(
2037 stt, *hf_cops_parameter,tvb, offset, octets, code16,
2038 "%-28s : %s (%u)",str,val_to_str(code16, vsp, "Unknown (0x%04x)"),code16);
2044 /* Get the next four octets */
2046 case FMT_FLT: codefl = tvb_get_ntohieee_float(tvb,offset);
2048 case FMT_IP: tvb_memcpy(tvb, (guint8 *)&code32, offset, 4);
2049 codeip = tvb_get_ntohl(tvb,offset);
2051 default: code32 = tvb_get_ntohl(tvb,offset);
2055 /* Hexadecimal format */
2056 if (mode==FMT_HEX) {
2057 proto_tree_add_uint_format(stt, *hf_cops_parameter,tvb,
2058 offset, octets, code32,"%-28s : 0x%08x",str,code32);
2061 /* Ip address format*/
2063 proto_tree_add_uint_format(stt, *hf_cops_parameter,tvb, offset,octets,
2064 codeip,"%-28s : %s",str,ip_to_str((guint8 *)&code32));
2067 /* Ieee float format */
2068 if (mode==FMT_FLT) {
2069 proto_tree_add_uint_format(stt, *hf_cops_parameter,tvb, offset, octets,
2070 codefl,"%-28s : %.10g",str,codefl);
2073 /* Print a 32 bits integer */
2074 proto_tree_add_uint_format(stt, *hf_cops_parameter,tvb, offset, octets,
2075 code32,"%-28s : %u",str,code32);
2077 /* Hexadecimal format */
2079 proto_tree_add_uint_format(stt, *hf_cops_parameter,tvb, offset, octets,
2080 code32,"%-28s : %s (0x%08x)",str,val_to_str(code32, vsp, "Unknown"),code32);
2082 /* String table indexed */
2083 proto_tree_add_uint_format(stt, *hf_cops_parameter,tvb, offset, octets,
2084 code32,"%-28s : %s (%u)",str,val_to_str(code32, vsp, "Unknown"),code32);
2088 /* In case of more than 4 octets.... */
2091 proto_tree_add_bytes(stt, *hf_cops_parameter,
2092 tvb, offset, octets, tvb_get_ptr(tvb, offset,octets));
2094 proto_tree_add_uint_format(stt, *hf_cops_parameter,
2095 tvb, offset, octets, code32,"%s",str);
2101 /* Print the subtree information */
2102 proto_tree *cops_to_subtree(tvbuff_t *tvb, proto_tree *st, int n, int offset, char *str) {
2105 tv = proto_tree_add_uint_format( st, hf_cops_subtree, tvb, offset, n, (guint)NULL, str);
2106 return( proto_item_add_subtree( tv, ett_cops_subtree ) );
2109 /* Cops - Section : Transaction ID */
2110 void cops_transaction_id(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
2116 /* Create a subtree */
2117 stt = cops_to_subtree(tvb,st,n,offset,"Transaction ID");
2119 /* Transaction Identifier */
2120 cops_to_disp_fmt(tvb,stt,offset,2,"Transaction Identifier", NULL,FMT_DEC,&hf_cops_pc_transaction_id);
2123 /* Gate Command Type */
2124 code16 = tvb_get_ntohs(tvb,offset);
2125 proto_tree_add_uint_format(stt, hf_cops_pc_gate_command_type,tvb, offset, 2,
2126 code16,"%-28s : %s (%u)", "Gate Command Type",
2127 val_to_str(code16,table_cops_transaction_id, "Unknown (0x%04x)"),code16);
2129 /* Write the right data into the 'info field' on the Gui */
2130 sprintf(info,"COPS %-20s - ",val_to_str(opcode_idx,cops_op_code_vals, "Unknown"));
2131 strcat(info,val_to_str(code16,table_cops_transaction_id, "Unknown"));
2133 if (check_col(cpinfo->cinfo, COL_INFO)) {
2134 col_clear(cpinfo->cinfo, COL_INFO);
2135 col_add_str(cpinfo->cinfo, COL_INFO,info);
2140 /* Cops - Section : Subscriber ID */
2141 void cops_subscriber_id_v4(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
2145 /* Create a subtree */
2146 tv = cops_to_subtree(tvb,st,n,offset,"Subscriber ID");
2148 /* Subscriber Identifier */
2149 cops_to_disp_fmt(tvb,tv,offset,4,"Subscriber Identifier (IPv4)", NULL,FMT_IP,&hf_cops_pc_subscriber_id);
2152 /* Cops - Section : Gate ID */
2153 void cops_gate_id(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
2157 /* Create a subtree */
2158 stt = cops_to_subtree(tvb,st,n,offset,"Gate ID");
2160 /* Gate Identifier */
2161 cops_to_disp_fmt(tvb,stt,offset,4,"Gate Identifier", NULL,FMT_HEX,&hf_cops_pc_gate_id);
2164 /* Cops - Section : Activity Count */
2165 void cops_activity_count(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
2169 /* Create a subtree */
2170 stt = cops_to_subtree(tvb,st,n,offset,"Activity Count");
2172 /* Activity Count */
2173 cops_to_disp_fmt(tvb,stt,offset,4,"Count", NULL,FMT_DEC,&hf_cops_pc_activity_count);
2176 /* Cops - Section : Gate Specifications */
2177 void cops_gate_specs(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
2181 /* Create a subtree */
2182 stt = cops_to_subtree(tvb,st,n,offset,"Gate Specifications");
2185 cops_to_disp_fmt(tvb,stt,offset,1,"Direction",table_cops_direction,FMT_DEC,&hf_cops_pc_direction);
2189 cops_to_disp_fmt(tvb,stt,offset,1,"Protocol ID",NULL,FMT_DEC,&hf_cops_pc_protocol_id);
2193 cops_to_disp_fmt(tvb,stt,offset,1,"Flags",NULL,FMT_DEC,&hf_cops_pc_gate_spec_flags);
2197 cops_to_disp_fmt(tvb,stt,offset,1,"Session Class",table_cops_session_class,FMT_DEC,&hf_cops_pc_session_class);
2200 /* Source IP Address */
2201 cops_to_disp_fmt(tvb,stt,offset,4,"Source IP Address",NULL,FMT_IP,&hf_cops_pc_src_ip);
2204 /* Destination IP Address */
2205 cops_to_disp_fmt(tvb,stt,offset,4,"Destination IP Address",NULL,FMT_IP,&hf_cops_pc_dest_ip);
2208 /* Source IP Port */
2209 cops_to_disp_fmt(tvb,stt,offset,2,"Source IP Port",NULL,FMT_DEC,&hf_cops_pc_src_port);
2212 /* Destination IP Port */
2213 cops_to_disp_fmt(tvb,stt,offset,2,"Destination IP Port",NULL,FMT_DEC,&hf_cops_pc_dest_port);
2216 /* DiffServ Code Point */
2217 cops_to_disp_fmt(tvb,stt,offset,1,"DS Field (DSCP or TOS)",NULL,FMT_HEX,&hf_cops_pc_ds_field);
2220 /* 3 octets Not specified */
2223 /* Timer T1 Value */
2224 cops_to_disp_fmt(tvb,stt,offset,2,"Timer T1 Value (sec)",NULL,FMT_DEC,&hf_cops_pc_t1_value);
2228 cops_to_disp_fmt(tvb,stt,offset,2,"Reserved",NULL,FMT_DEC,&hf_cops_pc_reserved);
2231 /* Timer T7 Value */
2232 cops_to_disp_fmt(tvb,stt,offset,2,"Timer T7 Value (sec)",NULL,FMT_DEC,&hf_cops_pc_t7_value);
2235 /* Timer T8 Value */
2236 cops_to_disp_fmt(tvb,stt,offset,2,"Timer T8 Value (sec)",NULL,FMT_DEC,&hf_cops_pc_t8_value);
2239 /* Token Bucket Rate */
2240 cops_to_disp_fmt(tvb,stt,offset,4,"Token Bucket Rate",NULL,FMT_FLT,&hf_cops_pc_token_bucket_rate);
2243 /* Token Bucket Size */
2244 cops_to_disp_fmt(tvb,stt,offset,4,"Token Bucket Size",NULL,FMT_FLT,&hf_cops_pc_token_bucket_size);
2247 /* Peak Data Rate */
2248 cops_to_disp_fmt(tvb,stt,offset,4,"Peak Data Rate",NULL,FMT_FLT,&hf_cops_pc_peak_data_rate);
2251 /* Minimum Policed Unit */
2252 cops_to_disp_fmt(tvb,stt,offset,4,"Minimum Policed Unit",NULL,FMT_DEC,&hf_cops_pc_min_policed_unit);
2255 /* Maximum Packet Size */
2256 cops_to_disp_fmt(tvb,stt,offset,4,"Maximum Packet Size",NULL,FMT_DEC,&hf_cops_pc_max_packet_size);
2260 cops_to_disp_fmt(tvb,stt,offset,4,"Rate",NULL,FMT_FLT,&hf_cops_pc_spec_rate);
2264 cops_to_disp_fmt(tvb,stt,offset,4,"Slack Term",NULL,FMT_DEC,&hf_cops_pc_slack_term);
2269 /* Cops - Section : Remote Gate */
2270 void cops_remote_gate_info(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
2274 /* Create a subtree */
2275 stt = cops_to_subtree(tvb,st,n,offset,"Remote Gate Info");
2277 /* CMTS IP Address */
2278 cops_to_disp_fmt(tvb,stt,offset,4,"CMTS IP Address", NULL,FMT_IP,&hf_cops_pc_cmts_ip);
2282 cops_to_disp_fmt(tvb,stt,offset,2,"CMTS IP Port",NULL,FMT_DEC,&hf_cops_pc_cmts_ip_port);
2286 cops_to_disp_fmt(tvb,stt,offset,2,"Flags",NULL,FMT_DEC,&hf_cops_pc_remote_flags);
2289 /* Remote Gate ID */
2290 cops_to_disp_fmt(tvb,stt,offset,4,"Remote Gate ID", NULL,FMT_HEX,&hf_cops_pc_remote_gate_id);
2294 cops_to_disp_fmt(tvb,stt,offset,2,"Algorithm", NULL,FMT_IP,&hf_cops_pc_algorithm);
2298 cops_to_disp_fmt(tvb,stt,offset,4,"Reserved", NULL,FMT_IP,&hf_cops_pc_reserved);
2302 cops_to_disp_fmt(tvb,stt,offset,4,"Security Key", NULL,FMT_HEX,&hf_cops_pc_key);
2306 cops_to_disp_fmt(tvb,stt,offset,4,"Security Key (cont)", NULL,FMT_HEX,&hf_cops_pc_key);
2310 cops_to_disp_fmt(tvb,stt,offset,4,"Security Key (cont)", NULL,FMT_HEX,&hf_cops_pc_key);
2314 cops_to_disp_fmt(tvb,stt,offset,4,"Security Key (cont)", NULL,FMT_HEX,&hf_cops_pc_key);
2317 /* Cops - Section : PacketCable reason */
2318 void cops_packetcable_reason(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
2323 /* Create a subtree */
2324 stt = cops_to_subtree(tvb,st,n,offset,"PacketCable Reason");
2327 code16 = tvb_get_ntohs(tvb,offset);
2328 proto_tree_add_uint_format(stt, hf_cops_pc_reason_code,tvb, offset, 2,
2329 code16, "%-28s : %s (%u)","Reason Code",
2330 val_to_str(code16, table_cops_reason_code, "Unknown (0x%04x)"),code16);
2333 if ( code16 == 0 ) {
2334 /* Reason Sub Code with Delete */
2335 cops_to_disp_fmt(tvb,stt,offset,2,"Reason Sub Code",table_cops_reason_subcode_delete,FMT_DEC,&hf_cops_pc_delete_subcode);
2337 /* Reason Sub Code with Close */
2338 cops_to_disp_fmt(tvb,stt,offset,2,"Reason Sub Code",table_cops_reason_subcode_close,FMT_DEC,&hf_cops_pc_close_subcode);
2342 /* Cops - Section : PacketCable error */
2343 void cops_packetcable_error(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
2347 /* Create a subtree */
2348 stt = cops_to_subtree(tvb,st,n,offset,"PacketCable Error");
2351 cops_to_disp_fmt(tvb,stt,offset,2,"Error Code",table_cops_packetcable_error,FMT_DEC,&hf_cops_pc_packetcable_err_code);
2354 /* Error Sub Code */
2355 cops_to_disp_fmt(tvb,stt,offset,2,"Error Sub Code",NULL,FMT_HEX,&hf_cops_pc_packetcable_sub_code);
2359 /* Analyze the PacketCable objects */
2360 void cops_analyze_packetcable_obj(tvbuff_t *tvb, proto_tree *tree, guint32 offset) {
2364 guint8 s_num, s_type;
2366 /* Only if this option is enabled by the Gui */
2367 if ( cops_packetcable == FALSE ) {
2371 /* Do the remaining client specific objects */
2372 remdata = tvb_length_remaining(tvb, offset);
2373 while (remdata > 4) {
2375 /* In case we have remaining data, then lets try to get this analyzed */
2376 object_len = tvb_get_ntohs(tvb, offset);
2377 s_num = tvb_get_guint8(tvb, offset + 2);
2378 s_type = tvb_get_guint8(tvb, offset + 3);
2383 /* Perform the appropriate functions */
2387 cops_transaction_id(tvb, tree, object_len, offset);
2392 cops_subscriber_id_v4(tvb, tree, object_len, offset);
2397 cops_gate_id(tvb, tree, object_len, offset);
2402 cops_activity_count(tvb, tree, object_len, offset);
2407 cops_gate_specs(tvb, tree, object_len, offset);
2412 cops_remote_gate_info(tvb, tree, object_len, offset);
2417 cops_packetcable_error(tvb, tree, object_len, offset);
2422 cops_packetcable_reason(tvb, tree, object_len, offset);
2428 offset += object_len-4;
2430 /* See what we can still get from the buffer */
2431 remdata = tvb_length_remaining(tvb, offset);
2435 /* End of PacketCable Addition */