aboutsummaryrefslogtreecommitdiffstats
path: root/packet-cops.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2003-09-08 19:40:10 +0000
committerGuy Harris <guy@alum.mit.edu>2003-09-08 19:40:10 +0000
commit495ddf2d53792e394d8292b9874774cc5b75f7e2 (patch)
tree7435affe6be91acd376c3042732c088a8860b547 /packet-cops.c
parentbc91283f0a312d1909f739d4234a684e909a40ac (diff)
From Kari Tiirikainen:
COPS Dissector as been updated to - Optionally read ASN.1 type and enumeration information from PIBs (first converted to MIBs using guidelines in RFC 3159, Appendix A) and use that information when decoding the BER encoded COPS-PR data. By default this option is disabled. This option requires that Ethereal is compiled with NET-SNMP library. Only PRID OIDs are printed in textual format if UCD-SNMP is used. - Decode the instaceids of PRIDs correctly (the textual decoding no longer hides the InstanceId) svn path=/trunk/; revision=8414
Diffstat (limited to 'packet-cops.c')
-rw-r--r--packet-cops.c2382
1 files changed, 1223 insertions, 1159 deletions
diff --git a/packet-cops.c b/packet-cops.c
index e26508f872..772a220303 100644
--- a/packet-cops.c
+++ b/packet-cops.c
@@ -4,7 +4,7 @@
*
* Copyright 2000, Heikki Vatiainen <hessu@cs.tut.fi>
*
- * $Id: packet-cops.c,v 1.33 2003/02/21 00:11:31 guy Exp $
+ * $Id: packet-cops.c,v 1.34 2003/09/08 19:40:10 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@@ -39,16 +39,34 @@
#include "packet-ipv6.h"
#include "packet-tcp.h"
+#ifdef HAVE_SOME_SNMP
+#ifdef HAVE_NET_SNMP
+# include <net-snmp/net-snmp-config.h>
+# include <net-snmp/mib_api.h>
+# include <net-snmp/library/default_store.h>
+# include <net-snmp/config_api.h>
+#else /* HAVE_NET_SNMP */
+# include <ucd-snmp/ucd-snmp-config.h>
+# include <ucd-snmp/asn1.h>
+# include <ucd-snmp/snmp_api.h>
+# include <ucd-snmp/snmp_impl.h>
+# include <ucd-snmp/mib.h>
+# include <ucd-snmp/default_store.h>
+# include <ucd-snmp/read_config.h>
+# include <ucd-snmp/tools.h>
+#endif /* HAVE_NET_SNMP */
+#endif /* HAVE_SOME_SNMP */
+
#include "asn1.h"
#include "format-oid.h"
#include "prefs.h"
#define TCP_PORT_COPS 3288
-/* Variable to hold the tcp port preference */
+/* Preference: Variable to hold the tcp port preference */
static guint global_cops_tcp_port = TCP_PORT_COPS;
-/* desegmentation of COPS */
+/* Preference: desegmentation of COPS */
static gboolean cops_desegment = TRUE;
/* Variable to allow for proper deletion of dissector registration
@@ -57,7 +75,18 @@ static gboolean cops_desegment = TRUE;
static guint cops_tcp_port = 0;
-static gchar *last_decoded_prid=NULL;
+/*Some local globals needed to read COPS-PR ASN.1 Types from PIB-MIBs */
+/*MAX_OID_LEN from NET-SNMP's asn1.h*/
+
+#ifdef HAVE_NET_SNMP
+static subid_t last_decoded_prid_oid[MAX_OID_LEN]={0};
+static subid_t last_decoded_prid_oid_length=0;
+extern struct tree *tree_head;
+
+/* Preference: COPS-PR ASN.1 type decoding based on PIB/MIB or data in packet */
+static gboolean cops_typefrommib = FALSE;
+
+#endif /* HAVE_NET_SNMP */
#define COPS_OBJECT_HDR_SIZE 4
@@ -117,236 +146,236 @@ static COPS_CNV CopsCnv [] =
static gchar *
cops_tag_cls2syntax ( guint tag, guint cls, gushort *syntax)
{
- COPS_CNV *cnv;
+ COPS_CNV *cnv;
- cnv = CopsCnv;
- while (cnv->syntax != -1)
+ cnv = CopsCnv;
+ while (cnv->syntax != -1)
+ {
+ if (cnv->tag == tag && cnv->class == cls)
{
- if (cnv->tag == tag && cnv->class == cls)
- {
- *syntax = cnv->syntax;
- return cnv->name;
- }
- cnv++;
+ *syntax = cnv->syntax;
+ return cnv->name;
}
- return NULL;
+ cnv++;
+ }
+ return NULL;
}
static const value_string cops_flags_vals[] = {
- { 0x00, "None" },
- { 0x01, "Solicited Message Flag Bit" },
- { 0, NULL },
+ { 0x00, "None" },
+ { 0x01, "Solicited Message Flag Bit" },
+ { 0, NULL },
};
/* The different COPS message types */
enum cops_op_code {
- COPS_NO_MSG, /* Not a COPS Message type */
-
- COPS_MSG_REQ, /* Request (REQ) */
- COPS_MSG_DEC, /* Decision (DEC) */
- COPS_MSG_RPT, /* Report State (RPT) */
- COPS_MSG_DRQ, /* Delete Request State (DRQ) */
- COPS_MSG_SSQ, /* Synchronize State Req (SSQ) */
- COPS_MSG_OPN, /* Client-Open (OPN) */
- COPS_MSG_CAT, /* Client-Accept (CAT) */
- COPS_MSG_CC, /* Client-Close (CC) */
- COPS_MSG_KA, /* Keep-Alive (KA) */
- COPS_MSG_SSC, /* Synchronize Complete (SSC) */
-
- COPS_LAST_OP_CODE /* For error checking */
+ COPS_NO_MSG, /* Not a COPS Message type */
+
+ COPS_MSG_REQ, /* Request (REQ) */
+ COPS_MSG_DEC, /* Decision (DEC) */
+ COPS_MSG_RPT, /* Report State (RPT) */
+ COPS_MSG_DRQ, /* Delete Request State (DRQ) */
+ COPS_MSG_SSQ, /* Synchronize State Req (SSQ) */
+ COPS_MSG_OPN, /* Client-Open (OPN) */
+ COPS_MSG_CAT, /* Client-Accept (CAT) */
+ COPS_MSG_CC, /* Client-Close (CC) */
+ COPS_MSG_KA, /* Keep-Alive (KA) */
+ COPS_MSG_SSC, /* Synchronize Complete (SSC) */
+
+ COPS_LAST_OP_CODE /* For error checking */
};
static const value_string cops_op_code_vals[] = {
- { COPS_MSG_REQ, "Request (REQ)" },
- { COPS_MSG_DEC, "Decision (DEC)" },
- { COPS_MSG_RPT, "Report State (RPT)" },
- { COPS_MSG_DRQ, "Delete Request State (DRQ)" },
- { COPS_MSG_SSQ, "Synchronize State Req (SSQ)" },
- { COPS_MSG_OPN, "Client-Open (OPN)" },
- { COPS_MSG_CAT, "Client-Accept (CAT)" },
- { COPS_MSG_CC, "Client-Close (CC)" },
- { COPS_MSG_KA, "Keep-Alive (KA)" },
- { COPS_MSG_SSC, "Synchronize Complete (SSC)" },
- { 0, NULL },
+ { COPS_MSG_REQ, "Request (REQ)" },
+ { COPS_MSG_DEC, "Decision (DEC)" },
+ { COPS_MSG_RPT, "Report State (RPT)" },
+ { COPS_MSG_DRQ, "Delete Request State (DRQ)" },
+ { COPS_MSG_SSQ, "Synchronize State Req (SSQ)" },
+ { COPS_MSG_OPN, "Client-Open (OPN)" },
+ { COPS_MSG_CAT, "Client-Accept (CAT)" },
+ { COPS_MSG_CC, "Client-Close (CC)" },
+ { COPS_MSG_KA, "Keep-Alive (KA)" },
+ { COPS_MSG_SSC, "Synchronize Complete (SSC)" },
+ { 0, NULL },
};
/* The different objects in COPS messages */
enum cops_c_num {
- COPS_NO_OBJECT, /* Not a COPS Object type */
-
- COPS_OBJ_HANDLE, /* Handle Object (Handle) */
- COPS_OBJ_CONTEXT, /* Context Object (Context) */
- COPS_OBJ_IN_INT, /* In-Interface Object (IN-Int) */
- COPS_OBJ_OUT_INT, /* Out-Interface Object (OUT-Int) */
- COPS_OBJ_REASON, /* Reason Object (Reason) */
- COPS_OBJ_DECISION, /* Decision Object (Decision) */
- COPS_OBJ_LPDPDECISION, /* LPDP Decision Object (LPDPDecision) */
- COPS_OBJ_ERROR, /* Error Object (Error) */
- COPS_OBJ_CLIENTSI, /* Client Specific Information Object (ClientSI) */
- COPS_OBJ_KATIMER, /* Keep-Alive Timer Object (KATimer) */
- COPS_OBJ_PEPID, /* PEP Identification Object (PEPID) */
- COPS_OBJ_REPORT_TYPE, /* Report-Type Object (Report-Type) */
- COPS_OBJ_PDPREDIRADDR, /* PDP Redirect Address Object (PDPRedirAddr) */
- COPS_OBJ_LASTPDPADDR, /* Last PDP Address (LastPDPaddr) */
- COPS_OBJ_ACCTTIMER, /* Accounting Timer Object (AcctTimer) */
- COPS_OBJ_INTEGRITY, /* Message Integrity Object (Integrity) */
- COPS_LAST_C_NUM /* For error checking */
+ COPS_NO_OBJECT, /* Not a COPS Object type */
+
+ COPS_OBJ_HANDLE, /* Handle Object (Handle) */
+ COPS_OBJ_CONTEXT, /* Context Object (Context) */
+ COPS_OBJ_IN_INT, /* In-Interface Object (IN-Int) */
+ COPS_OBJ_OUT_INT, /* Out-Interface Object (OUT-Int) */
+ COPS_OBJ_REASON, /* Reason Object (Reason) */
+ COPS_OBJ_DECISION, /* Decision Object (Decision) */
+ COPS_OBJ_LPDPDECISION, /* LPDP Decision Object (LPDPDecision) */
+ COPS_OBJ_ERROR, /* Error Object (Error) */
+ COPS_OBJ_CLIENTSI, /* Client Specific Information Object (ClientSI) */
+ COPS_OBJ_KATIMER, /* Keep-Alive Timer Object (KATimer) */
+ COPS_OBJ_PEPID, /* PEP Identification Object (PEPID) */
+ COPS_OBJ_REPORT_TYPE, /* Report-Type Object (Report-Type) */
+ COPS_OBJ_PDPREDIRADDR, /* PDP Redirect Address Object (PDPRedirAddr) */
+ COPS_OBJ_LASTPDPADDR, /* Last PDP Address (LastPDPaddr) */
+ COPS_OBJ_ACCTTIMER, /* Accounting Timer Object (AcctTimer) */
+ COPS_OBJ_INTEGRITY, /* Message Integrity Object (Integrity) */
+ COPS_LAST_C_NUM /* For error checking */
};
static const value_string cops_c_num_vals[] = {
- { COPS_OBJ_HANDLE, "Handle Object (Handle)" },
- { COPS_OBJ_CONTEXT, "Context Object (Context)" },
- { COPS_OBJ_IN_INT, "In-Interface Object (IN-Int)" },
- { COPS_OBJ_OUT_INT, "Out-Interface Object (OUT-Int)" },
- { COPS_OBJ_REASON, "Reason Object (Reason)" },
- { COPS_OBJ_DECISION, "Decision Object (Decision)" },
- { COPS_OBJ_LPDPDECISION, "LPDP Decision Object (LPDPDecision)" },
- { COPS_OBJ_ERROR, "Error Object (Error)" },
- { COPS_OBJ_CLIENTSI, "Client Specific Information Object (ClientSI)" },
- { COPS_OBJ_KATIMER, "Keep-Alive Timer Object (KATimer)" },
- { COPS_OBJ_PEPID, "PEP Identification Object (PEPID)" },
- { COPS_OBJ_REPORT_TYPE, "Report-Type Object (Report-Type)" },
- { COPS_OBJ_PDPREDIRADDR, "PDP Redirect Address Object (PDPRedirAddr)" },
- { COPS_OBJ_LASTPDPADDR, "Last PDP Address (LastPDPaddr)" },
- { COPS_OBJ_ACCTTIMER, "Accounting Timer Object (AcctTimer)" },
- { COPS_OBJ_INTEGRITY, "Message Integrity Object (Integrity)" },
- { 0, NULL },
+ { COPS_OBJ_HANDLE, "Handle Object (Handle)" },
+ { COPS_OBJ_CONTEXT, "Context Object (Context)" },
+ { COPS_OBJ_IN_INT, "In-Interface Object (IN-Int)" },
+ { COPS_OBJ_OUT_INT, "Out-Interface Object (OUT-Int)" },
+ { COPS_OBJ_REASON, "Reason Object (Reason)" },
+ { COPS_OBJ_DECISION, "Decision Object (Decision)" },
+ { COPS_OBJ_LPDPDECISION, "LPDP Decision Object (LPDPDecision)" },
+ { COPS_OBJ_ERROR, "Error Object (Error)" },
+ { COPS_OBJ_CLIENTSI, "Client Specific Information Object (ClientSI)" },
+ { COPS_OBJ_KATIMER, "Keep-Alive Timer Object (KATimer)" },
+ { COPS_OBJ_PEPID, "PEP Identification Object (PEPID)" },
+ { COPS_OBJ_REPORT_TYPE, "Report-Type Object (Report-Type)" },
+ { COPS_OBJ_PDPREDIRADDR, "PDP Redirect Address Object (PDPRedirAddr)" },
+ { COPS_OBJ_LASTPDPADDR, "Last PDP Address (LastPDPaddr)" },
+ { COPS_OBJ_ACCTTIMER, "Accounting Timer Object (AcctTimer)" },
+ { COPS_OBJ_INTEGRITY, "Message Integrity Object (Integrity)" },
+ { 0, NULL },
};
/* The different objects in COPS-PR messages */
enum cops_s_num {
- COPS_NO_PR_OBJECT, /* Not a COPS-PR Object type */
- COPS_OBJ_PRID, /* Provisioning Instance Identifier (PRID) */
- COPS_OBJ_PPRID, /* Prefix Provisioning Instance Identifier (PPRID) */
- COPS_OBJ_EPD, /* Encoded Provisioning Instance Data (EPD) */
- COPS_OBJ_GPERR, /* Global Provisioning Error Object (GPERR) */
- COPS_OBJ_CPERR, /* PRC Class Provisioning Error Object (CPERR) */
- COPS_OBJ_ERRPRID, /* Error Provisioning Instance Identifier (ErrorPRID)*/
-
- COPS_LAST_S_NUM /* For error checking */
+ COPS_NO_PR_OBJECT, /* Not a COPS-PR Object type */
+ COPS_OBJ_PRID, /* Provisioning Instance Identifier (PRID) */
+ COPS_OBJ_PPRID, /* Prefix Provisioning Instance Identifier (PPRID) */
+ COPS_OBJ_EPD, /* Encoded Provisioning Instance Data (EPD) */
+ COPS_OBJ_GPERR, /* Global Provisioning Error Object (GPERR) */
+ COPS_OBJ_CPERR, /* PRC Class Provisioning Error Object (CPERR) */
+ COPS_OBJ_ERRPRID, /* Error Provisioning Instance Identifier (ErrorPRID)*/
+
+ COPS_LAST_S_NUM /* For error checking */
};
static const value_string cops_s_num_vals[] = {
- { COPS_OBJ_PRID, "Provisioning Instance Identifier (PRID)" },
- { COPS_OBJ_PPRID, "Prefix Provisioning Instance Identifier (PPRID)" },
- { COPS_OBJ_EPD, "Encoded Provisioning Instance Data (EPD)" },
- { COPS_OBJ_GPERR, "Global Provisioning Error Object (GPERR)" },
- { COPS_OBJ_CPERR, "PRC Class Provisioning Error Object (CPERR)" },
- { COPS_OBJ_ERRPRID, "Error Provisioning Instance Identifier (ErrorPRID)" },
- { 0, NULL },
+ { COPS_OBJ_PRID, "Provisioning Instance Identifier (PRID)" },
+ { COPS_OBJ_PPRID, "Prefix Provisioning Instance Identifier (PPRID)" },
+ { COPS_OBJ_EPD, "Encoded Provisioning Instance Data (EPD)" },
+ { COPS_OBJ_GPERR, "Global Provisioning Error Object (GPERR)" },
+ { COPS_OBJ_CPERR, "PRC Class Provisioning Error Object (CPERR)" },
+ { COPS_OBJ_ERRPRID, "Error Provisioning Instance Identifier (ErrorPRID)" },
+ { 0, NULL },
};
/* R-Type is carried within the Context Object */
static const value_string cops_r_type_vals[] = {
- { 0x01, "Incoming-Message/Admission Control request" },
- { 0x02, "Resource-Allocation request" },
- { 0x04, "Outgoing-Message request" },
- { 0x08, "Configuration request" },
- { 0, NULL },
+ { 0x01, "Incoming-Message/Admission Control request" },
+ { 0x02, "Resource-Allocation request" },
+ { 0x04, "Outgoing-Message request" },
+ { 0x08, "Configuration request" },
+ { 0, NULL },
};
/* S-Type is carried within the ClientSI Object for COPS-PR*/
static const value_string cops_s_type_vals[] = {
- { 0x01, "BER" },
- { 0, NULL },
+ { 0x01, "BER" },
+ { 0, NULL },
};
/* Reason-Code is carried within the Reason object */
static const value_string cops_reason_vals[] = {
- { 1, "Unspecified" },
- { 2, "Management" },
- { 3, "Preempted (Another request state takes precedence)" },
- { 4, "Tear (Used to communicate a signaled state removal)" },
- { 5, "Timeout (Local state has timed-out)" },
- { 6, "Route Change (Change invalidates request state)" },
- { 7, "Insufficient Resources (No local resource available)" },
- { 8, "PDP's Directive (PDP decision caused the delete)" },
- { 9, "Unsupported decision (PDP decision not supported)" },
- { 10, "Synchronize Handle Unknown" },
- { 11, "Transient Handle (stateless event)" },
- { 12, "Malformed Decision (could not recover)" },
- { 13, "Unknown COPS Object from PDP" },
- { 0, NULL },
+ { 1, "Unspecified" },
+ { 2, "Management" },
+ { 3, "Preempted (Another request state takes precedence)" },
+ { 4, "Tear (Used to communicate a signaled state removal)" },
+ { 5, "Timeout (Local state has timed-out)" },
+ { 6, "Route Change (Change invalidates request state)" },
+ { 7, "Insufficient Resources (No local resource available)" },
+ { 8, "PDP's Directive (PDP decision caused the delete)" },
+ { 9, "Unsupported decision (PDP decision not supported)" },
+ { 10, "Synchronize Handle Unknown" },
+ { 11, "Transient Handle (stateless event)" },
+ { 12, "Malformed Decision (could not recover)" },
+ { 13, "Unknown COPS Object from PDP" },
+ { 0, NULL },
};
/* Command-Code is carried within the Decision object if C-Type is 1 */
static const value_string cops_dec_cmd_code_vals[] = {
- { 0, "NULL Decision (No configuration data available)" },
- { 1, "Install (Admit request/Install configuration)" },
- { 2, "Remove (Remove request/Remove configuration)" },
- { 0, NULL },
+ { 0, "NULL Decision (No configuration data available)" },
+ { 1, "Install (Admit request/Install configuration)" },
+ { 2, "Remove (Remove request/Remove configuration)" },
+ { 0, NULL },
};
/* Decision flags are also carried with the Decision object if C-Type is 1 */
static const value_string cops_dec_cmd_flag_vals[] = {
- { 0x00, "<None set>" },
- { 0x01, "Trigger Error (Trigger error message if set)" },
- { 0, NULL },
+ { 0x00, "<None set>" },
+ { 0x01, "Trigger Error (Trigger error message if set)" },
+ { 0, NULL },
};
/* Error-Code from Error object */
static const value_string cops_error_vals[] = {
- {1, "Bad handle" },
- {2, "Invalid handle reference" },
- {3, "Bad message format (Malformed Message)" },
- {4, "Unable to process (server gives up on query)" },
- {5, "Mandatory client-specific info missing" },
- {6, "Unsupported client" },
- {7, "Mandatory COPS object missing" },
- {8, "Client Failure" },
- {9, "Communication Failure" },
- {10, "Unspecified" },
- {11, "Shutting down" },
- {12, "Redirect to Preferred Server" },
- {13, "Unknown COPS Object" },
- {14, "Authentication Failure" },
- {15, "Authentication Required" },
- {0, NULL },
+ {1, "Bad handle" },
+ {2, "Invalid handle reference" },
+ {3, "Bad message format (Malformed Message)" },
+ {4, "Unable to process (server gives up on query)" },
+ {5, "Mandatory client-specific info missing" },
+ {6, "Unsupported client" },
+ {7, "Mandatory COPS object missing" },
+ {8, "Client Failure" },
+ {9, "Communication Failure" },
+ {10, "Unspecified" },
+ {11, "Shutting down" },
+ {12, "Redirect to Preferred Server" },
+ {13, "Unknown COPS Object" },
+ {14, "Authentication Failure" },
+ {15, "Authentication Required" },
+ {0, NULL },
};
/* Error-Code from GPERR object */
static const value_string cops_gperror_vals[] = {
- {1, "AvailMemLow" },
- {2, "AvailMemExhausted" },
- {3, "unknownASN.1Tag" },
- {4, "maxMsgSizeExceeded" },
- {5, "unknownError" },
- {6, "maxRequestStatesOpen" },
- {7, "invalidASN.1Length" },
- {8, "invalidObjectPad" },
- {9, "unknownPIBData" },
- {10, "unknownCOPSPRObject" },
- {11, "malformedDecision" },
- {0, NULL },
+ {1, "AvailMemLow" },
+ {2, "AvailMemExhausted" },
+ {3, "unknownASN.1Tag" },
+ {4, "maxMsgSizeExceeded" },
+ {5, "unknownError" },
+ {6, "maxRequestStatesOpen" },
+ {7, "invalidASN.1Length" },
+ {8, "invalidObjectPad" },
+ {9, "unknownPIBData" },
+ {10, "unknownCOPSPRObject" },
+ {11, "malformedDecision" },
+ {0, NULL },
};
/* Error-Code from CPERR object */
static const value_string cops_cperror_vals[] = {
- {1, "priSpaceExhausted" },
- {2, "priInstanceInvalid" },
- {3, "attrValueInvalid" },
- {4, "attrValueSupLimited" },
- {5, "attrEnumSupLimited" },
- {6, "attrMaxLengthExceeded" },
- {7, "attrReferenceUnknown" },
- {8, "priNotifyOnly" },
- {9, "unknownPrc" },
- {10, "tooFewAttrs" },
- {11, "invalidAttrType" },
- {12, "deletedInRef" },
- {13, "priSpecificError" },
+ {1, "priSpaceExhausted" },
+ {2, "priInstanceInvalid" },
+ {3, "attrValueInvalid" },
+ {4, "attrValueSupLimited" },
+ {5, "attrEnumSupLimited" },
+ {6, "attrMaxLengthExceeded" },
+ {7, "attrReferenceUnknown" },
+ {8, "priNotifyOnly" },
+ {9, "unknownPrc" },
+ {10, "tooFewAttrs" },
+ {11, "invalidAttrType" },
+ {12, "deletedInRef" },
+ {13, "priSpecificError" },
{0, NULL },
};
/* Report-Type from Report-Type object */
static const value_string cops_report_type_vals[] = {
- {1, " Success : Decision was successful at the PEP" },
- {2, " Failure : Decision could not be completed by PEP" },
- {3, " Accounting: Accounting update for an installed state" },
- {0, NULL },
+ {1, " Success : Decision was successful at the PEP" },
+ {2, " Failure : Decision could not be completed by PEP" },
+ {3, " Accounting: Accounting update for an installed state" },
+ {0, NULL },
};
/* Initialize the protocol and registered fields */
@@ -435,1060 +464,1095 @@ static void dissect_cops_object_data(tvbuff_t *tvb, guint32 offset, proto_tree *
static void dissect_cops_pr_objects(tvbuff_t *tvb, guint32 offset, proto_tree *tree, guint16 pr_len);
static int dissect_cops_pr_object_data(tvbuff_t *tvb, guint32 offset, proto_tree *tree,
- guint8 s_num, guint8 s_type, guint16 len);
+ guint8 s_num, guint8 s_type, guint16 len);
/* Code to actually dissect the packets */
static void
dissect_cops(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
- tcp_dissect_pdus(tvb, pinfo, tree, cops_desegment, 8,
- get_cops_pdu_len, dissect_cops_pdu);
+ tcp_dissect_pdus(tvb, pinfo, tree, cops_desegment, 8,
+ get_cops_pdu_len, dissect_cops_pdu);
}
static guint
get_cops_pdu_len(tvbuff_t *tvb, int offset)
{
- /*
- * Get the length of the COPS message.
- */
- return tvb_get_ntohl(tvb, offset + 4);
+ /*
+ * Get the length of the COPS message.
+ */
+ return tvb_get_ntohl(tvb, offset + 4);
}
static void
dissect_cops_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
- guint8 op_code;
- int object_len;
-
- if (check_col(pinfo->cinfo, COL_PROTOCOL))
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "COPS");
- if (check_col(pinfo->cinfo, COL_INFO))
- col_clear(pinfo->cinfo, COL_INFO);
-
- op_code = tvb_get_guint8(tvb, 1);
- if (check_col(pinfo->cinfo, COL_INFO))
- col_add_fstr(pinfo->cinfo, COL_INFO, "COPS %s",
- val_to_str(op_code, cops_op_code_vals, "Unknown Op Code"));
-
- if (tree) {
- proto_item *ti, *tv;
- proto_tree *cops_tree, *ver_flags_tree;
- guint32 msg_len;
- guint32 offset = 0;
- guint8 ver_flags;
- gint garbage;
-
- ti = proto_tree_add_item(tree, proto_cops, tvb, offset, -1, FALSE);
- cops_tree = proto_item_add_subtree(ti, ett_cops);
-
- /* Version and flags share the same byte, put them in a subtree */
- ver_flags = tvb_get_guint8(tvb, offset);
- tv = proto_tree_add_uint_format(cops_tree, hf_cops_ver_flags, tvb, offset, 1,
- ver_flags, "Version: %u, Flags: %s",
- hi_nibble(ver_flags),
- val_to_str(lo_nibble(ver_flags), cops_flags_vals, "Unknown"));
- ver_flags_tree = proto_item_add_subtree(tv, ett_cops_ver_flags);
- proto_tree_add_uint(ver_flags_tree, hf_cops_version, tvb, offset, 1, ver_flags);
- proto_tree_add_uint(ver_flags_tree, hf_cops_flags, tvb, offset, 1, ver_flags);
- offset++;
-
- proto_tree_add_item(cops_tree, hf_cops_op_code, tvb, offset, 1, FALSE);
- offset ++;
- proto_tree_add_item(cops_tree, hf_cops_client_type, tvb, offset, 2, FALSE);
- offset += 2;
-
- msg_len = tvb_get_ntohl(tvb, offset);
- proto_tree_add_uint(cops_tree, hf_cops_msg_len, tvb, offset, 4, msg_len);
- offset += 4;
-
- while (tvb_reported_length_remaining(tvb, offset) >= COPS_OBJECT_HDR_SIZE) {
- object_len = dissect_cops_object(tvb, offset, cops_tree);
- if (object_len < 0)
- return;
- offset += object_len;
- }
-
- garbage = tvb_length_remaining(tvb, offset);
- if (garbage > 0)
- proto_tree_add_text(cops_tree, tvb, offset, garbage,
- "Trailing garbage: %d byte%s", garbage,
- plurality(garbage, "", "s"));
- }
+ guint8 op_code;
+ int object_len;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "COPS");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ op_code = tvb_get_guint8(tvb, 1);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "COPS %s",
+ val_to_str(op_code, cops_op_code_vals, "Unknown Op Code"));
+
+ if (tree) {
+ proto_item *ti, *tv;
+ proto_tree *cops_tree, *ver_flags_tree;
+ guint32 msg_len;
+ guint32 offset = 0;
+ guint8 ver_flags;
+ gint garbage;
+
+ ti = proto_tree_add_item(tree, proto_cops, tvb, offset, -1, FALSE);
+ cops_tree = proto_item_add_subtree(ti, ett_cops);
+
+ /* Version and flags share the same byte, put them in a subtree */
+ ver_flags = tvb_get_guint8(tvb, offset);
+ tv = proto_tree_add_uint_format(cops_tree, hf_cops_ver_flags, tvb, offset, 1,
+ ver_flags, "Version: %u, Flags: %s",
+ hi_nibble(ver_flags),
+ val_to_str(lo_nibble(ver_flags), cops_flags_vals, "Unknown"));
+ ver_flags_tree = proto_item_add_subtree(tv, ett_cops_ver_flags);
+ proto_tree_add_uint(ver_flags_tree, hf_cops_version, tvb, offset, 1, ver_flags);
+ proto_tree_add_uint(ver_flags_tree, hf_cops_flags, tvb, offset, 1, ver_flags);
+ offset++;
+
+ proto_tree_add_item(cops_tree, hf_cops_op_code, tvb, offset, 1, FALSE);
+ offset ++;
+ proto_tree_add_item(cops_tree, hf_cops_client_type, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ msg_len = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(cops_tree, hf_cops_msg_len, tvb, offset, 4, msg_len);
+ offset += 4;
+
+ while (tvb_reported_length_remaining(tvb, offset) >= COPS_OBJECT_HDR_SIZE) {
+ object_len = dissect_cops_object(tvb, offset, cops_tree);
+ if (object_len < 0)
+ return;
+ offset += object_len;
+ }
+
+ garbage = tvb_length_remaining(tvb, offset);
+ if (garbage > 0)
+ proto_tree_add_text(cops_tree, tvb, offset, garbage,
+ "Trailing garbage: %d byte%s", garbage,
+ plurality(garbage, "", "s"));
+ }
}
static char *cops_c_type_to_str(guint8 c_num, guint8 c_type)
{
- switch (c_num) {
- case COPS_OBJ_HANDLE:
- if (c_type == 1)
- return "Client Handle";
- break;
- case COPS_OBJ_IN_INT:
- case COPS_OBJ_OUT_INT:
- if (c_type == 1)
- return "IPv4 Address + Interface";
- else if (c_type == 2)
- return "IPv6 Address + Interface";
- break;
- case COPS_OBJ_DECISION:
- case COPS_OBJ_LPDPDECISION:
- if (c_type == 1)
- return "Decision Flags (Mandatory)";
- else if (c_type == 2)
- return "Stateless Data";
- else if (c_type == 3)
- return "Replacement Data";
- else if (c_type == 4)
- return "Client Specific Decision Data";
- else if (c_type == 5)
- return "Named Decision Data";
- break;
- case COPS_OBJ_CLIENTSI:
- if (c_type == 1)
- return "Signaled ClientSI";
- else if (c_type == 2)
- return "Named ClientSI";
- break;
- case COPS_OBJ_KATIMER:
- if (c_type == 1)
- return "Keep-alive timer value";
- break;
- case COPS_OBJ_PDPREDIRADDR:
- case COPS_OBJ_LASTPDPADDR:
- if (c_type == 1)
- return "IPv4 Address + TCP Port";
- else if (c_type == 2)
- return "IPv6 Address + TCP Port";
- break;
- case COPS_OBJ_ACCTTIMER:
- if (c_type == 1)
- return "Accounting timer value";
- break;
- case COPS_OBJ_INTEGRITY:
- if (c_type == 1)
- return "HMAC digest";
- break;
- }
+ switch (c_num) {
+ case COPS_OBJ_HANDLE:
+ if (c_type == 1)
+ return "Client Handle";
+ break;
+ case COPS_OBJ_IN_INT:
+ case COPS_OBJ_OUT_INT:
+ if (c_type == 1)
+ return "IPv4 Address + Interface";
+ else if (c_type == 2)
+ return "IPv6 Address + Interface";
+ break;
+ case COPS_OBJ_DECISION:
+ case COPS_OBJ_LPDPDECISION:
+ if (c_type == 1)
+ return "Decision Flags (Mandatory)";
+ else if (c_type == 2)
+ return "Stateless Data";
+ else if (c_type == 3)
+ return "Replacement Data";
+ else if (c_type == 4)
+ return "Client Specific Decision Data";
+ else if (c_type == 5)
+ return "Named Decision Data";
+ break;
+ case COPS_OBJ_CLIENTSI:
+ if (c_type == 1)
+ return "Signaled ClientSI";
+ else if (c_type == 2)
+ return "Named ClientSI";
+ break;
+ case COPS_OBJ_KATIMER:
+ if (c_type == 1)
+ return "Keep-alive timer value";
+ break;
+ case COPS_OBJ_PDPREDIRADDR:
+ case COPS_OBJ_LASTPDPADDR:
+ if (c_type == 1)
+ return "IPv4 Address + TCP Port";
+ else if (c_type == 2)
+ return "IPv6 Address + TCP Port";
+ break;
+ case COPS_OBJ_ACCTTIMER:
+ if (c_type == 1)
+ return "Accounting timer value";
+ break;
+ case COPS_OBJ_INTEGRITY:
+ if (c_type == 1)
+ return "HMAC digest";
+ break;
+ }
- return "";
+ return "";
}
static int dissect_cops_object(tvbuff_t *tvb, guint32 offset, proto_tree *tree)
{
- int object_len, contents_len;
- guint8 c_num, c_type;
- proto_item *ti;
- proto_tree *obj_tree;
- char *type_str;
-
- object_len = tvb_get_ntohs(tvb, offset);
- if (object_len < COPS_OBJECT_HDR_SIZE) {
- /* Bogus! */
- proto_tree_add_text(tree, tvb, offset, 2,
- "Bad COPS object length: %u, should be at least %u\n",
- object_len, COPS_OBJECT_HDR_SIZE);
- return -1;
- }
- c_num = tvb_get_guint8(tvb, offset + 2);
- c_type = tvb_get_guint8(tvb, offset + 3);
+ int object_len, contents_len;
+ guint8 c_num, c_type;
+ proto_item *ti;
+ proto_tree *obj_tree;
+ char *type_str;
+
+ object_len = tvb_get_ntohs(tvb, offset);
+ if (object_len < COPS_OBJECT_HDR_SIZE) {
+ /* Bogus! */
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Bad COPS object length: %u, should be at least %u\n",
+ object_len, COPS_OBJECT_HDR_SIZE);
+ return -1;
+ }
+ c_num = tvb_get_guint8(tvb, offset + 2);
+ c_type = tvb_get_guint8(tvb, offset + 3);
- ti = proto_tree_add_uint_format(tree, hf_cops_obj_c_num, tvb, offset, object_len, c_num,
- "%s: %s", val_to_str(c_num, cops_c_num_vals, "Unknown"),
- cops_c_type_to_str(c_num, c_type));
- obj_tree = proto_item_add_subtree(ti, ett_cops_obj);
+ ti = proto_tree_add_uint_format(tree, hf_cops_obj_c_num, tvb, offset, object_len, c_num,
+ "%s: %s", val_to_str(c_num, cops_c_num_vals, "Unknown"),
+ cops_c_type_to_str(c_num, c_type));
+ obj_tree = proto_item_add_subtree(ti, ett_cops_obj);
- proto_tree_add_uint(obj_tree, hf_cops_obj_len, tvb, offset, 2, object_len);
- offset += 2;
+ proto_tree_add_uint(obj_tree, hf_cops_obj_len, tvb, offset, 2, object_len);
+ offset += 2;
- proto_tree_add_uint(obj_tree, hf_cops_obj_c_num, tvb, offset, 1, c_num);
- offset++;
+ proto_tree_add_uint(obj_tree, hf_cops_obj_c_num, tvb, offset, 1, c_num);
+ offset++;
- type_str = cops_c_type_to_str(c_num, c_type);
- proto_tree_add_text(obj_tree, tvb, offset, 1, "C-Type: %s%s%u%s",
- type_str,
- strlen(type_str) ? " (" : "",
- c_type,
- strlen(type_str) ? ")" : "");
- offset++;
+ type_str = cops_c_type_to_str(c_num, c_type);
+ proto_tree_add_text(obj_tree, tvb, offset, 1, "C-Type: %s%s%u%s",
+ type_str,
+ strlen(type_str) ? " (" : "",
+ c_type,
+ strlen(type_str) ? ")" : "");
+ offset++;
- contents_len = object_len - COPS_OBJECT_HDR_SIZE;
- dissect_cops_object_data(tvb, offset, obj_tree, c_num, c_type, contents_len);
+ contents_len = object_len - COPS_OBJECT_HDR_SIZE;
+ dissect_cops_object_data(tvb, offset, obj_tree, c_num, c_type, contents_len);
- /* Pad to 32bit boundary */
- if (object_len % sizeof (guint32))
- object_len += (sizeof (guint32) - object_len % sizeof (guint32));
+ /* Pad to 32bit boundary */
+ if (object_len % sizeof (guint32))
+ object_len += (sizeof (guint32) - object_len % sizeof (guint32));
- return object_len;
+ return object_len;
}
static void dissect_cops_pr_objects(tvbuff_t *tvb, guint32 offset, proto_tree *tree, guint16 pr_len)
{
- int object_len, contents_len;
- guint8 s_num, s_type;
- char *type_str;
- int ret;
- proto_tree *cops_pr_tree, *obj_tree;
- proto_item *ti;
-
- cops_pr_tree = proto_item_add_subtree(tree, ett_cops_pr_obj);
-
- while (pr_len >= COPS_OBJECT_HDR_SIZE) {
- object_len = tvb_get_ntohs(tvb, offset);
- if (object_len < COPS_OBJECT_HDR_SIZE) {
- /* Bogus! */
- proto_tree_add_text(tree, tvb, offset, 2,
- "Bad COPS PR object length: %u, should be at least %u\n",
- object_len, COPS_OBJECT_HDR_SIZE);
- return;
- }
- s_num = tvb_get_guint8(tvb, offset + 2);
-
- ti = proto_tree_add_uint_format(cops_pr_tree, hf_cops_obj_s_num, tvb, offset, object_len, s_num,
- "%s", val_to_str(s_num, cops_s_num_vals, "Unknown"));
- obj_tree = proto_item_add_subtree(cops_pr_tree, ett_cops_pr_obj);
-
- proto_tree_add_uint(obj_tree, hf_cops_obj_len, tvb, offset, 2, object_len);
- offset += 2;
- pr_len -= 2;
-
- proto_tree_add_uint(obj_tree, hf_cops_obj_s_num, tvb, offset, 1, s_num);
- offset++;
- pr_len--;
-
- s_type = tvb_get_guint8(tvb, offset);
- type_str = val_to_str(s_type, cops_s_type_vals, "Unknown");
- proto_tree_add_text(obj_tree, tvb, offset, 1, "S-Type: %s%s%u%s",
- type_str,
- strlen(type_str) ? " (" : "",
- s_type,
- strlen(type_str) ? ")" : "");
- offset++;
- pr_len--;
-
- contents_len = object_len - COPS_OBJECT_HDR_SIZE;
- ret = dissect_cops_pr_object_data(tvb, offset, obj_tree, s_num, s_type, contents_len);
- if (ret < 0)
- break;
-
- /*Pad to 32bit boundary */
- if (object_len % sizeof (guint32))
- object_len += (sizeof (guint32) - object_len % sizeof (guint32));
-
- pr_len -= object_len - COPS_OBJECT_HDR_SIZE;
- offset += object_len - COPS_OBJECT_HDR_SIZE;
- }
+ int object_len, contents_len;
+ guint8 s_num, s_type;
+ char *type_str;
+ int ret;
+ proto_tree *cops_pr_tree, *obj_tree;
+ proto_item *ti;
+
+ cops_pr_tree = proto_item_add_subtree(tree, ett_cops_pr_obj);
+
+ while (pr_len >= COPS_OBJECT_HDR_SIZE) {
+ object_len = tvb_get_ntohs(tvb, offset);
+ if (object_len < COPS_OBJECT_HDR_SIZE) {
+ /* Bogus! */
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Bad COPS PR object length: %u, should be at least %u\n",
+ object_len, COPS_OBJECT_HDR_SIZE);
+ return;
+ }
+ s_num = tvb_get_guint8(tvb, offset + 2);
+
+ ti = proto_tree_add_uint_format(cops_pr_tree, hf_cops_obj_s_num, tvb, offset, object_len, s_num,
+ "%s", val_to_str(s_num, cops_s_num_vals, "Unknown"));
+ obj_tree = proto_item_add_subtree(cops_pr_tree, ett_cops_pr_obj);
+
+ proto_tree_add_uint(obj_tree, hf_cops_obj_len, tvb, offset, 2, object_len);
+ offset += 2;
+ pr_len -= 2;
+
+ proto_tree_add_uint(obj_tree, hf_cops_obj_s_num, tvb, offset, 1, s_num);
+ offset++;
+ pr_len--;
+
+ s_type = tvb_get_guint8(tvb, offset);
+ type_str = val_to_str(s_type, cops_s_type_vals, "Unknown");
+ proto_tree_add_text(obj_tree, tvb, offset, 1, "S-Type: %s%s%u%s",
+ type_str,
+ strlen(type_str) ? " (" : "",
+ s_type,
+ strlen(type_str) ? ")" : "");
+ offset++;
+ pr_len--;
+
+ contents_len = object_len - COPS_OBJECT_HDR_SIZE;
+ ret = dissect_cops_pr_object_data(tvb, offset, obj_tree, s_num, s_type, contents_len);
+ if (ret < 0)
+ break;
+
+ /*Pad to 32bit boundary */
+ if (object_len % sizeof (guint32))
+ object_len += (sizeof (guint32) - object_len % sizeof (guint32));
+
+ pr_len -= object_len - COPS_OBJECT_HDR_SIZE;
+ offset += object_len - COPS_OBJECT_HDR_SIZE;
+ }
}
static void dissect_cops_object_data(tvbuff_t *tvb, guint32 offset, proto_tree *tree,
guint8 c_num, guint8 c_type, guint16 len)
{
- proto_item *ti;
- proto_tree *r_type_tree, *itf_tree, *reason_tree, *dec_tree, *error_tree, *clientsi_tree, *pdp_tree;
- guint16 r_type, m_type, reason, reason_sub, cmd_code, cmd_flags, error, error_sub, tcp_port;
- guint32 ipv4addr, ifindex;
- struct e_in6_addr ipv6addr;
-
- switch (c_num) {
- case COPS_OBJ_CONTEXT:
- r_type = tvb_get_ntohs(tvb, offset);
- m_type = tvb_get_ntohs(tvb, offset + 2);
- ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: R-Type: %s, M-Type: %u",
- val_to_str(r_type, cops_r_type_vals, "Unknown"),
- m_type);
-
- r_type_tree = proto_item_add_subtree(ti, ett_cops_r_type_flags);
- proto_tree_add_uint(r_type_tree, hf_cops_r_type_flags, tvb, offset, 2, r_type);
- offset += 2;
- proto_tree_add_uint(r_type_tree, hf_cops_m_type_flags, tvb, offset, 2, m_type);
-
- break;
- case COPS_OBJ_IN_INT:
- case COPS_OBJ_OUT_INT:
- if (c_type == 1) { /* IPv4 */
- tvb_memcpy(tvb, (guint8 *)&ipv4addr, offset, 4);
- ifindex = tvb_get_ntohl(tvb, offset + 4);
- ti = proto_tree_add_text(tree, tvb, offset, 8, "Contents: IPv4 address %s, ifIndex: %u",
- ip_to_str((guint8 *)&ipv4addr), ifindex);
- itf_tree = proto_item_add_subtree(ti, ett_cops_itf);
- proto_tree_add_ipv4(itf_tree,
- (c_num == COPS_OBJ_IN_INT) ? hf_cops_in_int_ipv4 : hf_cops_out_int_ipv4,
- tvb, offset, 4, ipv4addr);
- offset += 4;
- } else if (c_type == 2) { /* IPv6 */
- tvb_memcpy(tvb, (guint8 *)&ipv6addr, offset, sizeof ipv6addr);
- ifindex = tvb_get_ntohl(tvb, offset + sizeof ipv6addr);
- ti = proto_tree_add_text(tree, tvb, offset, 20, "Contents: IPv6 address %s, ifIndex: %u",
- ip6_to_str(&ipv6addr), ifindex);
- itf_tree = proto_item_add_subtree(ti, ett_cops_itf);
- proto_tree_add_ipv6(itf_tree,
- (c_num == COPS_OBJ_IN_INT) ? hf_cops_in_int_ipv6 : hf_cops_out_int_ipv6,
- tvb, offset, 16, (guint8 *)&ipv6addr);
- offset += 16;
- } else {
- break;
- }
- proto_tree_add_uint(itf_tree, hf_cops_int_ifindex, tvb, offset, 4, ifindex);
-
- break;
- case COPS_OBJ_REASON:
- reason = tvb_get_ntohs(tvb, offset);
- reason_sub = tvb_get_ntohs(tvb, offset + 2);
- ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Reason-Code: %s, Reason Sub-code: 0x%04x",
- val_to_str(reason, cops_reason_vals, "<Unknown value>"), reason_sub);
- reason_tree = proto_item_add_subtree(ti, ett_cops_reason);
- proto_tree_add_uint(reason_tree, hf_cops_reason, tvb, offset, 2, reason);
- offset += 2;
- if (reason == 13) {
- proto_tree_add_text(reason_tree, tvb, offset, 2, "Reason Sub-code: "
- "Unknown object's C-Num %u, C-Type %u",
- tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset + 1));
- } else
- proto_tree_add_uint(reason_tree, hf_cops_reason_sub, tvb, offset, 2, reason_sub);
-
- break;
- case COPS_OBJ_DECISION:
- case COPS_OBJ_LPDPDECISION:
- if (c_type == 1) {
- cmd_code = tvb_get_ntohs(tvb, offset);
- cmd_flags = tvb_get_ntohs(tvb, offset + 2);
- ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Command-Code: %s, Flags: %s",
- val_to_str(cmd_code, cops_dec_cmd_code_vals, "<Unknown value>"),
- val_to_str(cmd_flags, cops_dec_cmd_flag_vals, "<Unknown flag>"));
- dec_tree = proto_item_add_subtree(ti, ett_cops_decision);
- proto_tree_add_uint(dec_tree, hf_cops_dec_cmd_code, tvb, offset, 2, cmd_code);
- offset += 2;
- proto_tree_add_uint(dec_tree, hf_cops_dec_flags, tvb, offset, 2, cmd_flags);
- } else if (c_type == 5) { /*COPS-PR Data*/
- ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: %u bytes", len);
- dec_tree = proto_item_add_subtree(ti, ett_cops_decision);
- dissect_cops_pr_objects(tvb, offset, dec_tree, len);
- }
-
- break;
- case COPS_OBJ_ERROR:
- if (c_type != 1)
- break;
-
- error = tvb_get_ntohs(tvb, offset);
- error_sub = tvb_get_ntohs(tvb, offset + 2);
- ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Error-Code: %s, Error Sub-code: 0x%04x",
- val_to_str(error, cops_error_vals, "<Unknown value>"), error_sub);
- error_tree = proto_item_add_subtree(ti, ett_cops_error);
- proto_tree_add_uint(error_tree, hf_cops_error, tvb, offset, 2, error);
- offset += 2;
- if (error == 13) {
- proto_tree_add_text(error_tree, tvb, offset, 2, "Error Sub-code: "
- "Unknown object's C-Num %u, C-Type %u",
- tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset + 1));
- } else
- proto_tree_add_uint(error_tree, hf_cops_error_sub, tvb, offset, 2, error_sub);
-
- break;
- case COPS_OBJ_CLIENTSI:
-
- if (c_type != 2) /*Not COPS-PR data*/
- break;
-
- ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: %u bytes", len);
- clientsi_tree = proto_item_add_subtree(ti, ett_cops_clientsi);
-
- dissect_cops_pr_objects(tvb, offset, clientsi_tree, len);
-
- break;
- case COPS_OBJ_KATIMER:
- if (c_type != 1)
- break;
-
- proto_tree_add_item(tree, hf_cops_katimer, tvb, offset + 2, 2, FALSE);
- if (tvb_get_ntohs(tvb, offset + 2) == 0)
- proto_tree_add_text(tree, tvb, offset, 0, "Value of zero implies infinity.");
-
- break;
- case COPS_OBJ_PEPID:
- if (c_type != 1)
- break;
-
- if (tvb_strnlen(tvb, offset, len) == -1)
- proto_tree_add_text(tree, tvb, offset, len, "<PEP Id is not a NUL terminated ASCII string>");
- else
- proto_tree_add_item(tree, hf_cops_pepid, tvb, offset,
- tvb_strnlen(tvb, offset, len) + 1, FALSE);
-
- break;
- case COPS_OBJ_REPORT_TYPE:
- if (c_type != 1)
- break;
-
- proto_tree_add_item(tree, hf_cops_report_type, tvb, offset, 2, FALSE);
-
- break;
- case COPS_OBJ_PDPREDIRADDR:
- case COPS_OBJ_LASTPDPADDR:
- if (c_type == 1) { /* IPv4 */
- tvb_memcpy(tvb, (guint8 *)&ipv4addr, offset, 4);
- tcp_port = tvb_get_ntohs(tvb, offset + 4 + 2);
- ti = proto_tree_add_text(tree, tvb, offset, 8, "Contents: IPv4 address %s, TCP Port Number: %u",
- ip_to_str((guint8 *)&ipv4addr), tcp_port);
- pdp_tree = proto_item_add_subtree(ti, ett_cops_pdp);
- proto_tree_add_ipv4(pdp_tree,
- (c_num == COPS_OBJ_PDPREDIRADDR) ? hf_cops_pdprediraddr_ipv4 : hf_cops_lastpdpaddr_ipv4,
- tvb, offset, 4, ipv4addr);
- offset += 4;
- } else if (c_type == 2) { /* IPv6 */
- tvb_memcpy(tvb, (guint8 *)&ipv6addr, offset, sizeof ipv6addr);
- tcp_port = tvb_get_ntohs(tvb, offset + sizeof ipv6addr + 2);
- ti = proto_tree_add_text(tree, tvb, offset, 20, "Contents: IPv6 address %s, TCP Port Number: %u",
- ip6_to_str(&ipv6addr), tcp_port);
- pdp_tree = proto_item_add_subtree(ti, ett_cops_pdp);
- proto_tree_add_ipv6(pdp_tree,
- (c_num == COPS_OBJ_PDPREDIRADDR) ? hf_cops_pdprediraddr_ipv6 : hf_cops_lastpdpaddr_ipv6,
- tvb, offset, 16, (guint8 *)&ipv6addr);
- offset += 16;
- } else {
- break;
- }
- offset += 2;
- proto_tree_add_uint(pdp_tree, hf_cops_pdp_tcp_port, tvb, offset, 2, tcp_port);
-
- break;
- case COPS_OBJ_ACCTTIMER:
- if (c_type != 1)
- break;
-
- proto_tree_add_item(tree, hf_cops_accttimer, tvb, offset + 2, 2, FALSE);
- if (tvb_get_ntohs(tvb, offset + 2) == 0)
- proto_tree_add_text(tree, tvb, offset, 0, "Value of zero means "
- "there SHOULD be no unsolicited accounting updates.");
-
- break;
- case COPS_OBJ_INTEGRITY:
- if (c_type != 1)
- break; /* Not HMAC digest */
-
- proto_tree_add_item(tree, hf_cops_key_id, tvb, offset, 4, FALSE);
- proto_tree_add_item(tree, hf_cops_seq_num, tvb, offset + 4, 4, FALSE);
- proto_tree_add_text(tree, tvb, offset + 8 , len - 8, "Contents: Keyed Message Digest");
-
- break;
- default:
- proto_tree_add_text(tree, tvb, offset, len, "Contents: %u bytes", len);
-
- break;
- }
-}
+ proto_item *ti;
+ proto_tree *r_type_tree, *itf_tree, *reason_tree, *dec_tree, *error_tree, *clientsi_tree, *pdp_tree;
+ guint16 r_type, m_type, reason, reason_sub, cmd_code, cmd_flags, error, error_sub, tcp_port;
+ guint32 ipv4addr, ifindex;
+ struct e_in6_addr ipv6addr;
+
+ switch (c_num) {
+ case COPS_OBJ_CONTEXT:
+ r_type = tvb_get_ntohs(tvb, offset);
+ m_type = tvb_get_ntohs(tvb, offset + 2);
+ ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: R-Type: %s, M-Type: %u",
+ val_to_str(r_type, cops_r_type_vals, "Unknown"),
+ m_type);
+
+ r_type_tree = proto_item_add_subtree(ti, ett_cops_r_type_flags);
+ proto_tree_add_uint(r_type_tree, hf_cops_r_type_flags, tvb, offset, 2, r_type);
+ offset += 2;
+ proto_tree_add_uint(r_type_tree, hf_cops_m_type_flags, tvb, offset, 2, m_type);
+
+ break;
+ case COPS_OBJ_IN_INT:
+ case COPS_OBJ_OUT_INT:
+ if (c_type == 1) { /* IPv4 */
+ tvb_memcpy(tvb, (guint8 *)&ipv4addr, offset, 4);
+ ifindex = tvb_get_ntohl(tvb, offset + 4);
+ ti = proto_tree_add_text(tree, tvb, offset, 8, "Contents: IPv4 address %s, ifIndex: %u",
+ ip_to_str((guint8 *)&ipv4addr), ifindex);
+ itf_tree = proto_item_add_subtree(ti, ett_cops_itf);
+ proto_tree_add_ipv4(itf_tree,
+ (c_num == COPS_OBJ_IN_INT) ? hf_cops_in_int_ipv4 : hf_cops_out_int_ipv4,
+ tvb, offset, 4, ipv4addr);
+ offset += 4;
+ } else if (c_type == 2) { /* IPv6 */
+ tvb_memcpy(tvb, (guint8 *)&ipv6addr, offset, sizeof ipv6addr);
+ ifindex = tvb_get_ntohl(tvb, offset + sizeof ipv6addr);
+ ti = proto_tree_add_text(tree, tvb, offset, 20, "Contents: IPv6 address %s, ifIndex: %u",
+ ip6_to_str(&ipv6addr), ifindex);
+ itf_tree = proto_item_add_subtree(ti, ett_cops_itf);
+ proto_tree_add_ipv6(itf_tree,
+ (c_num == COPS_OBJ_IN_INT) ? hf_cops_in_int_ipv6 : hf_cops_out_int_ipv6,
+ tvb, offset, 16, (guint8 *)&ipv6addr);
+ offset += 16;
+ } else {
+ break;
+ }
+ proto_tree_add_uint(itf_tree, hf_cops_int_ifindex, tvb, offset, 4, ifindex);
+
+ break;
+ case COPS_OBJ_REASON:
+ reason = tvb_get_ntohs(tvb, offset);
+ reason_sub = tvb_get_ntohs(tvb, offset + 2);
+ ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Reason-Code: %s, Reason Sub-code: 0x%04x",
+ val_to_str(reason, cops_reason_vals, "<Unknown value>"), reason_sub);
+ reason_tree = proto_item_add_subtree(ti, ett_cops_reason);
+ proto_tree_add_uint(reason_tree, hf_cops_reason, tvb, offset, 2, reason);
+ offset += 2;
+ if (reason == 13) {
+ proto_tree_add_text(reason_tree, tvb, offset, 2, "Reason Sub-code: "
+ "Unknown object's C-Num %u, C-Type %u",
+ tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset + 1));
+ } else
+ proto_tree_add_uint(reason_tree, hf_cops_reason_sub, tvb, offset, 2, reason_sub);
+
+ break;
+ case COPS_OBJ_DECISION:
+ case COPS_OBJ_LPDPDECISION:
+ if (c_type == 1) {
+ cmd_code = tvb_get_ntohs(tvb, offset);
+ cmd_flags = tvb_get_ntohs(tvb, offset + 2);
+ ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Command-Code: %s, Flags: %s",
+ val_to_str(cmd_code, cops_dec_cmd_code_vals, "<Unknown value>"),
+ val_to_str(cmd_flags, cops_dec_cmd_flag_vals, "<Unknown flag>"));
+ dec_tree = proto_item_add_subtree(ti, ett_cops_decision);
+ proto_tree_add_uint(dec_tree, hf_cops_dec_cmd_code, tvb, offset, 2, cmd_code);
+ offset += 2;
+ proto_tree_add_uint(dec_tree, hf_cops_dec_flags, tvb, offset, 2, cmd_flags);
+ } else if (c_type == 5) { /*COPS-PR Data*/
+ ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: %u bytes", len);
+ dec_tree = proto_item_add_subtree(ti, ett_cops_decision);
+ dissect_cops_pr_objects(tvb, offset, dec_tree, len);
+ }
+ break;
+ case COPS_OBJ_ERROR:
+ if (c_type != 1)
+ break;
+
+ error = tvb_get_ntohs(tvb, offset);
+ error_sub = tvb_get_ntohs(tvb, offset + 2);
+ ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Error-Code: %s, Error Sub-code: 0x%04x",
+ val_to_str(error, cops_error_vals, "<Unknown value>"), error_sub);
+ error_tree = proto_item_add_subtree(ti, ett_cops_error);
+ proto_tree_add_uint(error_tree, hf_cops_error, tvb, offset, 2, error);
+ offset += 2;
+ if (error == 13) {
+ proto_tree_add_text(error_tree, tvb, offset, 2, "Error Sub-code: "
+ "Unknown object's C-Num %u, C-Type %u",
+ tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset + 1));
+ } else
+ proto_tree_add_uint(error_tree, hf_cops_error_sub, tvb, offset, 2, error_sub);
+
+ break;
+ case COPS_OBJ_CLIENTSI:
+
+ if (c_type != 2) /*Not COPS-PR data*/
+ break;
+
+ ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: %u bytes", len);
+ clientsi_tree = proto_item_add_subtree(ti, ett_cops_clientsi);
+
+ dissect_cops_pr_objects(tvb, offset, clientsi_tree, len);
+
+ break;
+ case COPS_OBJ_KATIMER:
+ if (c_type != 1)
+ break;
+
+ proto_tree_add_item(tree, hf_cops_katimer, tvb, offset + 2, 2, FALSE);
+ if (tvb_get_ntohs(tvb, offset + 2) == 0)
+ proto_tree_add_text(tree, tvb, offset, 0, "Value of zero implies infinity.");
+
+ break;
+ case COPS_OBJ_PEPID:
+ if (c_type != 1)
+ break;
+
+ if (tvb_strnlen(tvb, offset, len) == -1)
+ proto_tree_add_text(tree, tvb, offset, len, "<PEP Id is not a NUL terminated ASCII string>");
+ else
+ proto_tree_add_item(tree, hf_cops_pepid, tvb, offset,
+ tvb_strnlen(tvb, offset, len) + 1, FALSE);
+
+ break;
+ case COPS_OBJ_REPORT_TYPE:
+ if (c_type != 1)
+ break;
+
+ proto_tree_add_item(tree, hf_cops_report_type, tvb, offset, 2, FALSE);
+
+ break;
+ case COPS_OBJ_PDPREDIRADDR:
+ case COPS_OBJ_LASTPDPADDR:
+ if (c_type == 1) { /* IPv4 */
+ tvb_memcpy(tvb, (guint8 *)&ipv4addr, offset, 4);
+ tcp_port = tvb_get_ntohs(tvb, offset + 4 + 2);
+ ti = proto_tree_add_text(tree, tvb, offset, 8, "Contents: IPv4 address %s, TCP Port Number: %u",
+ ip_to_str((guint8 *)&ipv4addr), tcp_port);
+ pdp_tree = proto_item_add_subtree(ti, ett_cops_pdp);
+ proto_tree_add_ipv4(pdp_tree,
+ (c_num == COPS_OBJ_PDPREDIRADDR) ? hf_cops_pdprediraddr_ipv4 : hf_cops_lastpdpaddr_ipv4,
+ tvb, offset, 4, ipv4addr);
+ offset += 4;
+ } else if (c_type == 2) { /* IPv6 */
+ tvb_memcpy(tvb, (guint8 *)&ipv6addr, offset, sizeof ipv6addr);
+ tcp_port = tvb_get_ntohs(tvb, offset + sizeof ipv6addr + 2);
+ ti = proto_tree_add_text(tree, tvb, offset, 20, "Contents: IPv6 address %s, TCP Port Number: %u",
+ ip6_to_str(&ipv6addr), tcp_port);
+ pdp_tree = proto_item_add_subtree(ti, ett_cops_pdp);
+ proto_tree_add_ipv6(pdp_tree,
+ (c_num == COPS_OBJ_PDPREDIRADDR) ? hf_cops_pdprediraddr_ipv6 : hf_cops_lastpdpaddr_ipv6,
+ tvb, offset, 16, (guint8 *)&ipv6addr);
+ offset += 16;
+ } else {
+ break;
+ }
+ offset += 2;
+ proto_tree_add_uint(pdp_tree, hf_cops_pdp_tcp_port, tvb, offset, 2, tcp_port);
-/*convert hex to binary string (1010....)*/
-static gchar* xtobstr(guint8 *hex, guint len) {
+ break;
+ case COPS_OBJ_ACCTTIMER:
+ if (c_type != 1)
+ break;
- guint i=0,j=0,k=0, bit=0;
- gchar *binstr=NULL;
- guint8 mask = 0x80;
+ proto_tree_add_item(tree, hf_cops_accttimer, tvb, offset + 2, 2, FALSE);
+ if (tvb_get_ntohs(tvb, offset + 2) == 0)
+ proto_tree_add_text(tree, tvb, offset, 0, "Value of zero means "
+ "there SHOULD be no unsolicited accounting updates.");
- binstr = g_malloc(8*sizeof(gchar)*len);
+ break;
+ case COPS_OBJ_INTEGRITY:
+ if (c_type != 1)
+ break; /* Not HMAC digest */
- for (i=0; i < len; i++) {
- for ( j=0; j<8; j++ ) { /* for each bit */
- bit = (mask & hex[i]) ? 1 : 0; /* bit is 1 or 0 */
- sprintf(&binstr[k++],"%d",bit); /*put it in string */
- mask >>= 1; /* shift mask right */
- }
- mask = 0x80;
+ proto_tree_add_item(tree, hf_cops_key_id, tvb, offset, 4, FALSE);
+ proto_tree_add_item(tree, hf_cops_seq_num, tvb, offset + 4, 4, FALSE);
+ proto_tree_add_text(tree, tvb, offset + 8 , len - 8, "Contents: Keyed Message Digest");
+
+ break;
+ default:
+ proto_tree_add_text(tree, tvb, offset, len, "Contents: %u bytes", len);
+
+ break;
}
- return binstr;
}
-/*
- * XXX - we should perhaps support reading PIBs, as we support reading
- * MIBs, and use the PIBs we read to understand how to display COPS data
- * just as we use the MIBs we read to understand how to display SNMP
- * data.
- */
+#ifdef HAVE_NET_SNMP
+static guchar*format_asn_value (struct variable_list *variable, subid_t *variable_oid,
+ guint variable_oid_length,gushort type_from_packet)
+{
+ struct tree *subtree=tree_head;
+
+ guchar *buf=NULL;
+ size_t buf_len=0;
+ size_t out_len=0;
+
+ /*Get the ASN.1 type etc. from the PIB-MIB. If unsuccessful use the type from packet*/
+ subtree = get_tree(variable_oid,variable_oid_length, subtree);
+
+ if (subtree->type == 0)
+ variable->type=type_from_packet;
+
+ buf_len = SPRINT_MAX_LEN; /*defined in NET-SNMP's snmp-impl.h*/
+ buf = g_malloc(buf_len);
+ *buf = '\0';
+ out_len = 0;
+
+ /*If the ASN.1 type was found from PIB-MIB, use it for decoding*/
+ if (!variable->type)
+ variable->type=mib_to_asn_type(subtree->type);
+
+ if (!sprint_realloc_by_type(&buf, &buf_len, &out_len, TRUE, variable, subtree->enums, subtree->hint, NULL))
+ sprintf(buf,"%s","sprint_realloc_by_type failed");
+
+ return buf;
+}
+#endif /* HAVE_NET_SNMP */
+
static int decode_cops_pr_asn1_data(tvbuff_t *tvb, guint32 offset,
- proto_tree *tree, guint epdlen, gboolean inepd)
+ proto_tree *tree, guint epdlen, gboolean inepd
+#ifndef HAVE_NET_SNMP
+ _U_
+#endif
+ )
{
- ASN1_SCK asn1;
- int start;
- gboolean def;
- guint length;
-
- guint vb_length;
- gushort vb_type;
- gchar *vb_type_name;
-
- int ret;
- guint cls, con, tag;
-
- gint32 vb_integer_value;
- guint32 vb_uinteger_value;
-
- guint8 *vb_octet_string;
-
- subid_t *vb_oid;
- guint vb_oid_length;
-
- gchar *vb_display_string;
-
- unsigned int i=0;
- gchar *buf;
- int len;
-
- while (epdlen > 0) { /*while there is stuff to be decoded*/
- asn1_open(&asn1, tvb, offset);
-
- /* parse the type of the object */
-
- start = asn1.offset;
-
- ret = asn1_header_decode (&asn1, &cls, &con, &tag, &def,
- &vb_length);
- if (ret != ASN1_ERR_NOERROR)
- return 0;
- if (!def)
- return ASN1_ERR_LENGTH_NOT_DEFINITE;
-
- /* Convert the class, constructed flag, and tag to a type. */
- vb_type_name = cops_tag_cls2syntax(tag, cls, &vb_type);
- if (vb_type_name == NULL) {
- /*
- * Unsupported type.
- * Dissect the value as an opaque string of octets.
- */
- vb_type_name = "unsupported type";
- vb_type = COPS_OPAQUE;
- }
-
- /* parse the value */
-
- switch (vb_type) {
-
- case COPS_INTEGER:
- ret = asn1_int32_value_decode(&asn1, vb_length,
- &vb_integer_value);
- if (ret != ASN1_ERR_NOERROR)
- return ret;
- length = asn1.offset - start;
- if (tree) {
- proto_tree_add_text(tree, asn1.tvb, offset, length,
- "Value: %s: %d (%#x)", vb_type_name,
- vb_integer_value, vb_integer_value);
- }
- break;
-
- case COPS_UNSIGNED32:
- case COPS_TIMETICKS:
- ret = asn1_uint32_value_decode(&asn1, vb_length,
- &vb_uinteger_value);
- if (ret != ASN1_ERR_NOERROR)
- return ret;
- length = asn1.offset - start;
- if (tree) {
- proto_tree_add_text(tree, asn1.tvb, offset, length,
- "Value: %s: %u (%#x)", vb_type_name,
- vb_uinteger_value, vb_uinteger_value);
- }
- break;
-
- case COPS_OCTETSTR:
- case COPS_IPADDR:
- case COPS_OPAQUE:
- case COPS_UNSIGNED64:
- case COPS_INTEGER64:
- ret = asn1_string_value_decode (&asn1, vb_length,
- &vb_octet_string);
- if (ret != ASN1_ERR_NOERROR)
- return ret;
- length = asn1.offset - start;
- if (tree) {
- /* if this EPD belongs to ipFilter or
- frwkPrcSupport Entries print it correctly) */
- if ((strncmp(last_decoded_prid,"1.3.6.1.2.2.2.3.2.1",19)==0) || (strncmp(last_decoded_prid,"1.3.6.1.2.2.2.1.1.1",19)==0)) {
- if(strncmp(last_decoded_prid,"1.3.6.1.2.2.2.3.2.1",19)==0) {
- i=0;/* EPD belongs to
- IpFilters, print as
- bytes (IPv6 not printed
- ok - yet)*/
- } else {
- /* EPD belongs to
- frwkPrcSupportEntry,
- convert hex byte(s) to
- binary string*/
- vb_display_string =
- xtobstr(vb_octet_string,
- vb_length);
-
- proto_tree_add_text(tree, asn1.tvb,
- offset, length,
- "Value: %s: %s", vb_type_name,
- vb_display_string);
-
- g_free(vb_octet_string);
- g_free(vb_display_string);
-
- break;
- }
- } else {
- /* EPD doesn't belong to ipFilter or
- frwkPrcSupport Entries;
- check for unprintable characters*/
-
- for (i = 0; i < vb_length; i++) {
- if (!(isprint(vb_octet_string[i])
- ||isspace(vb_octet_string[i])))
- break;
- }
- }
-
- /*
- * If some characters are not printable,
- * display the string as bytes.
- */
- if (i < vb_length) {
- /*
- * We stopped, due to a non-printable
- * character, before we got to the end
- * of the string.
- */
- vb_display_string =
- g_malloc(4*vb_length);
- buf = &vb_display_string[0];
- len = sprintf(buf, "%03u",
- vb_octet_string[0]);
- buf += len;
- for (i = 1; i < vb_length; i++) {
- len = sprintf(buf, ".%03u",
- vb_octet_string[i]);
- buf += len;
- }
- proto_tree_add_text(tree,
- asn1.tvb, offset, length,
- "Value: %s: %s", vb_type_name,
- vb_display_string);
- g_free(vb_display_string);
- } else {
- proto_tree_add_text(tree,
- asn1.tvb, offset, length,
- "Value: %s: %.*s", vb_type_name,
- (int)vb_length,
- SAFE_STRING(vb_octet_string));
- }
- }
- g_free(vb_octet_string);
- break;
-
- case COPS_NULL:
- ret = asn1_null_decode (&asn1, vb_length);
- if (ret != ASN1_ERR_NOERROR)
- return ret;
- length = asn1.offset - start;
- if (tree) {
- proto_tree_add_text(tree, asn1.tvb, offset, length,
- "Value: %s", vb_type_name);
- }
- break;
-
- case COPS_OBJECTID:
- ret = asn1_oid_value_decode (&asn1, vb_length, &vb_oid,
- &vb_oid_length);
- if (ret != ASN1_ERR_NOERROR)
- return ret;
- length = asn1.offset - start;
-
- if (tree) {
- vb_display_string = format_oid(vb_oid,
- vb_oid_length);
- proto_tree_add_text(tree, asn1.tvb, offset, length,
- "Value: %s: %s", vb_type_name,
- vb_display_string);
-
- if (inepd) {
- /* we're decoding EPD */
- g_free(vb_display_string);
- } else {
- /* we're decoding PRID, so let's store
- the OID of the PRID so that later
- when we're decoding this PRID's EPD
- we can finetune the output. */
- if (last_decoded_prid)
- g_free(last_decoded_prid);
- last_decoded_prid = vb_display_string;
- }
- }
- g_free(vb_oid);
- break;
-
- default:
- g_assert_not_reached();
- return ASN1_ERR_WRONG_TYPE;
- }
-
- asn1_close(&asn1,&offset);
-
- epdlen -= length;
- }
- return 0;
+ ASN1_SCK asn1;
+ int start;
+ gboolean def;
+ guint length;
+
+ guint vb_length;
+ gushort vb_type;
+ gchar *vb_type_name;
+
+ int ret;
+ guint cls, con, tag;
+ subid_t epd_attribute_index=0;
+
+ gint32 vb_integer_value;
+ guint32 vb_uinteger_value;
+
+ guint8 *vb_octet_string;
+
+ subid_t *vb_oid;
+ guint vb_oid_length;
+
+ gchar *vb_display_string;
+ gchar *vb_display_string2;
+
+#ifdef HAVE_NET_SNMP
+ struct variable_list variable;
+ long value;
+#endif /* HAVE_NET_SNMP */
+
+ unsigned int i;
+ gchar *buf;
+ int len;
+
+ while (epdlen > 0) { /*while there is stuff to be decoded in the EPD*/
+
+ epd_attribute_index++;
+#ifdef HAVE_NET_SNMP
+ last_decoded_prid_oid[last_decoded_prid_oid_length-1]=epd_attribute_index;
+#endif /* HAVE_NET_SNMP */
+ asn1_open(&asn1, tvb, offset);
+
+ /* parse the type of the object */
+
+ start = asn1.offset;
+
+ ret = asn1_header_decode (&asn1, &cls, &con, &tag, &def, &vb_length);
+ if (ret != ASN1_ERR_NOERROR)
+ return 0;
+ if (!def)
+ return ASN1_ERR_LENGTH_NOT_DEFINITE;
+
+ /* Convert the class, constructed flag, and tag to a type. */
+ vb_type_name = cops_tag_cls2syntax(tag, cls, &vb_type);
+ if (vb_type_name == NULL) {
+ /*
+ * Unsupported type.
+ * Dissect the value as an opaque string of octets.
+ */
+ vb_type_name = "unsupported type";
+ vb_type = COPS_OPAQUE;
+ }
+
+ /* parse the value */
+
+ switch (vb_type) {
+
+ case COPS_INTEGER:
+ ret = asn1_int32_value_decode(&asn1, vb_length, &vb_integer_value);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+ length = asn1.offset - start;
+ if (tree) {
+#ifdef HAVE_NET_SNMP
+ if (cops_typefrommib == TRUE)
+ {
+ variable.type = NULL;
+ value = vb_integer_value;
+ variable.val.integer = &value;
+ variable.val_len = vb_length ;
+ vb_display_string=format_asn_value(&variable,
+ last_decoded_prid_oid,last_decoded_prid_oid_length,ASN_INTEGER);
+
+ proto_tree_add_text(tree, asn1.tvb, offset, length,
+ "Value: %s", vb_display_string);
+ g_free(vb_display_string);
+ }
+ else
+#endif /* HAVE_NET_SNMP */
+ proto_tree_add_text(tree, asn1.tvb, offset, length,
+ "Value: %s: %d (%#x)", vb_type_name,
+ vb_integer_value, vb_integer_value);
+ }
+ break;
+
+ case COPS_UNSIGNED32:
+ case COPS_TIMETICKS:
+ ret = asn1_uint32_value_decode(&asn1, vb_length, &vb_uinteger_value);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+ length = asn1.offset - start;
+ if (tree) {
+#ifdef HAVE_NET_SNMP
+ if (cops_typefrommib == TRUE)
+ {
+ variable.type = NULL;
+ value = vb_uinteger_value;
+ variable.val.integer = &value;
+ variable.val_len = vb_length;
+
+ vb_display_string=format_asn_value(&variable,
+ last_decoded_prid_oid,last_decoded_prid_oid_length,ASN_UINTEGER);
+
+ proto_tree_add_text(tree, asn1.tvb, offset, length, "Value %s: %s",vb_type_name, vb_display_string);
+
+ g_free(vb_display_string);
+ }
+ else
+#endif /* HAVE_NET_SNMP */
+ proto_tree_add_text(tree, asn1.tvb, offset, length,
+ "Value: %s: %u (%#x)", vb_type_name,
+ vb_uinteger_value, vb_uinteger_value);
+ }
+ break;
+
+ case COPS_OCTETSTR:
+ case COPS_IPADDR:
+ case COPS_OPAQUE:
+ case COPS_UNSIGNED64:
+ case COPS_INTEGER64:
+ ret = asn1_string_value_decode (&asn1, vb_length, &vb_octet_string);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+ length = asn1.offset - start;
+ if (tree) {
+#ifdef HAVE_NET_SNMP
+ if (cops_typefrommib == TRUE)
+ {
+ variable.type = NULL;
+ variable.val.string = vb_octet_string;
+ variable.val_len = vb_length;
+ vb_display_string = format_asn_value(&variable,
+ last_decoded_prid_oid,last_decoded_prid_oid_length,ASN_OCTET_STR);
+ proto_tree_add_text(tree, asn1.tvb, offset, length,
+ "Value: %s (ASN.1 type from packet: %s)", vb_display_string, vb_type_name);
+
+ g_free(vb_display_string);
+ }
+ else
+ {
+#endif /* HAVE_NET_SNMP */
+ for (i = 0; i < vb_length; i++) {
+ if (!(isprint(vb_octet_string[i]) ||isspace(vb_octet_string[i])))
+ break;
+ }
+
+ /*
+ * If some characters are not printable, display the string as bytes.
+ */
+ if (i < vb_length) {
+ /*
+ * We stopped, due to a non-printable character, before we got
+ * to the end of the string.
+ */
+ vb_display_string = g_malloc(4*vb_length);
+ buf = &vb_display_string[0];
+ len = sprintf(buf, "%03u", vb_octet_string[0]);
+ buf += len;
+ for (i = 1; i < vb_length; i++) {
+ len = sprintf(buf, ".%03u", vb_octet_string[i]);
+ buf += len;
+ }
+ proto_tree_add_text(tree, asn1.tvb, offset, length,
+ "Value: %s: %s", vb_type_name, vb_display_string);
+ g_free(vb_display_string);
+ } else {
+ proto_tree_add_text(tree, asn1.tvb, offset, length,
+ "Value: %s: %.*s", vb_type_name, (int)vb_length,
+ SAFE_STRING(vb_octet_string));
+ }
+#ifdef HAVE_NET_SNMP
+ }
+#endif /* HAVE_NET_SNMP */
+ }
+ g_free(vb_octet_string);
+ break;
+
+ case COPS_NULL:
+ ret = asn1_null_decode (&asn1, vb_length);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+ length = asn1.offset - start;
+ if (tree)
+ proto_tree_add_text(tree, asn1.tvb, offset, length, "Value: %s", vb_type_name);
+ break;
+
+ case COPS_OBJECTID:
+ ret = asn1_oid_value_decode (&asn1, vb_length, &vb_oid, &vb_oid_length);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+ length = asn1.offset - start;
+
+ if (tree) {
+ /*strip the instance Id from the OIDs before decoding and paste it back during printing*/
+ new_format_oid(vb_oid,vb_oid_length-1,&vb_display_string,&vb_display_string2);
+
+ /*if OID couldn't be decoded, print only numeric format*/
+ if (!vb_display_string2)
+ proto_tree_add_text(tree, asn1.tvb, offset, length,
+ "Value: %s: %s.%lu", vb_type_name,
+ vb_display_string,
+ (unsigned long)vb_oid[vb_oid_length-1]);
+ else
+ proto_tree_add_text(tree, asn1.tvb, offset, length,
+ "Value: %s: %s.%lu (%s.%lu)", vb_type_name,
+ vb_display_string,
+ (unsigned long)vb_oid[vb_oid_length-1],
+ vb_display_string2,
+ (unsigned long)vb_oid[vb_oid_length-1]);
+#ifdef HAVE_NET_SNMP
+ if (!inepd) {
+ /* we're decoding PRID, so let's store the OID of the PRID so that later
+ when we're decoding this PRID's EPD we can finetune the output.*/
+ memcpy(last_decoded_prid_oid,vb_oid,vb_oid_length*sizeof(subid_t));
+ last_decoded_prid_oid_length=vb_oid_length;
+ }
+#endif /* HAVE_NET_SNMP */
+ }
+ g_free(vb_display_string);
+ if(vb_display_string2)
+ g_free(vb_display_string2);
+ g_free(vb_oid);
+ break;
+
+ default:
+ g_assert_not_reached();
+ return ASN1_ERR_WRONG_TYPE;
+ }
+
+ asn1_close(&asn1,&offset);
+
+ epdlen -= length;
+ }
+ epd_attribute_index=0;
+ return 0;
}
static int dissect_cops_pr_object_data(tvbuff_t *tvb, guint32 offset, proto_tree *tree,
- guint8 s_num, guint8 s_type, guint16 len)
+ guint8 s_num, guint8 s_type, guint16 len)
{
- proto_item *ti;
- proto_tree *asn1_object_tree, *gperror_tree, *cperror_tree;
- guint16 gperror=0, gperror_sub=0, cperror=0, cperror_sub=0;
-
- switch (s_num){
- case COPS_OBJ_PRID:
- if (s_type != 1) /* Not Provisioning Instance Identifier (PRID) */
- break;
-
- ti=proto_tree_add_text(tree, tvb, offset, len, "Contents:");
- asn1_object_tree = proto_item_add_subtree(ti, ett_cops_asn1);
-
- decode_cops_pr_asn1_data(tvb, offset, asn1_object_tree, len, FALSE);
-
- break;
- case COPS_OBJ_PPRID:
- if (s_type != 1) /* Not Prefix Provisioning Instance Identifier (PPRID) */
- break;
-
- ti = proto_tree_add_text(tree, tvb, offset, len, "Contents:");
- asn1_object_tree = proto_item_add_subtree(ti, ett_cops_asn1);
-
- decode_cops_pr_asn1_data(tvb, offset, asn1_object_tree, len, FALSE);
-
- break;
- case COPS_OBJ_EPD:
- if (s_type != 1) /* Not Encoded Provisioning Instance Data (EPD) */
- break;
-
- ti = proto_tree_add_text(tree, tvb, offset, len, "Contents:");
- asn1_object_tree = proto_item_add_subtree(ti, ett_cops_asn1);
-
- decode_cops_pr_asn1_data(tvb, offset, asn1_object_tree, len, TRUE);
-
- break;
- case COPS_OBJ_GPERR:
- if (s_type != 1) /* Not Global Provisioning Error Object (GPERR) */
- break;
-
- gperror = tvb_get_ntohs(tvb, offset);
- gperror_sub = tvb_get_ntohs(tvb, offset + 2);
- ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Error-Code: %s, Error Sub-code: 0x%04x",
- val_to_str(gperror, cops_gperror_vals, "<Unknown value>"), gperror_sub);
- gperror_tree = proto_item_add_subtree(ti, ett_cops_gperror);
- proto_tree_add_uint(gperror_tree, hf_cops_gperror, tvb, offset, 2, gperror);
- offset += 2;
- if (cperror == 13) {
- proto_tree_add_text(gperror_tree, tvb, offset, 2, "Error Sub-code: "
- "Unknown object's C-Num %u, C-Type %u",
- tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset + 1));
- } else
- proto_tree_add_uint(gperror_tree, hf_cops_gperror_sub, tvb, offset, 2, gperror_sub);
-
- break;
- case COPS_OBJ_CPERR:
- if (s_type != 1) /*Not PRC Class Provisioning Error Object (CPERR) */
- break;
-
- break;
-
- cperror = tvb_get_ntohs(tvb, offset);
- cperror_sub = tvb_get_ntohs(tvb, offset + 2);
- ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Error-Code: %s, Error Sub-code: 0x%04x",
- val_to_str(cperror, cops_cperror_vals, "<Unknown value>"), cperror_sub);
- cperror_tree = proto_item_add_subtree(ti, ett_cops_cperror);
- proto_tree_add_uint(cperror_tree, hf_cops_cperror, tvb, offset, 2, cperror);
- offset += 2;
- if (cperror == 13) {
- proto_tree_add_text(cperror_tree, tvb, offset, 2, "Error Sub-code: "
- "Unknown object's S-Num %u, C-Type %u",
- tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset + 1));
- } else
- proto_tree_add_uint(cperror_tree, hf_cops_cperror_sub, tvb, offset, 2, cperror_sub);
-
- break;
- case COPS_OBJ_ERRPRID:
- if (s_type != 1) /*Not Error Provisioning Instance Identifier (ErrorPRID)*/
- break;
-
- ti = proto_tree_add_text(tree, tvb, offset, len, "Contents:");
- asn1_object_tree = proto_item_add_subtree(ti, ett_cops_asn1);
-
- decode_cops_pr_asn1_data(tvb, offset, asn1_object_tree, len, FALSE);
-
- break;
- default:
- proto_tree_add_text(tree, tvb, offset, len, "Contents: %u bytes", len);
- break;
- }
+ proto_item *ti;
+ proto_tree *asn1_object_tree, *gperror_tree, *cperror_tree;
+ guint16 gperror=0, gperror_sub=0, cperror=0, cperror_sub=0;
+
+ switch (s_num){
+ case COPS_OBJ_PRID:
+ if (s_type != 1) /* Not Provisioning Instance Identifier (PRID) */
+ break;
+
+ ti=proto_tree_add_text(tree, tvb, offset, len, "Contents:");
+ asn1_object_tree = proto_item_add_subtree(ti, ett_cops_asn1);
+
+ decode_cops_pr_asn1_data(tvb, offset, asn1_object_tree, len, FALSE);
+
+ break;
+ case COPS_OBJ_PPRID:
+ if (s_type != 1) /* Not Prefix Provisioning Instance Identifier (PPRID) */
+ break;
+
+ ti = proto_tree_add_text(tree, tvb, offset, len, "Contents:");
+ asn1_object_tree = proto_item_add_subtree(ti, ett_cops_asn1);
+
+ decode_cops_pr_asn1_data(tvb, offset, asn1_object_tree, len, FALSE);
+
+ break;
+ case COPS_OBJ_EPD:
+ if (s_type != 1) /* Not Encoded Provisioning Instance Data (EPD) */
+ break;
+
+ ti = proto_tree_add_text(tree, tvb, offset, len, "Contents:");
+ asn1_object_tree = proto_item_add_subtree(ti, ett_cops_asn1);
+
+ decode_cops_pr_asn1_data(tvb, offset, asn1_object_tree, len, TRUE);
+
+ break;
+ case COPS_OBJ_GPERR:
+ if (s_type != 1) /* Not Global Provisioning Error Object (GPERR) */
+ break;
+
+ gperror = tvb_get_ntohs(tvb, offset);
+ gperror_sub = tvb_get_ntohs(tvb, offset + 2);
+ ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Error-Code: %s, Error Sub-code: 0x%04x",
+ val_to_str(gperror, cops_gperror_vals, "<Unknown value>"), gperror_sub);
+ gperror_tree = proto_item_add_subtree(ti, ett_cops_gperror);
+ proto_tree_add_uint(gperror_tree, hf_cops_gperror, tvb, offset, 2, gperror);
+ offset += 2;
+ if (cperror == 13) {
+ proto_tree_add_text(gperror_tree, tvb, offset, 2, "Error Sub-code: "
+ "Unknown object's C-Num %u, C-Type %u",
+ tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset + 1));
+ } else
+ proto_tree_add_uint(gperror_tree, hf_cops_gperror_sub, tvb, offset, 2, gperror_sub);
+
+ break;
+ case COPS_OBJ_CPERR:
+ if (s_type != 1) /*Not PRC Class Provisioning Error Object (CPERR) */
+ break;
+
+ break;
+
+ cperror = tvb_get_ntohs(tvb, offset);
+ cperror_sub = tvb_get_ntohs(tvb, offset + 2);
+ ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Error-Code: %s, Error Sub-code: 0x%04x",
+ val_to_str(cperror, cops_cperror_vals, "<Unknown value>"), cperror_sub);
+ cperror_tree = proto_item_add_subtree(ti, ett_cops_cperror);
+ proto_tree_add_uint(cperror_tree, hf_cops_cperror, tvb, offset, 2, cperror);
+ offset += 2;
+ if (cperror == 13) {
+ proto_tree_add_text(cperror_tree, tvb, offset, 2, "Error Sub-code: "
+ "Unknown object's S-Num %u, C-Type %u",
+ tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset + 1));
+ } else
+ proto_tree_add_uint(cperror_tree, hf_cops_cperror_sub, tvb, offset, 2, cperror_sub);
+
+ break;
+ case COPS_OBJ_ERRPRID:
+ if (s_type != 1) /*Not Error Provisioning Instance Identifier (ErrorPRID)*/
+ break;
+
+ ti = proto_tree_add_text(tree, tvb, offset, len, "Contents:");
+ asn1_object_tree = proto_item_add_subtree(ti, ett_cops_asn1);
+
+ decode_cops_pr_asn1_data(tvb, offset, asn1_object_tree, len, FALSE);
+
+ break;
+ default:
+ proto_tree_add_text(tree, tvb, offset, len, "Contents: %u bytes", len);
+ break;
+ }
- return 0;
+ return 0;
}
/* Register the protocol with Ethereal */
void proto_register_cops(void)
{
- /* Setup list of header fields */
- static hf_register_info hf[] = {
- { &hf_cops_ver_flags,
- { "Version and Flags", "cops.ver_flags",
- FT_UINT8, BASE_HEX, NULL, 0x0,
- "Version and Flags in COPS Common Header", HFILL }
- },
- { &hf_cops_version,
- { "Version", "cops.version",
- FT_UINT8, BASE_DEC, NULL, 0xF0,
- "Version in COPS Common Header", HFILL }
- },
- { &hf_cops_flags,
- { "Flags", "cops.flags",
- FT_UINT8, BASE_HEX, VALS(cops_flags_vals), 0x0F,
- "Flags in COPS Common Header", HFILL }
- },
- { &hf_cops_op_code,
- { "Op Code", "cops.op_code",
- FT_UINT8, BASE_DEC, VALS(cops_op_code_vals), 0x0,
- "Op Code in COPS Common Header", HFILL }
- },
- { &hf_cops_client_type,
- { "Client Type", "cops.client_type",
- FT_UINT16, BASE_DEC, NULL, 0x0,
- "Client Type in COPS Common Header", HFILL }
- },
- { &hf_cops_msg_len,
- { "Message Length", "cops.msg_len",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "Message Length in COPS Common Header", HFILL }
- },
- { &hf_cops_obj_len,
- { "Object Length", "cops.obj.len",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "Object Length in COPS Object Header", HFILL }
- },
- { &hf_cops_obj_c_num,
- { "C-Num", "cops.c_num",
- FT_UINT8, BASE_DEC, VALS(cops_c_num_vals), 0x0,
- "C-Num in COPS Object Header", HFILL }
- },
- { &hf_cops_obj_c_type,
- { "C-Type", "cops.c_type",
- FT_UINT8, BASE_DEC, NULL, 0x0,
- "C-Type in COPS Object Header", HFILL }
- },
-
- { &hf_cops_obj_s_num,
- { "S-Num", "cops.s_num",
- FT_UINT8, BASE_DEC, VALS(cops_s_num_vals), 0x0,
- "S-Num in COPS-PR Object Header", HFILL }
- },
- { &hf_cops_obj_s_type,
- { "S-Type", "cops.s_type",
- FT_UINT8, BASE_DEC, NULL, 0x0,
- "S-Type in COPS-PR Object Header", HFILL }
- },
-
- { &hf_cops_r_type_flags,
- { "R-Type", "cops.context.r_type",
- FT_UINT16, BASE_HEX, VALS(cops_r_type_vals), 0xFFFF,
- "R-Type in COPS Context Object", HFILL }
- },
- { &hf_cops_m_type_flags,
- { "M-Type", "cops.context.m_type",
- FT_UINT16, BASE_HEX, NULL, 0xFFFF,
- "M-Type in COPS Context Object", HFILL }
- },
- { &hf_cops_in_int_ipv4,
- { "IPv4 address", "cops.in-int.ipv4",
- FT_IPv4, 0, NULL, 0xFFFF,
- "IPv4 address in COPS IN-Int object", HFILL }
- },
- { &hf_cops_in_int_ipv6,
- { "IPv6 address", "cops.in-int.ipv6",
- FT_IPv6, 0, NULL, 0xFFFF,
- "IPv6 address in COPS IN-Int object", HFILL }
- },
- { &hf_cops_out_int_ipv4,
- { "IPv4 address", "cops.out-int.ipv4",
- FT_IPv4, 0, NULL, 0xFFFF,
- "IPv4 address in COPS OUT-Int object", HFILL }
- },
- { &hf_cops_out_int_ipv6,
- { "IPv6 address", "cops.out-int.ipv6",
- FT_IPv6, 0, NULL, 0xFFFF,
- "IPv6 address in COPS OUT-Int", HFILL }
- },
- { &hf_cops_int_ifindex,
- { "ifIndex", "cops.in-out-int.ifindex",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "If SNMP is supported, corresponds to MIB-II ifIndex", HFILL }
- },
- { &hf_cops_reason,
- { "Reason", "cops.reason",
- FT_UINT16, BASE_DEC, VALS(cops_reason_vals), 0,
- "Reason in Reason object", HFILL }
- },
- { &hf_cops_reason_sub,
- { "Reason Sub-code", "cops.reason_sub",
- FT_UINT16, BASE_HEX, NULL, 0,
- "Reason Sub-code in Reason object", HFILL }
- },
- { &hf_cops_dec_cmd_code,
- { "Command-Code", "cops.decision.cmd",
- FT_UINT16, BASE_DEC, VALS(cops_dec_cmd_code_vals), 0,
- "Command-Code in Decision/LPDP Decision object", HFILL }
- },
- { &hf_cops_dec_flags,
- { "Flags", "cops.decision.flags",
- FT_UINT16, BASE_HEX, VALS(cops_dec_cmd_flag_vals), 0xffff,
- "Flags in Decision/LPDP Decision object", HFILL }
- },
- { &hf_cops_error,
- { "Error", "cops.error",
- FT_UINT16, BASE_DEC, VALS(cops_error_vals), 0,
- "Error in Error object", HFILL }
- },
- { &hf_cops_error_sub,
- { "Error Sub-code", "cops.error_sub",
- FT_UINT16, BASE_HEX, NULL, 0,
- "Error Sub-code in Error object", HFILL }
- },
- { &hf_cops_katimer,
- { "Contents: KA Timer Value", "cops.katimer.value",
- FT_UINT16, BASE_DEC, NULL, 0,
- "Keep-Alive Timer Value in KATimer object", HFILL }
- },
- { &hf_cops_pepid,
- { "Contents: PEP Id", "cops.pepid.id",
- FT_STRING, BASE_NONE, NULL, 0,
- "PEP Id in PEPID object", HFILL }
- },
- { &hf_cops_report_type,
- { "Contents: Report-Type", "cops.report_type",
- FT_UINT16, BASE_DEC, VALS(cops_report_type_vals), 0,
- "Report-Type in Report-Type object", HFILL }
- },
- { &hf_cops_pdprediraddr_ipv4,
- { "IPv4 address", "cops.pdprediraddr.ipv4",
- FT_IPv4, 0, NULL, 0xFFFF,
- "IPv4 address in COPS PDPRedirAddr object", HFILL }
- },
- { &hf_cops_pdprediraddr_ipv6,
- { "IPv6 address", "cops.pdprediraddr.ipv6",
- FT_IPv6, 0, NULL, 0xFFFF,
- "IPv6 address in COPS PDPRedirAddr object", HFILL }
- },
- { &hf_cops_lastpdpaddr_ipv4,
- { "IPv4 address", "cops.lastpdpaddr.ipv4",
- FT_IPv4, 0, NULL, 0xFFFF,
- "IPv4 address in COPS LastPDPAddr object", HFILL }
- },
- { &hf_cops_lastpdpaddr_ipv6,
- { "IPv6 address", "cops.lastpdpaddr.ipv6",
- FT_IPv6, 0, NULL, 0xFFFF,
- "IPv6 address in COPS LastPDPAddr object", HFILL }
- },
- { &hf_cops_pdp_tcp_port,
- { "TCP Port Number", "cops.pdp.tcp_port",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "TCP Port Number of PDP in PDPRedirAddr/LastPDPAddr object", HFILL }
- },
- { &hf_cops_accttimer,
- { "Contents: ACCT Timer Value", "cops.accttimer.value",
- FT_UINT16, BASE_DEC, NULL, 0,
- "Accounting Timer Value in AcctTimer object", HFILL }
- },
- { &hf_cops_key_id,
- { "Contents: Key ID", "cops.integrity.key_id",
- FT_UINT32, BASE_DEC, NULL, 0,
- "Key ID in Integrity object", HFILL }
- },
- { &hf_cops_seq_num,
- { "Contents: Sequence Number", "cops.integrity.seq_num",
- FT_UINT32, BASE_DEC, NULL, 0,
- "Sequence Number in Integrity object", HFILL }
- },
- { &hf_cops_gperror,
- { "Error", "cops.gperror",
- FT_UINT16, BASE_DEC, VALS(cops_gperror_vals), 0,
- "Error in Error object", HFILL }
- },
- { &hf_cops_gperror_sub,
- { "Error Sub-code", "cops.gperror_sub",
- FT_UINT16, BASE_HEX, NULL, 0,
- "Error Sub-code in Error object", HFILL }
- },
- { &hf_cops_cperror,
- { "Error", "cops.cperror",
- FT_UINT16, BASE_DEC, VALS(cops_cperror_vals), 0,
- "Error in Error object", HFILL }
- },
- { &hf_cops_cperror_sub,
- { "Error Sub-code", "cops.cperror_sub",
- FT_UINT16, BASE_HEX, NULL, 0,
- "Error Sub-code in Error object", HFILL }
- },
-
- };
-
- /* Setup protocol subtree array */
- static gint *ett[] = {
- &ett_cops,
- &ett_cops_ver_flags,
- &ett_cops_obj,
- &ett_cops_pr_obj,
- &ett_cops_obj_data,
- &ett_cops_r_type_flags,
- &ett_cops_itf,
- &ett_cops_reason,
- &ett_cops_decision,
- &ett_cops_error,
- &ett_cops_clientsi,
- &ett_cops_asn1,
- &ett_cops_gperror,
- &ett_cops_cperror,
- &ett_cops_pdp,
- };
-
- module_t* cops_module;
-
- /* Register the protocol name and description */
- proto_cops = proto_register_protocol("Common Open Policy Service",
- "COPS", "cops");
-
- /* Required function calls to register the header fields and subtrees used */
- proto_register_field_array(proto_cops, hf, array_length(hf));
- proto_register_subtree_array(ett, array_length(ett));
-
- /* Register our configuration options for cops,
- * particularly our ports
- */
- cops_module = prefs_register_protocol(proto_cops,
- proto_reg_handoff_cops);
- prefs_register_uint_preference(cops_module,"tcp.cops_port",
- "COPS TCP Port",
- "Set the TCP port for COPS messages",
- 10,&global_cops_tcp_port);
- prefs_register_bool_preference(cops_module, "desegment",
- "Desegment all COPS messages spanning multiple TCP segments",
- "Whether the COPS dissector should desegment all messages spanning multiple TCP segments",
- &cops_desegment);
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_cops_ver_flags,
+ { "Version and Flags", "cops.ver_flags",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Version and Flags in COPS Common Header", HFILL }
+ },
+ { &hf_cops_version,
+ { "Version", "cops.version",
+ FT_UINT8, BASE_DEC, NULL, 0xF0,
+ "Version in COPS Common Header", HFILL }
+ },
+ { &hf_cops_flags,
+ { "Flags", "cops.flags",
+ FT_UINT8, BASE_HEX, VALS(cops_flags_vals), 0x0F,
+ "Flags in COPS Common Header", HFILL }
+ },
+ { &hf_cops_op_code,
+ { "Op Code", "cops.op_code",
+ FT_UINT8, BASE_DEC, VALS(cops_op_code_vals), 0x0,
+ "Op Code in COPS Common Header", HFILL }
+ },
+ { &hf_cops_client_type,
+ { "Client Type", "cops.client_type",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Client Type in COPS Common Header", HFILL }
+ },
+ { &hf_cops_msg_len,
+ { "Message Length", "cops.msg_len",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Message Length in COPS Common Header", HFILL }
+ },
+ { &hf_cops_obj_len,
+ { "Object Length", "cops.obj.len",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Object Length in COPS Object Header", HFILL }
+ },
+ { &hf_cops_obj_c_num,
+ { "C-Num", "cops.c_num",
+ FT_UINT8, BASE_DEC, VALS(cops_c_num_vals), 0x0,
+ "C-Num in COPS Object Header", HFILL }
+ },
+ { &hf_cops_obj_c_type,
+ { "C-Type", "cops.c_type",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "C-Type in COPS Object Header", HFILL }
+ },
+
+ { &hf_cops_obj_s_num,
+ { "S-Num", "cops.s_num",
+ FT_UINT8, BASE_DEC, VALS(cops_s_num_vals), 0x0,
+ "S-Num in COPS-PR Object Header", HFILL }
+ },
+ { &hf_cops_obj_s_type,
+ { "S-Type", "cops.s_type",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "S-Type in COPS-PR Object Header", HFILL }
+ },
+
+ { &hf_cops_r_type_flags,
+ { "R-Type", "cops.context.r_type",
+ FT_UINT16, BASE_HEX, VALS(cops_r_type_vals), 0xFFFF,
+ "R-Type in COPS Context Object", HFILL }
+ },
+ { &hf_cops_m_type_flags,
+ { "M-Type", "cops.context.m_type",
+ FT_UINT16, BASE_HEX, NULL, 0xFFFF,
+ "M-Type in COPS Context Object", HFILL }
+ },
+ { &hf_cops_in_int_ipv4,
+ { "IPv4 address", "cops.in-int.ipv4",
+ FT_IPv4, 0, NULL, 0xFFFF,
+ "IPv4 address in COPS IN-Int object", HFILL }
+ },
+ { &hf_cops_in_int_ipv6,
+ { "IPv6 address", "cops.in-int.ipv6",
+ FT_IPv6, 0, NULL, 0xFFFF,
+ "IPv6 address in COPS IN-Int object", HFILL }
+ },
+ { &hf_cops_out_int_ipv4,
+ { "IPv4 address", "cops.out-int.ipv4",
+ FT_IPv4, 0, NULL, 0xFFFF,
+ "IPv4 address in COPS OUT-Int object", HFILL }
+ },
+ { &hf_cops_out_int_ipv6,
+ { "IPv6 address", "cops.out-int.ipv6",
+ FT_IPv6, 0, NULL, 0xFFFF,
+ "IPv6 address in COPS OUT-Int", HFILL }
+ },
+ { &hf_cops_int_ifindex,
+ { "ifIndex", "cops.in-out-int.ifindex",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "If SNMP is supported, corresponds to MIB-II ifIndex", HFILL }
+ },
+ { &hf_cops_reason,
+ { "Reason", "cops.reason",
+ FT_UINT16, BASE_DEC, VALS(cops_reason_vals), 0,
+ "Reason in Reason object", HFILL }
+ },
+ { &hf_cops_reason_sub,
+ { "Reason Sub-code", "cops.reason_sub",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Reason Sub-code in Reason object", HFILL }
+ },
+ { &hf_cops_dec_cmd_code,
+ { "Command-Code", "cops.decision.cmd",
+ FT_UINT16, BASE_DEC, VALS(cops_dec_cmd_code_vals), 0,
+ "Command-Code in Decision/LPDP Decision object", HFILL }
+ },
+ { &hf_cops_dec_flags,
+ { "Flags", "cops.decision.flags",
+ FT_UINT16, BASE_HEX, VALS(cops_dec_cmd_flag_vals), 0xffff,
+ "Flags in Decision/LPDP Decision object", HFILL }
+ },
+ { &hf_cops_error,
+ { "Error", "cops.error",
+ FT_UINT16, BASE_DEC, VALS(cops_error_vals), 0,
+ "Error in Error object", HFILL }
+ },
+ { &hf_cops_error_sub,
+ { "Error Sub-code", "cops.error_sub",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Error Sub-code in Error object", HFILL }
+ },
+ { &hf_cops_katimer,
+ { "Contents: KA Timer Value", "cops.katimer.value",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Keep-Alive Timer Value in KATimer object", HFILL }
+ },
+ { &hf_cops_pepid,
+ { "Contents: PEP Id", "cops.pepid.id",
+ FT_STRING, BASE_NONE, NULL, 0,
+ "PEP Id in PEPID object", HFILL }
+ },
+ { &hf_cops_report_type,
+ { "Contents: Report-Type", "cops.report_type",
+ FT_UINT16, BASE_DEC, VALS(cops_report_type_vals), 0,
+ "Report-Type in Report-Type object", HFILL }
+ },
+ { &hf_cops_pdprediraddr_ipv4,
+ { "IPv4 address", "cops.pdprediraddr.ipv4",
+ FT_IPv4, 0, NULL, 0xFFFF,
+ "IPv4 address in COPS PDPRedirAddr object", HFILL }
+ },
+ { &hf_cops_pdprediraddr_ipv6,
+ { "IPv6 address", "cops.pdprediraddr.ipv6",
+ FT_IPv6, 0, NULL, 0xFFFF,
+ "IPv6 address in COPS PDPRedirAddr object", HFILL }
+ },
+ { &hf_cops_lastpdpaddr_ipv4,
+ { "IPv4 address", "cops.lastpdpaddr.ipv4",
+ FT_IPv4, 0, NULL, 0xFFFF,
+ "IPv4 address in COPS LastPDPAddr object", HFILL }
+ },
+ { &hf_cops_lastpdpaddr_ipv6,
+ { "IPv6 address", "cops.lastpdpaddr.ipv6",
+ FT_IPv6, 0, NULL, 0xFFFF,
+ "IPv6 address in COPS LastPDPAddr object", HFILL }
+ },
+ { &hf_cops_pdp_tcp_port,
+ { "TCP Port Number", "cops.pdp.tcp_port",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "TCP Port Number of PDP in PDPRedirAddr/LastPDPAddr object", HFILL }
+ },
+ { &hf_cops_accttimer,
+ { "Contents: ACCT Timer Value", "cops.accttimer.value",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Accounting Timer Value in AcctTimer object", HFILL }
+ },
+ { &hf_cops_key_id,
+ { "Contents: Key ID", "cops.integrity.key_id",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "Key ID in Integrity object", HFILL }
+ },
+ { &hf_cops_seq_num,
+ { "Contents: Sequence Number", "cops.integrity.seq_num",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "Sequence Number in Integrity object", HFILL }
+ },
+ { &hf_cops_gperror,
+ { "Error", "cops.gperror",
+ FT_UINT16, BASE_DEC, VALS(cops_gperror_vals), 0,
+ "Error in Error object", HFILL }
+ },
+ { &hf_cops_gperror_sub,
+ { "Error Sub-code", "cops.gperror_sub",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Error Sub-code in Error object", HFILL }
+ },
+ { &hf_cops_cperror,
+ { "Error", "cops.cperror",
+ FT_UINT16, BASE_DEC, VALS(cops_cperror_vals), 0,
+ "Error in Error object", HFILL }
+ },
+ { &hf_cops_cperror_sub,
+ { "Error Sub-code", "cops.cperror_sub",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Error Sub-code in Error object", HFILL }
+ },
+
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_cops,
+ &ett_cops_ver_flags,
+ &ett_cops_obj,
+ &ett_cops_pr_obj,
+ &ett_cops_obj_data,
+ &ett_cops_r_type_flags,
+ &ett_cops_itf,
+ &ett_cops_reason,
+ &ett_cops_decision,
+ &ett_cops_error,
+ &ett_cops_clientsi,
+ &ett_cops_asn1,
+ &ett_cops_gperror,
+ &ett_cops_cperror,
+ &ett_cops_pdp,
+ };
+
+ module_t* cops_module;
+
+ /* Register the protocol name and description */
+ proto_cops = proto_register_protocol("Common Open Policy Service",
+ "COPS", "cops");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_cops, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* Register our configuration options for cops */
+ cops_module = prefs_register_protocol(proto_cops, proto_reg_handoff_cops);
+ prefs_register_uint_preference(cops_module,"tcp.cops_port",
+ "COPS TCP Port",
+ "Set the TCP port for COPS messages",
+ 10,&global_cops_tcp_port);
+ prefs_register_bool_preference(cops_module, "desegment",
+ "Desegment all COPS messages spanning multiple TCP segments",
+ "Whether the COPS dissector should desegment all messages spanning multiple TCP segments",
+ &cops_desegment);
+#ifdef HAVE_NET_SNMP /*enable preference only if compiled with NET-SNMP*/
+ prefs_register_bool_preference(cops_module, "typefrommib",
+ "Decode COPS-PR ASN.1 types by reading them from PIBs (converted to MIBs)",
+ "Whether the COPS dissector should decode COPS-PR ASN.1 types based on data types read from packet or PIBs (converted to MIBs)",
+ &cops_typefrommib);
+#endif /*HAVE_NET_SNMP*/
};
-void
-proto_reg_handoff_cops(void)
+void proto_reg_handoff_cops(void)
{
- static int cops_prefs_initialized = FALSE;
- static dissector_handle_t cops_handle;
-
- if (!cops_prefs_initialized) {
- cops_handle = create_dissector_handle(dissect_cops, proto_cops);
- cops_prefs_initialized = TRUE;
- } else
- dissector_delete("tcp.port",cops_tcp_port,cops_handle);
-
- /* Set our port numbers for future use */
- cops_tcp_port = global_cops_tcp_port;
-
- dissector_add("tcp.port", cops_tcp_port, cops_handle);
+ static int cops_prefs_initialized = FALSE;
+ static dissector_handle_t cops_handle;
+
+ if (!cops_prefs_initialized) {
+ cops_handle = create_dissector_handle(dissect_cops, proto_cops);
+ cops_prefs_initialized = TRUE;
+ } else
+ dissector_delete("tcp.port",cops_tcp_port,cops_handle);
+
+ /* Set our port numbers for future use */
+ cops_tcp_port = global_cops_tcp_port;
+
+ dissector_add("tcp.port", cops_tcp_port, cops_handle);
}