/* packet-pcp.c * Routines for Performace Co-Pilot protocol dissection * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include "packet-tcp.h" #include "packet-ssl-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_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 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; /* Magic numbers */ #define PCP_SECURE_ACK_SUCCESSFUL 0 static const value_string pcp_feature_flags[] = { #define PCP_PDU_FLAG_SECURE 0x1 { PCP_PDU_FLAG_SECURE, "SECURE" }, #define PCP_PDU_FLAG_COMPRESS 0x2 { PCP_PDU_FLAG_COMPRESS, "COMPRESS" }, #define PCP_PDU_FLAG_AUTH 0x4 { PCP_PDU_FLAG_AUTH, "AUTH"}, #define PCP_PDU_FLAG_CREDS_REQD 0x8 { PCP_PDU_FLAG_CREDS_REQD, "CREDS_REQD" }, #define PCP_PDU_FLAG_SECURE_ACK 0x10 { PCP_PDU_FLAG_SECURE_ACK, "SECURE_ACK" }, #define PCP_PDU_FLAG_NO_NSS_INIT 0x20 { PCP_PDU_FLAG_NO_NSS_INIT, "NO_NSS_INIT" }, #define PCP_PDU_FLAG_CONTAINER 0x40 { PCP_PDU_FLAG_CONTAINER, "CONTAINER" }, { 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" }, { 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 } }; typedef struct pcp_conv_info_t { struct pcp_conv_info_t *next; GArray *pmid_name_candidates; GHashTable *pmid_to_name; guint32 last_pmns_names_frame; guint32 last_processed_pmns_names_frame; } pcp_conv_info_t; static pcp_conv_info_t *pcp_conv_info_items = NULL; /* function prototypes */ static void pcp_cleanup(void); static pcp_conv_info_t* get_pcp_conversation_info(packet_info *pinfo); static int is_unvisited_pmns_names_frame(packet_info *pinfo); 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 clear_name_candidates(GArray *pmid_name_candidates); 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 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(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); /* 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 void clear_name_candidates(GArray *pmid_name_candidates) { if(pmid_name_candidates->len > 0) { g_array_remove_range(pmid_name_candidates, 0, pmid_name_candidates->len); } } static guint8* get_name_from_pmid(guint32 pmid, packet_info *pinfo) { guint8 *name; GHashTable *pmid_to_name; pmid_to_name = get_pcp_conversation_info(pinfo)->pmid_to_name; name = (guint8*)g_hash_table_lookup(pmid_to_name, GINT_TO_POINTER(pmid)); if(!name) { name = (guint8*)wmem_strdup(wmem_packet_scope(), "Metric name unknown"); } return name; } static const gchar *get_pcp_features_to_string(guint16 feature_flags) { const value_string *flag_under_test; wmem_strbuf_t *string_buffer; gsize string_length; string_buffer = wmem_strbuf_new(wmem_packet_scope(), ""); /* 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->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 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); g_array_append_val(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 = pcp_conv_info->pmid_name_candidates->len; 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; } clear_name_candidates(pcp_conv_info->pmid_name_candidates); } 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; ipmid_name_candidates, guint8*, i); if(g_hash_table_lookup(pcp_conv_info->pmid_to_name, GINT_TO_POINTER(pmid)) == NULL) { g_hash_table_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); clear_name_candidates(pcp_conv_info->pmid_name_candidates); } 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 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("ssl"), 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|ENC_NA); 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|ENC_NA); 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|ENC_NA); 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 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; icinfo, 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 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 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; jcinfo, 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|ENC_NA); 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|ENC_NA); 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); } /* 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 0) { proto_tree_add_item(pcp_instance_tree, hf_pcp_instance_name, tvb, offset, name_len, ENC_ASCII|ENC_NA); 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 _U_, 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 _U_, proto_tree *tree, int offset) { guint16 feature_flags; const gchar *feature_flags_string; static const int * pcp_feature_flags_header_fields[] = { &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(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; return offset; } /* 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 = (pcp_conv_info_t*)g_malloc(sizeof(pcp_conv_info_t)); conversation_add_proto_data(conversation, proto_pcp, pcp_conv_info); pcp_conv_info->pmid_name_candidates = g_array_new(TRUE, TRUE, sizeof(guint8 *)); pcp_conv_info->pmid_to_name = g_hash_table_new(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->next = pcp_conv_info_items; pcp_conv_info_items = pcp_conv_info; } 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 (pinfo->srcport == PCP_PORT || pinfo->srcport == PMPROXY_PORT) { 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; 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); } static void pcp_cleanup(void) { pcp_conv_info_t *pcp_conv_info; for(pcp_conv_info = pcp_conv_info_items; pcp_conv_info != NULL; ) { pcp_conv_info_t *last; g_hash_table_destroy(pcp_conv_info->pmid_to_name); /* Don't free array elements (FALSE arg) as their memory is controlled via wmem */ g_array_free(pcp_conv_info->pmid_name_candidates, FALSE); last = pcp_conv_info; pcp_conv_info = pcp_conv_info->next; g_free(last); } } /* 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_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_INT8, 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.scalespace", 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 } }, }; 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 }}, }; expert_module_t* expert_pcp; expert_pcp = expert_register_protocol(proto_pcp); expert_register_field_array(expert_pcp, ei, array_length(ei)); proto_pcp = proto_register_protocol("Performance Co-Pilot", "PCP", "pcp"); 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); register_cleanup_routine(pcp_cleanup); } void proto_reg_handoff_pcp(void) { dissector_add_uint("tcp.port", PCP_PORT, pcp_handle); } /* * Editor modelines - http://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: */