summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-pcp.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
commite4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch)
tree68cb5ef9081156392f1dd62a00c6ccc1451b93df /epan/dissectors/packet-pcp.c
parentInitial commit. (diff)
downloadwireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz
wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'epan/dissectors/packet-pcp.c')
-rw-r--r--epan/dissectors/packet-pcp.c2975
1 files changed, 2975 insertions, 0 deletions
diff --git a/epan/dissectors/packet-pcp.c b/epan/dissectors/packet-pcp.c
new file mode 100644
index 00000000..f53ec9b5
--- /dev/null
+++ b/epan/dissectors/packet-pcp.c
@@ -0,0 +1,2975 @@
+/* packet-pcp.c
+ * Routines for Performace Co-Pilot protocol dissection
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "config.h"
+
+#include <epan/packet.h>
+#include <epan/expert.h>
+#include "packet-tcp.h"
+#include "packet-tls-utils.h"
+
+void proto_register_pcp(void);
+void proto_reg_handoff_pcp(void);
+
+#define PCP_PORT 44321
+#define PMPROXY_PORT 44322
+#define PCP_HEADER_LEN 12
+
+#define PM_ERR_NAME -12357
+
+static dissector_handle_t pcp_handle;
+
+static int proto_pcp = -1;
+static int hf_pcp_pdu_length = -1;
+static int hf_pcp_pdu_type = -1;
+static int hf_pcp_pdu_pid = -1;
+static int hf_pcp_pdu_error = -1;
+static int hf_pcp_pdu_padding = -1;
+static int hf_pcp_creds_number_of = -1;
+static int hf_pcp_creds_type = -1;
+static int hf_pcp_creds_version = -1;
+static int hf_pcp_start = -1;
+static int hf_pcp_start_status = -1;
+static int hf_pcp_start_zero = -1;
+static int hf_pcp_start_version = -1;
+static int hf_pcp_start_licensed = -1;
+static int hf_pcp_features_flags = -1;
+static int hf_pcp_features_flags_secure = -1;
+static int hf_pcp_features_flags_compress = -1;
+static int hf_pcp_features_flags_auth = -1;
+static int hf_pcp_features_flags_creds_reqd = -1;
+static int hf_pcp_features_flags_secure_ack = -1;
+static int hf_pcp_features_flags_no_nss_init = -1;
+static int hf_pcp_features_flags_container = -1;
+static int hf_pcp_features_flags_cert_reqd = -1;
+static int hf_pcp_features_flags_bad_label = -1;
+static int hf_pcp_features_flags_labels = -1;
+static int hf_pcp_pmns_traverse = -1;
+static int hf_pcp_pmns_subtype = -1;
+static int hf_pcp_pmns_namelen = -1;
+static int hf_pcp_pmns_name = -1;
+static int hf_pcp_pmns_names = -1;
+static int hf_pcp_pmns_names_nstrbytes = -1;
+static int hf_pcp_pmns_names_numstatus = -1;
+static int hf_pcp_pmns_names_numnames = -1;
+static int hf_pcp_pmns_names_nametree = -1;
+static int hf_pcp_pmns_names_nametree_status = -1;
+static int hf_pcp_pmns_names_nametree_namelen = -1;
+static int hf_pcp_pmns_names_nametree_name = -1;
+static int hf_pcp_pmns_ids = -1;
+static int hf_pcp_pmns_ids_status = -1;
+static int hf_pcp_pmns_ids_numids = -1;
+static int hf_pcp_pmns_child = -1;
+static int hf_pcp_pmid = -1;
+static int hf_pcp_pmid_flag = -1;
+static int hf_pcp_pmid_domain = -1;
+static int hf_pcp_pmid_cluster = -1;
+static int hf_pcp_pmid_item = -1;
+static int hf_pcp_pmid_type = -1;
+static int hf_pcp_pmid_sem = -1;
+static int hf_pcp_pmid_inst = -1;
+static int hf_pcp_profile = -1;
+static int hf_pcp_ctxnum = -1;
+static int hf_pcp_profile_g_state = -1;
+static int hf_pcp_profile_numprof = -1;
+static int hf_pcp_profile_profile = -1;
+static int hf_pcp_profile_profile_state = -1;
+static int hf_pcp_profile_profile_numinst = -1;
+static int hf_pcp_fetch = -1;
+static int hf_pcp_fetch_numpmid = -1;
+static int hf_pcp_when = -1;
+static int hf_pcp_when_sec = -1;
+static int hf_pcp_when_usec = -1;
+static int hf_pcp_desc = -1;
+static int hf_pcp_desc_req = -1;
+static int hf_pcp_units = -1;
+static int hf_pcp_units_dimspace = -1;
+static int hf_pcp_units_dimtime = -1;
+static int hf_pcp_units_dimcount = -1;
+static int hf_pcp_units_scalespace = -1;
+static int hf_pcp_units_scaletime = -1;
+static int hf_pcp_units_scalecount = -1;
+static int hf_pcp_instance = -1;
+static int hf_pcp_instance_req = -1;
+static int hf_pcp_instance_namelen = -1;
+static int hf_pcp_instance_name = -1;
+static int hf_pcp_instance_indom = -1;
+static int hf_pcp_instance_valoffset = -1;
+static int hf_pcp_instance_vallength = -1;
+static int hf_pcp_instance_value_insitu = -1;
+static int hf_pcp_instance_value_ptr = -1;
+static int hf_pcp_instance_value_int = -1;
+static int hf_pcp_instance_value_uint = -1;
+static int hf_pcp_instance_value_int64 = -1;
+static int hf_pcp_instance_value_uint64 = -1;
+static int hf_pcp_instance_value_float = -1;
+static int hf_pcp_instance_value_double = -1;
+static int hf_pcp_instance_value_aggr = -1;
+static int hf_pcp_instances = -1;
+static int hf_pcp_instances_numinst = -1;
+static int hf_pcp_results = -1;
+static int hf_pcp_results_numpmid = -1;
+static int hf_pcp_result = -1;
+static int hf_pcp_result_numval = -1;
+static int hf_pcp_result_valfmt = -1;
+static int hf_pcp_text_req = -1;
+static int hf_pcp_text_type = -1;
+static int hf_pcp_text_type_format = -1;
+static int hf_pcp_text_type_ident = -1;
+static int hf_pcp_text = -1;
+static int hf_pcp_text_ident = -1;
+static int hf_pcp_text_buflen = -1;
+static int hf_pcp_text_buffer = -1;
+static int hf_pcp_user_auth_payload = -1;
+static int hf_pcp_label_req = -1;
+static int hf_pcp_label = -1;
+static int hf_pcp_label_ident = -1;
+static int hf_pcp_label_type = -1;
+static int hf_pcp_label_padding = -1;
+static int hf_pcp_label_nsets = -1;
+static int hf_pcp_label_sets = -1;
+static int hf_pcp_label_sets_inst = -1;
+static int hf_pcp_label_sets_nlabels = -1;
+static int hf_pcp_label_sets_json = -1;
+static int hf_pcp_label_sets_jsonlen = -1;
+static int hf_pcp_label_sets_labels = -1;
+static int hf_pcp_label_sets_labels_nameoffset = -1;
+static int hf_pcp_label_sets_labels_namelen = -1;
+static int hf_pcp_label_sets_labels_flags = -1;
+static int hf_pcp_label_sets_labels_valueoffset = -1;
+static int hf_pcp_label_sets_labels_valuelen = -1;
+static int hf_pcp_label_sets_labels_name = -1;
+static int hf_pcp_label_sets_labels_value = -1;
+
+static gint ett_pcp = -1;
+static gint ett_pcp_pdu_length = -1;
+static gint ett_pcp_pdu_type = -1;
+static gint ett_pcp_pdu_pid = -1;
+static gint ett_pcp_pdu_error = -1;
+static gint ett_pcp_pdu_padding = -1;
+static gint ett_pcp_creds_number_of = -1;
+static gint ett_pcp_creds_type = -1;
+static gint ett_pcp_creds_vala = -1;
+static gint ett_pcp_creds_valb = -1;
+static gint ett_pcp_creds_valc = -1;
+static gint ett_pcp_start = -1;
+static gint ett_pcp_start_status = -1;
+static gint ett_pcp_start_zero = -1;
+static gint ett_pcp_start_version = -1;
+static gint ett_pcp_start_licensed = -1;
+static gint ett_pcp_start_features = -1;
+static gint ett_pcp_pmns_traverse = -1;
+static gint ett_pcp_pmns_subtype = -1;
+static gint ett_pcp_pmns_namelen = -1;
+static gint ett_pcp_pmns_name = -1;
+static gint ett_pcp_pmns_names = -1;
+static gint ett_pcp_pmns_names_nstrbytes = -1;
+static gint ett_pcp_pmns_names_numstatus = -1;
+static gint ett_pcp_pmns_names_numnames = -1;
+static gint ett_pcp_pmns_names_nametree = -1;
+static gint ett_pcp_pmns_names_nametree_status = -1;
+static gint ett_pcp_pmns_names_nametree_namelen = -1;
+static gint ett_pcp_pmns_names_nametree_name = -1;
+static gint ett_pcp_pmns_ids = -1;
+static gint ett_pcp_pmns_ids_status = -1;
+static gint ett_pcp_pmns_ids_numids = -1;
+static gint ett_pcp_pmns_child = -1;
+static gint ett_pcp_pmid = -1;
+static gint ett_pcp_pmid_flag = -1;
+static gint ett_pcp_pmid_domain = -1;
+static gint ett_pcp_pmid_cluster = -1;
+static gint ett_pcp_pmid_item = -1;
+static gint ett_pcp_pmid_type = -1;
+static gint ett_pcp_pmid_sem = -1;
+static gint ett_pcp_profile = -1;
+static gint ett_pcp_ctxnum = -1;
+static gint ett_pcp_profile_g_state = -1;
+static gint ett_pcp_profile_numprof = -1;
+static gint ett_pcp_profile_profile = -1;
+static gint ett_pcp_profile_profile_state = -1;
+static gint ett_pcp_profile_profile_numinst = -1;
+static gint ett_pcp_fetch = -1;
+static gint ett_pcp_fetch_numpmid = -1;
+static gint ett_pcp_when = -1;
+static gint ett_pcp_when_sec = -1;
+static gint ett_pcp_when_usec = -1;
+static gint ett_pcp_desc_req = -1;
+static gint ett_pcp_units = -1;
+static gint ett_pcp_units_dimspace = -1;
+static gint ett_pcp_units_dimtime = -1;
+static gint ett_pcp_units_dimcount = -1;
+static gint ett_pcp_units_scalespace = -1;
+static gint ett_pcp_units_scaletime = -1;
+static gint ett_pcp_units_scalecount = -1;
+static gint ett_pcp_instance = -1;
+static gint ett_pcp_instance_req = -1;
+static gint ett_pcp_instance_namelen = -1;
+static gint ett_pcp_instance_name = -1;
+static gint ett_pcp_instance_inst = -1;
+static gint ett_pcp_instance_indom = -1;
+static gint ett_pcp_instance_valoffset = -1;
+static gint ett_pcp_instance_vallength = -1;
+static gint ett_pcp_instance_value_insitu = -1;
+static gint ett_pcp_instance_value_ptr = -1;
+static gint ett_pcp_instance_value_int = -1;
+static gint ett_pcp_instance_value_uint = -1;
+static gint ett_pcp_instance_value_int64 = -1;
+static gint ett_pcp_instance_value_uint64 = -1;
+static gint ett_pcp_instance_value_float = -1;
+static gint ett_pcp_instance_value_double = -1;
+static gint ett_pcp_instance_value_aggr = -1;
+static gint ett_pcp_instances = -1;
+static gint ett_pcp_instances_numinst = -1;
+static gint ett_pcp_results = -1;
+static gint ett_pcp_results_numpmid = -1;
+static gint ett_pcp_result = -1;
+static gint ett_pcp_result_numval = -1;
+static gint ett_pcp_result_valfmt = -1;
+static gint ett_pcp_text_req = -1;
+static gint ett_pcp_text_type = -1;
+static gint ett_pcp_text_type_format = -1;
+static gint ett_pcp_text_type_ident = -1;
+static gint ett_pcp_text = -1;
+static gint ett_pcp_text_ident = -1;
+static gint ett_pcp_text_buflen = -1;
+static gint ett_pcp_text_buffer = -1;
+
+static expert_field ei_pcp_type_event_unimplemented = EI_INIT;
+static expert_field ei_pcp_type_nosupport_unsupported = EI_INIT;
+static expert_field ei_pcp_type_unknown_unknown_value = EI_INIT;
+static expert_field ei_pcp_unimplemented_value = EI_INIT;
+static expert_field ei_pcp_unimplemented_packet_type = EI_INIT;
+static expert_field ei_pcp_ssl_upgrade = EI_INIT;
+static expert_field ei_pcp_ssl_upgrade_failed = EI_INIT;
+static expert_field ei_pcp_label_error = EI_INIT;
+static expert_field ei_pcp_label_error_endianness = EI_INIT;
+
+/* Magic numbers */
+#define PCP_SECURE_ACK_SUCCESSFUL 0
+
+static const value_string pcp_feature_flags[] = {
+#define PCP_PDU_FLAG_SECURE 0x0001
+ { PCP_PDU_FLAG_SECURE, "SECURE" },
+#define PCP_PDU_FLAG_COMPRESS 0x0002
+ { PCP_PDU_FLAG_COMPRESS, "COMPRESS" },
+#define PCP_PDU_FLAG_AUTH 0x0004
+ { PCP_PDU_FLAG_AUTH, "AUTH"},
+#define PCP_PDU_FLAG_CREDS_REQD 0x0008
+ { PCP_PDU_FLAG_CREDS_REQD, "CREDS_REQD" },
+#define PCP_PDU_FLAG_SECURE_ACK 0x0010
+ { PCP_PDU_FLAG_SECURE_ACK, "SECURE_ACK" },
+#define PCP_PDU_FLAG_NO_NSS_INIT 0x0020
+ { PCP_PDU_FLAG_NO_NSS_INIT, "NO_NSS_INIT" },
+#define PCP_PDU_FLAG_CONTAINER 0x0040
+ { PCP_PDU_FLAG_CONTAINER, "CONTAINER" },
+#define PCP_PDU_FLAG_CERT_REQD 0x0080
+ { PCP_PDU_FLAG_CERT_REQD, "CERT_REQD" },
+#define PCP_PDU_FLAG_BAD_LABEL 0x0100
+ { PCP_PDU_FLAG_BAD_LABEL, "BAD_LABEL" },
+#define PCP_PDU_FLAG_LABELS 0x0200
+ { PCP_PDU_FLAG_LABELS, "LABELS" },
+ { 0, NULL }
+};
+
+/* packet types */
+static const value_string packettypenames[] = {
+#define PCP_PDU_START_OR_ERROR 0x7000
+ {PCP_PDU_START_OR_ERROR, "START/ERROR" },
+#define PCP_PDU_RESULT 0x7001
+ {PCP_PDU_RESULT, "RESULT" },
+#define PCP_PDU_PROFILE 0x7002
+ {PCP_PDU_PROFILE, "PROFILE"},
+#define PCP_PDU_FETCH 0x7003
+ {PCP_PDU_FETCH, "FETCH"},
+#define PCP_PDU_DESC_REQ 0x7004
+ {PCP_PDU_DESC_REQ, "DESC_REQ"},
+#define PCP_PDU_DESC 0x7005
+ {PCP_PDU_DESC, "DESC"},
+#define PCP_PDU_INSTANCE_REQ 0x7006
+ {PCP_PDU_INSTANCE_REQ, "INSTANCE_REQ" },
+#define PCP_PDU_INSTANCE 0x7007
+ {PCP_PDU_INSTANCE, "INSTANCE" },
+#define PCP_PDU_TEXT_REQ 0x7008
+ {PCP_PDU_TEXT_REQ, "TEXT_REQ" },
+#define PCP_PDU_TEXT 0x7009
+ {PCP_PDU_TEXT, "TEXT" },
+#define PCP_PDU_CONTROL_REQ 0x700a
+ {PCP_PDU_CONTROL_REQ, "CONTROL_REQ" }, /* unimplemented (pmlc/pmlogger only) */
+#define PCP_PDU_DATA_X 0x700b
+ {PCP_PDU_DATA_X, "DATA_X" }, /* unimplemented (pmlc/pmlogger only) */
+#define PCP_PDU_CREDS 0x700c
+ {PCP_PDU_CREDS, "CREDS" },
+#define PCP_PDU_PMNS_IDS 0x700d
+ {PCP_PDU_PMNS_IDS, "PMNS_IDS" },
+#define PCP_PDU_PMNS_NAMES 0x700e
+ {PCP_PDU_PMNS_NAMES, "PMNS_NAMES" },
+#define PCP_PDU_PMNS_CHILD 0x700f
+ {PCP_PDU_PMNS_CHILD, "PMNS_CHILD" },
+#define PCP_PDU_PMNS_TRAVERSE 0x7010 /*also type FINISH as per pcp headers, but I can not see it used */
+ {PCP_PDU_PMNS_TRAVERSE, "PMNS_TRAVERSE" },
+#define PCP_PDU_USER_AUTH 0x7011
+ {PCP_PDU_USER_AUTH, "USER_AUTH" },
+#define PCP_PDU_LABEL_REQ 0x7012
+ {PCP_PDU_LABEL_REQ, "LABEL_REQ" },
+#define PCP_PDU_LABEL 0x7013
+ {PCP_PDU_LABEL, "LABEL" },
+ { 0, NULL }
+};
+
+static const value_string packettypenames_pm_units_space[] = {
+ { 0, "PM_SPACE_BYTE" },
+ { 1, "PM_SPACE_KBYTE" },
+ { 2, "PM_SPACE_MBYTE" },
+ { 3, "PM_SPACE_GBYTE" },
+ { 4, "PM_SPACE_TBYTE" },
+ { 5, "PM_SPACE_PBYTE" },
+ { 6, "PM_SPACE_EBYTE" },
+ { 0, NULL }
+};
+
+static const value_string packettypenames_pm_units_time[] = {
+ { 0, "PM_TIME_NSEC" },
+ { 1, "PM_TIME_USEC" },
+ { 2, "PM_TIME_MSEC" },
+ { 3, "PM_TIME_SEC" },
+ { 4, "PM_TIME_MIN" },
+ { 5, "PM_TIME_HOUR" },
+ { 0, NULL }
+};
+
+static const value_string packettypenames_pm_types[] = {
+ #define PM_TYPE_NOSUPPORT -1
+ { -1, "PM_TYPE_NOSUPPORT" },
+ #define PM_TYPE_32 0
+ { 0, "PM_TYPE_32" },
+ #define PM_TYPE_U32 1
+ { 1, "PM_TYPE_U32" },
+ #define PM_TYPE_64 2
+ { 2, "PM_TYPE_64" },
+ #define PM_TYPE_U64 3
+ { 3, "PM_TYPE_U64" },
+ #define PM_TYPE_FLOAT 4
+ { 4, "PM_TYPE_FLOAT" },
+ #define PM_TYPE_DOUBLE 5
+ { 5, "PM_TYPE_DOUBLE" },
+ #define PM_TYPE_STRING 6
+ { 6, "PM_TYPE_STRING" },
+ #define PM_TYPE_AGGREGATE 7
+ { 7, "PM_TYPE_AGGREGATE" },
+ #define PM_TYPE_AGGREGATE_STATIC 8
+ { 8, "PM_TYPE_AGGREGATE_STATIC" },
+ #define PM_TYPE_EVENT 9
+ { 9, "PM_TYPE_EVENT" },
+ #define PM_TYPE_UNKNOWN 255
+ { 255, "PM_TYPE_UNKNOWN" },
+ { 0, NULL }
+};
+
+static const value_string packettypenames_pm_types_sem[] = {
+ { 1, "PM_SEM_COUNTER" },
+ { 3, "PM_SEM_INSTANT" },
+ { 4, "PM_SEM_DISCRETE" },
+ { 0, NULL }
+};
+
+static const value_string packettypenames_text_type_format[] = {
+ #define PM_TEXT_ONELINE 1
+ { 1, "PM_TEXT_ONELINE" },
+ #define PM_TEXT_HELP 2
+ { 2, "PM_TEXT_HELP" },
+ { 0, NULL }
+};
+
+static const value_string packettypenames_text_type_ident[] = {
+ #define PM_TEXT_PMID 4
+ { 1, "PM_TEXT_PMID" },
+ #define PM_TEXT_INDOM 8
+ { 2, "PM_TEXT_INDOM" },
+ { 0, NULL }
+};
+
+static const value_string packettypenames_valfmt[] = {
+ #define PM_VAL_INSITU 0
+ { 0, "PM_VAL_INSITU" },
+ #define PM_VAL_DPTR 1
+ { 1, "PM_VAL_DPTR" },
+ #define PM_VAL_SPTR 2
+ { 2, "PM_VAL_SPTR" },
+ { 0, NULL }
+};
+
+static const value_string packettypenames_errors[] = {
+ { -12345, "PM_ERR_GENERIC" },
+ { -12346, "PM_ERR_PMNS" },
+ { -12347, "PM_ERR_NOPMNS" },
+ { -12348, "PM_ERR_DUPPMNS" },
+ { -12349, "PM_ERR_TEXT" },
+ { -12350, "PM_ERR_APPVERSION" },
+ { -12351, "PM_ERR_VALUE" },
+ { -12352, "PM_ERR_LICENSE" },
+ { -12353, "PM_ERR_TIMEOUT" },
+ { -12354, "PM_ERR_NODATA" },
+ { -12355, "PM_ERR_RESET" },
+ { -12356, "PM_ERR_FILE" },
+ { PM_ERR_NAME, "PM_ERR_NAME" },
+ { -12358, "PM_ERR_PMID" },
+ { -12359, "PM_ERR_INDOM" },
+ { -12360, "PM_ERR_INST" },
+ { -12361, "PM_ERR_UNIT" },
+ { -12362, "PM_ERR_CONV" },
+ { -12363, "PM_ERR_TRUNC" },
+ { -12364, "PM_ERR_SIGN" },
+ { -12365, "PM_ERR_PROFILE" },
+ { -12366, "PM_ERR_IPC" },
+ { -12367, "PM_ERR_NOASCII" },
+ { -12368, "PM_ERR_EOF" },
+ { -12369, "PM_ERR_NOTHOST" },
+ { -12370, "PM_ERR_EOL" },
+ { -12371, "PM_ERR_MODE" },
+ { -12372, "PM_ERR_LABEL" },
+ { -12373, "PM_ERR_LOGREC" },
+ { -12374, "PM_ERR_NOTARCHIVE" },
+ { -12375, "PM_ERR_LOGFILE" },
+ { -12376, "PM_ERR_NOCONTEXT" },
+ { -12377, "PM_ERR_PROFILESPEC" },
+ { -12378, "PM_ERR_PMID_LOG" },
+ { -12379, "PM_ERR_INDOM_LOG" },
+ { -12380, "PM_ERR_INST_LOG" },
+ { -12381, "PM_ERR_NOPROFILE" },
+ { -12386, "PM_ERR_NOAGENT" },
+ { -12387, "PM_ERR_PERMISSION" },
+ { -12388, "PM_ERR_CONNLIMIT" },
+ { -12389, "PM_ERR_AGAIN" },
+ { -12390, "PM_ERR_ISCONN" },
+ { -12391, "PM_ERR_NOTCONN" },
+ { -12392, "PM_ERR_NEEDPORT" },
+ { -12393, "PM_ERR_WANTACK" },
+ { -12394, "PM_ERR_NONLEAF" },
+ { -12395, "PM_ERR_OBJSTYLE" },
+ { -12396, "PM_ERR_PMCDLICENSE" },
+ { -12397, "PM_ERR_TYPE" },
+ { -12442, "PM_ERR_CTXBUSY" },
+ { -12443, "PM_ERR_TOOSMALL" },
+ { -12444, "PM_ERR_TOOBIG" },
+ { -13393, "PM_ERR_PMDAREADY" },
+ { -13394, "PM_ERR_PMDANOTREADY" },
+ { -21344, "PM_ERR_NYI" },
+ { 0, NULL }
+};
+
+static const value_string packettypenames_creds[]= {
+ { 1, "CVERSION" },
+ { 2, "CAUTH" },
+ { 0, NULL }
+};
+
+static const value_string packettypenames_label_req_type[]= {
+ { 1, "PM_LABEL_CONTEXT" },
+ { 2, "PM_LABEL_DOMAIN" },
+ { 4, "PM_LABEL_INDOM" },
+ { 8, "PM_LABEL_CLUSTER" },
+ { 16, "PM_LABEL_ITEM" },
+ { 32, "PM_LABEL_INSTANCES" },
+ { 0, NULL }
+};
+
+typedef struct pcp_conv_info_t {
+ wmem_array_t *pmid_name_candidates;
+ wmem_map_t *pmid_to_name;
+ guint32 last_pmns_names_frame;
+ guint32 last_processed_pmns_names_frame;
+ gboolean using_good_labels;
+} pcp_conv_info_t;
+
+/* function prototypes */
+static pcp_conv_info_t* get_pcp_conversation_info(packet_info *pinfo);
+static int is_unvisited_pmns_names_frame(packet_info *pinfo);
+static gboolean is_using_good_labels(packet_info *pinfo);
+static gboolean label_value_length_looks_like_wrong_endianness(tvbuff_t *tvb, guint16 value_offset, guint16 value_length);
+static void add_candidate_name_for_pmid_resolution(packet_info *pinfo, tvbuff_t *tvb, int offset, int name_len);
+static void mark_this_frame_as_last_pmns_names_frame(packet_info *pinfo);
+static inline int has_unprocessed_pmns_names_frame(pcp_conv_info_t *pcp_conv_info);
+static void create_pmid_to_name_map_from_candidates(pcp_conv_info_t *pcp_conv_info, tvbuff_t *tvb, int offset, guint32 num_ids);
+static void populate_pmids_to_names(packet_info *pinfo, tvbuff_t *tvb, int offset, guint32 num_ids);
+static inline int client_to_server(packet_info *pinfo);
+static inline int server_to_client(packet_info *pinfo);
+static guint8* get_name_from_pmid(guint32 pmid, packet_info *pinfo);
+static guint get_pcp_message_len(packet_info *pinfo, tvbuff_t *tvb, int offset, void *data);
+static const gchar *get_pcp_features_to_string(wmem_allocator_t *pool, guint16 feature_flags);
+static int dissect_pcp_message_creds(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+static int dissect_pcp_message_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+static int dissect_pcp_message_start(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+static int dissect_pcp_message_pmns_traverse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+static int dissect_pcp_message_pmns_names(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+static int dissect_pcp_message_pmns_child(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+static int dissect_pcp_message_pmns_ids(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+static int dissect_pcp_message_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+static int dissect_pcp_message_fetch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+static int dissect_pcp_message_result(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+static int dissect_pcp_message_desc_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+static int dissect_pcp_message_desc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+static int dissect_pcp_message_instance_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+static int dissect_pcp_message_instance(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+static int dissect_pcp_message_text_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+static int dissect_pcp_message_text(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+static int dissect_pcp_message_user_auth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+static int dissect_pcp_partial_pmid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+static int dissect_pcp_partial_when(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+static int dissect_pcp_partial_features(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+static int dissect_pcp_partial_label(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint32 json_start_offset);
+static int dissect_pcp_partial_labelset(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, int offset);
+
+/* message length for dissect_tcp */
+static guint get_pcp_message_len(packet_info *pinfo _U_, tvbuff_t *tvb,
+ int offset, void *data _U_)
+{
+ /* length is at the very start of the packet, after tcp header */
+ return (guint)tvb_get_ntohl(tvb, offset);
+}
+
+static void mark_this_frame_as_last_pmns_names_frame(packet_info *pinfo) {
+ pcp_conv_info_t *pcp_conv_info;
+ pcp_conv_info = get_pcp_conversation_info(pinfo);
+
+ if(pinfo->num > pcp_conv_info->last_pmns_names_frame) {
+ pcp_conv_info->last_pmns_names_frame = pinfo->num;
+ }
+}
+
+static inline int has_unprocessed_pmns_names_frame(pcp_conv_info_t *pcp_conv_info) {
+ return pcp_conv_info->last_pmns_names_frame > pcp_conv_info->last_processed_pmns_names_frame;
+}
+
+static inline int client_to_server(packet_info *pinfo) {
+ return pinfo->destport == PCP_PORT || pinfo->destport == PMPROXY_PORT;
+}
+
+static inline int server_to_client(packet_info *pinfo) {
+ return !client_to_server(pinfo);
+}
+
+static guint8* get_name_from_pmid(guint32 pmid, packet_info *pinfo) {
+ guint8 *name;
+ wmem_map_t *pmid_to_name;
+
+ pmid_to_name = get_pcp_conversation_info(pinfo)->pmid_to_name;
+
+ name = (guint8*)wmem_map_lookup(pmid_to_name, GINT_TO_POINTER(pmid));
+ if(!name) {
+ name = (guint8*)wmem_strdup(pinfo->pool, "Metric name unknown");
+ }
+
+ return name;
+}
+
+static const gchar *get_pcp_features_to_string(wmem_allocator_t *pool, guint16 feature_flags)
+{
+ const value_string *flag_under_test;
+ wmem_strbuf_t *string_buffer;
+ gsize string_length;
+
+ string_buffer = wmem_strbuf_new(pool, "");
+
+ /* Build the comma-separated list of feature flags as a string. EG 'SECURE, COMPRESS, AUTH, ' */
+ flag_under_test = &pcp_feature_flags[0];
+ while (flag_under_test->value) {
+ if (feature_flags & flag_under_test->value) {
+ wmem_strbuf_append_printf(string_buffer, "%s, ", flag_under_test->strptr);
+ }
+ flag_under_test++;
+ }
+
+ /* Cleanup the last remaining ', ' from the string */
+ string_length = wmem_strbuf_get_len(string_buffer);
+ if (string_length > 2) {
+ wmem_strbuf_truncate(string_buffer, string_length - 2);
+ }
+
+ return wmem_strbuf_get_str(string_buffer);
+}
+
+static pcp_conv_info_t* get_pcp_conversation_info(packet_info *pinfo) {
+ conversation_t *conversation;
+ pcp_conv_info_t *pcp_conv_info;
+
+ conversation = find_conversation_pinfo(pinfo, 0);
+
+ /* Conversation setup is done in the main dissecting routine so it should never be null */
+ DISSECTOR_ASSERT(conversation);
+
+ pcp_conv_info = (pcp_conv_info_t *)conversation_get_proto_data(conversation, proto_pcp);
+
+ /* Conversation data is initialized when creating the conversation so should never be null */
+ DISSECTOR_ASSERT(pcp_conv_info);
+
+ return pcp_conv_info;
+}
+
+static void add_candidate_name_for_pmid_resolution(packet_info *pinfo, tvbuff_t *tvb, int offset, int name_len) {
+ pcp_conv_info_t *pcp_conv_info;
+ guint8 *name;
+
+ pcp_conv_info = get_pcp_conversation_info(pinfo);
+
+ if(is_unvisited_pmns_names_frame(pinfo)) {
+ name = tvb_get_string_enc(wmem_file_scope(), tvb, offset, name_len, ENC_ASCII);
+ wmem_array_append_one(pcp_conv_info->pmid_name_candidates, name);
+ }
+}
+
+static int is_unvisited_pmns_names_frame(packet_info *pinfo) {
+ pcp_conv_info_t *pcp_conv_info;
+
+ pcp_conv_info = get_pcp_conversation_info(pinfo);
+
+ return pinfo->num > pcp_conv_info->last_processed_pmns_names_frame && pinfo->num > pcp_conv_info->last_pmns_names_frame;
+}
+
+static void populate_pmids_to_names(packet_info *pinfo, tvbuff_t *tvb, int offset, guint32 num_ids) {
+ pcp_conv_info_t *pcp_conv_info;
+ guint number_of_name_candidates;
+
+ pcp_conv_info = get_pcp_conversation_info(pinfo);
+ number_of_name_candidates = wmem_array_get_count(pcp_conv_info->pmid_name_candidates);
+
+ if(number_of_name_candidates == num_ids && has_unprocessed_pmns_names_frame(pcp_conv_info)) {
+ create_pmid_to_name_map_from_candidates(pcp_conv_info, tvb, offset, num_ids);
+ /* Set this frame to the one that we processed */
+ pcp_conv_info->last_processed_pmns_names_frame = pcp_conv_info->last_pmns_names_frame;
+ }
+
+ pcp_conv_info->pmid_name_candidates = wmem_array_new(wmem_file_scope(), sizeof(guint8 *));
+}
+
+static void create_pmid_to_name_map_from_candidates(pcp_conv_info_t *pcp_conv_info, tvbuff_t *tvb, int offset, guint32 num_ids) {
+ guint32 i;
+
+ for(i=0; i<num_ids; i++) {
+ guint32 pmid;
+ guint8 *pmid_name;
+
+ pmid = tvb_get_ntohl(tvb, offset);
+ pmid_name = *(guint8 **)wmem_array_index(pcp_conv_info->pmid_name_candidates, i);
+
+ if(wmem_map_lookup(pcp_conv_info->pmid_to_name, GINT_TO_POINTER(pmid)) == NULL) {
+ wmem_map_insert(pcp_conv_info->pmid_to_name, GINT_TO_POINTER(pmid), pmid_name);
+ }
+ offset += 4;
+ }
+}
+
+static int dissect_pcp_message_creds(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
+{
+ guint32 creds_length;
+ guint32 i;
+
+ /* append the type of packet */
+ col_append_fstr(pinfo->cinfo, COL_INFO, "[%s]",
+ val_to_str(PCP_PDU_CREDS, packettypenames, "Unknown Type:0x%02x"));
+
+ /* first is the number of creds */
+ proto_tree_add_item(tree, hf_pcp_creds_number_of, tvb, offset, 4, ENC_BIG_ENDIAN);
+ /* store the number of creds so we know how long to interate for */
+ creds_length = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+ /* go through each __pmVersionCred struct */
+ for (i = 0; i < creds_length; i++) {
+ /* __pmVersionCred.c_type */
+ proto_tree_add_item(tree, hf_pcp_creds_type, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ /* __pmVersionCred.c_version */
+ proto_tree_add_item(tree, hf_pcp_creds_version, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ /* __pmVersionCred.c_flags */
+ offset = dissect_pcp_partial_features(tvb, pinfo, tree, offset);
+ }
+ return offset;
+}
+
+/* ERROR packet format:
+ signed int error
+ */
+static int dissect_pcp_message_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
+{
+ gint32 error_num;
+ pcp_conv_info_t *pcp_conv_info;
+
+ /* append the type of packet, we can't look this up as it clashes with START */
+ col_append_str(pinfo->cinfo, COL_INFO, "[ERROR] ");
+
+ /* add the error item to the tree and column */
+ proto_tree_add_item(tree, hf_pcp_pdu_error, tvb, offset, 4, ENC_BIG_ENDIAN);
+ error_num = tvb_get_ntohl(tvb, offset);
+ col_append_fstr(pinfo->cinfo, COL_INFO, "error=%s ",
+ val_to_str(error_num, packettypenames_errors, "Unknown Error:%i"));
+ offset += 4;
+
+ /* Clean out candidate names if we got an error from a PMNS_NAMES lookup. This will allow subsequent PMNS_NAMES
+ lookups to work in the same conversation
+ */
+ if(error_num == PM_ERR_NAME) {
+ pcp_conv_info = get_pcp_conversation_info(pinfo);
+ pcp_conv_info->pmid_name_candidates = wmem_array_new(wmem_file_scope(), sizeof(guint8 *));
+ }
+
+ return offset;
+}
+
+/* START packet format:
+ unsigned int sts,
+ struct __pmPDUInfo
+ |
+ |> unsigned int zero : 1 bit
+ unsigned int version : 7 bits
+ unsigned int licensed : 8 bits
+ unsigned int features : 16 bits
+*/
+static int dissect_pcp_message_start(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
+{
+ /* create a start tree to hold the information*/
+ proto_item *pcp_start_item;
+ proto_tree *pcp_start_tree;
+ guint32 status;
+
+ pcp_start_item = proto_tree_add_item(tree, hf_pcp_start, tvb, 0, -1, ENC_NA);
+ pcp_start_tree = proto_item_add_subtree(pcp_start_item, ett_pcp);
+
+ /* append the type of packet, we can't look this up as it clashes with ERROR */
+ col_append_str(pinfo->cinfo, COL_INFO, "[START]");
+
+ /* status */
+ status = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_item(pcp_start_tree, hf_pcp_start_status, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ if(tvb_reported_length_remaining(tvb, offset) == 0){
+ /* Most likely we're in a SSL upgrade if this is the end of the start packet */
+ if(status == PCP_SECURE_ACK_SUCCESSFUL) {
+ expert_add_info(pinfo, tree, &ei_pcp_ssl_upgrade);
+ ssl_starttls_ack(find_dissector("tls"), pinfo, pcp_handle);
+ }
+ else {
+ expert_add_info(pinfo, tree, &ei_pcp_ssl_upgrade_failed);
+ }
+ }
+ else {
+ /* zero bit and version bits */
+ proto_tree_add_item(pcp_start_tree, hf_pcp_start_zero, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(pcp_start_tree, hf_pcp_start_version, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ /* licensed */
+ proto_tree_add_item(pcp_start_tree, hf_pcp_start_licensed, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ /* features */
+ offset = dissect_pcp_partial_features(tvb, pinfo, pcp_start_tree, offset);
+ }
+ return offset;
+}
+
+/* PMNS_TRAVERSE packet format:
+ guint32 subtype
+ guint32 namelen
+ char name[sizeof(namelen)] + padding
+*/
+static int dissect_pcp_message_pmns_traverse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
+{
+ proto_item *pcp_pmns_traverse_item;
+ proto_tree *pcp_pmns_traverse_tree;
+ guint32 name_len;
+ guint32 padding;
+
+ /* append the type of packet */
+ col_append_fstr(pinfo->cinfo, COL_INFO, "[%s]",
+ val_to_str(PCP_PDU_PMNS_TRAVERSE, packettypenames, "Unknown Type:0x%02x"));
+
+ pcp_pmns_traverse_item = proto_tree_add_item(tree, hf_pcp_pmns_traverse, tvb, offset, -1, ENC_NA);
+ pcp_pmns_traverse_tree = proto_item_add_subtree(pcp_pmns_traverse_item, ett_pcp);
+
+ /* subtype */
+ proto_tree_add_item(pcp_pmns_traverse_tree, hf_pcp_pmns_subtype, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ /* namelen */
+ proto_tree_add_item(pcp_pmns_traverse_tree, hf_pcp_pmns_namelen, tvb, offset, 4, ENC_BIG_ENDIAN);
+ name_len = tvb_get_ntohl(tvb, offset); /* get the actual length out so we can use it in the next item */
+ offset += 4;
+ /* name */
+ proto_tree_add_item(pcp_pmns_traverse_tree, hf_pcp_pmns_name, tvb, offset, name_len, ENC_ASCII);
+ offset += name_len; /* increment by whatever the length of the name string was */
+
+ /* "padding" (not really padding, just what is left over in the old buffer) */
+ padding = name_len % 4; /* names are padded to the nearest 4 byte boundary */
+ if (padding != 0) { /* if there is padding, keep going till the remainder of mod 4 */
+ padding = 4 - padding; /* we want the inverse of the remainder */
+
+ proto_tree_add_item(pcp_pmns_traverse_tree, hf_pcp_pdu_padding, tvb, offset, padding, ENC_NA);
+ offset += padding;
+ }
+ return offset;
+}
+
+/* PMNS_NAMES packet format:
+ guint32 nstrbytes (number of str bytes)
+ guint32 numstatus (0 if no status. Also, if 0, use name_t, otherwise use name_status_t )
+ guint32 numnames
+ __pmPDU names (if numstatus = 0, filled with name_t, otherwise name_status_t)
+ | |
+ | |> -- name_t --
+ | int namelen
+ | char name[sizeof(namelen)]
+ |
+ |> -- name_status_t --
+ int status
+ int namelen
+ char name[sizeof(namelen)]
+*/
+static int dissect_pcp_message_pmns_names(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
+{
+ proto_item *pcp_pmns_names_item;
+ proto_tree *pcp_pmns_names_tree;
+ proto_item *pcp_pmns_names_name_item;
+ proto_tree *pcp_pmns_names_name_tree;
+ guint32 is_pmns_names_status;
+ guint32 num_names;
+ guint32 name_len;
+ guint32 full_name_len;
+ guint32 padding;
+ guint32 i;
+
+ /* append the type of packet */
+ col_append_fstr(pinfo->cinfo, COL_INFO, "[%s]", val_to_str(PCP_PDU_PMNS_NAMES, packettypenames, "Unknown Type:0x%02x"));
+
+ pcp_pmns_names_item = proto_tree_add_item(tree, hf_pcp_pmns_names, tvb, offset, -1, ENC_NA);
+ pcp_pmns_names_tree = proto_item_add_subtree(pcp_pmns_names_item, ett_pcp);
+
+ /* nstrbytes */
+ proto_tree_add_item(pcp_pmns_names_tree, hf_pcp_pmns_names_nstrbytes, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* numstatus */
+ proto_tree_add_item(pcp_pmns_names_tree, hf_pcp_pmns_names_numstatus, tvb, offset, 4, ENC_BIG_ENDIAN);
+ is_pmns_names_status = tvb_get_ntohl(tvb, offset); /* is the status also present in this PDU? */
+ offset += 4;
+
+ /* numnames */
+ proto_tree_add_item(pcp_pmns_names_tree, hf_pcp_pmns_names_numnames, tvb, offset, 4, ENC_BIG_ENDIAN);
+ num_names = tvb_get_ntohl(tvb, offset); /* get the number of names to iterate through */
+ offset += 4;
+
+ /* nametrees */
+ for (i=0; i < num_names; i++) {
+ /* find out the size of the name_t/name_status_t before we create the tree */
+ if (is_pmns_names_status) {
+ name_len = tvb_get_ntohl(tvb, offset+4);
+ full_name_len = name_len + 8;
+ } else {
+ name_len = tvb_get_ntohl(tvb, offset);
+ full_name_len = name_len + 4;
+ }
+ /* add a new subtree for each name */
+ pcp_pmns_names_name_item = proto_tree_add_item(pcp_pmns_names_tree, hf_pcp_pmns_names_nametree,
+ tvb, offset, full_name_len, ENC_NA);
+ pcp_pmns_names_name_tree = proto_item_add_subtree(pcp_pmns_names_name_item, ett_pcp);
+
+ if (is_pmns_names_status) {
+ /* print out the name status and increment if we're supposed to have it */
+ proto_tree_add_item(pcp_pmns_names_name_tree, hf_pcp_pmns_names_nametree_status,
+ tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ }
+ /* namelen */
+ proto_tree_add_item(pcp_pmns_names_name_tree, hf_pcp_pmns_names_nametree_namelen,
+ tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ /* name */
+ if(client_to_server(pinfo)) {
+ add_candidate_name_for_pmid_resolution(pinfo, tvb, offset, name_len);
+ }
+ proto_tree_add_item(pcp_pmns_names_name_tree, hf_pcp_pmns_names_nametree_name,
+ tvb, offset, name_len, ENC_ASCII);
+ offset += name_len;
+ /* padding */
+ padding = name_len % 4; /* names are padded to the nearest 4 byte boundary */
+ if (padding != 0) {
+ padding = 4 - padding; /* we want the inverse of the remainder */
+ /* if there is padding, keep going till the remainder of mod 8 */
+ proto_tree_add_item(pcp_pmns_names_name_tree, hf_pcp_pdu_padding, tvb, offset, padding, ENC_NA);
+ offset += padding;
+ }
+ }
+ if(client_to_server(pinfo)) {
+ mark_this_frame_as_last_pmns_names_frame(pinfo);
+ }
+ return offset;
+}
+
+/* PMNS_CHILD packet format:
+ guint32 subtype
+ guint32 namelen
+ char name[namelen]
+*/
+static int dissect_pcp_message_pmns_child(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
+{
+ proto_item *pcp_pmns_child_item;
+ proto_tree *pcp_pmns_child_tree;
+ guint32 name_len;
+
+ pcp_pmns_child_item = proto_tree_add_item(tree, hf_pcp_pmns_child, tvb, offset, -1, ENC_NA);
+ pcp_pmns_child_tree = proto_item_add_subtree(pcp_pmns_child_item, ett_pcp);
+
+ /* append the type of packet */
+ col_append_fstr(pinfo->cinfo, COL_INFO, "[%s]", val_to_str(PCP_PDU_PMNS_CHILD, packettypenames, "Unknown Type:0x%02x"));
+
+ /* subtype */
+ proto_tree_add_item(pcp_pmns_child_tree, hf_pcp_pmns_subtype, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* namelen */
+ proto_tree_add_item(pcp_pmns_child_tree, hf_pcp_pmns_namelen, tvb, offset, 4, ENC_BIG_ENDIAN);
+ name_len = tvb_get_ntohl(tvb, offset); /* length of the next value */
+ offset += 4;
+
+ /* name */
+ proto_tree_add_item(pcp_pmns_child_tree, hf_pcp_pmns_name, tvb, offset, name_len, ENC_ASCII);
+ offset += 4;
+ return offset;
+}
+
+/* PMNS_IDS packet format
+ guint32 status
+ guint32 numids
+ pmID idlist[numids] (where pmID = uint32)
+
+*/
+static int dissect_pcp_message_pmns_ids(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
+{
+ proto_item *pcp_pmns_ids_item;
+ proto_tree *pcp_pmns_ids_tree;
+ guint32 num_ids;
+ guint32 i;
+
+ /* append the type of packet */
+ col_append_fstr(pinfo->cinfo, COL_INFO, "[%s]",
+ val_to_str(PCP_PDU_PMNS_IDS, packettypenames, "Unknown Type:0x%02x"));
+
+ pcp_pmns_ids_item = proto_tree_add_item(tree, hf_pcp_pmns_ids, tvb, offset, -1, ENC_NA);
+ pcp_pmns_ids_tree = proto_item_add_subtree(pcp_pmns_ids_item, ett_pcp);
+
+ /* status */
+ proto_tree_add_item(pcp_pmns_ids_tree, hf_pcp_pmns_ids_status, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* numids */
+ proto_tree_add_item(pcp_pmns_ids_tree, hf_pcp_pmns_ids_numids, tvb, offset, 4, ENC_BIG_ENDIAN);
+ num_ids = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+
+ /* Populate the PMID to name mapping */
+ populate_pmids_to_names(pinfo, tvb, offset, num_ids);
+
+ /* pmIDs */
+ for (i=0; i<num_ids; i++) {
+ /* pmID */
+ offset = dissect_pcp_partial_pmid(tvb, pinfo, pcp_pmns_ids_tree, offset);
+ }
+ return offset;
+}
+
+/* PROFILE packet format
+ guint32 ctxnum;
+ guint32 g_state;
+ guint32 numprof;
+ guint32 pad;
+ pmProfile profiles[numprof]
+ |
+ |> pmInDom indom;
+ int state;
+ int numinst;
+ int pad;
+*/
+static int dissect_pcp_message_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
+{
+ proto_item *pcp_profile_item;
+ proto_tree *pcp_profile_tree;
+ proto_item *pcp_profile_profile_item;
+ proto_tree *pcp_profile_profile_tree;
+ guint32 num_prof;
+ guint32 i;
+
+ /* append the type of packet */
+ col_append_fstr(pinfo->cinfo, COL_INFO, "[%s]", val_to_str(PCP_PDU_PROFILE, packettypenames, "Unknown Type:0x%02x"));
+
+ pcp_profile_item = proto_tree_add_item(tree, hf_pcp_profile, tvb, offset, -1, ENC_NA);
+ pcp_profile_tree = proto_item_add_subtree(pcp_profile_item, ett_pcp);
+
+ /* ctxnum */
+ proto_tree_add_item(pcp_profile_tree, hf_pcp_ctxnum, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* g_state */
+ proto_tree_add_item(pcp_profile_tree, hf_pcp_profile_g_state, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* numprof */
+ proto_tree_add_item(pcp_profile_tree, hf_pcp_profile_numprof, tvb, offset, 4, ENC_BIG_ENDIAN);
+ num_prof = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+
+ /* pad */
+ proto_tree_add_item(pcp_profile_tree, hf_pcp_pdu_padding, tvb, offset, 4, ENC_NA);
+ offset += 4;
+
+ /* iterate through each profile */
+ for (i=0; i<num_prof; i++) {
+ /* subtree for each profile */
+ pcp_profile_profile_item = proto_tree_add_item(pcp_profile_tree, hf_pcp_profile_profile, tvb, offset, 32, ENC_NA);
+ pcp_profile_profile_tree = proto_item_add_subtree(pcp_profile_profile_item, ett_pcp);
+
+ /* indom */
+ proto_tree_add_item(pcp_profile_profile_tree, hf_pcp_instance_indom, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* state - include/exclude */
+ proto_tree_add_item(pcp_profile_profile_tree, hf_pcp_profile_profile_state, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* numinst - number of instances to follow */
+ proto_tree_add_item(pcp_profile_profile_tree, hf_pcp_profile_profile_numinst, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* padding */
+ proto_tree_add_item(pcp_profile_tree, hf_pcp_pdu_padding, tvb, offset, 4, ENC_NA);
+ offset += 4;
+ }
+ return offset;
+}
+
+/* FETCH packet format
+ guint32 cxtnum
+ __pmTimeval when (unsigned int tv_sec, unsigned int tv_usec)
+ guint32 numpmid
+ pmID pmidlist[1-x] (unsigned int)
+ */
+static int dissect_pcp_message_fetch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
+{
+ proto_item *pcp_fetch_item;
+ proto_tree *pcp_fetch_tree;
+ guint32 num_pmid;
+ guint32 i;
+
+ /* append the type of packet */
+ col_append_fstr(pinfo->cinfo, COL_INFO, "[%s]",
+ val_to_str(PCP_PDU_FETCH, packettypenames, "Unknown Type:0x%02x"));
+
+ pcp_fetch_item = proto_tree_add_item(tree, hf_pcp_fetch, tvb, offset, -1, ENC_NA);
+ pcp_fetch_tree = proto_item_add_subtree(pcp_fetch_item, ett_pcp);
+
+ /* ctxnum */
+ proto_tree_add_item(pcp_fetch_tree, hf_pcp_ctxnum, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* when */
+ offset = dissect_pcp_partial_when(tvb, pinfo, pcp_fetch_tree, offset);
+
+ /* numpmid */
+ proto_tree_add_item(pcp_fetch_tree, hf_pcp_fetch_numpmid, tvb, offset, 4, ENC_BIG_ENDIAN);
+ num_pmid = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+
+ /* pmIDs*/
+ for (i=0; i<num_pmid; i++) {
+ /* decode partial PMID message */
+ offset = dissect_pcp_partial_pmid(tvb, pinfo, pcp_fetch_tree, offset);
+ }
+ return offset;
+}
+
+/* RESULT packet format
+
+ __pmTimeval when (unsigned int tv_sec, unsigned int tv_usec)
+ int numpmid
+ _pmPDU data[1-n] (contains v_list types)
+ |
+ |> pmID pmid
+ int numval
+ int valfmt
+ __pmValue_PDU vlist[1-n] (contains pmValue PDUs)
+ |
+ |> int inst
+ int offset/value
+ (if valfmt == PTR type)
+ int8 type
+ int24 length
+ char value[length]
+*/
+static int dissect_pcp_message_result(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
+{
+ proto_item *pcp_results_item;
+ proto_tree *pcp_results_tree;
+ proto_item *pcp_result_item;
+ proto_tree *pcp_result_tree;
+ proto_item *pcp_result_instance_item;
+ proto_tree *pcp_result_instance_tree;
+ guint32 num_pmid;
+ guint32 num_val;
+ guint32 offset_start;
+ guint32 valfmt_type;
+ guint32 value_type;
+ guint32 pmvalueblock_offset;
+ guint32 pmvalueblock_value_length;
+ guint32 i;
+ guint32 j;
+
+ /* append the type of packet */
+ col_append_fstr(pinfo->cinfo, COL_INFO, "[%s]", val_to_str(PCP_PDU_RESULT, packettypenames, "Unknown Type:0x%02x"));
+
+ pcp_results_item = proto_tree_add_item(tree, hf_pcp_results, tvb, offset, -1, ENC_NA);
+ pcp_results_tree = proto_item_add_subtree(pcp_results_item, ett_pcp);
+
+ /* when */
+ offset = dissect_pcp_partial_when(tvb, pinfo, pcp_results_tree, offset);
+
+ /* numpmid */
+ proto_tree_add_item(pcp_results_tree, hf_pcp_results_numpmid, tvb, offset, 4, ENC_BIG_ENDIAN);
+ num_pmid = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+
+ /* result */
+ for (i=0; i<num_pmid; i++) {
+ /* work out how long each result should be - set starting offset */
+ offset_start = offset;
+
+ pcp_result_item = proto_tree_add_item(pcp_results_tree, hf_pcp_result, tvb, offset, -1, ENC_NA);
+ pcp_result_tree = proto_item_add_subtree(pcp_result_item, ett_pcp);
+
+ /* pmID */
+ offset = dissect_pcp_partial_pmid(tvb, pinfo, pcp_result_tree, offset);
+
+ /* numval */
+ proto_tree_add_item(pcp_result_tree, hf_pcp_result_numval, tvb, offset, 4, ENC_BIG_ENDIAN);
+ num_val = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+
+ /* if there are no numvals, then the valfmt isn't sent */
+ if (num_val > 0) {
+
+ /* valfmt */
+ proto_tree_add_item(pcp_result_tree, hf_pcp_result_valfmt, tvb, offset, 4, ENC_BIG_ENDIAN);
+ valfmt_type = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+
+ /* instance */
+ for (j=0; j<num_val; j++) {
+ /* give the subtree name length of inst (int) + offset/va (int) */
+ pcp_result_instance_item = proto_tree_add_item(pcp_result_tree, hf_pcp_instance,
+ tvb, offset, 8, ENC_NA);
+ pcp_result_instance_tree = proto_item_add_subtree(pcp_result_instance_item, ett_pcp);
+
+ /* inst */
+ proto_tree_add_item(pcp_result_instance_tree, hf_pcp_pmid_inst, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* valoffset/value: depending on the format, the next 32 bits is the value _OR_ the offset to where
+ the value is */
+ if (valfmt_type == PM_VAL_INSITU) {
+ proto_tree_add_item(pcp_result_instance_tree, hf_pcp_instance_value_insitu,
+ tvb, offset, 4, ENC_BIG_ENDIAN);
+ } else {
+ /* offset in the packet to find pmValueBlock */
+ proto_tree_add_item(pcp_result_instance_tree, hf_pcp_instance_valoffset,
+ tvb, offset, 4, ENC_BIG_ENDIAN);
+ /* get the offset (not the offset of the count we are at) but where we should look */
+ pmvalueblock_offset = tvb_get_ntohl(tvb, offset);
+ pmvalueblock_offset = pmvalueblock_offset * 4; /* offset values are in 32bit units */
+
+ /* type */
+ value_type = tvb_get_guint8(tvb, pmvalueblock_offset);
+ proto_tree_add_item(pcp_result_instance_tree, hf_pcp_pmid_type,
+ tvb, pmvalueblock_offset, 1, ENC_BIG_ENDIAN);
+ pmvalueblock_offset += 1;
+
+ /* length */
+ pmvalueblock_value_length = tvb_get_ntoh24(tvb, pmvalueblock_offset);
+ /* can't add a tree item the ususal way as it is outside of the tree */
+ proto_tree_add_item(pcp_result_instance_tree, hf_pcp_instance_vallength,
+ tvb, pmvalueblock_offset, 3, ENC_BIG_ENDIAN);
+ pmvalueblock_offset += 3;
+
+ /* value - note we go up to the pmvalueblock_value_length - 4,
+ as this value includes the previous 4 bytes */
+ switch (value_type) {
+ case PM_TYPE_32:
+ proto_tree_add_item(pcp_result_instance_tree, hf_pcp_instance_value_int, tvb,
+ pmvalueblock_offset, pmvalueblock_value_length-4, ENC_BIG_ENDIAN);
+ break;
+ case PM_TYPE_U32:
+ proto_tree_add_item(pcp_result_instance_tree, hf_pcp_instance_value_uint, tvb,
+ pmvalueblock_offset, pmvalueblock_value_length-4, ENC_BIG_ENDIAN);
+ break;
+ case PM_TYPE_64:
+ proto_tree_add_item(pcp_result_instance_tree, hf_pcp_instance_value_int64, tvb,
+ pmvalueblock_offset, pmvalueblock_value_length-4, ENC_BIG_ENDIAN);
+ break;
+ case PM_TYPE_U64:
+ proto_tree_add_item(pcp_result_instance_tree, hf_pcp_instance_value_uint64, tvb,
+ pmvalueblock_offset, pmvalueblock_value_length-4, ENC_BIG_ENDIAN);
+ break;
+ case PM_TYPE_FLOAT:
+ proto_tree_add_item(pcp_result_instance_tree, hf_pcp_instance_value_float, tvb,
+ pmvalueblock_offset, pmvalueblock_value_length-4, ENC_BIG_ENDIAN);
+ break;
+ case PM_TYPE_DOUBLE:
+ proto_tree_add_item(pcp_result_instance_tree, hf_pcp_instance_value_double, tvb,
+ pmvalueblock_offset, pmvalueblock_value_length-4, ENC_BIG_ENDIAN);
+ break;
+ case PM_TYPE_STRING:
+ proto_tree_add_item(pcp_result_instance_tree, hf_pcp_instance_value_ptr, tvb,
+ pmvalueblock_offset, pmvalueblock_value_length-4, ENC_ASCII);
+ break;
+ case PM_TYPE_AGGREGATE:
+ case PM_TYPE_AGGREGATE_STATIC:
+ proto_tree_add_item(pcp_result_instance_tree, hf_pcp_instance_value_aggr, tvb,
+ pmvalueblock_offset, pmvalueblock_value_length-4, ENC_NA);
+ break;
+ case PM_TYPE_EVENT:
+ expert_add_info(pinfo, pcp_result_instance_tree, &ei_pcp_type_event_unimplemented);
+ break;
+ case PM_TYPE_NOSUPPORT:
+ expert_add_info(pinfo, pcp_result_instance_tree, &ei_pcp_type_nosupport_unsupported);
+ break;
+ case PM_TYPE_UNKNOWN:
+ expert_add_info(pinfo, pcp_result_instance_tree, &ei_pcp_type_unknown_unknown_value);
+ break;
+ default:
+ expert_add_info(pinfo, pcp_result_instance_tree, &ei_pcp_unimplemented_value);
+ break;
+ }
+ }
+ /* bump the offset after the instance value _or_ the offset into
+ the packet (pcp.instance.valoffset) , each being 4 bytes */
+ offset += 4;
+ }
+
+ }
+ /* we now know how long the field is */
+ proto_item_set_len(pcp_result_tree, offset-offset_start);
+
+ }
+ return offset;
+}
+
+/* DESC_REQ pcaket format
+ pmID pmid (32bit int)
+*/
+static int dissect_pcp_message_desc_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
+{
+ proto_item *pcp_desc_req_item;
+ proto_tree *pcp_desc_req_tree;
+
+ /* append the type of packet */
+ col_append_fstr(pinfo->cinfo, COL_INFO, "[%s]", val_to_str(PCP_PDU_DESC_REQ, packettypenames, "Unknown Type:0x%02x"));
+
+ /* subtree for packet type */
+ pcp_desc_req_item = proto_tree_add_item(tree, hf_pcp_desc_req, tvb, offset, -1, ENC_NA);
+ pcp_desc_req_tree = proto_item_add_subtree(pcp_desc_req_item, ett_pcp);
+
+ offset = dissect_pcp_partial_pmid(tvb, pinfo, pcp_desc_req_tree, offset);
+
+ return offset;
+}
+
+/* DESC packet format
+ pmID pmid
+ int type (base data type)
+ pmInDom indom
+ int sem (semantics of the value: instant? counter? etc..)
+ pmUnits units
+ |
+ v
+ signed int dimSpace : 4
+ signed int dimTime : 4
+ signed int dimCount : 4
+ unsigned int scaleSpace : 4
+ unsigned int scaleTime : 4
+ signed int scaleCount : 4
+ unsigned int pad : 8
+*/
+static int dissect_pcp_message_desc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
+{
+ proto_item *pcp_desc_item;
+ proto_tree *pcp_desc_tree;
+ proto_item *pcp_desc_units_item;
+ proto_tree *pcp_desc_units_tree;
+ guint32 bits_offset;
+
+ /* append the type of packet */
+ col_append_fstr(pinfo->cinfo, COL_INFO, "[%s]", val_to_str(PCP_PDU_DESC, packettypenames, "Unknown Type:0x%02x"));
+
+ /* root desc tree */
+ pcp_desc_item = proto_tree_add_item(tree, hf_pcp_desc, tvb, offset, 4, ENC_NA);
+ pcp_desc_tree = proto_item_add_subtree(pcp_desc_item, ett_pcp);
+
+ /* pmID */
+ offset = dissect_pcp_partial_pmid(tvb, pinfo, pcp_desc_tree, offset);
+
+ /* type */
+ proto_tree_add_item(pcp_desc_tree, hf_pcp_pmid_type, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* indom */
+ proto_tree_add_item(pcp_desc_tree, hf_pcp_instance_indom, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* sem */
+ proto_tree_add_item(pcp_desc_tree, hf_pcp_pmid_sem, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* pmUnits */
+ bits_offset = offset*8; /* create the bits offset */
+ pcp_desc_units_item = proto_tree_add_item(pcp_desc_tree, hf_pcp_units, tvb, offset, -1, ENC_NA);
+ pcp_desc_units_tree = proto_item_add_subtree(pcp_desc_units_item, ett_pcp);
+
+ /* dimspace */
+ proto_tree_add_bits_item(pcp_desc_units_tree, hf_pcp_units_dimspace, tvb, bits_offset, 4, ENC_BIG_ENDIAN);
+ bits_offset += 4;
+ /* dimtime */
+ proto_tree_add_bits_item(pcp_desc_units_tree, hf_pcp_units_dimtime, tvb, bits_offset, 4, ENC_BIG_ENDIAN);
+ bits_offset += 4;
+ /* dimcount */
+ proto_tree_add_bits_item(pcp_desc_units_tree, hf_pcp_units_dimcount, tvb, bits_offset, 4, ENC_BIG_ENDIAN);
+ bits_offset += 4;
+ /* scalespace */
+ proto_tree_add_bits_item(pcp_desc_units_tree, hf_pcp_units_scalespace, tvb, bits_offset, 4, ENC_BIG_ENDIAN);
+ bits_offset += 4;
+ /* scaletime */
+ proto_tree_add_bits_item(pcp_desc_units_tree, hf_pcp_units_scaletime, tvb, bits_offset, 4, ENC_BIG_ENDIAN);
+ bits_offset += 4;
+ /* scalecount */
+ proto_tree_add_bits_item(pcp_desc_units_tree, hf_pcp_units_scalecount, tvb, bits_offset, 4, ENC_BIG_ENDIAN);
+ /*bits_offset += 4;*/
+ /* padding */
+ offset += 3; /* total offset of pmunits before */
+ proto_tree_add_item(pcp_desc_units_tree, hf_pcp_pdu_padding, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ /*bits_offset += 8;*/
+ return offset;
+
+}
+
+/* INSTANCE_REQ packet format
+ pmInDom indom
+ __pmTimeval when
+ int inst
+ int namelen
+ char name
+*/
+static int dissect_pcp_message_instance_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
+{
+ proto_item *pcp_instance_req_item;
+ proto_tree *pcp_instance_req_tree;
+ guint32 name_len;
+
+ /* append the type of packet */
+ col_append_fstr(pinfo->cinfo, COL_INFO, "[%s]", val_to_str(PCP_PDU_INSTANCE_REQ, packettypenames, "Unknown Type:0x%02x"));
+
+ pcp_instance_req_item = proto_tree_add_item(tree, hf_pcp_instance_req, tvb, offset, -1, ENC_NA);
+ pcp_instance_req_tree = proto_item_add_subtree(pcp_instance_req_item, ett_pcp);
+
+ /* indom */
+ proto_tree_add_item(pcp_instance_req_tree, hf_pcp_instance_indom, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* when */
+ offset = dissect_pcp_partial_when(tvb, pinfo, pcp_instance_req_tree, offset);
+
+ /* inst */
+ proto_tree_add_item(pcp_instance_req_tree, hf_pcp_pmid_inst, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* namelen */
+ proto_tree_add_item(pcp_instance_req_tree, hf_pcp_instance_namelen, tvb, offset, 4, ENC_BIG_ENDIAN);
+ name_len = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+
+ /* name */
+ if (name_len > 0) {
+ proto_tree_add_item(pcp_instance_req_tree, hf_pcp_instance_name, tvb, offset, name_len, ENC_ASCII);
+ offset += name_len;
+ }
+ return offset;
+}
+
+/* TEXT_REQ packet format
+ int ident
+ int type
+*/
+static int dissect_pcp_message_text_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
+{
+ proto_item *pcp_text_req_item;
+ proto_tree *pcp_text_req_tree;
+ proto_item *pcp_text_req_type_item;
+ proto_tree *pcp_text_req_type_tree;
+ guint32 bits_offset;
+ guint32 type;
+
+ /* append the type of packet */
+ col_append_fstr(pinfo->cinfo, COL_INFO, "[%s]", val_to_str(PCP_PDU_TEXT_REQ, packettypenames, "Unknown Type:0x%02x"));
+
+ pcp_text_req_item = proto_tree_add_item(tree, hf_pcp_text_req, tvb, offset, -1, ENC_NA);
+ pcp_text_req_tree = proto_item_add_subtree(pcp_text_req_item, ett_pcp);
+
+ /* peek at type to decode ident correctly */
+ type = tvb_get_ntohl(tvb, offset + 4);
+
+ /* ident */
+ if (type & PM_TEXT_PMID) {
+ offset = dissect_pcp_partial_pmid(tvb, pinfo, pcp_text_req_tree, offset);
+ } else if (type & PM_TEXT_INDOM) {
+ proto_tree_add_item(pcp_text_req_tree, hf_pcp_instance_indom, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ }
+
+ /* type */
+ pcp_text_req_type_item = proto_tree_add_item(pcp_text_req_tree, hf_pcp_text_type, tvb, offset, 4, ENC_NA);
+ pcp_text_req_type_tree = proto_item_add_subtree(pcp_text_req_type_item, ett_pcp);
+ bits_offset = offset * 8 + 28;
+ proto_tree_add_bits_item(pcp_text_req_type_tree, hf_pcp_text_type_ident, tvb, bits_offset, 2, ENC_BIG_ENDIAN);
+ bits_offset += 2;
+ proto_tree_add_bits_item(pcp_text_req_type_tree, hf_pcp_text_type_format, tvb, bits_offset, 2, ENC_BIG_ENDIAN);
+
+ offset += 4;
+ return offset;
+}
+
+/* TEXT packet format
+ int ident
+ int buflen
+ char buffer
+*/
+static int dissect_pcp_message_text(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
+{
+ proto_item *pcp_text_item;
+ proto_tree *pcp_text_tree;
+ guint32 buflen;
+
+ /* append the type of packet */
+ col_append_fstr(pinfo->cinfo, COL_INFO, "[%s]", val_to_str(PCP_PDU_TEXT, packettypenames, "Unknown Type:0x%02x"));
+
+ pcp_text_item = proto_tree_add_item(tree, hf_pcp_text, tvb, offset, -1, ENC_NA);
+ pcp_text_tree = proto_item_add_subtree(pcp_text_item, ett_pcp);
+
+ /* ident */
+ proto_tree_add_item(pcp_text_tree, hf_pcp_text_ident, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* buflen */
+ buflen = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_item(pcp_text_tree, hf_pcp_text_buflen, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* buffer */
+ proto_tree_add_item(pcp_text_tree, hf_pcp_text_buffer, tvb, offset, buflen, ENC_ASCII);
+ offset += buflen;
+
+ return offset;
+}
+
+/* USER_AUTH packet format
+ int ident
+ int buflen
+ char buffer
+*/
+static int dissect_pcp_message_user_auth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
+{
+ /* append the type of packet */
+ col_append_fstr(pinfo->cinfo, COL_INFO, "[%s]", val_to_str(PCP_PDU_USER_AUTH, packettypenames, "Unknown Type:0x%02x"));
+
+ proto_tree_add_item(tree, hf_pcp_user_auth_payload, tvb, offset, -1, ENC_NA);
+
+ return tvb_reported_length(tvb);
+}
+
+/* LABEL_REQ packet format
+ int ident
+ int type
+*/
+static int dissect_pcp_message_label_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
+{
+ /* append the type of packet */
+ col_append_fstr(pinfo->cinfo, COL_INFO, "[%s]", val_to_str(PCP_PDU_LABEL_REQ, packettypenames, "Unknown Type:0x%02x"));
+
+ proto_item *pcp_label_req_item = proto_tree_add_item(tree, hf_pcp_label_req, tvb, offset, -1, ENC_NA);
+ proto_tree *pcp_label_req_tree = proto_item_add_subtree(pcp_label_req_item, ett_pcp);
+
+ /* ident */
+ proto_tree_add_item(pcp_label_req_tree, hf_pcp_label_ident, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* type */
+ proto_tree_add_item(pcp_label_req_tree, hf_pcp_label_type, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ return offset;
+}
+
+/* LABEL packet format
+ int ident
+ int type
+ int padding;
+ int nsets;
+ labelset_t sets[1];
+ |
+ |> int inst
+ int nlabels
+ int json
+ int jsonlen
+ pmLabel labels[0]
+*/
+static int dissect_pcp_message_label(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
+{
+ /* append the type of packet */
+ col_append_fstr(pinfo->cinfo, COL_INFO, "[%s]", val_to_str(PCP_PDU_LABEL, packettypenames, "Unknown Type:0x%02x"));
+
+ proto_item *pcp_label_item = proto_tree_add_item(tree, hf_pcp_label, tvb, offset, -1, ENC_NA);
+ proto_tree *pcp_label_tree = proto_item_add_subtree(pcp_label_item, ett_pcp);
+
+ /* ident */
+ proto_tree_add_item(pcp_label_tree, hf_pcp_label_ident, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* type */
+ proto_tree_add_item(pcp_label_tree, hf_pcp_label_type, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* padding */
+ proto_tree_add_item(pcp_label_tree, hf_pcp_label_padding, tvb, offset, 4, ENC_NA);
+ offset += 4;
+
+ /* number of label sets */
+ gint32 nsets;
+ proto_tree_add_item_ret_int(pcp_label_tree, hf_pcp_label_nsets, tvb, offset, 4, ENC_NA, &nsets);
+ offset += 4;
+
+
+ for (gint32 i = 0; i < nsets; i++) {
+ offset = dissect_pcp_partial_labelset(tvb, pcp_label_tree, pinfo, offset);
+ }
+
+ return offset;
+}
+
+/* INSTANCE packet type
+ pmInDom indom
+ int numinst
+ instlist_t instlist[numinst]
+ |
+ |> int inst
+ int namelen
+ char name
+ */
+static int dissect_pcp_message_instance(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
+{
+ proto_item *pcp_instances_item;
+ proto_tree *pcp_instances_tree;
+ proto_item *pcp_instance_item;
+ proto_tree *pcp_instance_tree;
+ guint32 num_inst;
+ guint32 i;
+ guint32 name_len;
+ guint32 padding;
+
+ /* append the type of packet */
+ col_append_fstr(pinfo->cinfo, COL_INFO, "[%s]", val_to_str(PCP_PDU_INSTANCE, packettypenames, "Unknown Type:0x%02x"));
+
+ pcp_instances_item = proto_tree_add_item(tree, hf_pcp_instances, tvb, offset, -1, ENC_NA);
+ pcp_instances_tree = proto_item_add_subtree(pcp_instances_item, ett_pcp);
+
+ /* indom */
+ proto_tree_add_item(pcp_instances_tree, hf_pcp_instance_indom, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ /* numinst */
+ proto_tree_add_item(pcp_instances_tree, hf_pcp_instances_numinst, tvb, offset, 4, ENC_BIG_ENDIAN);
+ num_inst = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+
+ /* instlist */
+ for (i=0; i<num_inst; i++) {
+ /* get the size of the name first, so we know how much offset to give */
+ name_len = tvb_get_ntohl(tvb, offset+4);
+
+ /* give the subtree name length + 2 ints */
+ pcp_instance_item = proto_tree_add_item(pcp_instances_tree, hf_pcp_instance, tvb, offset, name_len+8, ENC_NA);
+ pcp_instance_tree = proto_item_add_subtree(pcp_instance_item, ett_pcp);
+
+ /* inst */
+ proto_tree_add_item(pcp_instance_tree, hf_pcp_pmid_inst, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* namelen */
+ proto_tree_add_item(pcp_instance_tree, hf_pcp_instance_namelen, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* name */
+ if (name_len > 0) {
+ proto_tree_add_item(pcp_instance_tree, hf_pcp_instance_name, tvb, offset, name_len, ENC_ASCII);
+ offset += name_len;
+ }
+
+ /* padding */
+ padding = name_len % 4; /* names are padded to the nearest 4 byte boundary */
+ if (padding != 0) { /* if there is padding, keep going till the remainder of mod 4 */
+ padding = 4 - padding; /* we want the inverse of the remainder */
+
+ proto_tree_add_item(pcp_instance_tree, hf_pcp_pdu_padding, tvb, offset, padding, ENC_NA);
+ offset += padding;
+ }
+ }
+ return offset;
+}
+
+/* PARTIAL DISSECTOR ROUTINES
+ these routines are called by dissect_pcp_message_* as needed
+*/
+
+static int dissect_pcp_partial_pmid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
+{
+ proto_item *pcp_pmid_item;
+ proto_tree *pcp_pmid_tree;
+ guint32 bits_offset;
+ guint32 pmid;
+ guint8 *name;
+
+ bits_offset = offset * 8;
+
+ pmid = tvb_get_ntohl(tvb, offset);
+ name = get_name_from_pmid(pmid, pinfo);
+
+ /* subtree for pmid */
+ pcp_pmid_item = proto_tree_add_item(tree, hf_pcp_pmid, tvb, offset, 4, ENC_BIG_ENDIAN);
+ proto_item_append_text(pcp_pmid_item, " (%s)", name);
+ pcp_pmid_tree = proto_item_add_subtree(pcp_pmid_item, ett_pcp);
+
+ /* flag - 1 bit */
+ proto_tree_add_bits_item(pcp_pmid_tree, hf_pcp_pmid_flag, tvb, bits_offset, 1, ENC_BIG_ENDIAN);
+ bits_offset += 1;
+ /* domain - 9 bits */
+ proto_tree_add_bits_item(pcp_pmid_tree, hf_pcp_pmid_domain, tvb, bits_offset, 9, ENC_BIG_ENDIAN);
+ bits_offset += 9;
+ /* cluster - 12 bits */
+ proto_tree_add_bits_item(pcp_pmid_tree, hf_pcp_pmid_cluster, tvb, bits_offset, 12, ENC_BIG_ENDIAN);
+ bits_offset += 12;
+ /* item - 10 bits */
+ proto_tree_add_bits_item(pcp_pmid_tree, hf_pcp_pmid_item, tvb, bits_offset, 10, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ return offset;
+}
+
+static int dissect_pcp_partial_when(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
+{
+ proto_item *pcp_when_item;
+ proto_tree *pcp_when_tree;
+
+ /* when - create a new subtree for each val */
+ pcp_when_item = proto_tree_add_item(tree, hf_pcp_when, tvb, offset, 8, ENC_NA);
+ pcp_when_tree = proto_item_add_subtree(pcp_when_item, ett_pcp);
+
+ /* when tv_sec */
+ proto_tree_add_item(pcp_when_tree, hf_pcp_when_sec, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ /* when tv_usec */
+ proto_tree_add_item(pcp_when_tree, hf_pcp_when_usec, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ return offset;
+}
+
+static int dissect_pcp_partial_features(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
+{
+ guint16 feature_flags;
+ const gchar *feature_flags_string;
+
+ static int * const pcp_feature_flags_header_fields[] = {
+ &hf_pcp_features_flags_labels,
+ &hf_pcp_features_flags_bad_label,
+ &hf_pcp_features_flags_cert_reqd,
+ &hf_pcp_features_flags_container,
+ &hf_pcp_features_flags_no_nss_init,
+ &hf_pcp_features_flags_secure_ack,
+ &hf_pcp_features_flags_creds_reqd,
+ &hf_pcp_features_flags_auth,
+ &hf_pcp_features_flags_compress,
+ &hf_pcp_features_flags_secure,
+ NULL
+ };
+
+ feature_flags = tvb_get_ntohs(tvb, offset);
+ feature_flags_string = get_pcp_features_to_string(pinfo->pool, feature_flags);
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Features=[%s]", feature_flags_string);
+
+ proto_tree_add_bitmask(tree, tvb, offset, hf_pcp_features_flags, ett_pcp_start_features, pcp_feature_flags_header_fields, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ if ((feature_flags & PCP_PDU_FLAG_LABELS) == PCP_PDU_FLAG_LABELS && server_to_client(pinfo)) {
+ pcp_conv_info_t *pcp_conv_info = get_pcp_conversation_info(pinfo);
+ pcp_conv_info->using_good_labels = TRUE;
+ }
+
+ return offset;
+}
+
+static int dissect_pcp_partial_labelset(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, int offset)
+{
+ proto_item *pcp_label_sets_item = proto_tree_add_item(tree, hf_pcp_label_sets, tvb, offset, -1, ENC_NA);
+ proto_tree *pcp_label_sets_tree = proto_item_add_subtree(pcp_label_sets_item, ett_pcp);
+
+ /* Instance */
+ proto_tree_add_item(pcp_label_sets_tree, hf_pcp_label_sets_inst, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* Number of labels or error */
+ gint32 nlabels_or_error = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_item(pcp_label_sets_tree, hf_pcp_label_sets_nlabels, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ if (nlabels_or_error < 0) {
+ expert_add_info(pinfo, pcp_label_sets_tree, &ei_pcp_label_error);
+ }
+
+ /* Offset to start of JSON */
+ guint32 json_start_offset = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_item(pcp_label_sets_tree, hf_pcp_label_sets_json, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* Length of JSON string */
+ proto_tree_add_item(pcp_label_sets_tree, hf_pcp_label_sets_jsonlen, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* pmLabels */
+ for (gint i = 0; i < nlabels_or_error; i++) {
+ offset = dissect_pcp_partial_label(tvb, pinfo, pcp_label_sets_tree, offset, json_start_offset);
+ }
+
+ /* Fix up end length */
+ proto_item_set_end(pcp_label_sets_item, tvb, offset);
+
+ return offset;
+
+}
+
+static int dissect_pcp_partial_label(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint32 json_start_offset)
+{
+ proto_item *pcp_label_sets_label_item = proto_tree_add_item(tree, hf_pcp_label_sets_labels, tvb, offset, -1, ENC_NA);
+ proto_tree *pcp_label_sets_label_tree = proto_item_add_subtree(pcp_label_sets_label_item, ett_pcp);
+
+ /* Name offset*/
+ guint16 name_offset = tvb_get_guint16(tvb, offset, ENC_BIG_ENDIAN);
+ proto_tree_add_item(pcp_label_sets_label_tree, hf_pcp_label_sets_labels_nameoffset, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ /* Name length */
+ guint32 name_length = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(pcp_label_sets_label_tree, hf_pcp_label_sets_labels_namelen, tvb, offset, 1, ENC_NA);
+ offset += 1;
+
+ /* Flags */
+ proto_tree_add_item(pcp_label_sets_label_tree, hf_pcp_label_sets_labels_flags, tvb, offset, 1, ENC_NA);
+ offset += 1;
+
+ /* Value offset */
+ guint16 value_offset = tvb_get_guint16(tvb, offset, ENC_BIG_ENDIAN);
+ proto_tree_add_item(pcp_label_sets_label_tree, hf_pcp_label_sets_labels_valueoffset, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ /* Value Length */
+ guint16 value_length = tvb_get_guint16(tvb, offset, ENC_BIG_ENDIAN);
+ /* Value length was not correctly converted to network-byte order in pcp v4.0.0-v4.0.1, it was encoded with whatever
+ * byte order the host uses. We try and pick this up and accommodate either by detecting the feature off the START PDU
+ * and failing that, check if the offset+length would be greater than the length of the captured packets. This isn't
+ * exhaustive but there is not much else to do apart from _only_ dissecting the known good LABEL PDUs.
+ */
+ if(is_using_good_labels(pinfo)) {
+ proto_tree_add_item(pcp_label_sets_label_tree, hf_pcp_label_sets_labels_valuelen, tvb, offset, 2, ENC_BIG_ENDIAN);
+ }
+ else if(label_value_length_looks_like_wrong_endianness(tvb, value_offset, value_length)) {
+ /* We're _probably_ using the wrong endianness but we didn't capture the initial exchange to find out */
+ value_length = tvb_get_guint16(tvb, offset, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(pcp_label_sets_label_tree, hf_pcp_label_sets_labels_valuelen, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ expert_add_info(pinfo, pcp_label_sets_label_tree, &ei_pcp_label_error_endianness);
+ } else {
+ proto_tree_add_item(pcp_label_sets_label_tree, hf_pcp_label_sets_labels_valuelen, tvb, offset, 2, ENC_BIG_ENDIAN);
+ expert_add_info(pinfo, pcp_label_sets_label_tree, &ei_pcp_label_error_endianness);
+ }
+ offset += 2;
+
+ /* Name */
+ proto_tree_add_item(pcp_label_sets_label_tree, hf_pcp_label_sets_labels_name, tvb, json_start_offset + name_offset, name_length, ENC_ASCII | ENC_NA);
+
+ /* Value */
+ proto_tree_add_item(pcp_label_sets_label_tree, hf_pcp_label_sets_labels_value, tvb, json_start_offset + value_offset, value_length, ENC_ASCII | ENC_NA);
+
+ /* Add to subtree */
+ guint8 *name = tvb_get_string_enc(pinfo->pool, tvb, json_start_offset + name_offset, name_length, ENC_ASCII | ENC_NA);
+ guint8 *value = tvb_get_string_enc(pinfo->pool, tvb, json_start_offset + value_offset, value_length, ENC_ASCII | ENC_NA);
+ proto_item_append_text(pcp_label_sets_label_item, " (%s:%s)", name, value);
+
+ proto_item_set_end(pcp_label_sets_label_item, tvb, offset);
+
+ return offset;
+}
+
+static gboolean is_using_good_labels(packet_info *pinfo)
+{
+ /* Try to establish if we've got good labels from an earlier START PDU */
+ return get_pcp_conversation_info(pinfo)->using_good_labels;
+}
+
+static gboolean label_value_length_looks_like_wrong_endianness(tvbuff_t *tvb, guint16 value_offset, guint16 value_length)
+{
+ /* Try to detect if the offset + length is greater than the TVB length which may happen with a
+ * wrongly-encoded endianness. This may fail in some cases if the label is early on in the frame and has
+ * many other labels that wouldn't push it over of the TVB length.
+ */
+ return tvb_reported_length(tvb) < ((guint)value_offset + (guint)value_length);
+}
+
+/* MAIN DISSECTING ROUTINE (after passed from dissect_tcp, all non-ssl packets hit function) */
+static int dissect_pcp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_item *root_pcp_item;
+ proto_tree *pcp_tree;
+ conversation_t *conversation;
+ pcp_conv_info_t *pcp_conv_info;
+ guint32 packet_type;
+ gint32 err_bytes;
+ int offset = 0;
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PCP");
+ col_clear(pinfo->cinfo, COL_INFO);
+
+
+ conversation = find_or_create_conversation(pinfo);
+
+ pcp_conv_info = (pcp_conv_info_t*)conversation_get_proto_data(conversation, proto_pcp);
+
+ if(pcp_conv_info == NULL) {
+ pcp_conv_info = wmem_new(wmem_file_scope(), pcp_conv_info_t);
+ conversation_add_proto_data(conversation, proto_pcp, pcp_conv_info);
+
+ pcp_conv_info->pmid_name_candidates = wmem_array_new(wmem_file_scope(), sizeof(guint8 *));
+ pcp_conv_info->pmid_to_name = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
+ pcp_conv_info->last_pmns_names_frame = 0;
+ pcp_conv_info->last_processed_pmns_names_frame = 0;
+ pcp_conv_info->using_good_labels = FALSE;
+ }
+
+ root_pcp_item = proto_tree_add_item(tree, proto_pcp, tvb, 0, -1, ENC_NA);
+ pcp_tree = proto_item_add_subtree(root_pcp_item, ett_pcp);
+
+ packet_type = tvb_get_ntohl(tvb, 4);
+
+ /* check if we are the client requesting or the server */
+ if (server_to_client(pinfo)) {
+ col_set_str(pinfo->cinfo, COL_INFO, "Server > Client ");
+ } else {
+ col_set_str(pinfo->cinfo, COL_INFO, "Client > Server ");
+ }
+
+ /* PCP packet length */
+ proto_tree_add_item(pcp_tree, hf_pcp_pdu_length, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ /* PCP Packet type */
+ proto_tree_add_item(pcp_tree, hf_pcp_pdu_type, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ /* PCP Remote PID */
+ proto_tree_add_item(pcp_tree, hf_pcp_pdu_pid, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* dissect the rest of the packet depending on the type */
+ switch (packet_type) {
+ case PCP_PDU_CREDS:
+ dissect_pcp_message_creds(tvb, pinfo, pcp_tree, offset);
+ break;
+
+ case PCP_PDU_START_OR_ERROR:
+ err_bytes = tvb_get_ntohl(tvb, offset); /* get the first 4 bytes, determine if this is an error or not */
+ /* errors are signed and are all negative so check for a negative number.
+ It's the only way we can differentiate between start/error packets */
+ if (err_bytes < 0) {
+ dissect_pcp_message_error(tvb, pinfo, pcp_tree, offset);
+ } else {
+ dissect_pcp_message_start(tvb, pinfo, pcp_tree, offset);
+ }
+ break;
+
+ case PCP_PDU_PMNS_TRAVERSE:
+ dissect_pcp_message_pmns_traverse(tvb, pinfo, pcp_tree, offset);
+ break;
+
+ case PCP_PDU_PMNS_NAMES:
+ dissect_pcp_message_pmns_names(tvb, pinfo, pcp_tree, offset);
+ break;
+
+ case PCP_PDU_PMNS_CHILD:
+ dissect_pcp_message_pmns_child(tvb, pinfo, pcp_tree, offset);
+ break;
+
+ case PCP_PDU_PMNS_IDS:
+ dissect_pcp_message_pmns_ids(tvb, pinfo, pcp_tree, offset);
+ break;
+
+ case PCP_PDU_PROFILE:
+ dissect_pcp_message_profile(tvb, pinfo, pcp_tree, offset);
+ break;
+
+ case PCP_PDU_FETCH:
+ dissect_pcp_message_fetch(tvb, pinfo, pcp_tree, offset);
+ break;
+
+ case PCP_PDU_RESULT:
+ dissect_pcp_message_result(tvb, pinfo, pcp_tree, offset);
+ break;
+
+ case PCP_PDU_DESC_REQ:
+ dissect_pcp_message_desc_req(tvb, pinfo, pcp_tree, offset);
+ break;
+
+ case PCP_PDU_DESC:
+ dissect_pcp_message_desc(tvb, pinfo, pcp_tree, offset);
+ break;
+
+ case PCP_PDU_INSTANCE_REQ:
+ dissect_pcp_message_instance_req(tvb, pinfo, pcp_tree, offset);
+ break;
+
+ case PCP_PDU_INSTANCE:
+ dissect_pcp_message_instance(tvb, pinfo, pcp_tree, offset);
+ break;
+
+ case PCP_PDU_TEXT_REQ:
+ dissect_pcp_message_text_req(tvb, pinfo, pcp_tree, offset);
+ break;
+
+ case PCP_PDU_TEXT:
+ dissect_pcp_message_text(tvb, pinfo, pcp_tree, offset);
+ break;
+
+ case PCP_PDU_USER_AUTH:
+ dissect_pcp_message_user_auth(tvb, pinfo, pcp_tree, offset);
+ break;
+
+ case PCP_PDU_LABEL_REQ:
+ dissect_pcp_message_label_req(tvb, pinfo, pcp_tree, offset);
+ break;
+
+ case PCP_PDU_LABEL:
+ dissect_pcp_message_label(tvb, pinfo, pcp_tree, offset);
+ break;
+
+ default:
+ /* append the type of packet */
+ col_append_str(pinfo->cinfo, COL_INFO, "[UNIMPLEMENTED TYPE]");
+ /* if we got here, then we didn't get a packet type that we know of */
+ expert_add_info(pinfo, pcp_tree, &ei_pcp_unimplemented_packet_type);
+ break;
+ }
+ return tvb_captured_length(tvb);
+}
+
+static int dissect_pcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
+{
+ /* pass all packets through TCP-reassembly */
+ tcp_dissect_pdus(tvb, pinfo, tree, TRUE, PCP_HEADER_LEN, get_pcp_message_len, dissect_pcp_message, data);
+ return tvb_captured_length(tvb);
+}
+
+/* setup the dissecting */
+void proto_register_pcp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_pcp_pdu_length,
+ { "PDU Length", "pcp.length",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pdu_type,
+ { "Type", "pcp.type",
+ FT_UINT32, BASE_HEX,
+ VALS(packettypenames), 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pdu_pid,
+ { "From", "pcp.from",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pdu_error,
+ { "Error", "pcp.error",
+ FT_INT32, BASE_DEC,
+ VALS(packettypenames_errors), 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pdu_padding,
+ { "Padding", "pcp.padding",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_creds_number_of,
+ { "Number of Credentials", "pcp.creds.number",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_creds_type,
+ { "Credentials Type", "pcp.creds.type",
+ FT_UINT8, BASE_DEC,
+ VALS(packettypenames_creds), 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_creds_version,
+ { "Credentials Version", "pcp.creds.version",
+ FT_UINT8, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_start,
+ { "Start", "pcp.start",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_start_zero,
+ { "Start Bit", "pcp.start.zero",
+ FT_BOOLEAN, 8,
+ TFS(&tfs_set_notset), 0x80,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_start_version,
+ { "Version", "pcp.start.version",
+ FT_UINT8, BASE_DEC, /* not a real 8 bit int, only uses 7 bits */
+ NULL, 0x7F,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_start_status,
+ { "Start Status", "pcp.start.status",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_start_licensed,
+ { "Licensed", "pcp.start.licensed",
+ FT_UINT8, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_features_flags,
+ { "Features", "pcp.features.flags",
+ FT_UINT16, BASE_HEX,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_features_flags_secure,
+ { "Secure", "pcp.features.flags.secure",
+ FT_BOOLEAN, 16,
+ TFS(&tfs_set_notset), PCP_PDU_FLAG_SECURE,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_features_flags_compress,
+ { "Compression", "pcp.features.flags.compression",
+ FT_BOOLEAN, 16,
+ TFS(&tfs_set_notset), PCP_PDU_FLAG_COMPRESS,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_features_flags_auth,
+ { "Authentication", "pcp.features.flags.auth",
+ FT_BOOLEAN, 16,
+ TFS(&tfs_set_notset), PCP_PDU_FLAG_AUTH,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_features_flags_creds_reqd,
+ { "Credentials Required", "pcp.features.flags.creds_reqd",
+ FT_BOOLEAN, 16,
+ TFS(&tfs_set_notset), PCP_PDU_FLAG_CREDS_REQD,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_features_flags_secure_ack,
+ { "Secure Acknowledgement", "pcp.features.flags.secure_ack",
+ FT_BOOLEAN, 16,
+ TFS(&tfs_set_notset), PCP_PDU_FLAG_SECURE_ACK,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_features_flags_no_nss_init,
+ { "No NSS Init", "pcp.features.flags.no_nss_init",
+ FT_BOOLEAN, 16,
+ TFS(&tfs_set_notset), PCP_PDU_FLAG_NO_NSS_INIT,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_features_flags_container,
+ { "Container", "pcp.features.flags.container",
+ FT_BOOLEAN, 16,
+ TFS(&tfs_set_notset), PCP_PDU_FLAG_CONTAINER,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_features_flags_cert_reqd,
+ { "Certificate Required", "pcp.features.flags.cert_reqd",
+ FT_BOOLEAN, 16,
+ TFS(&tfs_set_notset), PCP_PDU_FLAG_CERT_REQD,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_features_flags_bad_label,
+ { "Bad Label", "pcp.features.flags.bad_label",
+ FT_BOOLEAN, 16,
+ TFS(&tfs_set_notset), PCP_PDU_FLAG_BAD_LABEL,
+ "Legacy label support. Incorrectly implemented in pcp v4.0.0-v4.0.1", HFILL
+ }
+ },
+ { &hf_pcp_features_flags_labels,
+ { "Labels", "pcp.features.flags.labels",
+ FT_BOOLEAN, 16,
+ TFS(&tfs_set_notset), PCP_PDU_FLAG_LABELS,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pmns_traverse,
+ { "PMNS Traverse", "pcp.pmns_traverse",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pmns_subtype,
+ { "Subtype", "pcp.pmns.subtype",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pmns_namelen,
+ { "Name Length", "pcp.pmns.namelen",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pmns_name,
+ { "Name", "pcp.pmns.name",
+ FT_STRING, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pmns_names,
+ { "PMNS Names", "pcp.pmns_names",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pmns_names_nstrbytes,
+ { "String Bytes", "pcp.pmns_names.nstrbytes",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pmns_names_numstatus,
+ { "Status", "pcp.pmns_names.numstatus",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pmns_names_numnames,
+ { "Number of Names", "pcp.pmns_names.numnames",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pmns_names_nametree,
+ { "Names", "pcp.pmns_names.nametree",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pmns_names_nametree_status,
+ { "Status", "pcp.pmns_names.nametree.status",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pmns_names_nametree_namelen,
+ { "Length", "pcp.pmns_names.nametree.namelen",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pmns_names_nametree_name,
+ { "Name", "pcp.pmns_names.nametree.name",
+ FT_STRING, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pmns_ids,
+ { "PMNS IDs", "pcp.pmns_ids",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pmns_ids_status,
+ { "Status", "pcp.pmns_ids.status",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pmns_ids_numids,
+ { "Number of IDs", "pcp.pmns_ids.numids",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pmns_child,
+ { "PMID Child", "pcp.pmns.child",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pmid,
+ { "PMID", "pcp.pmid",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pmid_flag,
+ { "Flag", "pcp.pmid.flag",
+ FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pmid_domain,
+ { "Domain", "pcp.pmid.domain",
+ FT_UINT16, BASE_DEC, /* uses 9 bits */
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pmid_cluster,
+ { "Cluster", "pcp.pmid.cluster",
+ FT_UINT16, BASE_DEC, /* uses 12 bits */
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pmid_item,
+ { "Item", "pcp.pmid.item",
+ FT_UINT16, BASE_DEC, /* uses 10 bits */
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pmid_type,
+ { "Type", "pcp.pmid.type",
+ FT_INT32, BASE_DEC,
+ VALS(packettypenames_pm_types), 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pmid_sem,
+ { "Type Semantics", "pcp.pmid.sem",
+ FT_UINT32, BASE_DEC,
+ VALS(packettypenames_pm_types_sem), 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_pmid_inst,
+ { "Instance", "pcp.pmid.inst",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_profile,
+ { "Profile", "pcp.profile",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_ctxnum,
+ { "Context Number", "pcp.ctxnum",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_profile_g_state,
+ { "Global Include/Exclude State", "pcp.profile.g_state",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_profile_numprof,
+ { "Number of Profiles", "pcp.profile.numprof",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_profile_profile,
+ { "Each Profile", "pcp.profile.profile",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_profile_profile_state,
+ { "Include/Exclude State", "pcp.profile.profile.state",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_profile_profile_numinst,
+ { "Number Instances to Follow", "pcp.profile.profile.numinst",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_fetch,
+ { "Fetch", "pcp.fetch",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_fetch_numpmid,
+ { "Number PMIDs", "pcp.fetch.numpmid",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_when,
+ { "Time Value", "pcp.when",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_when_sec,
+ { "Seconds", "pcp.when.sec",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_when_usec,
+ { "Microseconds", "pcp.when.usec",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_desc_req,
+ { "Description Request", "pcp.desc_req",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_desc,
+ { "Description Response", "pcp.desc",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_units,
+ { "PMID Units", "pcp.units",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_units_dimspace,
+ { "Dimension Space", "pcp.units.dimspace",
+ FT_UINT8, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_units_dimtime,
+ { "Dimension Time", "pcp.units.dimtime",
+ FT_UINT8, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_units_dimcount,
+ { "Dimension Count", "pcp.units.dimcount",
+ FT_UINT8, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_units_scalespace,
+ { "Scale Space", "pcp.units.scalespace",
+ FT_UINT8, BASE_DEC,
+ VALS(packettypenames_pm_units_space), 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_units_scaletime,
+ { "Scale Time", "pcp.units.scaletime",
+ FT_UINT8, BASE_DEC,
+ VALS(packettypenames_pm_units_time), 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_units_scalecount,
+ { "Scale Count", "pcp.units.scalecount",
+ FT_UINT8, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_instance_req,
+ { "Instance Request", "pcp.instance_req",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_instances,
+ { "Instance Response", "pcp.instances",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_instances_numinst,
+ { "Number of Instances", "pcp.instance_resp.numinst",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_instance,
+ { "Instance", "pcp.instance",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_instance_namelen,
+ { "Name Length", "pcp.instance.namelen",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_instance_name,
+ { "Name", "pcp.instance.name",
+ FT_STRING, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_instance_indom,
+ { "Instance Domain", "pcp.instance.indom",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_instance_valoffset,
+ { "Instance Offset", "pcp.instance.valoffset",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_instance_vallength,
+ { "Instance Value Length", "pcp.instance.vallength",
+ FT_INT24, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_instance_value_insitu,
+ { "Instance Value", "pcp.instance.value.uint",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_instance_value_ptr,
+ { "Instance Value", "pcp.instance.value.string",
+ FT_STRING, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_instance_value_int,
+ { "Instance Value", "pcp.instance.value.int",
+ FT_INT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_instance_value_uint,
+ { "Instance Value", "pcp.instance.value.uint",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_instance_value_int64,
+ { "Instance Value", "pcp.instance.value.int64",
+ FT_INT64, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_instance_value_uint64,
+ { "Instance Value", "pcp.instance.value.uint64",
+ FT_UINT64, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_instance_value_float,
+ { "Instance Value", "pcp.instance.value.float",
+ FT_FLOAT, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_instance_value_double,
+ { "Instance Value", "pcp.instance.value.float",
+ FT_DOUBLE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_instance_value_aggr,
+ { "Instance Value", "pcp.instance.value.bytes",
+ FT_BYTES, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_results,
+ { "Fetch Results", "pcp.results",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_results_numpmid,
+ { "Number of PMIDs", "pcp.results.numpmid",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_result,
+ { "Result", "pcp.result",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_result_numval,
+ { "Number of Values", "pcp.result.numval",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_result_valfmt,
+ { "Value Encoding Format", "pcp.result.valfmt",
+ FT_UINT32, BASE_DEC,
+ VALS(packettypenames_valfmt), 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_text_req,
+ { "Text Request", "pcp.text_req",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_text_type,
+ { "Help Text Type", "pcp.text.type",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_text_type_format,
+ { "Text Type Format", "pcp.text.type.format",
+ FT_UINT8, BASE_DEC,
+ VALS(packettypenames_text_type_format), 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_text_type_ident,
+ { "Text Type Ident", "pcp.text.type.ident",
+ FT_UINT8, BASE_DEC,
+ VALS(packettypenames_text_type_ident), 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_text,
+ { "Text Response", "pcp.text",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_text_ident,
+ { "Text Ident (raw)", "pcp.text.ident",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_text_buflen,
+ { "Text Buffer Length", "pcp.text.buflen",
+ FT_UINT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_text_buffer,
+ { "Text Buffer", "pcp.text.buffer",
+ FT_STRING, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_user_auth_payload,
+ { "User Authentication Payload", "pcp.user_auth_payload",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_label_req,
+ { "Label Request", "pcp.label_req",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_label_ident,
+ { "Label Ident", "pcp.label.ident",
+ FT_INT32, BASE_DEC,
+ NULL, 0x0,
+ "Domain, PMID or pmInDom identifier", HFILL
+ }
+ },
+ { &hf_pcp_label_type,
+ { "Label Type", "pcp.label.type",
+ FT_INT32, BASE_DEC,
+ VALS(packettypenames_label_req_type), 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_label,
+ { "Labels", "pcp.label",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_label_padding,
+ { "Padding", "pcp.label.padding",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_label_nsets,
+ { "Num Label Sets", "pcp.label.nsets",
+ FT_INT32, BASE_DEC,
+ NULL, 0x0,
+ "Number of Label Sets", HFILL
+ }
+ },
+ { &hf_pcp_label_sets,
+ { "Label Set", "pcp.label.sets",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_label_sets_inst,
+ { "Instance", "pcp.label.sets.inst",
+ FT_INT32, BASE_DEC,
+ NULL, 0x0,
+ "Instance identifier or PM_IN_NULL", HFILL
+ }
+ },
+ { &hf_pcp_label_sets_nlabels,
+ { "Num of Labels", "pcp.label.sets.nlabels",
+ FT_INT32, BASE_DEC,
+ NULL, 0x0,
+ "Number of labels or error code", HFILL
+ }
+ },
+ { &hf_pcp_label_sets_json,
+ { "JSON Offset", "pcp.label.sets.json",
+ FT_INT32, BASE_DEC,
+ NULL, 0x0,
+ "Offset to start of JSON string", HFILL
+ }
+ },
+ { &hf_pcp_label_sets_jsonlen,
+ { "JSON Length", "pcp.label.sets.jsonlen",
+ FT_INT32, BASE_DEC,
+ NULL, 0x0,
+ "Length of bytes of the JSON string", HFILL
+ }
+ },
+ { &hf_pcp_label_sets_labels,
+ { "Label", "pcp.label.sets.label",
+ FT_NONE, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_pcp_label_sets_labels_nameoffset,
+ { "Name Offset", "pcp.label.sets.label.nameoffset",
+ FT_INT16, BASE_DEC,
+ NULL, 0x0,
+ "Label name offset in the JSONB string", HFILL
+ }
+ },
+ { &hf_pcp_label_sets_labels_namelen,
+ { "Name Length", "pcp.label.sets.label.namelen",
+ FT_INT8, BASE_DEC,
+ NULL, 0x0,
+ "Length of name excluding NULL terminator", HFILL
+ }
+ },
+ { &hf_pcp_label_sets_labels_flags,
+ { "Flags", "pcp.label.sets.label.flags",
+ FT_INT8, BASE_DEC,
+ NULL, 0x0,
+ "Information about this label", HFILL
+ }
+ },
+ { &hf_pcp_label_sets_labels_valueoffset,
+ { "Value Offset", "pcp.label.sets.label.valueoffset",
+ FT_INT16, BASE_DEC,
+ NULL, 0x0,
+ "Offset of the label value", HFILL
+ }
+ },
+ { &hf_pcp_label_sets_labels_valuelen,
+ { "Value Length", "pcp.label.sets.label.valuelen",
+ FT_INT16, BASE_DEC,
+ NULL, 0x0,
+ "Length of the value in bytes", HFILL
+ }
+ },
+ { &hf_pcp_label_sets_labels_name,
+ { "Name", "pcp.label.sets.label.name",
+ FT_STRING, BASE_NONE,
+ NULL, 0x0,
+ "Label name", HFILL
+ }
+ },
+ { &hf_pcp_label_sets_labels_value,
+ { "Value", "pcp.label.sets.label.value",
+ FT_STRING, BASE_NONE,
+ NULL, 0x0,
+ "Label value", HFILL
+ }
+ },
+
+
+ };
+
+ static gint *ett[] = {
+ &ett_pcp,
+ &ett_pcp_pdu_length,
+ &ett_pcp_pdu_type,
+ &ett_pcp_pdu_pid,
+ &ett_pcp_pdu_error,
+ &ett_pcp_pdu_padding,
+ &ett_pcp_creds_number_of,
+ &ett_pcp_creds_type,
+ &ett_pcp_creds_vala,
+ &ett_pcp_creds_valb,
+ &ett_pcp_creds_valc,
+ &ett_pcp_start,
+ &ett_pcp_start_status,
+ &ett_pcp_start_zero,
+ &ett_pcp_start_version,
+ &ett_pcp_start_licensed,
+ &ett_pcp_start_features,
+ &ett_pcp_pmns_traverse,
+ &ett_pcp_pmns_subtype,
+ &ett_pcp_pmns_namelen,
+ &ett_pcp_pmns_name,
+ &ett_pcp_pmns_names,
+ &ett_pcp_pmns_names_nstrbytes,
+ &ett_pcp_pmns_names_numstatus,
+ &ett_pcp_pmns_names_numnames,
+ &ett_pcp_pmns_names_nametree,
+ &ett_pcp_pmns_names_nametree_status,
+ &ett_pcp_pmns_names_nametree_namelen,
+ &ett_pcp_pmns_names_nametree_name,
+ &ett_pcp_pmns_ids,
+ &ett_pcp_pmns_ids_status,
+ &ett_pcp_pmns_ids_numids,
+ &ett_pcp_pmns_child,
+ &ett_pcp_pmid,
+ &ett_pcp_pmid_flag,
+ &ett_pcp_pmid_domain,
+ &ett_pcp_pmid_cluster,
+ &ett_pcp_pmid_item,
+ &ett_pcp_pmid_type,
+ &ett_pcp_pmid_sem,
+ &ett_pcp_profile,
+ &ett_pcp_ctxnum,
+ &ett_pcp_profile_g_state,
+ &ett_pcp_profile_numprof,
+ &ett_pcp_profile_profile,
+ &ett_pcp_profile_profile_state,
+ &ett_pcp_profile_profile_numinst,
+ &ett_pcp_fetch,
+ &ett_pcp_fetch_numpmid,
+ &ett_pcp_when,
+ &ett_pcp_when_sec,
+ &ett_pcp_when_usec,
+ &ett_pcp_desc_req,
+ &ett_pcp_units,
+ &ett_pcp_units_dimspace,
+ &ett_pcp_units_dimtime,
+ &ett_pcp_units_dimcount,
+ &ett_pcp_units_scalespace,
+ &ett_pcp_units_scaletime,
+ &ett_pcp_units_scalecount,
+ &ett_pcp_instance,
+ &ett_pcp_instance_req,
+ &ett_pcp_instance_namelen,
+ &ett_pcp_instance_name,
+ &ett_pcp_instance_indom,
+ &ett_pcp_instance_inst,
+ &ett_pcp_instance_valoffset,
+ &ett_pcp_instance_vallength,
+ &ett_pcp_instance_value_insitu,
+ &ett_pcp_instance_value_ptr,
+ &ett_pcp_instance_value_int,
+ &ett_pcp_instance_value_uint,
+ &ett_pcp_instance_value_int64,
+ &ett_pcp_instance_value_uint64,
+ &ett_pcp_instance_value_float,
+ &ett_pcp_instance_value_double,
+ &ett_pcp_instance_value_aggr,
+ &ett_pcp_instances,
+ &ett_pcp_instances_numinst,
+ &ett_pcp_results,
+ &ett_pcp_results_numpmid,
+ &ett_pcp_result,
+ &ett_pcp_result_numval,
+ &ett_pcp_result_valfmt,
+ &ett_pcp_text_req,
+ &ett_pcp_text_type,
+ &ett_pcp_text_type_format,
+ &ett_pcp_text_type_ident,
+ &ett_pcp_text,
+ &ett_pcp_text_ident,
+ &ett_pcp_text_buflen,
+ &ett_pcp_text_buffer,
+ };
+
+ static ei_register_info ei[] = {
+ { &ei_pcp_type_event_unimplemented, { "pcp.pmid.type.event.unimplemented", PI_UNDECODED, PI_WARN, "PM_TYPE_EVENT: Unimplemented Value Type", EXPFILL }},
+ { &ei_pcp_type_nosupport_unsupported, { "pcp.pmid.type.nosupport.unsupported", PI_UNDECODED, PI_WARN, "PM_TYPE_NOSUPPORT: Unsupported Value Type", EXPFILL }},
+ { &ei_pcp_type_unknown_unknown_value, { "pcp.pmid.type.unknown.unknown_value", PI_UNDECODED, PI_WARN, "PM_TYPE_UNKNOWN: Unknown Value Type", EXPFILL }},
+ { &ei_pcp_unimplemented_value, { "pcp.pmid.type.unimplemented", PI_UNDECODED, PI_WARN, "Unimplemented Value Type", EXPFILL }},
+ { &ei_pcp_unimplemented_packet_type, { "pcp.type.unimplemented", PI_UNDECODED, PI_WARN, "Unimplemented Packet Type", EXPFILL }},
+ { &ei_pcp_ssl_upgrade, { "pcp.ssl_upgrade", PI_COMMENTS_GROUP, PI_COMMENT, "SSL upgrade via SECURE_ACK", EXPFILL }},
+ { &ei_pcp_ssl_upgrade_failed, { "pcp.ssl_upgrade_failed", PI_RESPONSE_CODE, PI_WARN, "SSL upgrade via SECURE_ACK failed", EXPFILL }},
+ { &ei_pcp_label_error, { "pcp.label.error", PI_RESPONSE_CODE, PI_NOTE, "Label returned an error", EXPFILL }},
+ { &ei_pcp_label_error_endianness, { "pcp.label.error.endianness", PI_RESPONSE_CODE, PI_NOTE, "Value length has been decoded without knowing the endianness. It has been attempted to be detected but may be wrong", EXPFILL }},
+ };
+
+ expert_module_t* expert_pcp;
+
+ proto_pcp = proto_register_protocol("Performance Co-Pilot", "PCP", "pcp");
+
+ expert_pcp = expert_register_protocol(proto_pcp);
+ expert_register_field_array(expert_pcp, ei, array_length(ei));
+
+ proto_register_field_array(proto_pcp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ pcp_handle = register_dissector("pcp", dissect_pcp, proto_pcp);
+}
+
+void proto_reg_handoff_pcp(void)
+{
+ dissector_add_uint_with_preference("tcp.port", PCP_PORT, pcp_handle);
+}
+
+/*
+* Editor modelines - https://www.wireshark.org/tools/modelines.html
+*
+* Local variables:
+* c-basic-offset: 4
+* tab-width: 8
+* indent-tabs-mode: nil
+* End:
+*
+* vi: set shiftwidth=4 tabstop=8 expandtab:
+* :indentSize=4:tabSize=8:noTabs=true:
+*/